Converted display hooks to be display-local. Plus many bugfixes.
[bpt/emacs.git] / src / xterm.c
index 9189d6a..fcb431a 100644 (file)
@@ -54,7 +54,6 @@ Boston, MA 02111-1307, USA.  */
 #include <sys/ioctl.h>
 #endif /* ! defined (BSD_SYSTEM) */
 
-#include "systty.h"
 #include "systime.h"
 
 #ifndef INCLUDED_FCNTL
@@ -131,6 +130,7 @@ extern void _XEditResCheckMessages ();
 #include <X11/Xaw3d/Simple.h>
 #include <X11/Xaw3d/Scrollbar.h>
 #define ARROW_SCROLLBAR
+#define XAW_ARROW_SCROLLBARS
 #include <X11/Xaw3d/ScrollbarP.h>
 #else /* !HAVE_XAW3D */
 #include <X11/Xaw/Simple.h>
@@ -286,7 +286,7 @@ extern Lisp_Object Vcommand_line_args, Vsystem_name;
 
 extern Lisp_Object Vx_no_window_manager;
 
-extern Lisp_Object Qface, Qmouse_face, Qeql;
+extern Lisp_Object Qeql;
 
 extern int errno;
 
@@ -324,6 +324,8 @@ void x_raise_frame P_ ((struct frame *));
 void x_set_window_size P_ ((struct frame *, int, int, int));
 void x_wm_set_window_state P_ ((struct frame *, int));
 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
+struct display *x_create_frame_display P_ ((struct x_display_info *));
+void x_delete_frame_display P_ ((struct display *));
 void x_initialize P_ ((void));
 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
 static int x_compute_min_glyph_bounds P_ ((struct frame *));
@@ -356,7 +358,7 @@ static void x_flush P_ ((struct frame *f));
 static void x_update_begin P_ ((struct frame *));
 static void x_update_window_begin P_ ((struct window *));
 static void x_after_update_window_line P_ ((struct glyph_row *));
-static struct scroll_bar *x_window_to_scroll_bar P_ ((Window));
+static struct scroll_bar *x_window_to_scroll_bar P_ ((Display *, Window));
 static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *,
                                            enum scroll_bar_part *,
                                            Lisp_Object *, Lisp_Object *,
@@ -381,7 +383,8 @@ x_flush (f)
     {
       Lisp_Object rest, frame;
       FOR_EACH_FRAME (rest, frame)
-       x_flush (XFRAME (frame));
+        if (FRAME_X_P (XFRAME (frame)))
+          x_flush (XFRAME (frame));
     }
   else if (FRAME_X_P (f))
     XFlush (FRAME_X_DISPLAY (f));
@@ -468,7 +471,6 @@ x_update_begin (f)
   /* Nothing to do.  */
 }
 
-
 /* Start update of window W.  Set the global variable updated_window
    to the window being updated and set output_cursor to the cursor
    position of W.  */
@@ -1364,7 +1366,8 @@ x_frame_of_widget (widget)
   for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
     if (GC_FRAMEP (XCAR (tail))
        && (f = XFRAME (XCAR (tail)),
-           (f->output_data.nothing != 1
+           (FRAME_X_P (f)
+             && f->output_data.nothing != 1
             && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
        && f->output_data.x->widget == widget)
       return f;
@@ -3208,16 +3211,22 @@ x_detect_focus_change (dpyinfo, event, bufp, numchars)
     {
     case EnterNotify:
     case LeaveNotify:
-      if (event->xcrossing.detail != NotifyInferior
-          && event->xcrossing.focus
-          && ! (frame->output_data.x->focus_state & FOCUS_EXPLICIT))
-        nr_events = x_focus_changed ((event->type == EnterNotify
-                                      ? FocusIn : FocusOut),
-                                     FOCUS_IMPLICIT,
-                                     dpyinfo,
-                                     frame,
-                                     bufp,
-                                     numchars);
+      {
+        struct frame *focus_frame = dpyinfo->x_focus_event_frame;
+        int focus_state
+          = focus_frame ? focus_frame->output_data.x->focus_state : 0;
+
+        if (event->xcrossing.detail != NotifyInferior
+            && event->xcrossing.focus
+            && ! (focus_state & FOCUS_EXPLICIT))
+          nr_events = x_focus_changed ((event->type == EnterNotify
+                                        ? FocusIn : FocusOut),
+                                       FOCUS_IMPLICIT,
+                                       dpyinfo,
+                                       frame,
+                                       bufp,
+                                       numchars);
+      }
       break;
 
     case FocusIn:
@@ -3656,7 +3665,8 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 
       /* Clear the mouse-moved flag for every frame on this display.  */
       FOR_EACH_FRAME (tail, frame)
-       if (FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
+       if (FRAME_X_P (XFRAME (frame))
+            && FRAME_X_DISPLAY (XFRAME (frame)) == FRAME_X_DISPLAY (*fp))
          XFRAME (frame)->mouse_moved = 0;
 
       last_mouse_scroll_bar = Qnil;
@@ -3770,7 +3780,9 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
        /* If not, is it one of our scroll bars?  */
        if (! f1)
          {
-           struct scroll_bar *bar = x_window_to_scroll_bar (win);
+           struct scroll_bar *bar;
+
+            bar = x_window_to_scroll_bar (FRAME_X_DISPLAY (*fp), win);
 
            if (bar)
              {
@@ -3841,18 +3853,20 @@ XTmouse_position (fp, insist, bar_window, part, x, y, time)
 
 /* Scroll bar support.  */
 
-/* Given an X window ID, find the struct scroll_bar which manages it.
+/* Given an X window ID and a DISPLAY, find the struct scroll_bar which
+   manages it.
    This can be called in GC, so we have to make sure to strip off mark
    bits.  */
 
 static struct scroll_bar *
-x_window_to_scroll_bar (window_id)
+x_window_to_scroll_bar (display, window_id)
+     Display *display;
      Window window_id;
 {
   Lisp_Object tail;
 
 #ifdef USE_GTK
-  window_id = (Window) xg_get_scroll_id_for_window (window_id);
+  window_id = (Window) xg_get_scroll_id_for_window (display, window_id);
 #endif /* USE_GTK */
 
   for (tail = Vframe_list;
@@ -3866,6 +3880,9 @@ x_window_to_scroll_bar (window_id)
       if (! GC_FRAMEP (frame))
        abort ();
 
+      if (! FRAME_X_P (XFRAME (frame)))
+        continue;
+      
       /* Scan this frame's scroll bar list for a scroll bar with the
          right window ID.  */
       condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
@@ -3876,7 +3893,8 @@ x_window_to_scroll_bar (window_id)
                               condemned = Qnil,
                               ! GC_NILP (bar));
           bar = XSCROLL_BAR (bar)->next)
-       if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
+       if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id &&
+            FRAME_X_DISPLAY (XFRAME (frame)) == display)
          return XSCROLL_BAR (bar);
     }
 
@@ -3899,11 +3917,14 @@ x_window_to_menu_bar (window)
        XGCTYPE (tail) == Lisp_Cons;
        tail = XCDR (tail))
     {
-      Lisp_Object frame = XCAR (tail);
-      Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
+      if (FRAME_X_P (XFRAME (XCAR (tail))))
+        {
+          Lisp_Object frame = XCAR (tail);
+          Widget menu_bar = XFRAME (frame)->output_data.x->menubar_widget;
 
-      if (menu_bar && xlwmenu_window_p (menu_bar, window))
-       return menu_bar;
+          if (menu_bar && xlwmenu_window_p (menu_bar, window))
+            return menu_bar;
+        }
     }
 
   return NULL;
@@ -5662,7 +5683,6 @@ x_filter_event (dpyinfo, event)
 #endif
 
 #ifdef USE_GTK
-static struct x_display_info *current_dpyinfo;
 static struct input_event **current_bufp;
 static int *current_numcharsp;
 static int current_count;
@@ -5677,26 +5697,34 @@ event_handler_gdk (gxev, ev, data)
      GdkEvent *ev;
      gpointer data;
 {
-  XEvent *xev = (XEvent*)gxev;
+  XEvent *xev = (XEvent *) gxev;
 
   if (current_numcharsp)
     {
+      struct x_display_info *dpyinfo;
+
+      dpyinfo = x_display_info_for_display (xev->xany.display);
+
 #ifdef HAVE_X_I18N
       /* Filter events for the current X input method.
          GTK calls XFilterEvent but not for key press and release,
          so we do it here.  */
       if (xev->type == KeyPress || xev->type == KeyRelease)
-        if (x_filter_event (current_dpyinfo, xev))
+        if (dpyinfo && x_filter_event (dpyinfo, xev))
           return GDK_FILTER_REMOVE;
 #endif
-      current_count += handle_one_xevent (current_dpyinfo,
-                                          xev,
-                                          current_bufp,
-                                          current_numcharsp,
-                                          &current_finish);
+
+      if (! dpyinfo)
+        current_finish = X_EVENT_NORMAL;
+      else
+        current_count += handle_one_xevent (dpyinfo,
+                                            xev,
+                                            current_bufp,
+                                            current_numcharsp,
+                                            &current_finish);
     }
   else
-    current_finish = x_dispatch_event (xev, GDK_DISPLAY ());
+    current_finish = x_dispatch_event (xev, xev->xany.display);
 
   if (current_finish == X_EVENT_GOTO_OUT || current_finish == X_EVENT_DROP)
     return GDK_FILTER_REMOVE;
@@ -6036,7 +6064,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           /* Dispatch event to the widget.  */
           goto OTHER;
 #else /* not USE_TOOLKIT_SCROLL_BARS */
-          bar = x_window_to_scroll_bar (event.xexpose.window);
+          bar = x_window_to_scroll_bar (event.xexpose.display,
+                                        event.xexpose.window);
 
           if (bar)
             x_scroll_bar_expose (bar, &event);
@@ -6662,7 +6691,7 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
                 /* Window will be selected only when it is not selected now and
                    last mouse movement event was not in it.  Minibuffer window
                    will be selected iff it is active.  */
-                if (WINDOWP(window)
+                if (WINDOWP (window)
                     && !EQ (window, last_window)
                     && !EQ (window, selected_window)
                     && numchars > 0)
@@ -6681,7 +6710,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
           {
 #ifndef USE_TOOLKIT_SCROLL_BARS
             struct scroll_bar *bar
-              = x_window_to_scroll_bar (event.xmotion.window);
+              = x_window_to_scroll_bar (event.xmotion.display,
+                                        event.xmotion.window);
 
             if (bar)
               x_scroll_bar_note_movement (bar, &event);
@@ -6844,7 +6874,8 @@ handle_one_xevent (dpyinfo, eventp, bufp_r, numcharsp, finish)
         else
           {
             struct scroll_bar *bar
-              = x_window_to_scroll_bar (event.xbutton.window);
+              = x_window_to_scroll_bar (event.xbutton.display,
+                                        event.xbutton.window);
 
 #ifdef USE_TOOLKIT_SCROLL_BARS
             /* Make the "Ctrl-Mouse-2 splits window" work for toolkit
@@ -7005,9 +7036,7 @@ x_dispatch_event (event, display)
     EVENT_INIT (*bufpp);
   bufpp = bufp;
 
-  for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
-    if (dpyinfo->display == display)
-      break;
+  dpyinfo = x_display_info_for_display (display);
 
   if (dpyinfo)
     {
@@ -7037,8 +7066,7 @@ x_dispatch_event (event, display)
    EXPECTED is nonzero if the caller knows input is available.  */
 
 static int
-XTread_socket (sd, bufp, numchars, expected)
-     register int sd;
+XTread_socket (bufp, numchars, expected)
      /* register */ struct input_event *bufp;
      /* register */ int numchars;
      int expected;
@@ -7109,30 +7137,7 @@ XTread_socket (sd, bufp, numchars, expected)
       UNBLOCK_INPUT;
 #endif
 
-#ifdef USE_GTK
-      /* For GTK we must use the GTK event loop.  But XEvents gets passed
-         to our filter function above, and then to the big event switch.
-         We use a bunch of globals to communicate with our filter function,
-         that is kind of ugly, but it works. */
-      current_dpyinfo = dpyinfo;
-
-      while (gtk_events_pending ())
-        {
-          current_count = count;
-          current_numcharsp = &numchars;
-          current_bufp = &bufp;
-
-          gtk_main_iteration ();
-
-          count = current_count;
-          current_bufp = 0;
-          current_numcharsp = 0;
-
-          if (current_finish == X_EVENT_GOTO_OUT)
-            goto out;
-        }
-
-#else /* not USE_GTK */
+#ifndef USE_GTK
       while (XPending (dpyinfo->display))
        {
           int finish;
@@ -7155,9 +7160,36 @@ XTread_socket (sd, bufp, numchars, expected)
           if (finish == X_EVENT_GOTO_OUT)
             goto out;
         }
-#endif /* USE_GTK */
+#endif /* not USE_GTK */
     }
 
+#ifdef USE_GTK
+
+  /* For GTK we must use the GTK event loop.  But XEvents gets passed
+     to our filter function above, and then to the big event switch.
+     We use a bunch of globals to communicate with our filter function,
+     that is kind of ugly, but it works.
+
+     There is no way to do one display at the time, GTK just does events
+     from all displays.  */
+
+  while (gtk_events_pending ())
+    {
+      current_count = count;
+      current_numcharsp = &numchars;
+      current_bufp = &bufp;
+
+      gtk_main_iteration ();
+
+      count = current_count;
+      current_bufp = 0;
+      current_numcharsp = 0;
+
+      if (current_finish == X_EVENT_GOTO_OUT)
+        break;
+    }
+#endif /* USE_GTK */
+
  out:;
 
   /* On some systems, an X bug causes Emacs to get no more events
@@ -7247,13 +7279,6 @@ x_draw_hollow_cursor (w, row)
   struct glyph *cursor_glyph;
   GC gc;
 
-  /* Compute frame-relative coordinates from window-relative
-     coordinates.  */
-  x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
-  y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
-       + row->ascent - w->phys_cursor_ascent);
-  h = row->height - 1;
-
   /* Get the glyph the cursor is on.  If we can't tell because
      the current matrix is invalid or such, give up.  */
   cursor_glyph = get_phys_cursor_glyph (w);
@@ -7270,6 +7295,19 @@ x_draw_hollow_cursor (w, row)
     wd = min (FRAME_COLUMN_WIDTH (f), wd);
   w->phys_cursor_width = wd;
 
+  /* Compute frame-relative coordinates from window-relative
+     coordinates.  */
+  x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
+  y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
+
+  /* Compute the proper height and ascent of the rectangle, based
+     on the actual glyph.  Using the full height of the row looks
+     bad when there are tall images on that row.  */
+  h = max (FRAME_LINE_HEIGHT (f), cursor_glyph->ascent + cursor_glyph->descent);
+  if (h < row->height)
+    y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
+  h--;
+
   /* The foreground of cursor_gc is typically the same as the normal
      background color, which can cause the cursor box to be invisible.  */
   xgcv.foreground = f->output_data.x->cursor_pixel;
@@ -7475,13 +7513,13 @@ x_bitmap_icon (f, file)
   if (STRINGP (file))
     {
 #ifdef USE_GTK
-      /* Use gtk_window_set_icon_from_file() if available,
+      /* Use gtk_window_set_icon_from_file () if available,
         It's not restricted to bitmaps */
-      if (xg_set_icon(f, file))
+      if (xg_set_icon (f, file))
        return 0;
 #endif /* USE_GTK */
       bitmap_id = x_create_bitmap_from_file (f, file);
-      x_create_bitmap_mask(f, bitmap_id);
+      x_create_bitmap_mask (f, bitmap_id);
     }
   else
     {
@@ -7491,7 +7529,7 @@ x_bitmap_icon (f, file)
          FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id
            = x_create_bitmap_from_data (f, gnu_bits,
                                         gnu_width, gnu_height);
-         x_create_bitmap_mask(f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
+         x_create_bitmap_mask (f, FRAME_X_DISPLAY_INFO (f)->icon_bitmap_id);
        }
 
       /* The first time we create the GNU bitmap and mask,
@@ -7760,6 +7798,11 @@ x_connection_closed (dpy, error_message)
     }
 #endif
 
+#ifdef USE_GTK
+  if (dpyinfo)
+    xg_display_close (dpyinfo->display);
+#endif
+
   /* Indicate that this display is dead.  */
   if (dpyinfo)
     dpyinfo->display = 0;
@@ -7993,7 +8036,7 @@ xim_destroy_callback (xim, client_data, call_data)
   FOR_EACH_FRAME (tail, frame)
     {
       struct frame *f = XFRAME (frame);
-      if (FRAME_X_DISPLAY_INFO (f) == dpyinfo)
+      if (FRAME_X_P (f) && FRAME_X_DISPLAY_INFO (f) == dpyinfo)
        {
          FRAME_XIC (f) = NULL;
          if (FRAME_XIC_FONTSET (f))
@@ -8096,7 +8139,8 @@ xim_instantiate_callback (display, client_data, call_data)
        {
          struct frame *f = XFRAME (frame);
 
-         if (FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
+         if (FRAME_X_P (f)
+              && FRAME_X_DISPLAY_INFO (f) == xim_inst->dpyinfo)
            if (FRAME_XIC (f) == NULL)
              {
                create_frame_xic (f);
@@ -8337,8 +8381,11 @@ x_set_offset (f, xoff, yoff, change_gravity)
 
   if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_A)
     {
-      modified_left += FRAME_X_OUTPUT (f)->x_pixels_outer_diff;
-      modified_top += FRAME_X_OUTPUT (f)->y_pixels_outer_diff;
+      /* Some WMs (twm, wmaker at least) has an offset that is smaller
+         than the WM decorations.  So we use the calculated offset instead
+         of the WM decoration sizes here (x/y_pixels_outer_diff).  */
+      modified_left += FRAME_X_OUTPUT (f)->move_offset_left;
+      modified_top += FRAME_X_OUTPUT (f)->move_offset_top;
     }
 
   XMoveWindow (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f),
@@ -8399,11 +8446,13 @@ x_check_expected_move (f)
   {
     int expect_top = FRAME_X_OUTPUT (f)->expected_top;
     int expect_left = FRAME_X_OUTPUT (f)->expected_left;
-    
+
     if (expect_top != f->top_pos || expect_left != f->left_pos)
       {
-        if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
-          FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
+        FRAME_X_DISPLAY_INFO (f)->wm_type = X_WMTYPE_A;
+        FRAME_X_OUTPUT (f)->move_offset_left = expect_left - f->left_pos;
+        FRAME_X_OUTPUT (f)->move_offset_top = expect_top - f->top_pos;
+
         x_set_offset (f, expect_left, expect_top, 1);
       }
     else if (FRAME_X_DISPLAY_INFO (f)->wm_type == X_WMTYPE_UNKNOWN)
@@ -9437,11 +9486,11 @@ x_list_fonts (f, pattern, size, maxnames)
   Display *dpy = dpyinfo->display;
   int try_XLoadQueryFont = 0;
   int count;
-  int allow_scalable_fonts_p = 0;
+  int allow_auto_scaled_font = 0;
 
   if (size < 0)
     {
-      allow_scalable_fonts_p = 1;
+      allow_auto_scaled_font = 1;
       size = 0;
     }
 
@@ -9464,7 +9513,7 @@ x_list_fonts (f, pattern, size, maxnames)
         ((((PATTERN . MAXNAMES) . SCALABLE) (FONTNAME . WIDTH) ...) ...)  */
       tem = XCDR (dpyinfo->name_list_element);
       key = Fcons (Fcons (pattern, make_number (maxnames)),
-                  allow_scalable_fonts_p ? Qt : Qnil);
+                  allow_auto_scaled_font ? Qt : Qnil);
       list = Fassoc (key, tem);
       if (!NILP (list))
        {
@@ -9570,25 +9619,28 @@ x_list_fonts (f, pattern, size, maxnames)
            {
              int width = 0;
              char *p = names[i];
-             int average_width = -1, dashes = 0;
+             int average_width = -1, resx = 0, dashes = 0;
 
              /* Count the number of dashes in NAMES[I].  If there are
-                14 dashes, and the field value following 12th dash
-                (AVERAGE_WIDTH) is 0, this is a auto-scaled font which
-                is usually too ugly to be used for editing.  Let's
-                ignore it.  */
+                14 dashes, the field value following 9th dash
+                (RESOLUTION_X) is nonzero, and the field value
+                following 12th dash (AVERAGE_WIDTH) is 0, this is a
+                auto-scaled font which is usually too ugly to be used
+                for editing.  Let's ignore it.  */
              while (*p)
                if (*p++ == '-')
                  {
                    dashes++;
                    if (dashes == 7) /* PIXEL_SIZE field */
                      width = atoi (p);
+                   else if (dashes == 9)
+                     resx = atoi (p);
                    else if (dashes == 12) /* AVERAGE_WIDTH field */
                      average_width = atoi (p);
                  }
 
-             if (allow_scalable_fonts_p
-                 || dashes < 14 || average_width != 0)
+             if (allow_auto_scaled_font
+                 || dashes < 14 || average_width != 0 || resx == 0)
                {
                  tem = build_string (names[i]);
                  if (NILP (Fassoc (tem, list)))
@@ -10177,6 +10229,7 @@ x_term_init (display_name, xrm_option, resource_name)
 {
   int connection;
   Display *dpy;
+  struct display *display;
   struct x_display_info *dpyinfo;
   XrmDatabase xrdb;
 
@@ -10196,59 +10249,65 @@ x_term_init (display_name, xrm_option, resource_name)
     char **argv2 = argv;
     GdkAtom atom;
 
-    /* GTK 2.0 can only handle one display, GTK 2.2 can handle more
-       than one, but this remains to be implemented.  */
-    if (x_initialized > 1)
-      return 0;
-
-    for (argc = 0; argc < NUM_ARGV; ++argc)
-      argv[argc] = 0;
+    if (x_initialized++ > 1)
+      {
+        /* Opening another display.  If xg_display_open returns less
+           than zero, we are probably on GTK 2.0, which can only handle
+           one display.  GTK 2.2 or later can handle more than one.  */
+        if (xg_display_open (SDATA (display_name), &dpy) < 0)
+          error ("Sorry, this version of GTK can only handle one display");
+     }
+    else
+      {
+        for (argc = 0; argc < NUM_ARGV; ++argc)
+          argv[argc] = 0;
 
-    argc = 0;
-    argv[argc++] = initial_argv[0];
+        argc = 0;
+        argv[argc++] = initial_argv[0];
 
-    if (! NILP (display_name))
-      {
-        argv[argc++] = "--display";
-        argv[argc++] = SDATA (display_name);
-      }
+        if (! NILP (display_name))
+          {
+            argv[argc++] = "--display";
+            argv[argc++] = SDATA (display_name);
+          }
 
-    argv[argc++] = "--name";
-    argv[argc++] = resource_name;
+        argv[argc++] = "--name";
+        argv[argc++] = resource_name;
 
 #ifdef HAVE_X11R5
-    XSetLocaleModifiers ("");
+        XSetLocaleModifiers ("");
 #endif
 
-    gtk_init (&argc, &argv2);
+        gtk_init (&argc, &argv2);
 
-    /* gtk_init does set_locale.  We must fix locale after calling it.  */
-    fixup_locale ();
-    xg_initialize ();
+        /* gtk_init does set_locale.  We must fix locale after calling it.  */
+        fixup_locale ();
+        xg_initialize ();
 
-    dpy = GDK_DISPLAY ();
+        dpy = GDK_DISPLAY ();
 
-    /* NULL window -> events for all windows go to our function */
-    gdk_window_add_filter (NULL, event_handler_gdk, NULL);
+        /* NULL window -> events for all windows go to our function */
+        gdk_window_add_filter (NULL, event_handler_gdk, NULL);
 
-    /* Load our own gtkrc if it exists.  */
-    {
-      struct gcpro gcpro1, gcpro2;
-      char *file = "~/.emacs.d/gtkrc";
-      Lisp_Object s, abs_file;
+        /* Load our own gtkrc if it exists.  */
+        {
+          struct gcpro gcpro1, gcpro2;
+          char *file = "~/.emacs.d/gtkrc";
+          Lisp_Object s, abs_file;
 
-      GCPRO2 (s, abs_file);
-      s = make_string (file, strlen (file));
-      abs_file = Fexpand_file_name(s, Qnil);
+          GCPRO2 (s, abs_file);
+          s = make_string (file, strlen (file));
+          abs_file = Fexpand_file_name (s, Qnil);
 
-      if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
-        gtk_rc_parse (SDATA (abs_file));
+          if (! NILP (abs_file) && !NILP (Ffile_readable_p (abs_file)))
+            gtk_rc_parse (SDATA (abs_file));
 
-      UNGCPRO;
-    }
+          UNGCPRO;
+        }
 
-    XSetErrorHandler (x_error_handler);
-    XSetIOErrorHandler (x_io_error_quitter);
+        XSetErrorHandler (x_error_handler);
+        XSetIOErrorHandler (x_io_error_quitter);
+      }
   }
 #else /* not USE_GTK */
 #ifdef USE_X_TOOLKIT
@@ -10305,6 +10364,8 @@ x_term_init (display_name, xrm_option, resource_name)
   dpyinfo = (struct x_display_info *) xmalloc (sizeof (struct x_display_info));
   bzero (dpyinfo, sizeof *dpyinfo);
 
+  display = x_create_frame_display (dpyinfo);
+
 #ifdef MULTI_KBOARD
   {
     struct x_display_info *share;
@@ -10369,6 +10430,11 @@ x_term_init (display_name, xrm_option, resource_name)
   x_find_modifier_meanings (dpyinfo);
 
   /* Get the scroll bar cursor.  */
+#ifdef USE_GTK
+  /* We must create a GTK cursor, it is required for GTK widgets.  */
+  dpyinfo->xg_cursor = xg_create_default_cursor (dpyinfo->display);
+#endif /* USE_GTK */
+
   dpyinfo->vertical_scroll_bar_cursor
     = XCreateFontCursor (dpyinfo->display, XC_sb_v_double_arrow);
 
@@ -10649,6 +10715,19 @@ void
 x_delete_display (dpyinfo)
      struct x_display_info *dpyinfo;
 {
+  int i;
+  
+  {
+    /* Delete the generic struct display for this X display. */
+    struct display *d;
+    for (d = display_list; d; d = d->next_display)
+      if (d->type == output_x_window && d->display_info.x != dpyinfo)
+        {
+          delete_display (d);
+          break;
+        }
+  }
+    
   delete_keyboard_wait_descriptor (dpyinfo->connection);
 
   /* Discard this display from x_display_name_list and x_display_list.
@@ -10700,6 +10779,18 @@ x_delete_display (dpyinfo)
     xim_close_dpy (dpyinfo);
 #endif
 
+  /* Free the font names in the font table.  */
+  for (i = 0; i < dpyinfo->n_fonts; i++)
+    if (dpyinfo->font_table[i].name)
+      {
+       if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
+         xfree (dpyinfo->font_table[i].full_name);
+       xfree (dpyinfo->font_table[i].name);
+      }
+
+  if (dpyinfo->font_table->font_encoder)
+    xfree (dpyinfo->font_table->font_encoder);
+
   xfree (dpyinfo->font_table);
   xfree (dpyinfo->x_id_name);
   xfree (dpyinfo->color_cells);
@@ -10734,68 +10825,95 @@ x_process_timeouts (timer)
 extern frame_parm_handler x_frame_parm_handlers[];
 
 static struct redisplay_interface x_redisplay_interface =
-{
-  x_frame_parm_handlers,
-  x_produce_glyphs,
-  x_write_glyphs,
-  x_insert_glyphs,
-  x_clear_end_of_line,
-  x_scroll_run,
-  x_after_update_window_line,
-  x_update_window_begin,
-  x_update_window_end,
-  x_cursor_to,
-  x_flush,
+  {
+    x_frame_parm_handlers,
+    x_produce_glyphs,
+    x_write_glyphs,
+    x_insert_glyphs,
+    x_clear_end_of_line,
+    x_scroll_run,
+    x_after_update_window_line,
+    x_update_window_begin,
+    x_update_window_end,
+    x_cursor_to,
+    x_flush,
 #ifndef XFlush
-  x_flush,
+    x_flush,
 #else
-  0,  /* flush_display_optional */
+    0,  /* flush_display_optional */
 #endif
-  x_clear_window_mouse_face,
-  x_get_glyph_overhangs,
-  x_fix_overlapping_area,
-  x_draw_fringe_bitmap,
-  x_per_char_metric,
-  x_encode_char,
-  x_compute_glyph_string_overhangs,
-  x_draw_glyph_string,
-  x_define_frame_cursor,
-  x_clear_frame_area,
-  x_draw_window_cursor,
-  x_draw_vertical_window_border,
-  x_shift_glyphs_for_insert
-};
+    x_clear_window_mouse_face,
+    x_get_glyph_overhangs,
+    x_fix_overlapping_area,
+    x_draw_fringe_bitmap,
+    x_per_char_metric,
+    x_encode_char,
+    x_compute_glyph_string_overhangs,
+    x_draw_glyph_string,
+    x_define_frame_cursor,
+    x_clear_frame_area,
+    x_draw_window_cursor,
+    x_draw_vertical_window_border,
+    x_shift_glyphs_for_insert
+  };
+
+
+/* This function is called when the last frame on a display is deleted. */
+void
+x_delete_frame_display (struct display *display)
+{
+  /* We don't do anything, the connection to the X server must remain
+     open. */
+}
+
+
+struct display *
+x_create_frame_display (struct x_display_info *dpyinfo)
+{
+  struct display *display;
+  
+  display = create_display ();
+
+  display->type = output_x_window;
+  display->display_info.x = dpyinfo;
+  dpyinfo->frame_display = display;
+  
+  display->clear_frame_hook = x_clear_frame;
+  display->ins_del_lines_hook = x_ins_del_lines;
+  display->delete_glyphs_hook = x_delete_glyphs;
+  display->ring_bell_hook = XTring_bell;
+  display->reset_terminal_modes_hook = XTreset_terminal_modes;
+  display->set_terminal_modes_hook = XTset_terminal_modes;
+  display->update_begin_hook = x_update_begin;
+  display->update_end_hook = x_update_end;
+  display->set_terminal_window_hook = XTset_terminal_window;
+  display->read_socket_hook = XTread_socket;
+  display->frame_up_to_date_hook = XTframe_up_to_date;
+  display->mouse_position_hook = XTmouse_position;
+  display->frame_rehighlight_hook = XTframe_rehighlight;
+  display->frame_raise_lower_hook = XTframe_raise_lower;
+  display->set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
+  display->condemn_scroll_bars_hook = XTcondemn_scroll_bars;
+  display->redeem_scroll_bar_hook = XTredeem_scroll_bar;
+  display->judge_scroll_bars_hook = XTjudge_scroll_bars;
+
+  display->delete_frame_hook = x_destroy_window;
+  display->delete_display_hook = x_delete_frame_display;
+  
+  display->rif = &x_redisplay_interface;
+  display->scroll_region_ok = 1; /* We'll scroll partial frames. */
+  display->char_ins_del_ok = 1;
+  display->line_ins_del_ok = 1;        /* We'll just blt 'em. */
+  display->fast_clear_end_of_line = 1; /* X does this well. */
+  display->memory_below_frame = 0; /* We don't remember what scrolls
+                                        off the bottom. */
+
+  return display;
+}
 
 void
 x_initialize ()
 {
-  rif = &x_redisplay_interface;
-
-  clear_frame_hook = x_clear_frame;
-  ins_del_lines_hook = x_ins_del_lines;
-  delete_glyphs_hook = x_delete_glyphs;
-  ring_bell_hook = XTring_bell;
-  reset_terminal_modes_hook = XTreset_terminal_modes;
-  set_terminal_modes_hook = XTset_terminal_modes;
-  update_begin_hook = x_update_begin;
-  update_end_hook = x_update_end;
-  set_terminal_window_hook = XTset_terminal_window;
-  read_socket_hook = XTread_socket;
-  frame_up_to_date_hook = XTframe_up_to_date;
-  mouse_position_hook = XTmouse_position;
-  frame_rehighlight_hook = XTframe_rehighlight;
-  frame_raise_lower_hook = XTframe_raise_lower;
-  set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
-  condemn_scroll_bars_hook = XTcondemn_scroll_bars;
-  redeem_scroll_bar_hook = XTredeem_scroll_bar;
-  judge_scroll_bars_hook = XTjudge_scroll_bars;
-
-  scroll_region_ok = 1;                /* we'll scroll partial frames */
-  char_ins_del_ok = 1;
-  line_ins_del_ok = 1;         /* we'll just blt 'em */
-  fast_clear_end_of_line = 1;  /* X does this well */
-  memory_below_frame = 0;      /* we don't remember what scrolls
-                                  off the bottom */
   baud_rate = 19200;
 
   x_noop_count = 0;