]> git.eshelyaron.com Git - emacs.git/commitdiff
Enable TTY child frames on MS-DOS
authorPo Lu <luangruo@yahoo.com>
Fri, 20 Dec 2024 03:12:22 +0000 (11:12 +0800)
committerEshel Yaron <me@eshelyaron.com>
Mon, 23 Dec 2024 15:17:30 +0000 (16:17 +0100)
* src/conf_post.h (ENOTSUP): Define to ENOSYS as msdos.h once
did.
(IFTODT): Copy definition from Gnulib.

* src/dispnew.c (is_tty_frame): Also test FRAME_MSDOS_P.

* src/frame.c (tty_child_pos_param, tty_child_size_param):
Export functions.

* src/msdos.c (mouse_get_xy, mouse_moveto, mouse_pressed):
Offset mouse positions by those of the selected frame.
(it_face_override): New function.
(IT_set_face): New argument F.  Load FACE_ID from its face
cache.
(IT_write_glyphs): Track the frames on which glyphs were
generated and apply faces from their individual face caches.
(IT_write_glyphs_with_face): New function.
(tty_draw_row_with_mouse_face): Reimplement in line with tty.c
and eliminate an obsolete optimization.
(IT_clear_end_of_line, IT_clear_screen): Load faces from the
cache of the provided frame.
(IT_set_frame_parameters): Adjust frame geometry and garbage
frames after geometry parameters change as a child frame.
(BUILD_CHAR_GLYPH): Accept new parameter F.
(IT_menu_display): Offset cursor positions by those of the
selected frame.

* src/msdos.h (ENOTSUP): Move to conf_post.h for Gnulib.

* src/xdisp.c (redisplay_internal): Redisplay MSDOS frames
unconditionally as with terminal frames.

(cherry picked from commit cc5afea98e8efb1a04baedf98e66863d31974ae6)

src/conf_post.h
src/dispnew.c
src/frame.c
src/frame.h
src/msdos.c
src/msdos.h
src/xdisp.c

index e68d5a56d9b14c049bc3420c35c2cee64fc9ae69..9d3f5711beff0d580ba4f51e1a503babb1c6b761 100644 (file)
@@ -480,5 +480,10 @@ extern int emacs_setenv_TZ (char const *);
 /* These are required by file-has-acl.c but defined in dirent.h and
    errno.h, which are not generated on DOS.  */
 #define _GL_DT_NOTDIR 0x100   /* Not a directory */
-#define ENOTSUP 2007
+#define ENOTSUP ENOSYS
+# define IFTODT(mode) \
+   (S_ISREG (mode) ? DT_REG : S_ISDIR (mode) ? DT_DIR \
+    : S_ISLNK (mode) ? DT_LNK : S_ISBLK (mode) ? DT_BLK \
+    : S_ISCHR (mode) ? DT_CHR : S_ISFIFO (mode) ? DT_FIFO \
+    : S_ISSOCK (mode) ? DT_SOCK : DT_UNKNOWN)
 #endif /* MSDOS */
index 3c4b20c23b766a629fde0b9d7c9304a5bc9b6a2e..33caa6aca88b9b0641e5c5eed2a595a487e4e150 100644 (file)
@@ -3465,7 +3465,7 @@ tty_raise_lower_frame (struct frame *f, bool raise)
 bool
 is_tty_frame (struct frame *f)
 {
-  return FRAME_TERMCAP_P (f);
+  return FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f);
 }
 
 /* Return true if frame F is a tty child frame.  */
index 8423836a80f8e465919a46603ad29cbcf71020db..d66723e78b8373859ef6698753efdd4b9d01eedc 100644 (file)
@@ -1390,7 +1390,7 @@ get_future_frame_param (Lisp_Object parameter,
 
 #endif
 
-static int
+int
 tty_child_pos_param (struct frame *child, Lisp_Object key,
                     Lisp_Object params, int dflt)
 {
@@ -1404,7 +1404,7 @@ tty_child_pos_param (struct frame *child, Lisp_Object key,
   return dflt;
 }
 
-static int
+int
 tty_child_size_param (struct frame *child, Lisp_Object key,
                      Lisp_Object params, int dflt)
 {
index cb03d5550bbd4abab5f88588b52a5bdabec0a373..9ed2f66be2218ae7cc78859d081848c0129e1da3 100644 (file)
@@ -1490,6 +1490,10 @@ extern struct frame *decode_live_frame (Lisp_Object);
 extern struct frame *decode_any_frame (Lisp_Object);
 extern struct frame *make_initial_frame (void);
 extern struct frame *make_frame (bool);
+extern int tty_child_pos_param (struct frame *, Lisp_Object,
+                               Lisp_Object, int);
+extern int tty_child_size_param (struct frame *, Lisp_Object,
+                                Lisp_Object, int);
 #ifdef HAVE_WINDOW_SYSTEM
 extern bool display_available (void);
 #endif
index 42eee89d748542f3d34240550c575cf55cda2692..78f53d5511c5be63f32eb8074c136f52e3c4a18d 100644 (file)
@@ -237,11 +237,12 @@ static void
 mouse_get_xy (int *x, int *y)
 {
   union REGS regs;
+  struct frame *f = SELECTED_FRAME ();
 
   regs.x.ax = 0x0003;
   int86 (0x33, &regs, &regs);
-  *x = regs.x.cx / 8;
-  *y = regs.x.dx / 8;
+  *x = (regs.x.cx / 8) - f->left_pos;
+  *y = (regs.x.dx / 8) - f->top_pos;
 }
 
 void
@@ -249,12 +250,15 @@ mouse_moveto (int x, int y)
 {
   union REGS regs;
   struct tty_display_info *tty = CURTTY ();
+  struct frame *f = SELECTED_FRAME ();
 
   if (tty->termscript)
     fprintf (tty->termscript, "<M_XY=%dx%d>", x, y);
   regs.x.ax = 0x0004;
   mouse_last_x = regs.x.cx = x * 8;
   mouse_last_y = regs.x.dx = y * 8;
+  regs.x.cx += f->left_pos * 8;
+  regs.x.dx += f->top_pos * 8;
   int86 (0x33, &regs, &regs);
 }
 
@@ -262,6 +266,7 @@ static int
 mouse_pressed (int b, int *xp, int *yp)
 {
   union REGS regs;
+  struct frame *f = SELECTED_FRAME ();
 
   if (b >= mouse_button_count)
     return 0;
@@ -269,7 +274,10 @@ mouse_pressed (int b, int *xp, int *yp)
   regs.x.bx = mouse_button_translate[b];
   int86 (0x33, &regs, &regs);
   if (regs.x.bx)
-    *xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
+    {
+      *xp = regs.x.cx / 8 - f->left_pos;
+      *yp = regs.x.dx / 8 - f->top_pos;
+    }
   return (regs.x.bx != 0);
 }
 
@@ -789,19 +797,23 @@ IT_ring_bell (struct frame *f)
     }
 }
 
+/* If otherwise than -1, a face ID that will override the FACE argument
+   to IT_set_face.  */
+static int it_face_override = -1;
+
 /* Given a face id FACE, extract the face parameters to be used for
    display until the face changes.  The face parameters (actually, its
    color) are used to construct the video attribute byte for each
    glyph during the construction of the buffer that is then blitted to
    the video RAM.  */
 static void
-IT_set_face (int face)
+IT_set_face (struct frame *f, int face_id)
 {
-  struct frame *sf = SELECTED_FRAME ();
-  struct face *fp  = FACE_FROM_ID_OR_NULL (sf, face);
-  struct face *dfp = FACE_FROM_ID_OR_NULL (sf, DEFAULT_FACE_ID);
+  int face = (it_face_override == -1 ? face_id : it_face_override);
+  struct face *fp  = FACE_FROM_ID_OR_NULL (f, face);
+  struct face *dfp = FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID);
   unsigned long fg, bg, dflt_fg, dflt_bg;
-  struct tty_display_info *tty = FRAME_TTY (sf);
+  struct tty_display_info *tty = FRAME_TTY (f);
 
   if (!fp)
     {
@@ -822,13 +834,13 @@ IT_set_face (int face)
      16 colors to be available for the background, since Emacs switches
      on this mode (and loses the blinking attribute) at startup.  */
   if (fg == FACE_TTY_DEFAULT_COLOR || fg == FACE_TTY_DEFAULT_FG_COLOR)
-    fg = FRAME_FOREGROUND_PIXEL (sf);
+    fg = FRAME_FOREGROUND_PIXEL (f);
   else if (fg == FACE_TTY_DEFAULT_BG_COLOR)
-    fg = FRAME_BACKGROUND_PIXEL (sf);
+    fg = FRAME_BACKGROUND_PIXEL (f);
   if (bg == FACE_TTY_DEFAULT_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR)
-    bg = FRAME_BACKGROUND_PIXEL (sf);
+    bg = FRAME_BACKGROUND_PIXEL (f);
   else if (bg == FACE_TTY_DEFAULT_FG_COLOR)
-    bg = FRAME_FOREGROUND_PIXEL (sf);
+    bg = FRAME_FOREGROUND_PIXEL (f);
 
   /* Make sure highlighted lines really stand out, come what may.  */
   if (fp->tty_reverse_p && (fg == dflt_fg && bg == dflt_bg))
@@ -876,8 +888,8 @@ IT_write_glyphs (struct frame *f, struct glyph *str, int str_len)
   int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
   register int sl = str_len;
   struct tty_display_info *tty = FRAME_TTY (f);
-  struct frame *sf;
   unsigned char *conversion_buffer;
+  struct frame *cf_frame = f;
 
   /* If terminal_coding does any conversion, use it, otherwise use
      safe_terminal_coding.  We can't use CODING_REQUIRE_ENCODING here
@@ -889,14 +901,12 @@ IT_write_glyphs (struct frame *f, struct glyph *str, int str_len)
 
   if (str_len <= 0) return;
 
-  sf = SELECTED_FRAME ();
-
   /* Since faces get cached and uncached behind our back, we can't
      rely on their indices in the cache being consistent across
      invocations.  So always reset the screen face to the default
      face of the frame, before writing glyphs, and let the glyphs
      set the right face if it's different from the default.  */
-  IT_set_face (DEFAULT_FACE_ID);
+  IT_set_face (f, DEFAULT_FACE_ID);
 
   /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
      the tail.  */
@@ -910,8 +920,10 @@ IT_write_glyphs (struct frame *f, struct glyph *str, int str_len)
       /* If the face of this glyph is different from the current
         screen face, update the screen attribute byte.  */
       cf = str->face_id;
-      if (cf != screen_face)
-       IT_set_face (cf);       /* handles invalid faces gracefully */
+      if ((cf != screen_face && cf != it_face_override)
+         || cf_frame != str->frame)
+       IT_set_face (str->frame, cf);   /* handles invalid faces gracefully */
+      cf_frame = str->frame;
 
       /* Identify a run of glyphs with the same face.  */
       for (n = 1; n < sl; ++n)
@@ -964,6 +976,18 @@ popup_activated (void)
   return mouse_preempted;
 }
 
+/* Write a string of glyphs STRING of length LEN to F, disregarding
+   their invidiual faces in favor of FACE.  */
+
+static void
+IT_write_glyphs_with_face (struct frame *f, struct glyph *string,
+                          int len, int face_id)
+{
+  it_face_override = face_id;
+  IT_write_glyphs (f, string, len);
+  it_face_override = -1;
+}
+
 /* Draw TEXT_AREA glyphs between START and END of glyph row ROW on
    window W.  X is relative to TEXT_AREA in W.  HL is a face override
    for drawing the glyphs.  */
@@ -975,70 +999,38 @@ tty_draw_row_with_mouse_face (struct window *w, struct glyph_row *row,
   struct frame *f = XFRAME (WINDOW_FRAME (w));
   struct tty_display_info *tty = FRAME_TTY (f);
   Mouse_HLInfo *hlinfo = &tty->mouse_highlight;
+  int nglyphs = end_hpos - start_hpos;
+  int pos_y, pos_x, save_y, save_x;
 
-  if (hl == DRAW_MOUSE_FACE)
-    {
-      int vpos = row->y + WINDOW_TOP_EDGE_Y (w);
-      int kstart = (start_hpos + WINDOW_LEFT_EDGE_X (w)
-                   + row->used[LEFT_MARGIN_AREA]);
-      int nglyphs = end_hpos - start_hpos;
-      int offset = ScreenPrimary + 2*(vpos*screen_size_X + kstart) + 1;
-      int start_offset = offset;
+  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 (end_hpos >= row->used[TEXT_AREA])
-       nglyphs = row->used[TEXT_AREA] - start_hpos;
+  /* Save current cursor position.  */
+  save_x = f->left_pos + new_pos_X;
+  save_y = f->top_pos + new_pos_Y;
 
-      if (tty->termscript)
-       fprintf (tty->termscript, "\n<MH+ %d-%d:%d>",
-                kstart, kstart + nglyphs - 1, vpos);
+  /* This applies child frame offsets.  */
+  cursor_to (f, pos_y, pos_x);
+  mouse_off ();
 
-      mouse_off ();
-      IT_set_face (hlinfo->mouse_face_face_id);
-      /* Since we are going to change only the _colors_ of already
-        displayed text, there's no need to go through all the pain of
-        generating and encoding the text from the glyphs.  Instead,
-        we simply poke the attribute byte of each affected position
-        in video memory with the colors computed by IT_set_face!  */
-      _farsetsel (_dos_ds);
-      while (nglyphs--)
-       {
-         _farnspokeb (offset, ScreenAttrib);
-         offset += 2;
-       }
-      if (screen_virtual_segment)
-       dosv_refresh_virtual_screen (start_offset, end_hpos - start_hpos);
-      mouse_on ();
-    }
-  else if (hl == DRAW_NORMAL_TEXT)
-    {
-      /* We are removing a previously-drawn mouse highlight.  The
-        safest way to do so is to redraw the glyphs anew, since all
-        kinds of faces and display tables could have changed behind
-        our back.  */
-      int nglyphs = end_hpos - start_hpos;
-      int save_x = new_pos_X, save_y = new_pos_Y;
-
-      if (end_hpos >= row->used[TEXT_AREA])
-       nglyphs = row->used[TEXT_AREA] - start_hpos;
-
-      /* IT_write_glyphs writes at cursor position, so we need to
-        temporarily move cursor coordinates to the beginning of
-        the highlight region.  */
-      new_pos_X = start_hpos + WINDOW_LEFT_EDGE_X (w);
-      /* The coordinates supplied by the caller are relative to the
-        text area, not the window itself.  */
-      new_pos_X += row->used[LEFT_MARGIN_AREA];
-      new_pos_Y = row->y + WINDOW_TOP_EDGE_Y (w);
+  /* Write the glyphs and restore cursor position.  */
 
-      if (tty->termscript)
-       fprintf (tty->termscript, "<MH- %d-%d:%d>",
-                new_pos_X, new_pos_X + nglyphs - 1, new_pos_Y);
-      IT_write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
-      if (tty->termscript)
-       fputs ("\n", tty->termscript);
-      new_pos_X = save_x;
-      new_pos_Y = save_y;
+  if (hl == DRAW_MOUSE_FACE)
+    {
+      struct glyph *glyph = row->glyphs[TEXT_AREA] + start_hpos;
+      int face_id = tty->mouse_highlight.mouse_face_face_id;
+      IT_write_glyphs_with_face (f, glyph, nglyphs, face_id);
     }
+  else
+    IT_write_glyphs (f, row->glyphs[TEXT_AREA] + start_hpos,
+                    nglyphs);
+
+  mouse_on ();
+  new_pos_X = save_x;
+  new_pos_Y = save_y;
 }
 
 static void
@@ -1051,7 +1043,7 @@ IT_clear_end_of_line (struct frame *f, int first_unused)
   if (new_pos_X >= first_unused || fatal_error_in_progress)
     return;
 
-  IT_set_face (0);
+  IT_set_face (f, 0);
   i = (j = first_unused - new_pos_X) * 2;
   if (tty->termscript)
     fprintf (tty->termscript, "<CLR:EOL[%d..%d)>", new_pos_X, first_unused);
@@ -1086,10 +1078,10 @@ IT_clear_screen (struct frame *f)
      any valid faces and will abort.  Instead, use the initial screen
      colors; that should mimic what a Unix tty does, which simply clears
      the screen with whatever default colors are in use.  */
-  if (FACE_FROM_ID_OR_NULL (SELECTED_FRAME (), DEFAULT_FACE_ID) == NULL)
+  if (FACE_FROM_ID_OR_NULL (f, DEFAULT_FACE_ID) == NULL)
     ScreenAttrib = (initial_screen_colors[0] << 4) | initial_screen_colors[1];
   else
-    IT_set_face (0);
+    IT_set_face (f, 0);
   mouse_off ();
   ScreenClear ();
   if (screen_virtual_segment)
@@ -1720,6 +1712,33 @@ IT_set_frame_parameters (struct frame *f, Lisp_Object alist)
       store_frame_param (f, prop, val);
     }
 
+  /* If this frame has become a child frame, process its visibility and
+     a nuumber of other flags.  */
+  if (is_tty_child_frame (f))
+    {
+      int x = tty_child_pos_param (f, Qleft, alist, f->left_pos);
+      int y = tty_child_pos_param (f, Qtop, alist, f->top_pos);
+      if (x != f->left_pos || y != f->top_pos)
+       {
+         f->left_pos = x;
+         f->top_pos = y;
+         SET_FRAME_GARBAGED (root_frame (f));
+       }
+
+      int w = tty_child_size_param (f, Qwidth, alist, f->total_cols);
+      int h = tty_child_size_param (f, Qheight, alist, f->total_lines);
+      if (w != f->total_cols || h != f->total_lines)
+       change_frame_size (f, w, h, false, false, false);
+
+      Lisp_Object visible = Fassq (Qvisibility, alist);
+      if (CONSP (visible))
+       SET_FRAME_VISIBLE (f, !NILP (Fcdr (visible)));
+
+      Lisp_Object no_special = Fassq (Qno_special_glyphs, alist);
+      if (CONSP (no_special))
+       FRAME_NO_SPECIAL_GLYPHS (f) = !NILP (Fcdr (no_special));
+    }
+
   /* If they specified "reverse", but not the colors, we need to swap
      the current frame colors.  */
   if (reverse)
@@ -2861,13 +2880,13 @@ IT_menu_calc_size (XMenu *menu, int *width, int *height)
 
 /* Display MENU at (X,Y) using FACES.  */
 
-#define BUILD_CHAR_GLYPH(GLYPH, CODE, FACE_ID, PADDING_P)  \
-  do                                                      \
-    {                                                     \
-      (GLYPH).type = CHAR_GLYPH;                          \
-      SET_CHAR_GLYPH (GLYPH, CODE, FACE_ID, PADDING_P);           \
-      (GLYPH).charpos = -1;                               \
-    }                                                     \
+#define BUILD_CHAR_GLYPH(F, GLYPH, CODE, FACE_ID, PADDING_P)   \
+  do                                                           \
+    {                                                          \
+      (GLYPH).type = CHAR_GLYPH;                               \
+      SET_CHAR_GLYPH (F, GLYPH, CODE, FACE_ID, PADDING_P);     \
+      (GLYPH).charpos = -1;                                    \
+    }                                                          \
   while (0)
 
 static void
@@ -2891,7 +2910,7 @@ IT_menu_display (XMenu *menu, int y, int x, int pn, int *faces, int disp_help)
     {
       int max_width = width + 2;
 
-      IT_cursor_to (sf, y + i, x);
+      cursor_to (sf, y + i, x);
       enabled
        = (!menu->submenu[i] && menu->panenumber[i]) || (menu->submenu[i]);
       mousehere = (y + i == my && x <= mx && mx < x + max_width);
@@ -2905,7 +2924,7 @@ IT_menu_display (XMenu *menu, int y, int x, int pn, int *faces, int disp_help)
          menu_help_itemno = i;
        }
       p = text;
-      BUILD_CHAR_GLYPH (*p, ' ', face, 0);
+      BUILD_CHAR_GLYPH (sf, *p, ' ', face, 0);
       p++;
       for (j = 0, q = menu->text[i]; *q; j++)
        {
@@ -2913,15 +2932,15 @@ IT_menu_display (XMenu *menu, int y, int x, int pn, int *faces, int disp_help)
 
          if (c > 26)
            {
-             BUILD_CHAR_GLYPH (*p, c, face, 0);
+             BUILD_CHAR_GLYPH (sf, *p, c, face, 0);
              p++;
            }
          else  /* make '^x' */
            {
-             BUILD_CHAR_GLYPH (*p, '^', face, 0);
+             BUILD_CHAR_GLYPH (sf, *p, '^', face, 0);
              p++;
              j++;
-             BUILD_CHAR_GLYPH (*p, c + 64, face, 0);
+             BUILD_CHAR_GLYPH (sf, *p, c + 64, face, 0);
              p++;
            }
        }
@@ -2932,16 +2951,16 @@ IT_menu_display (XMenu *menu, int y, int x, int pn, int *faces, int disp_help)
          text[max_width - 1].u.ch = '$'; /* indicate it's truncated */
        }
       for (; j < max_width - 2; j++, p++)
-       BUILD_CHAR_GLYPH (*p, ' ', face, 0);
+       BUILD_CHAR_GLYPH (sf, *p, ' ', face, 0);
 
       /* 16 is the character code of a character that on DOS terminal
         produces a nice-looking right-pointing arrow glyph.  */
-      BUILD_CHAR_GLYPH (*p, menu->submenu[i] ? 16 : ' ', face, 0);
+      BUILD_CHAR_GLYPH (sf, *p, menu->submenu[i] ? 16 : ' ', face, 0);
       p++;
       IT_write_glyphs (sf, text, max_width);
     }
   IT_update_end (sf);
-  IT_cursor_to (sf, row, col);
+  cursor_to (sf, row, col);
   xfree (text);
 }
 \f
index b245d9ea761051b02d3a81290dc27500f8808017..ad19e4c89c61263dc28f1748b8b639e5ef355e7b 100644 (file)
@@ -78,7 +78,6 @@ void syms_of_win16select (void);
 
 /* Constants.  */
 #define EINPROGRESS 112
-#define ENOTSUP     ENOSYS
 /* Gnulib sets O_CLOEXEC to O_NOINHERIT, which gets in the way when we
    need to redirect standard handles for subprocesses using temporary
    files created by mkostemp, see callproc.c.  */
index 013fd543ff20b548e9c3c8afed981fcd643629f9..50d6ced5f8ee14fbd1075997f07a54072fb8bc38 100644 (file)
@@ -17460,7 +17460,8 @@ redisplay_internal (void)
            }
 
        retry_frame:
-         if (FRAME_WINDOW_P (f) || FRAME_TERMCAP_P (f) || f == sf)
+         if (FRAME_WINDOW_P (f)
+             || FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f) || f == sf)
            {
              /* Only GC scrollbars when we redisplay the whole frame.  */
              bool gcscrollbars = f->redisplay || !REDISPLAY_SOME_P ();