(free_frame_menubar) [USE_X_TOOLKIT]. New function to destroy the X Widget
[bpt/emacs.git] / src / xterm.c
index 7623018..ccbb59f 100644 (file)
@@ -38,8 +38,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include <config.h>
 
 /* Need syssignal.h for various externs and definitions that may be required
- * by some configurations for calls to signal() later in this source file.
- */
+   by some configurations for calls to signal later in this source file.  */
 #include "syssignal.h"
 
 #ifdef HAVE_X_WINDOWS
@@ -465,7 +464,8 @@ XTcursor_to (row, col)
    compute_char_face and compute_glyph_face on everything it puts in
    the display structure, we can assume that the face code on each
    glyph is a valid index into FRAME_COMPUTED_FACES (f), and the one
-   to which we can actually apply intern_face.  */
+   to which we can actually apply intern_face.
+   Call this function with input blocked.  */
 
 #if 1
 /* This is the multi-face code.  */
@@ -524,11 +524,11 @@ dumpglyphs (f, left, top, gp, n, hl)
        /* First look at the face of the text itself.  */
        if (cf != 0)
          {
-           /* The face codes on the glyphs must be valid indices into the
-              frame's face table.  */
+           /* It's possible for the display table to specify
+              a face code that is out of range.  Use 0 in that case.  */
            if (cf < 0 || cf >= FRAME_N_COMPUTED_FACES (f)
                || FRAME_COMPUTED_FACES (f) [cf] == 0)
-             abort ();
+             cf = 0;
 
            if (cf == 1)
              face = FRAME_MODE_LINE_FACE (f);
@@ -752,7 +752,8 @@ XTclear_end_of_line (first_unused)
 /* Erase the character (if any) at the position just before X, Y in frame F,
    then redraw it and the character before it.
    This is necessary when we erase starting at X,
-   in case the character after X overlaps into the one before X.  */
+   in case the character after X overlaps into the one before X.
+   Call this function with input blocked.  */
 
 static void
 redraw_previous_char (f, x, y)
@@ -920,9 +921,9 @@ XTflash (f)
 /* Make audible bell.  */
 
 #ifdef HAVE_X11
-#define XRINGBELL XBell(x_current_display, 0)
+#define XRINGBELL XBell (x_current_display, 0)
 #else /* ! defined (HAVE_X11) */
-#define XRINGBELL XFeep(0);
+#define XRINGBELL XFeep (0);
 #endif /* ! defined (HAVE_X11) */
 
 XTring_bell ()
@@ -1147,7 +1148,8 @@ static void clear_cursor ();
 /* Output into a rectangle of an X-window (for frame F)
    the characters in f->phys_lines that overlap that rectangle.
    TOP and LEFT are the position of the upper left corner of the rectangle.
-   ROWS and COLS are the size of the rectangle.  */
+   ROWS and COLS are the size of the rectangle.
+   Call this function with input blocked.  */
 
 static void
 dumprectangle (f, left, top, cols, rows)
@@ -2002,7 +2004,7 @@ x_window_to_scroll_bar (window_id)
           ! GC_NILP (bar) || (bar = condemned,
                               condemned = Qnil,
                               ! GC_NILP (bar));
-          bar = XSCROLL_BAR(bar)->next)
+          bar = XSCROLL_BAR (bar)->next)
        if (SCROLL_BAR_X_WINDOW (XSCROLL_BAR (bar)) == window_id)
          return XSCROLL_BAR (bar);
     }
@@ -2649,6 +2651,8 @@ process_expose_from_menu (event)
 {
   FRAME_PTR f;
 
+  BLOCK_INPUT;
+
   f = x_window_to_frame (event.xexpose.window);
   if (f)
     {
@@ -2673,6 +2677,8 @@ process_expose_from_menu (event)
       if (bar)
        x_scroll_bar_expose (bar, &event);
     }
+
+  UNBLOCK_INPUT;
 }
 
 \f
@@ -3618,6 +3624,13 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
        }
     }
 
+#ifdef X_IO_BUG
+  if (! event_found)
+    /* On some systems, an X bug causes Emacs to get no more events
+       when the window is destroyed.  Detect that.  */
+    XNoOp (x_current_display);
+#endif /* X_IO_BUG */
+
 #ifdef HAVE_SELECT
   if (expected && ! event_found)
     {
@@ -3944,6 +3957,8 @@ x_display_cursor (f, on)
      struct frame *f;
      int on;
 {
+  BLOCK_INPUT;
+
   if (FRAME_DESIRED_CURSOR (f) == filled_box_cursor)
     x_display_box_cursor (f, on);
   else if (FRAME_DESIRED_CURSOR (f) == bar_cursor)
@@ -3951,6 +3966,8 @@ x_display_cursor (f, on)
   else
     /* Those are the only two we have implemented!  */
     abort ();
+
+  UNBLOCK_INPUT;
 }
 \f
 /* Icons.  */
@@ -4211,7 +4228,7 @@ x_error_catcher (display, error)
 
    Calling x_uncatch_errors resumes the normal error handling.  */
 
-void x_catch_errors(), x_check_errors (), x_uncatch_errors ();
+void x_catch_errors (), x_check_errors (), x_uncatch_errors ();
 
 void
 x_catch_errors ()
@@ -4397,7 +4414,7 @@ x_new_font (f, fontname)
       XSetFont (x_current_display, f->display.x->cursor_gc,
                f->display.x->font->fid);
 
-      x_set_window_size (f, f->width, f->height);
+      x_set_window_size (f, 0, f->width, f->height);
     }
 
   {
@@ -4429,7 +4446,7 @@ x_new_font (f, newname)
   f->display.x->font = temp;
 
   if (FRAME_X_WINDOW (f) != 0)
-    x_set_window_size (f, f->width, f->height);
+    x_set_window_size (f, 0, f->width, f->height);
 
   return 0;
 }
@@ -4507,20 +4524,31 @@ x_set_offset (f, xoff, yoff)
               f->display.x->left_pos, f->display.x->top_pos);
 #endif /* not USE_X_TOOLKIT */
 #ifdef HAVE_X11
-  x_wm_set_size_hint (f, 0, xoff, yoff);
+  x_wm_set_size_hint (f, 0, 1, xoff, yoff);
 #endif /* ! defined (HAVE_X11) */
   UNBLOCK_INPUT;
 }
 
-/* Call this to change the size of frame F's x-window. */
+/* Call this to change the size of frame F's x-window.
+   If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
+   for this size change and subsequent size changes.
+   Otherwise we leave the window gravity unchanged.  */
 
-x_set_window_size (f, cols, rows)
+x_set_window_size (f, change_gravity, cols, rows)
      struct frame *f;
+     int change_gravity;
      int cols, rows;
 {
   int pixelwidth, pixelheight;
   int mask;
 
+#ifdef USE_X_TOOLKIT
+  BLOCK_INPUT;
+  EmacsFrameSetCharSize (f->display.x->edit_widget, cols, rows);
+  UNBLOCK_INPUT;
+
+#else /* not USE_X_TOOLKIT */
+
   BLOCK_INPUT;
 
   check_frame_size (f, &rows, &cols);
@@ -4531,13 +4559,8 @@ x_set_window_size (f, cols, rows)
   pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
   pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
 
-#if 0
-#ifdef USE_X_TOOLKIT
-  EmacsFrameSetCharSize (f->display.x->edit_widget, cols, rows);
-#endif /* USE_X_TOOLKIT */
-#endif
 #ifdef HAVE_X11
-  x_wm_set_size_hint (f, 0, 0, 0);
+  x_wm_set_size_hint (f, 0, change_gravity, 0, 0);
 #endif /* ! defined (HAVE_X11) */
   XChangeWindowSize (FRAME_X_WINDOW (f), pixelwidth, pixelheight);
 
@@ -4563,6 +4586,7 @@ x_set_window_size (f, cols, rows)
 
   XFlushQueue ();
   UNBLOCK_INPUT;
+#endif /* not USE_X_TOOLKIT */
 }
 
 #ifndef HAVE_X11
@@ -4739,8 +4763,13 @@ x_make_frame_invisible (f)
 
 #ifdef HAVE_X11R4
 
+#ifdef USE_X_TOOLKIT
+  if (! XWithdrawWindow (x_current_display, XtWindow (f->display.x->widget),
+                        DefaultScreen (x_current_display)))
+#else /* not USE_X_TOOLKIT */
   if (! XWithdrawWindow (x_current_display, FRAME_X_WINDOW (f),
                         DefaultScreen (x_current_display)))
+#endif /* not USE_X_TOOLKIT */
     {
       UNBLOCK_INPUT_RESIGNAL;
       error ("can't notify window manager of window withdrawal");
@@ -4755,7 +4784,11 @@ x_make_frame_invisible (f)
       XEvent unmap;
 
       unmap.xunmap.type = UnmapNotify;
+#ifdef USE_X_TOOLKIT
+      unmap.xunmap.window = XtWindow (f->display.x->widget);
+#else /* not USE_X_TOOLKIT */
       unmap.xunmap.window = FRAME_X_WINDOW (f);
+#endif /* not USE_X_TOOLKIT */
       unmap.xunmap.event = DefaultRootWindow (x_current_display);
       unmap.xunmap.from_configure = False;
       if (! XSendEvent (x_current_display,
@@ -4770,8 +4803,11 @@ x_make_frame_invisible (f)
     }
 
   /* Unmap the window ourselves.  Cheeky!  */
+#ifdef USE_X_TOOLKIT
+  XUnmapWindow (x_current_display, XtWindow (f->display.x->widget));
+#else /* not USE_X_TOOLKIT */
   XUnmapWindow (x_current_display, FRAME_X_WINDOW (f));
-
+#endif /* not USE_X_TOOLKIT */
 #else /* ! defined (HAVE_X11) */
 
   XUnmapWindow (FRAME_X_WINDOW (f));
@@ -4804,7 +4840,7 @@ x_iconify_frame (f)
 #ifdef USE_X_TOOLKIT
   BLOCK_INPUT;
   result = XIconifyWindow (x_current_display,
-                          XtWindow(f->display.x->widget),
+                          XtWindow (f->display.x->widget),
                           DefaultScreen (x_current_display));
   UNBLOCK_INPUT;
 
@@ -4812,6 +4848,10 @@ x_iconify_frame (f)
     error ("Can't notify window manager of iconification.");
 
   f->async_iconified = 1;
+
+  BLOCK_INPUT;
+  XFlushQueue ();
+  UNBLOCK_INPUT;
 #else /* not USE_X_TOOLKIT */
 
   BLOCK_INPUT;
@@ -4865,10 +4905,10 @@ x_iconify_frame (f)
       refreshicon (f);
     }
 #endif /* ! defined (HAVE_X11) */
-#endif /* not USE_X_TOOLKIT */
 
   XFlushQueue ();
   UNBLOCK_INPUT;
+#endif /* not USE_X_TOOLKIT */
 }
 
 /* Destroy the X window of frame F.  */
@@ -4976,18 +5016,24 @@ mouse_event_pending_p ()
 
 #ifdef HAVE_X11
 
+/* Record the gravity used previously, in case CHANGE_GRAVITY is 0.  */
+static int previous_gravity;
+
 /* SPEC_X and SPEC_Y are the specified positions.
-   We look only at their sign, to decide the gravity.  */
+   We look only at their sign, to decide the gravity.
+   If CHANGE_GRAVITY is 0, we ignore SPEC_X and SPEC_Y
+   and leave the gravity unchanged.  */
 
-x_wm_set_size_hint (f, prompting, spec_x, spec_y)
+x_wm_set_size_hint (f, prompting, change_gravity, spec_x, spec_y)
      struct frame *f;
      long prompting;
+     int change_gravity;
      int spec_x, spec_y;
 {
   XSizeHints size_hints;
 
 #ifdef USE_X_TOOLKIT
-  Window window = XtWindow(f->display.x->widget);
+  Window window = XtWindow (f->display.x->widget);
 #else /* not USE_X_TOOLKIT */
   Window window = FRAME_X_WINDOW (f);
 #endif /* not USE_X_TOOLKIT */
@@ -5058,21 +5104,28 @@ x_wm_set_size_hint (f, prompting, spec_x, spec_y)
        size_hints.flags |= USSize;
     }
 #if defined (PWinGravity)
-  switch (((spec_x < 0) << 1) + (spec_y < 0))
+  if (change_gravity)
     {
-    case 0:
-      size_hints.win_gravity = NorthWestGravity;
-      break;
-    case 1:
-      size_hints.win_gravity = NorthEastGravity;
-      break;
-    case 2:
-      size_hints.win_gravity = SouthWestGravity;
-      break;
-    case 3:
-      size_hints.win_gravity = SouthEastGravity;
-      break;
+      switch (((spec_x < 0) << 1) + (spec_y < 0))
+       {
+       case 0:
+         size_hints.win_gravity = NorthWestGravity;
+         break;
+       case 1:
+         size_hints.win_gravity = NorthEastGravity;
+         break;
+       case 2:
+         size_hints.win_gravity = SouthWestGravity;
+         break;
+       case 3:
+         size_hints.win_gravity = SouthEastGravity;
+         break;
+       }
+      previous_gravity = size_hints.win_gravity;
     }
+  else
+    size_hints.win_gravity = previous_gravity;
+
   size_hints.flags |= PWinGravity;
 #endif /* PWinGravity */
 
@@ -5089,7 +5142,7 @@ x_wm_set_window_state (f, state)
      int state;
 {
 #ifdef USE_X_TOOLKIT
-  Window window = XtWindow(f->display.x->widget);
+  Window window = XtWindow (f->display.x->widget);
 #else /* not USE_X_TOOLKIT */
   Window window = FRAME_X_WINDOW (f);
 #endif /* not USE_X_TOOLKIT */
@@ -5175,7 +5228,7 @@ x_term_init (display_name)
   argv [2] = display_name;
   argc = 3;
   Xt_app_shell = XtAppInitialize (&Xt_app_con, "Emacs",
-                                 emacs_options, XtNumber(emacs_options),
+                                 emacs_options, XtNumber (emacs_options),
                                  &argc, argv,
                                  NULL, NULL, 0);
   XtFree (argv);
@@ -5191,30 +5244,10 @@ Check the DISPLAY environment variable or use \"-d\"\n",
 
 #ifdef HAVE_X11
   {
-    int hostname_size = 256;
-
-    hostname = (char *) xmalloc (hostname_size);
-
 #if 0
     XSetAfterFunction (x_current_display, x_trace_wire);
 #endif /* ! 0 */
-
-    /* Try to get the host name; if the buffer is too short, try
-       again.  Apparently, the only indication gethostname gives of
-       whether the buffer was large enough is the presence or absence
-       of a '\0' in the string.  Eech.  */
-    for (;;)
-      {
-       gethostname (hostname, hostname_size - 1);
-       hostname[hostname_size - 1] = '\0';
-
-       /* Was the buffer large enough for gethostname to store the '\0'?  */
-       if (strlen (hostname) < hostname_size - 1)
-         break;
-
-       hostname_size <<= 1;
-       hostname = (char *) xrealloc (hostname, hostname_size);
-      }
+    hostname = get_system_name ();
     x_id_name = (char *) xmalloc (XSTRING (Vinvocation_name)->size
                                + strlen (hostname)
                                + 2);