]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix -nw sessions on MS-Windows
authorEli Zaretskii <eliz@gnu.org>
Mon, 3 Feb 2025 16:36:11 +0000 (18:36 +0200)
committerEshel Yaron <me@eshelyaron.com>
Sun, 9 Feb 2025 08:00:46 +0000 (09:00 +0100)
* src/w32console.c (w32con_clear_end_of_line): Set the space
glyphs' frame to NULL.
(w32con_write_glyphs): Handle face_id_frame == NULL, when called
from 'w32con_clear_end_of_line'.
(tty_draw_row_with_mouse_face): Adjust to changes in term.c.

(cherry picked from commit a22e971a119dfd1385fe38d6f594bccfe8911152)

src/w32console.c

index 9cfedde3b3f8adf451544e98d03d31c58bd0af64..b18eda437adcbc9d7366f6e09df187a49ad2eec6 100644 (file)
@@ -167,7 +167,7 @@ w32con_clear_end_of_line (struct frame *f, int end)
       for (i = 0; i < glyphs_len; i++)
         {
          memcpy (&glyphs[i], &space_glyph, sizeof (struct glyph));
-         glyphs[i].frame = f;
+         glyphs[i].frame = NULL;
         }
       ceol_initialized = TRUE;
     }
@@ -339,8 +339,10 @@ w32con_write_glyphs (struct frame *f, register struct glyph *string,
              && string[n].frame == face_id_frame))
          break;
 
+      /* w32con_clear_end_of_line sets frame of glyphs to NULL.  */
+      struct frame *attr_frame = face_id_frame ? face_id_frame : f;
       /* Turn appearance modes of the face of the run on.  */
-      char_attr = w32_face_attributes (face_id_frame, face_id);
+      char_attr = w32_face_attributes (attr_frame, face_id);
 
       if (n == len)
        /* This is the last run.  */
@@ -425,34 +427,88 @@ w32con_write_glyphs_with_face (struct frame *f, register int x, register int y,
 
 /* Implementation of draw_row_with_mouse_face for W32 console.  */
 void
-tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
-                             int start_hpos, int end_hpos,
+tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *window_row,
+                             int window_start_x, int window_end_x,
                              enum draw_glyphs_face draw)
 {
-  int nglyphs = end_hpos - start_hpos;
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  struct tty_display_info *tty = FRAME_TTY (f);
-  int face_id = tty->mouse_highlight.mouse_face_face_id;
-  int pos_x, pos_y;
-
-  if (end_hpos >= row->used[TEXT_AREA])
-    nglyphs = row->used[TEXT_AREA] - start_hpos;
-
-  pos_y = row->y + WINDOW_TOP_EDGE_Y (w);
-  pos_x = row->used[LEFT_MARGIN_AREA] + start_hpos + WINDOW_LEFT_EDGE_X (w);
-
-  if (draw == DRAW_MOUSE_FACE)
-    w32con_write_glyphs_with_face (f, pos_x, pos_y,
-                                  row->glyphs[TEXT_AREA] + start_hpos,
-                                  nglyphs, face_id);
-  else if (draw == DRAW_NORMAL_TEXT)
+  struct frame *root = root_frame (f);
+
+  /* Window coordinates are relative to the text area.  Make
+     them relative to the window's left edge,  */
+  window_end_x = min (window_end_x, window_row->used[TEXT_AREA]);
+  window_start_x += window_row->used[LEFT_MARGIN_AREA];
+  window_end_x += window_row->used[LEFT_MARGIN_AREA];
+
+  /* Translate from window to window's frame.  */
+  int frame_start_x = WINDOW_LEFT_EDGE_X (w) + window_start_x;
+  int frame_end_x = WINDOW_LEFT_EDGE_X (w) + window_end_x;
+  int frame_y = window_row->y + WINDOW_TOP_EDGE_Y (w);
+
+  /* Translate from (possible) child frame to root frame.  */
+  int root_start_x, root_end_x, root_y;
+  root_xy (f, frame_start_x, frame_y, &root_start_x, &root_y);
+  root_xy (f, frame_end_x, frame_y, &root_end_x, &root_y);
+  struct glyph_row *root_row = MATRIX_ROW (root->current_matrix, root_y);
+
+  /* Remember current cursor coordinates so that we can restore
+     them at the end.  */
+  COORD save_coords = cursor_coords;
+
+  /* If the root frame displays child frames, we cannot naively
+     write to the terminal what the window thinks should be drawn.
+     Instead, write only those parts that are not obscured by
+     other frames.  */
+  for (int root_x = root_start_x; root_x < root_end_x; )
     {
-      COORD save_coords = cursor_coords;
+      /* Find the start of a run of glyphs from frame F.  */
+      struct glyph *root_start = root_row->glyphs[TEXT_AREA] + root_x;
+      while (root_x < root_end_x && root_start->frame != f)
+       ++root_x, ++root_start;
+
+      /* If start of a run of glyphs from F found.  */
+      int root_run_start_x = root_x;
+      if (root_run_start_x < root_end_x)
+       {
+         /* Find the end of the run of glyphs from frame F.  */
+         struct glyph *root_end = root_start;
+         while (root_x < root_end_x && root_end->frame == f)
+           ++root_x, ++root_end;
 
-      w32con_move_cursor (f, pos_y, pos_x);
-      write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
-      w32con_move_cursor (f, save_coords.Y, save_coords.X);
+         /* If we have a run glyphs to output, do it.  */
+         if (root_end > root_start)
+           {
+             w32con_move_cursor (root, root_y, root_run_start_x);
+
+             ptrdiff_t nglyphs = root_end - root_start;
+             switch (draw)
+               {
+               case DRAW_NORMAL_TEXT:
+                 write_glyphs (f, root_start, nglyphs);
+                 break;
+
+               case DRAW_MOUSE_FACE:
+                 {
+                   struct tty_display_info *tty = FRAME_TTY (f);
+                   int face_id = tty->mouse_highlight.mouse_face_face_id;
+                   w32con_write_glyphs_with_face (f, root_run_start_x, root_y,
+                                                  root_start, nglyphs,
+                                                  face_id);
+                 }
+                 break;
+
+               case DRAW_INVERSE_VIDEO:
+               case DRAW_CURSOR:
+               case DRAW_IMAGE_RAISED:
+               case DRAW_IMAGE_SUNKEN:
+                 emacs_abort ();
+               }
+           }
+       }
     }
+
+  /* Restore cursor where it was before.  */
+  w32con_move_cursor (f, save_coords.Y, save_coords.X);
 }
 
 static void