]> code.delx.au - gnu-emacs/blobdiff - src/xfns.c
(MAXREQUEST): Defined.
[gnu-emacs] / src / xfns.c
index f2d12df3e0271a979f97b4645cf9714911b8208b..6f42dcf2cd46b59fe50f5168dcd58d95ca096149 100644 (file)
@@ -39,7 +39,11 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 extern void abort ();
 
 #ifndef VMS
+#if 1 /* Used to be #ifdef EMACS_BITMAP_FILES, but this should always work.  */
+#include "bitmaps/gray.xbm"
+#else
 #include <X11/bitmaps/gray>
+#endif
 #else
 #include "[.bitmaps]gray.xbm"
 #endif
@@ -54,8 +58,14 @@ static XrmDatabase xrdb;
 /* The class of this X application.  */
 #define EMACS_CLASS "Emacs"
 
-/* The name we're using for this X application.  */
-Lisp_Object Vxrdb_name;
+#ifdef HAVE_X11R4
+#define MAXREQUEST(dpy) (XMaxRequestSize (dpy))
+#else
+#define MAXREQUEST(dpy) ((dpy)->max_request_size)
+#endif
+
+/* The name we're using in resource queries.  */
+Lisp_Object Vx_resource_name;
 
 /* Title name and application name for X stuff. */
 extern char *x_id_name;
@@ -169,7 +179,7 @@ Lisp_Object Qcursor_type;
 Lisp_Object Qfont;
 Lisp_Object Qforeground_color;
 Lisp_Object Qgeometry;
-Lisp_Object Qicon;
+/* Lisp_Object Qicon; */
 Lisp_Object Qicon_left;
 Lisp_Object Qicon_top;
 Lisp_Object Qicon_type;
@@ -188,13 +198,10 @@ Lisp_Object Qx_frame_parameter;
 
 /* The below are defined in frame.c. */
 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
-extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qicon;
+extern Lisp_Object Qunsplittable, Qmenu_bar_lines;
 
 extern Lisp_Object Vwindow_system_version;
 
-/* Mouse map for clicks in windows.  */
-extern Lisp_Object Vglobal_mouse_map;
-
 \f
 /* Error if we are not connected to X.  */
 static void
@@ -332,26 +339,48 @@ x_set_frame_parameters (f, alist)
   /* Same here.  */
   Lisp_Object left, top;
 
-  width = height = top = left = Qnil;
+  /* Record in these vectors all the parms specified.  */
+  Lisp_Object *parms;
+  Lisp_Object *values;
+  int i;
+  
+  i = 0;
+  for (tail = alist; CONSP (tail); tail = Fcdr (tail))
+    i++;
+
+  parms = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
+  values = (Lisp_Object *) alloca (i * sizeof (Lisp_Object));
+
+  /* Extract parm names and values into those vectors.  */
 
+  i = 0;
   for (tail = alist; CONSP (tail); tail = Fcdr (tail))
     {
       Lisp_Object elt, prop, val;
 
       elt = Fcar (tail);
-      prop = Fcar (elt);
-      val = Fcdr (elt);
+      parms[i] = Fcar (elt);
+      values[i] = Fcdr (elt);
+      i++;
+    }
+
+  width = height = top = left = Qunbound;
+
+  /* Now process them in reverse of specified order.  */
+  for (i--; i >= 0; i--)
+    {
+      Lisp_Object prop, val;
 
-      /* Ignore all but the first set presented.  You're supposed to
-        be able to append two parameter lists and have the first
-        shadow the second.  */
-      if (EQ (prop, Qwidth) && NILP (width))
+      prop = parms[i];
+      val = values[i];
+
+      if (EQ (prop, Qwidth))
        width = val;
-      else if (EQ (prop, Qheight) && NILP (height))
+      else if (EQ (prop, Qheight))
        height = val;
-      else if (EQ (prop, Qtop) && NILP (top))
+      else if (EQ (prop, Qtop))
        top = val;
-      else if (EQ (prop, Qleft) && NILP (left))
+      else if (EQ (prop, Qleft))
        left = val;
       else
        {
@@ -367,23 +396,23 @@ x_set_frame_parameters (f, alist)
        }
     }
 
-  /* Don't call these unless they've changed; the window may not actually
-     exist yet.  */
+  /* Don't set these parameters these unless they've been explicitly
+     specified.  The window might be mapped or resized while we're in
+     this function, and we don't want to override that unless the lisp
+     code has asked for it.
+
+     Don't set these parameters unless they actually differ from the
+     window's current parameters; the window may not actually exist
+     yet.  */
   {
     Lisp_Object frame;
 
-    if (NILP (width))  XSET (width,  Lisp_Int, FRAME_WIDTH  (f));
-    if (NILP (height)) XSET (height, Lisp_Int, FRAME_HEIGHT (f));
-
-    if (NILP (top))    XSET (top, Lisp_Int, f->display.x->top_pos);
-    if (NILP (left))   XSET (left, Lisp_Int, f->display.x->left_pos);
-
     XSET (frame, Lisp_Frame, f);
-    if (XINT (width) != FRAME_WIDTH (f)
-       || XINT (height) != FRAME_HEIGHT (f))
+    if ((NUMBERP (width) && XINT (width) != FRAME_WIDTH (f))
+       || (NUMBERP (height) && XINT (height) != FRAME_HEIGHT (f)))
       Fset_frame_size (frame, width, height);
-    if (XINT (left) != f->display.x->left_pos
-       || XINT (top) != f->display.x->top_pos)
+    if ((NUMBERP (left) && XINT (left) != f->display.x->left_pos)
+       || (NUMBERP (top) && XINT (top) != f->display.x->top_pos))
       Fset_frame_position (frame, left, top);
   }
 }
@@ -561,7 +590,7 @@ x_set_mouse_color (f, arg, oldval)
   BLOCK_INPUT;
 #ifdef HAVE_X11
 
-  /* It's not okay to crash if the user selects a screwey cursor.  */
+  /* It's not okay to crash if the user selects a screwy cursor.  */
   x_catch_errors ();
 
   if (!EQ (Qnil, Vx_pointer_shape))
@@ -910,17 +939,20 @@ x_set_menu_bar_lines_1 (window, n)
   Lisp_Object window;
   int n;
 {
-  for (; !NILP (window); window = XWINDOW (window)->next)
-    {
-      struct window *w = XWINDOW (window);
+  struct window *w = XWINDOW (window);
 
-      XFASTINT (w->top) += n;
+  XFASTINT (w->top) += n;
+  XFASTINT (w->height) -= n;
 
-      if (!NILP (w->vchild))
-       x_set_menu_bar_lines_1 (w->vchild, n);
+  /* Handle just the top child in a vertical split.  */
+  if (!NILP (w->vchild))
+    x_set_menu_bar_lines_1 (w->vchild, n);
 
-      if (!NILP (w->hchild))
-       x_set_menu_bar_lines_1 (w->hchild, n);
+  /* Adjust all children in a horizontal split.  */
+  for (window = w->hchild; !NILP (window); window = w->next)
+    {
+      w = XWINDOW (window);
+      x_set_menu_bar_lines_1 (window, n);
     }
 }
 
@@ -946,16 +978,6 @@ x_set_menu_bar_lines (f, value, oldval)
 
   FRAME_MENU_BAR_LINES (f) = nlines;
   x_set_menu_bar_lines_1 (f->root_window, nlines - olines);
-  /* Use FRAME_NEW_WIDTH, HEIGHT so as not to override a size change
-     made by the user but not fully reflected in the Emacs frame object.  */
-  x_set_window_size (f,
-                    (FRAME_NEW_WIDTH (f)
-                     ? FRAME_NEW_WIDTH (f)
-                     : FRAME_WIDTH (f)),
-                    ((FRAME_NEW_HEIGHT (f)
-                      ? FRAME_NEW_HEIGHT (f)
-                      : FRAME_HEIGHT (f))
-                     + nlines - olines));
 }
 
 /* Change the name of frame F to ARG.  If ARG is nil, set F's name to
@@ -1085,17 +1107,28 @@ x_set_vertical_scroll_bars (f, arg, oldval)
 /* Subroutines of creating an X frame.  */
 
 #ifdef HAVE_X11
+
+/* Make sure that Vx_resource_name is set to a reasonable value.  */
+static void
+validate_x_resource_name ()
+{
+  if (! STRINGP (Vx_resource_name))
+    Vx_resource_name = make_string ("emacs", 5);
+}
+
+
 extern char *x_get_string_resource ();
 extern XrmDatabase x_load_resources ();
 
 DEFUN ("x-get-resource", Fx_get_resource, Sx_get_resource, 2, 4, 0,
   "Return the value of ATTRIBUTE, of class CLASS, from the X defaults database.\n\
-This uses `INSTANCE.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
-class, where INSTANCE is the name under which Emacs was invoked.\n\
+This uses `NAME.ATTRIBUTE' as the key and `Emacs.CLASS' as the\n\
+class, where INSTANCE is the name under which Emacs was invoked, or\n\
+the name specified by the `-name' or `-rn' command-line arguments.\n\
 \n\
 The optional arguments COMPONENT and SUBCLASS add to the key and the\n\
 class, respectively.  You must specify both of them or neither.\n\
-If you specify them, the key is `INSTANCE.COMPONENT.ATTRIBUTE'\n\
+If you specify them, the key is `NAME.COMPONENT.ATTRIBUTE'\n\
 and the class is `Emacs.CLASS.SUBCLASS'.")
   (attribute, class, component, subclass)
      Lisp_Object attribute, class, component, subclass;
@@ -1116,11 +1149,13 @@ and the class is `Emacs.CLASS.SUBCLASS'.")
   if (NILP (component) != NILP (subclass))
     error ("x-get-resource: must specify both COMPONENT and SUBCLASS or neither");
 
+  validate_x_resource_name ();
+
   if (NILP (component))
     {
       /* Allocate space for the components, the dots which separate them,
         and the final '\0'.  */
-      name_key = (char *) alloca (XSTRING (Vxrdb_name)->size
+      name_key = (char *) alloca (XSTRING (Vx_resource_name)->size
                                  + XSTRING (attribute)->size
                                  + 2);
       class_key = (char *) alloca ((sizeof (EMACS_CLASS) - 1)
@@ -1128,7 +1163,7 @@ and the class is `Emacs.CLASS.SUBCLASS'.")
                                   + 2);
 
       sprintf (name_key, "%s.%s",
-              XSTRING (Vxrdb_name)->data,
+              XSTRING (Vx_resource_name)->data,
               XSTRING (attribute)->data);
       sprintf (class_key, "%s.%s",
               EMACS_CLASS,
@@ -1136,7 +1171,7 @@ and the class is `Emacs.CLASS.SUBCLASS'.")
     }
   else
     {
-      name_key = (char *) alloca (XSTRING (Vxrdb_name)->size
+      name_key = (char *) alloca (XSTRING (Vx_resource_name)->size
                                  + XSTRING (component)->size
                                  + XSTRING (attribute)->size
                                  + 3);
@@ -1147,7 +1182,7 @@ and the class is `Emacs.CLASS.SUBCLASS'.")
                                   + 3);
 
       sprintf (name_key, "%s.%s.%s",
-              XSTRING (Vxrdb_name)->data,
+              XSTRING (Vx_resource_name)->data,
               XSTRING (component)->data,
               XSTRING (attribute)->data);
       sprintf (class_key, "%s.%s.%s",
@@ -1509,7 +1544,8 @@ x_window (f)
                     screen_visual, /* set in Fx_open_connection */
                     attribute_mask, &attributes);
 
-  class_hints.res_name = (char *) XSTRING (Vxrdb_name)->data;
+  validate_x_resource_name ();
+  class_hints.res_name = (char *) XSTRING (Vx_resource_name)->data;
   class_hints.res_class = EMACS_CLASS;
   XSetClassHint (x_current_display, FRAME_X_WINDOW (f), &class_hints);
 
@@ -1720,16 +1756,48 @@ be shared by the new frame.")
 
   /* Extract the window parameters from the supplied values
      that are needed to determine window geometry.  */
-  x_default_parameter (f, parms, Qfont, 
-                      build_string
-                      /* If we use an XLFD name for this font, the lisp code
-                         knows how to find variants which are bold, italic,
-                         etcetera.  */
-                      ("-*-fixed-*-*-*-*-*-120-*-*-c-*-iso8859-1"),
-                      "font", "Font", string);
+  {
+    Lisp_Object font;
+
+    font = x_get_arg (parms, Qfont, "font", "Font", string);
+    BLOCK_INPUT;
+    /* First, try whatever font the caller has specified.  */
+    if (STRINGP (font))
+      font = x_new_font (f, XSTRING (font)->data);
+    /* Try out a font which we hope has bold and italic variations.  */
+    if (!STRINGP (font))
+      font = x_new_font (f, "-misc-fixed-medium-r-normal-*-*-120-*-*-c-*-iso8859-1");
+    if (! STRINGP (font))
+      font = x_new_font (f, "-*-*-medium-r-normal-*-*-120-*-*-c-*-iso8859-1");
+    if (! STRINGP (font))
+      /* This was formerly the first thing tried, but it finds too many fonts
+        and takes too long.  */
+      font = x_new_font (f, "-*-*-medium-r-*-*-*-*-*-*-c-*-iso8859-1");
+    /* If those didn't work, look for something which will at least work.  */
+    if (! STRINGP (font))
+      font = x_new_font (f, "-*-fixed-*-*-*-*-*-120-*-*-c-*-iso8859-1");
+    UNBLOCK_INPUT;
+    if (! STRINGP (font))
+      font = build_string ("fixed");
+
+    x_default_parameter (f, parms, Qfont, font, 
+                        "font", "Font", string);
+  }
   x_default_parameter (f, parms, Qborder_width, make_number (2),
                       "borderwidth", "BorderWidth", number);
-  /* This defaults to 2 in order to match xterm.  */
+  /* This defaults to 2 in order to match xterm.  We recognize either
+     internalBorderWidth or internalBorder (which is what xterm calls
+     it).  */
+  if (NILP (Fassq (Qinternal_border_width, parms)))
+    {
+      Lisp_Object value;
+
+      value = x_get_arg (parms, Qinternal_border_width,
+                        "internalBorder", "BorderWidth", number);
+      if (! EQ (value, Qunbound))
+       parms = Fcons (Fcons (Qinternal_border_width, value),
+                      parms);
+    }
   x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
                       "internalBorderWidth", "BorderWidth", number);
   x_default_parameter (f, parms, Qvertical_scroll_bars, Qt,
@@ -1840,7 +1908,7 @@ be shared by the new frame.")
   f->display.x = (struct x_display *) xmalloc (sizeof (struct x_display));
   bzero (f->display.x, sizeof (struct x_display));
 
-  /* Some temprorary default values for height and width. */
+  /* Some temporary default values for height and width. */
   width = 80;
   height = 40;
   f->display.x->left_pos = -1;
@@ -2192,12 +2260,12 @@ fonts), even if they match PATTERN and FACE.")
       FRAME_PTR f = NILP (frame) ? selected_frame : XFRAME (frame);
       int face_id = face_name_id_number (f, face);
 
-      if (face_id < 0 || face_id >= FRAME_N_FACES (f)
-         || FRAME_FACES (f) [face_id] == 0)
+      if (face_id < 0 || face_id >= FRAME_N_PARAM_FACES (f)
+         || FRAME_PARAM_FACES (f) [face_id] == 0)
        size_ref = f->display.x->font;
       else
        {
-         size_ref = FRAME_FACES (f) [face_id]->font;
+         size_ref = FRAME_PARAM_FACES (f) [face_id]->font;
          if (size_ref == (XFontStruct *) (~0))
            size_ref = f->display.x->font;
        }
@@ -2211,22 +2279,24 @@ fonts), even if they match PATTERN and FACE.")
                              &info); /* info_return */
   UNBLOCK_INPUT;
 
-  {
-    Lisp_Object *tail;
-    int i;
-
-    list = Qnil;
-    tail = &list;
-    for (i = 0; i < num_fonts; i++)
-      if (! size_ref 
-         || same_size_fonts (&info[i], size_ref))
-       {
-         *tail = Fcons (build_string (names[i]), Qnil);
-         tail = &XCONS (*tail)->cdr;
-       }
+  list = Qnil;
 
-    XFreeFontInfo (names, info, num_fonts);
-  }
+  if (names)
+    {
+      Lisp_Object *tail;
+      int i;
+
+      tail = &list;
+      for (i = 0; i < num_fonts; i++)
+       if (! size_ref 
+           || same_size_fonts (&info[i], size_ref))
+         {
+           *tail = Fcons (build_string (names[i]), Qnil);
+           tail = &XCONS (*tail)->cdr;
+         }
+
+      XFreeFontInfo (names, info, num_fonts);
+    }
 
   return list;
 }
@@ -2314,6 +2384,18 @@ DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
   return make_number (DisplayCells (dpy, DefaultScreen (dpy)));
 }
 
+DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
+       Sx_server_max_request_size,
+  0, 1, 0,
+  "Returns the maximum request size of the X server FRAME is using.")
+  (frame)
+     Lisp_Object frame;
+{
+  Display *dpy = x_current_display;
+  check_x ();
+  return make_number (MAXREQUEST (dpy));
+}
+
 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
   "Returns the vendor ID string of the X server FRAME is on.")
   (frame)
@@ -2805,7 +2887,7 @@ clip_contour_top (y_pos, x_pos)
     }
 }
 
-/* Erase the top horzontal lines of the contour, and then extend
+/* Erase the top horizontal lines of the contour, and then extend
    the contour upwards. */
 
 static void
@@ -3335,8 +3417,15 @@ also be depressed for NEWSTRING to appear.")
          mod = Fcar (rest);
          CHECK_STRING (mod, 3);
          modifier_list[i] = XStringToKeysym ((char *) XSTRING (mod)->data);
+#ifndef HAVE_X11R5
+         if (modifier_list[i] == NoSymbol
+             || !(IsModifierKey (modifier_list[i]) 
+                   || ((unsigned)(modifier_list[i]) == XK_Mode_switch)
+                   || ((unsigned)(modifier_list[i]) == XK_Num_Lock)))
+#else
          if (modifier_list[i] == NoSymbol
              || !IsModifierKey (modifier_list[i]))
+#endif
            error ("Element is not a modifier keysym");
          i++;
        }
@@ -3432,8 +3521,8 @@ select_visual (screen, depth)
 
 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
        1, 2, 0, "Open a connection to an X server.\n\
-DISPLAY is the name of the display to connect to.  Optional second\n\
-arg XRM_STRING is a string of resources in xrdb format.")
+DISPLAY is the name of the display to connect to.\n\
+Optional second arg XRM_STRING is a string of resources in xrdb format.")
   (display, xrm_string)
      Lisp_Object display, xrm_string;
 {
@@ -3443,6 +3532,8 @@ arg XRM_STRING is a string of resources in xrdb format.")
   CHECK_STRING (display, 0);
   if (x_current_display != 0)
     error ("X server connection is already initialized");
+  if (! NILP (xrm_string))
+    CHECK_STRING (xrm_string, 1);
 
   /* This is what opens the connection and sets x_current_display.
      This also initializes many symbols, such as those used for input. */
@@ -3451,33 +3542,24 @@ arg XRM_STRING is a string of resources in xrdb format.")
 #ifdef HAVE_X11
   XFASTINT (Vwindow_system_version) = 11;
 
-  if (!EQ (xrm_string, Qnil))
-    {
-      CHECK_STRING (xrm_string, 1);
-      xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
-    }
+  if (! NILP (xrm_string))
+    xrm_option = (unsigned char *) XSTRING (xrm_string)->data;
   else
     xrm_option = (unsigned char *) 0;
-  xrdb = x_load_resources (x_current_display, xrm_option, EMACS_CLASS);
-#if defined (HAVE_X11R5) && ! defined (NO_XRM_SET_DATBASE)
+
+  validate_x_resource_name ();
+
+  BLOCK_INPUT;
+  xrdb = x_load_resources (x_current_display, xrm_option,
+                          (char *) XSTRING (Vx_resource_name)->data,
+                          EMACS_CLASS);
+  UNBLOCK_INPUT;
+#if defined (HAVE_X11R5)
   XrmSetDatabase (x_current_display, xrdb);
 #else
   x_current_display->db = xrdb;
 #endif
 
-  /* Make a version of Vinvocation_name suitable for use in xrdb
-     queries - i.e. containing no dots or asterisks.  */
-  Vxrdb_name = Fcopy_sequence (Vinvocation_name);
-  {
-    int i;
-    int len = XSTRING (Vxrdb_name)->size;
-    char *data = XSTRING (Vxrdb_name)->data;
-    
-    for (i = 0; i < len; i++)
-      if (data[i] == '.' || data[i] == '*')
-       data[i] = '-';
-  }
-
   x_screen = DefaultScreenOfDisplay (x_current_display);
 
   screen_visual = select_visual (x_screen, &n_planes);
@@ -3580,8 +3662,6 @@ syms_of_xfns ()
   staticpro (&Qforeground_color);
   Qgeometry = intern ("geometry");
   staticpro (&Qgeometry);
-  Qicon = intern ("icon");
-  staticpro (&Qicon);
   Qicon_left = intern ("icon-left");
   staticpro (&Qicon_left);
   Qicon_top = intern ("icon-top");
@@ -3622,16 +3702,24 @@ syms_of_xfns ()
   init_x_parm_symbols ();
 
   DEFVAR_INT ("mouse-buffer-offset", &mouse_buffer_offset,
-             "The buffer offset of the character under the pointer.");
+    "The buffer offset of the character under the pointer.");
   mouse_buffer_offset = 0;
 
   DEFVAR_INT ("x-pointer-shape", &Vx_pointer_shape,
-             "The shape of the pointer when over text.\n\
+    "The shape of the pointer when over text.\n\
 Changing the value does not affect existing frames\n\
 unless you set the mouse color.");
   Vx_pointer_shape = Qnil;
 
-  staticpro (&Vxrdb_name);
+  DEFVAR_LISP ("x-resource-name", &Vx_resource_name,
+    "The name Emacs uses to look up X resources; for internal use only.\n\
+`x-get-resource' uses this as the first component of the instance name\n\
+when requesting resource values.\n\
+Emacs initially sets `x-resource-name' to the name under which Emacs\n\
+was invoked, or to the value specified with the `-name' or `-rn'\n\
+switches, if present.");
+  Vx_resource_name = Qnil;
+  staticpro (&Vx_resource_name);
 
 #if 0
   DEFVAR_INT ("x-nontext-pointer-shape", &Vx_nontext_pointer_shape,
@@ -3667,6 +3755,7 @@ unless you set the mouse color.");
   defsubr (&Sx_display_color_p);
   defsubr (&Sx_list_fonts);
   defsubr (&Sx_color_defined_p);
+  defsubr (&Sx_server_max_request_size);
   defsubr (&Sx_server_vendor);
   defsubr (&Sx_server_version);
   defsubr (&Sx_display_pixel_width);