Fix glitches in previous change.
[bpt/emacs.git] / src / xterm.c
index 17d57f1..474082d 100644 (file)
@@ -95,8 +95,13 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #ifdef USE_X_TOOLKIT
 extern XtAppContext Xt_app_con;
 extern Widget Xt_app_shell;
+extern void free_frame_menubar ();
 #endif /* USE_X_TOOLKIT */
 
+#ifndef USE_X_TOOLKIT
+#define x_any_window_to_frame x_window_to_frame
+#endif
+
 #ifdef HAVE_X11
 #define XMapWindow XMapRaised          /* Raise them when mapping. */
 #else /* ! defined (HAVE_X11) */
@@ -464,7 +469,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.  */
@@ -491,7 +497,7 @@ dumpglyphs (f, left, top, gp, n, hl)
       int g = *gp;
 
       GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
-      cf = GLYPH_FACE (g);
+      cf = FAST_GLYPH_FACE (g);
 
       /* Find the run of consecutive glyphs with the same face-code.
         Extract their character codes into BUF.  */
@@ -500,10 +506,10 @@ dumpglyphs (f, left, top, gp, n, hl)
        {
          g = *gp;
          GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
-         if (GLYPH_FACE (g) != cf)
+         if (FAST_GLYPH_FACE (g) != cf)
            break;
 
-         *cp++ = GLYPH_CHAR (g);
+         *cp++ = FAST_GLYPH_CHAR (g);
          --n;
          ++gp;
        }
@@ -567,7 +573,25 @@ dumpglyphs (f, left, top, gp, n, hl)
                unsigned long mask;
 
                xgcv.background = f->display.x->cursor_pixel;
-               xgcv.foreground = f->display.x->cursor_foreground_pixel;
+               if (face == FRAME_DEFAULT_FACE (f))
+                 xgcv.foreground = f->display.x->cursor_foreground_pixel;
+               else
+                 xgcv.foreground = face->foreground;
+               /* If the glyph would be invisible,
+                  try a different foreground.  */
+               if (xgcv.foreground == xgcv.background)
+                 xgcv.foreground = face->background;
+               if (xgcv.foreground == xgcv.background)
+                 xgcv.foreground = f->display.x->cursor_foreground_pixel;
+               if (xgcv.foreground == xgcv.background)
+                 xgcv.foreground = face->foreground;
+               /* Make sure the cursor is distinct from text in this face.  */
+               if (xgcv.background == face->background
+                   && xgcv.foreground == face->foreground)
+                 {
+                   xgcv.background = face->foreground;
+                   xgcv.foreground = face->background;
+                 }
                xgcv.font = face->font->fid;
                xgcv.graphics_exposures = 0;
                mask = GCForeground | GCBackground | GCFont | GCGraphicsExposures;
@@ -751,7 +775,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)
@@ -1146,7 +1171,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)
@@ -1538,6 +1564,10 @@ x_find_modifier_meanings ()
          KeyCode code =
            mods->modifiermap[(row * mods->max_keypermod) + col];
 
+         /* Zeroes are used for filler.  Skip them.  */
+         if (code == 0)
+           continue;
+
          /* Are any of this keycode's keysyms a meta key?  */
          {
            int code_col;
@@ -1597,31 +1627,6 @@ x_find_modifier_meanings ()
   XFreeModifiermap (mods);
 }
 
-/* Prepare a menu-event in *RESULT for placement in the input queue.  */
-
-static Lisp_Object
-construct_menu_click (result, event, f)
-     struct input_event *result;
-     XButtonEvent *event;
-     struct frame *f;
-{
-  /* Make the event type no_event; we'll change that when we decide
-     otherwise.  */
-  result->kind = mouse_click;
-  XSET (result->code, Lisp_Int, event->button - Button1);
-  result->timestamp = event->time;
-  result->modifiers = (x_x_to_emacs_modifiers (event->state)
-                      | (event->type == ButtonRelease
-                         ? up_modifier 
-                         : down_modifier));
-
-  {
-    XFASTINT (result->x) = event->x;
-    XFASTINT (result->y) = -1;    /* special meaning for menubar */
-    XSET (result->frame_or_window, Lisp_Frame, f);
-  }
-}
-
 /* Convert between the modifier bits X uses and the modifier bits
    Emacs uses.  */
 static unsigned int
@@ -1672,7 +1677,7 @@ x_is_vendor_fkey (sym)
    that the glyph at X, Y occupies, if BOUNDS != 0.
    If NOCLIP is nonzero, do not force the value into range.  */
 
-static void
+void
 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
      FRAME_PTR f;
      register int pix_x, pix_y;
@@ -1715,6 +1720,16 @@ pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
   *y = pix_y;
 }
 
+void
+glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
+     FRAME_PTR f;
+     register int x, y;
+     register int *pix_x, *pix_y;
+{
+  *pix_x = CHAR_TO_PIXEL_COL (f, x);
+  *pix_y = CHAR_TO_PIXEL_ROW (f, y);
+}
+
 /* Prepare a mouse-event in *RESULT for placement in the input queue.
 
    If the event is a button press, then note that we have grabbed
@@ -1754,12 +1769,39 @@ construct_mouse_click (result, event, f)
   {
     int row, column;
 
+#if 0
     pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL, 0);
     XFASTINT (result->x) = column;
     XFASTINT (result->y) = row;
+#endif
+    XFASTINT (result->x) = event->x;
+    XFASTINT (result->y) = event->y;
     XSET (result->frame_or_window, Lisp_Frame, f);
   }
 }
+
+/* Prepare a menu-event in *RESULT for placement in the input queue.  */
+
+static Lisp_Object
+construct_menu_click (result, event, f)
+     struct input_event *result;
+     XButtonEvent *event;
+     struct frame *f;
+{
+  /* Make the event type no_event; we'll change that when we decide
+     otherwise.  */
+  result->kind = mouse_click;
+  XSET (result->code, Lisp_Int, event->button - Button1);
+  result->timestamp = event->time;
+  result->modifiers = (x_x_to_emacs_modifiers (event->state)
+                      | (event->type == ButtonRelease
+                         ? up_modifier 
+                         : down_modifier));
+
+  XFASTINT (result->x) = event->x;
+  XSETINT (result->y, -1);
+  XSET (result->frame_or_window, Lisp_Frame, f);
+}
 \f
 /* Function to report a mouse movement to the mainstream Emacs code.
    The input handler calls this.
@@ -1929,7 +1971,7 @@ XTmouse_position (f, bar_window, part, x, y, time)
               never use them in that case.)  */
 
            /* Is win one of our frames?  */
-           f1 = x_window_to_frame (win);
+           f1 = x_any_window_to_frame (win);
          }
       
        /* If not, is it one of our scroll bars?  */
@@ -1947,10 +1989,11 @@ XTmouse_position (f, bar_window, part, x, y, time)
 
        if (f1)
          {
-           /* Ok, we found a frame.  Convert from pixels to characters
-              and store all the values.  */
+           int ignore1, ignore2;
 
-           pixel_to_glyph_coords (f1, win_x, win_y, &win_x, &win_y,
+           /* Ok, we found a frame.  Store all the values.  */
+
+           pixel_to_glyph_coords (f1, win_x, win_y, &ignore1, &ignore2,
                                   &last_mouse_glyph, x_mouse_grabbed);
 
            *bar_window = Qnil;
@@ -1985,9 +2028,9 @@ x_window_to_scroll_bar (window_id)
        XGCTYPE (tail) == Lisp_Cons;
        tail = XCONS (tail)->cdr)
     {
-      Lisp_Object frame = XCONS (tail)->car;
-      Lisp_Object bar, condemned;
+      Lisp_Object frame, bar, condemned;
 
+      frame = XCONS (tail)->car;
       /* All elements of Vframe_list should be frames.  */
       if (XGCTYPE (frame) != Lisp_Frame)
        abort ();
@@ -2042,12 +2085,12 @@ x_scroll_bar_create (window, top, left, width, height)
     XtSetArg (al[ac], XtNheight, height); ac++;
     XtSetArg (al[ac], XtNborderWidth, 0); ac++;
     sb_widget = XtCreateManagedWidget ("box",
-                                        boxWidgetClass,
-                                        frame->display.x->edit_widget, al, ac);
-   SET_SCROLL_BAR_X_WINDOW
+                                      boxWidgetClass,
+                                      frame->display.x->edit_widget, al, ac);
+    SET_SCROLL_BAR_X_WINDOW
       (bar, sb_widget->core.window);
 #endif    
-   SET_SCROLL_BAR_X_WINDOW
+    SET_SCROLL_BAR_X_WINDOW
       (bar, 
        XCreateWindow (x_current_display, FRAME_X_WINDOW (frame),
 
@@ -2419,12 +2462,6 @@ x_scroll_bar_expose (bar, event)
                  /* x, y, width, height */
                  0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1);
 
-  /* Draw another line to make the extra-thick border on the right.  */
-  XFillRectangle (x_current_display, w, gc,
-
-                 /* x, y, width, height */
-                 XINT (bar->width) - 2, 1, 1, XINT (bar->height) - 2);
-
   UNBLOCK_INPUT;
 }
 
@@ -2648,6 +2685,8 @@ process_expose_from_menu (event)
 {
   FRAME_PTR f;
 
+  BLOCK_INPUT;
+
   f = x_window_to_frame (event.xexpose.window);
   if (f)
     {
@@ -2672,6 +2711,8 @@ process_expose_from_menu (event)
       if (bar)
        x_scroll_bar_expose (bar, &event);
     }
+
+  UNBLOCK_INPUT;
 }
 
 \f
@@ -2811,7 +2852,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
                  }
                else if (event.xclient.data.l[0] == Xatom_wm_delete_window)
                  {
-                   struct frame *f = x_window_to_frame (event.xclient.window);
+                   struct frame *f = x_any_window_to_frame (event.xclient.window);
 
                    if (f)
                      {
@@ -3118,7 +3159,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
 #ifdef HAVE_X11
        case KeyPress:
-         f = x_window_to_frame (event.xkey.window);
+         f = x_any_window_to_frame (event.xkey.window);
 
          if (f != 0)
            {
@@ -3311,7 +3352,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
             then a mere LeaveNotify is enough to free you.  */
 
        case EnterNotify:
-         f = x_window_to_frame (event.xcrossing.window);
+         f = x_any_window_to_frame (event.xcrossing.window);
 
          if (event.xcrossing.focus)            /* Entered Window */
            {
@@ -3332,7 +3373,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
          break;
 
        case FocusIn:
-         f = x_window_to_frame (event.xfocus.window);
+         f = x_any_window_to_frame (event.xfocus.window);
          if (event.xfocus.detail != NotifyPointer) 
            x_focus_event_frame = f;
          if (f)
@@ -3344,7 +3385,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
 
 
        case LeaveNotify:
-         f = x_window_to_frame (event.xcrossing.window);
+         f = x_any_window_to_frame (event.xcrossing.window);
 
          if (event.xcrossing.focus)
            {
@@ -3366,7 +3407,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
          break;
 
        case FocusOut:
-         f = x_window_to_frame (event.xfocus.window);
+         f = x_any_window_to_frame (event.xfocus.window);
          if (event.xfocus.detail != NotifyPointer
              && f == x_focus_event_frame)
            x_focus_event_frame = 0;
@@ -3437,11 +3478,43 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
          break;
 
        case ConfigureNotify:
+          f = x_any_window_to_frame (event.xconfigure.window);
 #ifdef USE_X_TOOLKIT
-             /* process done in widget.c */
-         goto OTHER;
+          if (f
+              && ! event.xconfigure.send_event
+              && (event.xconfigure.window == XtWindow (f->display.x->widget)))
+            {
+              Window win, child;
+              int win_x, win_y;
+
+              /* Find the position of the outside upper-left corner of
+                 the window, in the root coordinate system.  Don't
+                 refer to the parent window here; we may be processing
+                 this event after the window manager has changed our
+                 parent, but before we have reached the ReparentNotify.  */
+              XTranslateCoordinates (x_current_display,
+
+                                     /* From-window, to-window.  */
+                                     XtWindow (f->display.x->widget),
+                                     ROOT_WINDOW,
+
+                                     /* From-position, to-position.  */
+                                     -event.xconfigure.border_width,
+                                     -event.xconfigure.border_width,
+                                     &win_x, &win_y,
+
+                                     /* Child of win.  */
+                                     &child);
+              event.xconfigure.x = win_x;
+              event.xconfigure.y = win_y;
+
+              f->display.x->pixel_width = event.xconfigure.width;
+              f->display.x->pixel_height = event.xconfigure.height;
+              f->display.x->left_pos = event.xconfigure.x;
+              f->display.x->top_pos = event.xconfigure.y;
+            }
+          goto OTHER;
 #else /* not USE_X_TOOLKIT */
-         f = x_window_to_frame (event.xconfigure.window);
          if (f)
            {
              int rows = PIXEL_TO_CHAR_HEIGHT (f, event.xconfigure.height);
@@ -3620,10 +3693,15 @@ 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.  */
+       when the window is destroyed.  Detect that.  (1994.)  */
     XNoOp (x_current_display);
 #endif /* X_IO_BUG */
 
+#if 0 /* This fails for serial-line connections to the X server, 
+        because the characters arrive one by one, and a partial
+        command makes select return but gives nothing to read.
+        We'll have to hope that the bug that this tried to fix
+        in 1988 has been fixed in Xlib or the X server.  */
 #ifdef HAVE_SELECT
   if (expected && ! event_found)
     {
@@ -3644,6 +3722,7 @@ XTread_socket (sd, bufp, numchars, waitp, expected)
        kill (getpid (), SIGHUP);
     }
 #endif /* HAVE_SELECT */
+#endif /* 0 */
 
 #ifndef HAVE_X11
   if (updating_frame == 0)
@@ -3950,6 +4029,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)
@@ -3957,6 +4038,8 @@ x_display_cursor (f, on)
   else
     /* Those are the only two we have implemented!  */
     abort ();
+
+  UNBLOCK_INPUT;
 }
 \f
 /* Icons.  */
@@ -4237,6 +4320,7 @@ x_catch_errors ()
 /* If any X protocol errors have arrived since the last call to
    x_catch_errors or x_check_errors, signal an Emacs error using
    sprintf (a buffer, FORMAT, the x error message text) as the text.  */
+
 void
 x_check_errors (format)
      char *format;
@@ -4254,6 +4338,19 @@ x_check_errors (format)
     }
 }
 
+/* Nonzero if we had any X protocol errors since we did x_catch_errors.  */
+
+int
+x_had_errors_p ()
+{
+  /* Make sure to catch any errors incurred so far.  */
+  XSync (x_current_display, False);
+
+  return x_caught_error_message[0] != 0;
+}
+
+/* Stop catching X protocol errors and let them make Emacs die.  */
+
 void
 x_uncatch_errors ()
 {
@@ -4407,8 +4504,9 @@ x_new_font (f, fontname)
     }
 
   {
-    Lisp_Object lispy_name = build_string (fontname);
+    Lisp_Object lispy_name;
 
+    lispy_name = build_string (fontname);
 
     /* Free the information from XListFonts.  The data
        we actually retain comes from XLoadQueryFont.  */
@@ -4912,6 +5010,7 @@ x_destroy_window (f)
   XDestroyWindow (XDISPLAY f->display.x->window_desc);
 #ifdef USE_X_TOOLKIT
   XtDestroyWidget (f->display.x->widget);
+  free_frame_menubar (f);
 #endif /* USE_X_TOOLKIT */
 
   free_frame_faces (f);