]> code.delx.au - gnu-emacs/blobdiff - src/xterm.c
(x_draw_glyph_string): For stretch glyphs, don't call
[gnu-emacs] / src / xterm.c
index a02c7b955c8507b88976690ff509e6a61c6322cd..4d74910fec7fe21e61dbb45b69dc82eda8c802fe 100644 (file)
@@ -84,6 +84,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "atimer.h"
 #include "keymap.h"
 #include "font.h"
+#include "fontset.h"
 
 #ifdef USE_X_TOOLKIT
 #include <X11/Shell.h>
@@ -467,13 +468,15 @@ x_set_frame_alpha (f)
   struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
   Display *dpy = FRAME_X_DISPLAY (f);
   Window win = FRAME_OUTER_WINDOW (f);
+  double alpha = 1.0;
+  double alpha_min = 1.0;
+  unsigned long opac;
+
   if (FRAME_X_DISPLAY_INFO (f)->root_window != FRAME_X_OUTPUT (f)->parent_desc)
     /* Since the WM decoration lies under the FRAME_OUTER_WINDOW,
        we must treat the former instead of the latter. */
     win = FRAME_X_OUTPUT(f)->parent_desc;
 
-  double alpha = 1.0, alpha_min = 1.0;
-
   if (dpyinfo->x_highlight_frame == f)
     alpha = f->alpha[0];
   else
@@ -484,39 +487,59 @@ x_set_frame_alpha (f)
   else if (INTEGERP (Vframe_alpha_lower_limit))
     alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
 
-  if (alpha < 0.0 || 1.0 < alpha)
+  if (alpha < 0.0)
+    return;
+  else if (alpha > 1.0)
     alpha = 1.0;
   else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
     alpha = alpha_min;
 
-  unsigned int opac = (unsigned int)(alpha * OPAQUE);
+  opac = alpha * OPAQUE;
 
   /* return unless necessary */
   {
     unsigned char *data;
     Atom actual;
-    int format;
+    int rc, format;
     unsigned long n, left;
 
-    XGetWindowProperty(dpy, win, XInternAtom(dpy, OPACITY, False),
-                      0L, 1L, False, XA_CARDINAL, &actual, &format, &n, &left,
-                      (unsigned char **) &data);
-    if (data != None)
-      if (*(unsigned int *)data == opac)
+    x_catch_errors (dpy);
+    rc = XGetWindowProperty(dpy, win, XInternAtom(dpy, OPACITY, False),
+                           0L, 1L, False, XA_CARDINAL,
+                           &actual, &format, &n, &left,
+                           &data);
+
+    if (rc == Success && actual != None)
+      if (*(unsigned long *)data == opac)
        {
          XFree ((void *) data);
+         x_uncatch_errors ();
          return;
        }
       else
-       {
-         XFree ((void *) data);
-       }
+       XFree ((void *) data);
+    x_uncatch_errors ();
   }
 
+  x_catch_errors (dpy);
   XChangeProperty (dpy, win, XInternAtom (dpy, OPACITY, False),
                   XA_CARDINAL, 32, PropModeReplace,
                   (unsigned char *) &opac, 1L);
-  XSync (dpy, False);
+  x_uncatch_errors ();
+}
+
+int
+x_display_pixel_height (dpyinfo)
+     struct x_display_info *dpyinfo;
+{
+  return HeightOfScreen (dpyinfo->screen);
+}
+
+int
+x_display_pixel_width (dpyinfo)
+     struct x_display_info *dpyinfo;
+{
+  return WidthOfScreen (dpyinfo->screen);
 }
 
 \f
@@ -1305,6 +1328,7 @@ x_draw_composite_glyph_string_foreground (s)
      struct glyph_string *s;
 {
   int i, j, x;
+  struct font *font = s->font;
 
   /* If first glyph of S has a left box line, start drawing the text
      of S to the right of that box line.  */
@@ -1314,73 +1338,66 @@ x_draw_composite_glyph_string_foreground (s)
   else
     x = s->x;
 
-  /* S is a glyph string for a composition.  S->gidx is the index of
-     the first character drawn for glyphs of this composition.
-     S->gidx == 0 means we are drawing the very first character of
+  /* S is a glyph string for a composition.  S->cmp_from is the index
+     of the first character drawn for glyphs of this composition.
+     S->cmp_from == 0 means we are drawing the very first character of
      this composition.  */
 
   /* Draw a rectangle for the composition if the font for the very
      first character of the composition could not be loaded.  */
   if (s->font_not_found_p)
     {
-      if (s->gidx == 0)
+      if (s->cmp_from == 0)
        XDrawRectangle (s->display, s->window, s->gc, x, s->y,
                        s->width - 1, s->height - 1);
     }
+  else if (! s->first_glyph->u.cmp.automatic)
+    {
+      int y = s->ybase;
+
+      for (i = 0, j = s->cmp_from; i < s->nchars; i++, j++)
+       if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
+         {
+           int xx = x + s->cmp->offsets[j * 2];
+           int yy = y - s->cmp->offsets[j * 2 + 1];
+
+           font->driver->draw (s, j, j + 1, xx, yy, 0);
+           if (s->face->overstrike)
+             font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
+         }
+    }
   else
     {
-      struct font *font = s->font;
+      Lisp_Object gstring = composition_gstring_from_id (s->cmp_id);
+      Lisp_Object glyph;
       int y = s->ybase;
       int width = 0;
 
-      if (s->cmp->method == COMPOSITION_WITH_GLYPH_STRING)
+      for (i = j = s->cmp_from; i < s->cmp_to; i++)
        {
-         Lisp_Object gstring = AREF (XHASH_TABLE (composition_hash_table)
-                                     ->key_and_value,
-                                     s->cmp->hash_index * 2);
-         int from;
-
-         for (i = from = 0; i < s->nchars; i++)
+         glyph = LGSTRING_GLYPH (gstring, i);
+         if (NILP (LGLYPH_ADJUSTMENT (glyph)))
+           width += LGLYPH_WIDTH (glyph);
+         else
            {
-             Lisp_Object g = LGSTRING_GLYPH (gstring, i);
-             Lisp_Object adjustment = LGLYPH_ADJUSTMENT (g);
              int xoff, yoff, wadjust;
 
-             if (! VECTORP (adjustment))
+             if (j < i)
                {
-                 width += LGLYPH_WIDTH (g);
-                 continue;
-               }
-             if (from < i)
-               {
-                 font->driver->draw (s, from, i, x, y, 0);
+                 font->driver->draw (s, j, i, x, y, 0);
                  x += width;
                }
-             xoff = XINT (AREF (adjustment, 0));
-             yoff = XINT (AREF (adjustment, 1));
-             wadjust = XINT (AREF (adjustment, 2));
-
+             xoff = LGLYPH_XOFF (glyph);
+             yoff = LGLYPH_YOFF (glyph);
+             wadjust = LGLYPH_WADJUST (glyph);
              font->driver->draw (s, i, i + 1, x + xoff, y + yoff, 0);
              x += wadjust;
-             from = i + 1;
+             j = i + 1;
              width = 0;
            }
-         if (from < i)
-           font->driver->draw (s, from, i, x, y, 0);
-       }
-      else
-       {
-         for (i = 0, j = s->gidx; i < s->nchars; i++, j++)
-           if (COMPOSITION_GLYPH (s->cmp, j) != '\t')
-             {
-               int xx = x + s->cmp->offsets[j * 2];
-               int yy = y - s->cmp->offsets[j * 2 + 1];
-
-               font->driver->draw (s, j, j + 1, xx, yy, 0);
-               if (s->face->overstrike)
-                 font->driver->draw (s, j, j + 1, xx + 1, yy, 0);
-             }
        }
+      if (j < i)
+       font->driver->draw (s, j, i, x, y, 0);
     }
 }
 
@@ -2636,13 +2653,17 @@ x_draw_glyph_string (s)
       int width;
       struct glyph_string *next;
 
-      for (width = 0, next = s->next; next;
+      for (width = 0, next = s->next;
+          next && width < s->right_overhang;
           width += next->width, next = next->next)
        if (next->first_glyph->type != IMAGE_GLYPH)
          {
            x_set_glyph_string_gc (next);
            x_set_glyph_string_clipping (next);
-           x_draw_glyph_string_background (next, 1);
+           if (next->first_glyph->type == STRETCH_GLYPH)
+             x_draw_stretch_glyph_string (next);
+           else
+             x_draw_glyph_string_background (next, 1);
            next->num_clips = 0;
          }
     }
@@ -2664,8 +2685,10 @@ x_draw_glyph_string (s)
       x_set_glyph_string_clipping (s);
       relief_drawn_p = 1;
     }
-  else if ((s->prev && s->prev->hl != s->hl && s->left_overhang)
-          || (s->next && s->next->hl != s->hl && s->right_overhang))
+  else if (!s->clip_head /* draw_glyphs didn't specify a clip mask. */
+          && !s->clip_tail
+          && ((s->prev && s->prev->hl != s->hl && s->left_overhang)
+              || (s->next && s->next->hl != s->hl && s->right_overhang)))
     /* We must clip just this glyph.  left_overhang part has already
        drawn when s->prev was drawn, and right_overhang part will be
        drawn later when s->next is drawn. */
@@ -2692,7 +2715,8 @@ x_draw_glyph_string (s)
       break;
 
     case COMPOSITE_GLYPH:
-      if (s->for_overlaps || s->gidx > 0)
+      if (s->for_overlaps || (s->cmp_from > 0
+                             && ! s->first_glyph->u.cmp.automatic))
        s->background_filled_p = 1;
       else
        x_draw_glyph_string_background (s, 1);
@@ -2725,7 +2749,7 @@ x_draw_glyph_string (s)
              else
                thickness = 1;
              if (x_underline_at_descent_line)
-               position = (s->height - thickness) - s->ybase;
+               position = (s->height - thickness) - (s->ybase - s->y);
              else
                {
                  /* Get the underline position.  This is the recommended
@@ -2742,9 +2766,16 @@ x_draw_glyph_string (s)
                  else if (s->font)
                    position = (s->font->descent + 1) / 2;
                }
-             s->underline_thickness = thickness;
-             s->underline_position = position;
+             position = max (position, underline_minimum_offset);
            }
+         /* Check the sanity of thickness and position.  We should
+            avoid drawing underline out of the current line area.  */
+         if (s->y + s->height <= s->ybase + position)
+           position = (s->height - 1) - (s->ybase - s->y);
+         if (s->y + s->height < s->ybase + position + thickness)
+           thickness = (s->y + s->height) - (s->ybase + position);
+         s->underline_thickness = thickness;
+         s->underline_position = position;
          y = s->ybase + position;
          if (s->face->underline_defaulted_p)
            XFillRectangle (s->display, s->window, s->gc,
@@ -6697,8 +6728,9 @@ handle_one_xevent (dpyinfo, eventp, finish, hold_quit)
         if (f)
           {
 
-            /* Generate SELECT_WINDOW_EVENTs when needed.  */
-            if (!NILP (Vmouse_autoselect_window))
+            /* Generate SELECT_WINDOW_EVENTs when needed.
+               Don't let popup menus influence things (bug#1261).  */
+            if (!NILP (Vmouse_autoselect_window) && !popup_activated ())
               {
                 Lisp_Object window;
 
@@ -7416,7 +7448,7 @@ x_draw_bar_cursor (w, row, width, kind)
                          WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
                          WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
                                                   row->height - width),
-                         cursor_glyph->pixel_width,
+                         min (FRAME_COLUMN_WIDTH (f), cursor_glyph->pixel_width),
                          width);
 
       XSetClipMask (dpy, gc, None);
@@ -8294,9 +8326,11 @@ xim_close_dpy (dpyinfo)
        XUnregisterIMInstantiateCallback (dpyinfo->display, dpyinfo->xrdb,
                                          NULL, EMACS_CLASS,
                                          xim_instantiate_callback, NULL);
-#endif /* not HAVE_X11R6_XIM */
+#else /* not HAVE_X11R6_XIM */
+      /* If we have X11R6 xim, this causes a double-free.  */
       if (dpyinfo->display)
        XCloseIM (dpyinfo->xim);
+#endif /* HAVE_X11R6_XIM */
       dpyinfo->xim = NULL;
       XFree (dpyinfo->xim_styles);
     }
@@ -8324,8 +8358,8 @@ x_calc_absolute_position (f)
   /* Treat negative positions as relative to the leftmost bottommost
      position that fits on the screen.  */
   if (flags & XNegative)
-    f->left_pos = (FRAME_X_DISPLAY_INFO (f)->width
-                   - FRAME_PIXEL_WIDTH (f) + f->left_pos);
+    f->left_pos = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
+      - FRAME_PIXEL_WIDTH (f) + f->left_pos;
 
   {
     int height = FRAME_PIXEL_HEIGHT (f);
@@ -8346,8 +8380,9 @@ x_calc_absolute_position (f)
     XtVaGetValues (f->output_data.x->column_widget, XtNheight, &height, NULL);
 #endif
 
-  if (flags & YNegative)
-    f->top_pos = (FRAME_X_DISPLAY_INFO (f)->height - height + f->top_pos);
+    if (flags & YNegative)
+      f->top_pos = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
+       - height + f->top_pos;
   }
 
   /* The left_pos and top_pos
@@ -9505,9 +9540,7 @@ x_free_frame_resources (f)
       XFlush (FRAME_X_DISPLAY (f));
     }
 
-  if (f->output_data.x->saved_menu_event)
-    xfree (f->output_data.x->saved_menu_event);
-
+  xfree (f->output_data.x->saved_menu_event);
   xfree (f->output_data.x);
   f->output_data.x = NULL;
 
@@ -9595,10 +9628,10 @@ x_wm_set_size_hint (f, flags, user_position)
 
   size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
   size_hints.height_inc = FRAME_LINE_HEIGHT (f);
-  size_hints.max_width
-    = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
-  size_hints.max_height
-    = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
+  size_hints.max_width = x_display_pixel_width (FRAME_X_DISPLAY_INFO (f))
+    - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
+  size_hints.max_height = x_display_pixel_height (FRAME_X_DISPLAY_INFO (f))
+    - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
 
   /* Calculate the base and minimum sizes.
 
@@ -9845,7 +9878,6 @@ static int x_initialized;
 static int x_session_initialized;
 #endif
 
-#ifdef MULTI_KBOARD
 /* Test whether two display-name strings agree up to the dot that separates
    the screen number from the server number.  */
 static int
@@ -9892,7 +9924,6 @@ same_x_server (name1, name2)
          && (*name1 == '.' || *name1 == '\0')
          && (*name2 == '.' || *name2 == '\0'));
 }
-#endif
 
 /* Count number of set bits in mask and number of bits to shift to
    get to the first bit.  With MASK 0x7e0, *BITS is set to 6, and *OFFSET
@@ -10091,7 +10122,6 @@ x_term_init (display_name, xrm_option, resource_name)
 
   terminal = x_create_terminal (dpyinfo);
 
-#ifdef MULTI_KBOARD
   {
     struct x_display_info *share;
     Lisp_Object tail;
@@ -10111,11 +10141,15 @@ x_term_init (display_name, xrm_option, resource_name)
        if (!EQ (XSYMBOL (Qvendor_specific_keysyms)->function, Qunbound))
          {
            char *vendor = ServerVendor (dpy);
+           /* Temporarily hide the partially initialized terminal */
+           terminal_list = terminal->next_terminal;
            UNBLOCK_INPUT;
            terminal->kboard->Vsystem_key_alist
              = call1 (Qvendor_specific_keysyms,
                       vendor ? build_string (vendor) : empty_unibyte_string);
            BLOCK_INPUT;
+           terminal->next_terminal = terminal_list;
+           terminal_list = terminal;
          }
 
        terminal->kboard->next_kboard = all_kboards;
@@ -10128,7 +10162,6 @@ x_term_init (display_name, xrm_option, resource_name)
       }
     terminal->kboard->reference_count++;
   }
-#endif
 
   /* Put this display on the chain.  */
   dpyinfo->next = x_display_list;
@@ -10184,8 +10217,6 @@ x_term_init (display_name, xrm_option, resource_name)
                                     DefaultScreen (dpyinfo->display));
   select_visual (dpyinfo);
   dpyinfo->cmap = DefaultColormapOfScreen (dpyinfo->screen);
-  dpyinfo->height = HeightOfScreen (dpyinfo->screen);
-  dpyinfo->width = WidthOfScreen (dpyinfo->screen);
   dpyinfo->root_window = RootWindowOfScreen (dpyinfo->screen);
   dpyinfo->client_leader_window = 0;
   dpyinfo->grabbed = 0;
@@ -10504,7 +10535,8 @@ x_delete_display (dpyinfo)
          tail->next = tail->next->next;
     }
 
-#ifndef USE_X_TOOLKIT   /* I'm told Xt does this itself.  */
+  /* Xt and GTK do this themselves.  */
+#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK)
 #ifndef AIX            /* On AIX, XCloseDisplay calls this.  */
   XrmDestroyDatabase (dpyinfo->xrdb);
 #endif
@@ -10514,10 +10546,8 @@ x_delete_display (dpyinfo)
     xim_close_dpy (dpyinfo);
 #endif
 
-  if (dpyinfo->x_id_name)
-    xfree (dpyinfo->x_id_name);
-  if (dpyinfo->color_cells)
-    xfree (dpyinfo->color_cells);
+  xfree (dpyinfo->x_id_name);
+  xfree (dpyinfo->color_cells);
   xfree (dpyinfo);
 }
 
@@ -10777,7 +10807,9 @@ syms_of_xterm ()
      doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
 A value of nil means ignore them.  If you encounter fonts with bogus
 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
-to 4.1, set this to nil.  */);
+to 4.1, set this to nil.  You can also use `underline-minimum-offset'
+to override the font's UNDERLINE_POSITION for small font display
+sizes.  */);
   x_use_underline_position_properties = 1;
 
   DEFVAR_BOOL ("x-underline-at-descent-line",