[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
master cc5afea98e8 1/2: Enable TTY child frames on MS-DOS
From: |
Po Lu |
Subject: |
master cc5afea98e8 1/2: Enable TTY child frames on MS-DOS |
Date: |
Thu, 19 Dec 2024 22:23:21 -0500 (EST) |
branch: master
commit cc5afea98e8efb1a04baedf98e66863d31974ae6
Author: Po Lu <luangruo@yahoo.com>
Commit: Po Lu <luangruo@yahoo.com>
Enable TTY child frames on MS-DOS
* 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.
---
src/conf_post.h | 7 +-
src/dispnew.c | 2 +-
src/frame.c | 4 +-
src/frame.h | 4 ++
src/msdos.c | 207 +++++++++++++++++++++++++++++++-------------------------
src/msdos.h | 1 -
src/xdisp.c | 3 +-
7 files changed, 128 insertions(+), 100 deletions(-)
diff --git a/src/conf_post.h b/src/conf_post.h
index e68d5a56d9b..9d3f5711bef 100644
--- a/src/conf_post.h
+++ b/src/conf_post.h
@@ -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 */
diff --git a/src/dispnew.c b/src/dispnew.c
index 2e95016b5f3..180bc173f31 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -3468,7 +3468,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. */
diff --git a/src/frame.c b/src/frame.c
index 5518201fca7..250e7e53dd4 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -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)
{
diff --git a/src/frame.h b/src/frame.h
index cb03d5550bb..9ed2f66be22 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -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
diff --git a/src/msdos.c b/src/msdos.c
index 42eee89d748..78f53d5511c 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -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, ®s, ®s);
- *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, ®s, ®s);
}
@@ -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, ®s, ®s);
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);
}
diff --git a/src/msdos.h b/src/msdos.h
index b245d9ea761..ad19e4c89c6 100644
--- a/src/msdos.h
+++ b/src/msdos.h
@@ -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. */
diff --git a/src/xdisp.c b/src/xdisp.c
index 08016a6e2a5..91db3a87aae 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -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 ();