Merge from trunk
[bpt/emacs.git] / src / w32term.c
index fc03034..7145efb 100644 (file)
@@ -1,7 +1,8 @@
 /* Implementation of GUI terminal on the Microsoft W32 API.
-   Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998,
-                 1999, 2000, 2001, 2002, 2003, 2004, 2005,
-                 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+
+Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+  2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
 
@@ -21,7 +22,6 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <config.h>
 #include <signal.h>
 #include <stdio.h>
-#include <stdlib.h>
 #include <setjmp.h>
 #include "lisp.h"
 #include "blockinput.h"
@@ -505,7 +505,7 @@ static void
 x_update_window_begin (struct window *w)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
+  Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
 
   /* Hide the system caret during an update.  */
   if (w32_use_visible_system_caret && w32_system_caret_hwnd)
@@ -518,15 +518,15 @@ x_update_window_begin (struct window *w)
 
   BLOCK_INPUT;
 
-  if (f == display_info->mouse_face_mouse_frame)
+  if (f == hlinfo->mouse_face_mouse_frame)
     {
       /* Don't do highlighting for mouse motion during the update.  */
-      display_info->mouse_face_defer = 1;
+      hlinfo->mouse_face_defer = 1;
 
       /* If F needs to be redrawn, simply forget about any prior mouse
         highlighting.  */
       if (FRAME_GARBAGED_P (f))
-       display_info->mouse_face_window = Qnil;
+       hlinfo->mouse_face_window = Qnil;
 
 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
         their mouse_face_p flag set, which means that they are always
@@ -540,8 +540,8 @@ x_update_window_begin (struct window *w)
         Likewise, don't do anything if the frame is garbaged;
         in that case, the frame's current matrix that we would use
         is all wrong, and we will redisplay that line anyway.  */
-      if (!NILP (display_info->mouse_face_window)
-         && w == XWINDOW (display_info->mouse_face_window))
+      if (!NILP (hlinfo->mouse_face_window)
+         && w == XWINDOW (hlinfo->mouse_face_window))
        {
          int i;
 
@@ -550,7 +550,7 @@ x_update_window_begin (struct window *w)
              break;
 
          if (i < w->desired_matrix->nrows)
-           clear_mouse_face (display_info);
+           clear_mouse_face (hlinfo);
        }
 #endif /* 0 */
     }
@@ -601,7 +601,7 @@ static void
 x_update_window_end (struct window *w, int cursor_on_p,
                     int mouse_face_overwritten_p)
 {
-  struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
+  Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (XFRAME (w->frame));
 
   if (!w->pseudo_window_p)
     {
@@ -622,9 +622,9 @@ x_update_window_end (struct window *w, int cursor_on_p,
      XTframe_up_to_date to redisplay the mouse highlight.  */
   if (mouse_face_overwritten_p)
     {
-      dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
-      dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
-      dpyinfo->mouse_face_window = Qnil;
+      hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
+      hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
+      hlinfo->mouse_face_window = Qnil;
     }
 
   /* Unhide the caret.  This won't actually show the cursor, unless it
@@ -649,7 +649,7 @@ x_update_end (struct frame *f)
     return;
 
   /* Mouse highlight may be displayed again.  */
-  FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
+  MOUSE_HL_INFO (f)->mouse_face_defer = 0;
 }
 
 
@@ -662,17 +662,17 @@ w32_frame_up_to_date (struct frame *f)
 {
   if (FRAME_W32_P (f))
     {
-      struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+      Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
 
-      if (dpyinfo->mouse_face_deferred_gc
-         || f == dpyinfo->mouse_face_mouse_frame)
+      if (hlinfo->mouse_face_deferred_gc
+         || f == hlinfo->mouse_face_mouse_frame)
        {
          BLOCK_INPUT;
-         if (dpyinfo->mouse_face_mouse_frame)
-           note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
-                                 dpyinfo->mouse_face_mouse_x,
-                                 dpyinfo->mouse_face_mouse_y);
-         dpyinfo->mouse_face_deferred_gc = 0;
+         if (hlinfo->mouse_face_mouse_frame)
+           note_mouse_highlight (hlinfo->mouse_face_mouse_frame,
+                                 hlinfo->mouse_face_mouse_x,
+                                 hlinfo->mouse_face_mouse_y);
+         hlinfo->mouse_face_deferred_gc = 0;
          UNBLOCK_INPUT;
        }
     }
@@ -894,7 +894,7 @@ w32_set_terminal_modes (struct terminal *term)
 {
 }
 
-/* This is called when exiting or suspending Emacs. Exiting will make
+/* This is called when exiting or suspending Emacs.  Exiting will make
    the W32 windows go away, and suspending requires no action. */
 
 static void
@@ -999,7 +999,7 @@ x_set_mouse_face_gc (struct glyph_string *s)
   struct face *face;
 
   /* What face has to be used last for the mouse face?  */
-  face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
+  face_id = MOUSE_HL_INFO (s->f)->mouse_face_face_id;
   face = FACE_FROM_ID (s->f, face_id);
   if (face == NULL)
     face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
@@ -1394,6 +1394,94 @@ x_draw_composite_glyph_string_foreground (struct glyph_string *s)
 }
 
 
+/* Draw the foreground of glyph string S for glyphless characters.  */
+
+static void
+x_draw_glyphless_glyph_string_foreground (struct glyph_string *s)
+{
+  struct glyph *glyph = s->first_glyph;
+  XChar2b char2b[8];
+  int x, i, j;
+  int with_background;
+
+  /* If first glyph of S has a left box line, start drawing the text
+     of S to the right of that box line.  */
+  if (s->face->box != FACE_NO_BOX
+      && s->first_glyph->left_box_line_p)
+    x = s->x + eabs (s->face->box_line_width);
+  else
+    x = s->x;
+
+  SetTextColor (s->hdc, s->gc->foreground);
+  SetBkColor (s->hdc, s->gc->background);
+  SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
+
+  s->char2b = char2b;
+  with_background = ! (s->for_overlaps
+                      || (s->background_filled_p && s->hl != DRAW_CURSOR));
+  for (i = 0; i < s->nchars; i++, glyph++)
+    {
+      char buf[7], *str = NULL;
+      int len = glyph->u.glyphless.len;
+
+      if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_ACRONYM)
+       {
+         if (len > 1
+             && CHAR_TABLE_P (Vglyphless_char_display)
+             && (CHAR_TABLE_EXTRA_SLOTS (XCHAR_TABLE (Vglyphless_char_display))
+                 >= 1))
+           {
+             Lisp_Object acronym
+               = (! glyph->u.glyphless.for_no_font
+                  ? CHAR_TABLE_REF (Vglyphless_char_display,
+                                    glyph->u.glyphless.ch)
+                  : XCHAR_TABLE (Vglyphless_char_display)->extras[0]);
+             if (STRINGP (acronym))
+               str = (char *) SDATA (acronym);
+           }
+       }
+      else if (glyph->u.glyphless.method == GLYPHLESS_DISPLAY_HEX_CODE)
+       {
+         sprintf ((char *) buf, "%0*X",
+                  glyph->u.glyphless.ch < 0x10000 ? 4 : 6,
+                  glyph->u.glyphless.ch);
+         str = buf;
+       }
+
+      if (glyph->u.glyphless.method != GLYPHLESS_DISPLAY_THIN_SPACE)
+       w32_draw_rectangle (s->hdc, s->gc,
+                           x, s->ybase - glyph->ascent,
+                           glyph->pixel_width - 1,
+                           glyph->ascent + glyph->descent - 1);
+      if (str)
+       {
+         struct font *font = s->font;
+         int upper_len = (len + 1) / 2;
+         unsigned code;
+         HFONT old_font;
+
+         old_font = SelectObject (s->hdc, FONT_HANDLE (font));
+         /* It is certain that all LEN characters in STR are ASCII.  */
+         for (j = 0; j < len; j++)
+           {
+             code = font->driver->encode_char (font, str[j]);
+             STORE_XCHAR2B (char2b + j, code >> 8, code & 0xFF);
+           }
+         font->driver->draw (s, 0, upper_len,
+                             x + glyph->slice.glyphless.upper_xoff,
+                             s->ybase + glyph->slice.glyphless.upper_yoff,
+                             with_background);
+         font->driver->draw (s, upper_len, len,
+                             x + glyph->slice.glyphless.lower_xoff,
+                             s->ybase + glyph->slice.glyphless.lower_yoff,
+                             with_background);
+         SelectObject (s->hdc, old_font);
+       }
+      x += glyph->pixel_width;
+   }
+}
+
+
 /* Brightness beyond which a color won't have its highlight brightness
    boosted.
 
@@ -2106,17 +2194,34 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
   if (s->hl == DRAW_CURSOR
       && !x_stretch_cursor_p)
     {
-      /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
-        as wide as the stretch glyph.  */
+      /* If `x-stretch-cursor' is nil, don't draw a block cursor as
+        wide as the stretch glyph.  */
       int width, background_width = s->background_width;
-      int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
+      int x = s->x;
 
-      if (x < left_x)
+      if (!s->row->reversed_p)
        {
-         background_width -= left_x - x;
-         x = left_x;
+         int left_x = window_box_left_offset (s->w, TEXT_AREA);
+
+         if (x < left_x)
+           {
+             background_width -= left_x - x;
+             x = left_x;
+           }
+       }
+      else
+       {
+         /* In R2L rows, draw the cursor on the right edge of the
+            stretch glyph.  */
+         int right_x = window_box_right_offset (s->w, TEXT_AREA);
+
+         if (x + background_width > right_x)
+           background_width -= x - right_x;
+         x += background_width;
        }
       width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
+      if (s->row->reversed_p)
+       x -= width;
 
       /* Draw cursor.  */
       x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
@@ -2130,7 +2235,10 @@ x_draw_stretch_glyph_string (struct glyph_string *s)
          RECT r;
           HDC hdc = s->hdc;
 
-         x += width;
+         if (!s->row->reversed_p)
+           x += width;
+         else
+           x = s->x;
          if (s->row->mouse_face_p
              && cursor_in_mouse_face_p (s->w))
            {
@@ -2262,6 +2370,14 @@ x_draw_glyph_string (struct glyph_string *s)
       x_draw_composite_glyph_string_foreground (s);
       break;
 
+    case GLYPHLESS_GLYPH:
+      if (s->for_overlaps)
+       s->background_filled_p = 1;
+      else
+       x_draw_glyph_string_background (s, 0);
+      x_draw_glyphless_glyph_string_foreground (s);
+      break;
+
     default:
       abort ();
     }
@@ -3935,7 +4051,7 @@ static char dbcs_lead = 0;
    recursively with different messages by the system.
 */
 
-int
+static int
 w32_read_socket (struct terminal *terminal, int expected,
                 struct input_event *hold_quit)
 {
@@ -3944,6 +4060,7 @@ w32_read_socket (struct terminal *terminal, int expected,
   W32Msg msg;
   struct frame *f;
   struct w32_display_info *dpyinfo = &one_w32_display_info;
+  Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
 
   if (interrupt_input_blocked)
     {
@@ -4044,11 +4161,11 @@ w32_read_socket (struct terminal *terminal, int expected,
 
          if (f && !f->iconified)
            {
-             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
-                 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
+             if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+                 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
                {
-                 clear_mouse_face (dpyinfo);
-                 dpyinfo->mouse_face_hidden = 1;
+                 clear_mouse_face (hlinfo);
+                 hlinfo->mouse_face_hidden = 1;
                }
 
              if (temp_index == sizeof temp_buffer / sizeof (short))
@@ -4069,11 +4186,11 @@ w32_read_socket (struct terminal *terminal, int expected,
 
          if (f && !f->iconified)
            {
-             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
-                 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
+             if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+                 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
                {
-                 clear_mouse_face (dpyinfo);
-                 dpyinfo->mouse_face_hidden = 1;
+                 clear_mouse_face (hlinfo);
+                 hlinfo->mouse_face_hidden = 1;
                }
 
              if (temp_index == sizeof temp_buffer / sizeof (short))
@@ -4147,11 +4264,11 @@ w32_read_socket (struct terminal *terminal, int expected,
 
          if (f && !f->iconified)
            {
-             if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
-                 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
+             if (!hlinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
+                 && !EQ (f->tool_bar_window, hlinfo->mouse_face_window))
                {
-                 clear_mouse_face (dpyinfo);
-                 dpyinfo->mouse_face_hidden = 1;
+                 clear_mouse_face (hlinfo);
+                 hlinfo->mouse_face_hidden = 1;
                }
 
              if (temp_index == sizeof temp_buffer / sizeof (short))
@@ -4185,10 +4302,10 @@ w32_read_socket (struct terminal *terminal, int expected,
          else
            f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
 
-         if (dpyinfo->mouse_face_hidden)
+         if (hlinfo->mouse_face_hidden)
            {
-             dpyinfo->mouse_face_hidden = 0;
-             clear_mouse_face (dpyinfo);
+             hlinfo->mouse_face_hidden = 0;
+             clear_mouse_face (hlinfo);
            }
 
          if (f)
@@ -4200,7 +4317,7 @@ w32_read_socket (struct terminal *terminal, int expected,
                  int x = LOWORD (msg.msg.lParam);
                  int y = HIWORD (msg.msg.lParam);
 
-                 window = window_from_coordinates (f, x, y, 0, 0, 0, 0);
+                 window = window_from_coordinates (f, x, y, 0, 0);
 
                  /* Window will be selected only when it is not
                     selected now and last mouse movement event was
@@ -4220,7 +4337,7 @@ w32_read_socket (struct terminal *terminal, int expected,
                      inev.frame_or_window = window;
                    }
 
-                 last_window=window;
+                 last_window = window;
                }
              if (!note_mouse_movement (f, &msg.msg))
                help_echo_string = previous_help_echo_string;
@@ -4229,7 +4346,7 @@ w32_read_socket (struct terminal *terminal, int expected,
             {
               /* If we move outside the frame, then we're
                  certainly no longer on any text in the frame.  */
-              clear_mouse_face (dpyinfo);
+              clear_mouse_face (hlinfo);
             }
 
           /* If the contents of the global variable help_echo_string
@@ -4279,7 +4396,7 @@ w32_read_socket (struct terminal *terminal, int expected,
                    int x = XFASTINT (inev.x);
                    int y = XFASTINT (inev.y);
 
-                    window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
+                    window = window_from_coordinates (f, x, y, 0, 1);
 
                     if (EQ (window, f->tool_bar_window))
                       {
@@ -4518,12 +4635,12 @@ w32_read_socket (struct terminal *terminal, int expected,
          f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
          if (f)
            {
-             if (f == dpyinfo->mouse_face_mouse_frame)
+             if (f == hlinfo->mouse_face_mouse_frame)
                {
                  /* If we move outside the frame, then we're
                     certainly no longer on any text in the frame.  */
-                 clear_mouse_face (dpyinfo);
-                 dpyinfo->mouse_face_mouse_frame = 0;
+                 clear_mouse_face (hlinfo);
+                 hlinfo->mouse_face_mouse_frame = 0;
                }
 
              /* Generate a nil HELP_EVENT to cancel a help-echo.
@@ -4553,12 +4670,12 @@ w32_read_socket (struct terminal *terminal, int expected,
               if (f == dpyinfo->w32_focus_frame)
                 x_new_focus_frame (dpyinfo, 0);
 
-              if (f == dpyinfo->mouse_face_mouse_frame)
+              if (f == hlinfo->mouse_face_mouse_frame)
                 {
                   /* If we move outside the frame, then we're
                      certainly no longer on any text in the frame.  */
-                  clear_mouse_face (dpyinfo);
-                  dpyinfo->mouse_face_mouse_frame = 0;
+                  clear_mouse_face (hlinfo);
+                  hlinfo->mouse_face_mouse_frame = 0;
                 }
 
               /* Generate a nil HELP_EVENT to cancel a help-echo.
@@ -4877,6 +4994,11 @@ x_draw_bar_cursor (struct window *w, struct glyph_row *row,
 
          w->phys_cursor_width = width;
 
+         /* If the character under cursor is R2L, draw the bar cursor
+            on the right of its glyph, rather than on the left.  */
+         if ((cursor_glyph->resolved_level & 1) != 0)
+           x += cursor_glyph->pixel_width - width;
+
          w32_fill_area (f, hdc, cursor_color, x,
                         WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
                         width, row->height);
@@ -5577,7 +5699,7 @@ x_make_frame_visible (struct frame *f)
          /* Adjust vertical window position in order to avoid being
             covered by a task bar placed at the bottom of the desktop. */
          SystemParametersInfo (SPI_GETWORKAREA, 0, &workarea_rect, 0);
-         GetWindowRect (FRAME_W32_WINDOW(f), &window_rect);
+         GetWindowRect (FRAME_W32_WINDOW (f), &window_rect);
          if (window_rect.bottom > workarea_rect.bottom
              && window_rect.top > workarea_rect.top)
            f->top_pos = max (window_rect.top
@@ -5701,6 +5823,7 @@ void
 x_free_frame_resources (struct frame *f)
 {
   struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
+  Mouse_HLInfo *hlinfo = MOUSE_HL_INFO (f);
 
   BLOCK_INPUT;
 
@@ -5739,15 +5862,15 @@ x_free_frame_resources (struct frame *f)
   if (f == dpyinfo->x_highlight_frame)
     dpyinfo->x_highlight_frame = 0;
 
-  if (f == dpyinfo->mouse_face_mouse_frame)
+  if (f == hlinfo->mouse_face_mouse_frame)
     {
-      dpyinfo->mouse_face_beg_row
-       = dpyinfo->mouse_face_beg_col = -1;
-      dpyinfo->mouse_face_end_row
-       = dpyinfo->mouse_face_end_col = -1;
-      dpyinfo->mouse_face_window = Qnil;
-      dpyinfo->mouse_face_deferred_gc = 0;
-      dpyinfo->mouse_face_mouse_frame = 0;
+      hlinfo->mouse_face_beg_row
+       = hlinfo->mouse_face_beg_col = -1;
+      hlinfo->mouse_face_end_row
+       = hlinfo->mouse_face_end_col = -1;
+      hlinfo->mouse_face_window = Qnil;
+      hlinfo->mouse_face_deferred_gc = 0;
+      hlinfo->mouse_face_mouse_frame = 0;
     }
 
   UNBLOCK_INPUT;
@@ -5813,6 +5936,7 @@ void
 w32_initialize_display_info (Lisp_Object display_name)
 {
   struct w32_display_info *dpyinfo = &one_w32_display_info;
+  Mouse_HLInfo *hlinfo = &dpyinfo->mouse_highlight;
 
   memset (dpyinfo, 0, sizeof (*dpyinfo));
 
@@ -5838,12 +5962,12 @@ w32_initialize_display_info (Lisp_Object display_name)
   dpyinfo->smallest_font_height = 1;
   dpyinfo->smallest_char_width = 1;
 
-  dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
-  dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
-  dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
-  dpyinfo->mouse_face_window = Qnil;
-  dpyinfo->mouse_face_overlay = Qnil;
-  dpyinfo->mouse_face_hidden = 0;
+  hlinfo->mouse_face_beg_row = hlinfo->mouse_face_beg_col = -1;
+  hlinfo->mouse_face_end_row = hlinfo->mouse_face_end_col = -1;
+  hlinfo->mouse_face_face_id = DEFAULT_FACE_ID;
+  hlinfo->mouse_face_window = Qnil;
+  hlinfo->mouse_face_overlay = Qnil;
+  hlinfo->mouse_face_hidden = 0;
 
   dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
   /* TODO: dpyinfo->gray */
@@ -6312,7 +6436,9 @@ the cursor have no effect.  */);
      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 = 0;
 
   DEFVAR_BOOL ("x-underline-at-descent-line",
@@ -6324,12 +6450,14 @@ baseline level.  The default value is nil.  */);
   x_underline_at_descent_line = 0;
 
   DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
-              doc: /* If not nil, Emacs uses toolkit scroll bars.  */);
+              doc: /* Which toolkit scroll bars Emacs uses, if any.
+A value of nil means Emacs doesn't use toolkit scroll bars.
+With the X Window system, the value is a symbol describing the
+X toolkit.  Possible values are: gtk, motif, xaw, or xaw3d.
+With MS Windows, the value is t.  */);
   Vx_toolkit_scroll_bars = Qt;
 
   staticpro (&last_mouse_motion_frame);
   last_mouse_motion_frame = Qnil;
 }
 
-/* arch-tag: 5fa70624-ab86-499c-8a85-473958ee4646
-   (do not change this comment) */