/* Updating of data structures for redisplay.
- Copyright (C) 1985, 86, 87, 88, 93, 94, 95, 97, 98, 1999, 2000, 2001, 2002
+ Copyright (C) 1985,86,87,88,93,94,95,97,98,1999,2000,01,02,2003
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#endif
#include "lisp.h"
+#include "systty.h" /* For emacs_tty in termchar.h */
#include "termchar.h"
#include "termopts.h"
#include "termhooks.h"
struct frame *last_nonminibuf_frame;
-/* Stdio stream being used for copy of all output. */
-
-FILE *termscript;
-
-/* Structure for info on cursor positioning. */
-
-struct cm Wcm;
-
/* 1 means SIGWINCH happened when not safe. */
int delayed_size_change;
int left = -1, right = -1;
int window_width = -1, window_height;
- /* See if W had a header line that has disappeared now, or vice versa. */
+ /* See if W had a header line that has disappeared now, or vice versa.
+ Get W's size. */
if (w)
{
+ window_box (w, -1, 0, 0, &window_width, &window_height);
+
header_line_p = WINDOW_WANTS_HEADER_LINE_P (w);
header_line_changed_p = header_line_p != matrix->header_line_p;
}
matrix->header_line_p = header_line_p;
- /* Do nothing if MATRIX' size, position, vscroll, and marginal areas
+ /* If POOL is null, MATRIX is a window matrix for window-based redisplay.
+ Do nothing if MATRIX' size, position, vscroll, and marginal areas
haven't changed. This optimization is important because preserving
the matrix means preventing redisplay. */
if (matrix->pool == NULL)
{
- window_box (w, -1, 0, 0, &window_width, &window_height);
left = margin_glyphs_to_reserve (w, dim.width, w->left_margin_cols);
right = margin_glyphs_to_reserve (w, dim.width, w->right_margin_cols);
xassert (left >= 0 && right >= 0);
else
{
/* If MATRIX->pool is null, MATRIX is responsible for managing
- its own memory. Allocate glyph memory from the heap. */
+ its own memory. It is a window matrix for window-based redisplay.
+ Allocate glyph memory from the heap. */
if (dim.width > matrix->matrix_w
|| new_rows
|| header_line_changed_p
{
int c = glyph->u.ch;
int face_id = glyph->face_id;
- if (must_write_spaces)
+ if (TTY_MUST_WRITE_SPACES (CURTTY ()))
c -= SPACEGLYPH;
hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + c;
hash = (((hash << 4) + (hash >> 24)) & 0x0fffffff) + face_id;
int glyph_table_len = GLYPH_TABLE_LENGTH;
/* Ignore trailing and leading spaces if we can. */
- if (!must_write_spaces)
+ if (!TTY_MUST_WRITE_SPACES (CURTTY ()))
{
/* Skip from the end over trailing spaces. */
while (end > beg && CHAR_GLYPH_SPACE_P (*(end - 1)))
#if GLYPH_DEBUG
-/* Flush standard output. This is sometimes useful to call from
- the debugger. */
+/* Flush standard output. This is sometimes useful to call from the debugger.
+ XXX Maybe this should be changed to flush the current terminal instead of
+ stdout.
+*/
void
flush_stdout ()
clear_frame ();
clear_current_matrices (f);
update_end (f);
- fflush (stdout);
+ fflush (TTY_OUTPUT (FRAME_TTY (f)));
windows_or_buffers_changed++;
/* Mark all windows as inaccurate, so that every window will have
its redisplay done. */
/* If we can't insert glyphs, we can use this method only
at the end of a line. */
- if (!char_ins_del_ok)
+ if (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f)))
if (PT != ZV && FETCH_BYTE (PT_BYTE) != '\n')
return 0;
rif->update_window_end_hook (w, 1, 0);
update_end (f);
updated_row = NULL;
- fflush (stdout);
+ fflush (TTY_OUTPUT (CURTTY ()));
TRACE ((stderr, "direct output for insert\n"));
mark_window_display_accurate (it.window, 1);
cursor_to (y, x);
}
- fflush (stdout);
+ fflush (TTY_OUTPUT (CURTTY ()));
redisplay_performed_directly_p = 1;
return 1;
}
paused_p = update_frame_1 (f, force_p, inhibit_hairy_id_p);
update_end (f);
- if (termscript)
- fflush (termscript);
- fflush (stdout);
+ if (TTY_TERMSCRIPT (FRAME_TTY (f)))
+ fflush (TTY_TERMSCRIPT (FRAME_TTY (f)));
+ fflush (TTY_OUTPUT (FRAME_TTY (f)));
/* Check window matrices for lost pointers. */
#if GLYPH_DEBUG
/* If old row extends to the end of the text area, clear. */
if (i >= desired_row->used[TEXT_AREA])
rif->cursor_to (vpos, i, desired_row->y,
- desired_row->x + desired_row->pixel_width);
+ desired_row->pixel_width);
rif->clear_end_of_line (-1);
changed_p = 1;
}
if (i >= desired_row->used[TEXT_AREA])
rif->cursor_to (vpos, i, desired_row->y,
- desired_row->x + desired_row->pixel_width);
+ desired_row->pixel_width);
/* If cursor is displayed at the end of the line, make sure
it's cleared. Nowadays we don't have a phys_cursor_glyph
x = -1;
}
else
- x = current_row->x + current_row->pixel_width;
+ x = current_row->pixel_width;
rif->clear_end_of_line (x);
changed_p = 1;
}
}
/* If we cannot insert/delete lines, it's no use trying it. */
- if (!line_ins_del_ok)
+ if (!TTY_LINE_INS_DEL_OK (FRAME_TTY (f)))
inhibit_id_p = 1;
/* See if any of the desired lines are enabled; don't compute for
Also flush out if likely to have more than 1k buffered
otherwise. I'm told that some telnet connections get
really screwed by more than 1k output at once. */
- int outq = PENDING_OUTPUT_COUNT (stdout);
+ int outq = PENDING_OUTPUT_COUNT (TTY_OUTPUT (FRAME_TTY (f)));
if (outq > 900
|| (outq > 20 && ((i - 1) % preempt_count == 0)))
{
- fflush (stdout);
+ fflush (TTY_OUTPUT (FRAME_TTY (f)));
if (preempt_count == 1)
{
#ifdef EMACS_OUTQSIZE
if (EMACS_OUTQSIZE (0, &outq) < 0)
/* Probably not a tty. Ignore the error and reset
the outq count. */
- outq = PENDING_OUTPUT_COUNT (stdout);
+ outq = PENDING_OUTPUT_COUNT (TTY_OUTPUT (FRAME_TTY (f)));
#endif
outq *= 10;
if (baud_rate <= outq && baud_rate > 0)
}
/* If changed lines are few, don't allow preemption, don't scroll. */
- if ((!scroll_region_ok && changed_lines < baud_rate / 2400)
+ if ((!TTY_SCROLL_REGION_OK (FRAME_TTY (frame))
+ && changed_lines < baud_rate / 2400)
|| unchanged_at_bottom == FRAME_LINES (frame))
return 1;
window_size = (FRAME_LINES (frame) - unchanged_at_top
- unchanged_at_bottom);
- if (scroll_region_ok)
+ if (TTY_SCROLL_REGION_OK (FRAME_TTY (frame)))
free_at_end_vpos -= unchanged_at_bottom;
- else if (memory_below_frame)
+ else if (TTY_MEMORY_BELOW_FRAME (FRAME_TTY (frame)))
free_at_end_vpos = -1;
/* If large window, fast terminal and few lines in common between
current frame and desired frame, don't bother with i/d calc. */
- if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400
+ if (!TTY_SCROLL_REGION_OK (FRAME_TTY (frame))
+ && window_size >= 18 && baud_rate > 2400
&& (window_size >=
10 * scrolling_max_lines_saved (unchanged_at_top,
FRAME_LINES (frame) - unchanged_at_bottom,
struct glyph_row *current_row = MATRIX_ROW (current_matrix, vpos);
struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, vpos);
int must_write_whole_line_p;
- int write_spaces_p = must_write_spaces;
+ int write_spaces_p = TTY_MUST_WRITE_SPACES (FRAME_TTY (f));
int colored_spaces_p = (FACE_FROM_ID (f, DEFAULT_FACE_ID)->background
!= FACE_TTY_DEFAULT_BG_COLOR);
nlen--;
/* If there's no i/d char, quickly do the best we can without it. */
- if (!char_ins_del_ok)
+ if (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f)))
{
int i, j;
tem = (nlen - nsp) - (olen - osp);
if (endmatch && tem
- && (!char_ins_del_ok || endmatch <= char_ins_del_cost (f)[tem]))
+ && (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f))
+ || endmatch <= char_ins_del_cost (f)[tem]))
endmatch = 0;
/* nsp - osp is the distance to insert or delete.
Is it worth it? */
if (nsp != osp
- && (!char_ins_del_ok
+ && (!TTY_CHAR_INS_DEL_OK (FRAME_TTY (f))
|| begmatch + endmatch <= char_ins_del_cost (f)[nsp - osp]))
{
begmatch = 0;
/* Determine what's under window-relative pixel position (*X, *Y).
Return in *OBJECT the object (string or buffer) that's there.
Return in *POS the position in that object. Adjust *X and *Y
- to character boundaries. */
+ to character positions. */
void
-buffer_posn_from_coords (w, x, y, object, pos)
+buffer_posn_from_coords (w, x, y, dx, dy, object, pos)
struct window *w;
int *x, *y;
+ int *dx, *dy;
Lisp_Object *object;
struct display_pos *pos;
{
struct it it;
struct buffer *old_current_buffer = current_buffer;
struct text_pos startp;
- int left_area_width;
+ int x0, x1;
current_buffer = XBUFFER (w->buffer);
SET_TEXT_POS_FROM_MARKER (startp, w->start);
BYTEPOS (startp) = min (ZV_BYTE, max (BEGV_BYTE, BYTEPOS (startp)));
start_display (&it, w, startp);
- left_area_width = WINDOW_LEFT_MARGIN_WIDTH (w);
- move_it_to (&it, -1, *x + it.first_visible_x - left_area_width, *y, -1,
+ x0 = *x - WINDOW_LEFT_MARGIN_WIDTH (w);
+ move_it_to (&it, -1, x0 + it.first_visible_x, *y, -1,
MOVE_TO_X | MOVE_TO_Y);
- *x = it.current_x - it.first_visible_x + left_area_width;
- *y = it.current_y;
current_buffer = old_current_buffer;
- *object = STRINGP (it.string) ? it.string : w->buffer;
+ *dx = x0 + it.first_visible_x - it.current_x;
+ *dy = *y - it.current_y;
+
+ *object = w->buffer;
+
+#ifdef HAVE_WINDOW_SYSTEM
+ if (it.what == IT_IMAGE)
+ {
+ struct image *img;
+ if ((img = IMAGE_FROM_ID (it.f, it.image_id)) != NULL
+ && !NILP (img->spec))
+ {
+ struct glyph_row *row = MATRIX_ROW (w->current_matrix, it.vpos);
+ struct glyph *glyph;
+
+ if (it.hpos < row->used[TEXT_AREA]
+ && (glyph = row->glyphs[TEXT_AREA] + it.hpos,
+ glyph->type == IMAGE_GLYPH))
+ {
+ *dy -= row->ascent - glyph->ascent;
+ *object = img->spec;
+ }
+ }
+ }
+ else
+#endif
+ if (STRINGP (it.string))
+ *object = it.string;
+
*pos = it.current;
+
+ /* Add extra (default width) columns if clicked after EOL. */
+ x1 = max(0, it.current_x + it.pixel_width - it.first_visible_x);
+ if (x0 > x1)
+ it.hpos += (x0 - x1) / WINDOW_FRAME_COLUMN_WIDTH (w);
+
+ *x = it.hpos;
+ *y = it.vpos;
}
the string returned. */
Lisp_Object
-mode_line_string (w, x, y, part, charpos)
+mode_line_string (w, x, y, dx, dy, part, charpos)
struct window *w;
- int x, y;
+ int *x, *y;
+ int *dx, *dy;
enum window_part part;
int *charpos;
{
struct glyph_row *row;
struct glyph *glyph, *end;
- struct frame *f = XFRAME (w->frame);
- int x0;
+ int x0, y0;
Lisp_Object string = Qnil;
if (part == ON_MODE_LINE)
row = MATRIX_MODE_LINE_ROW (w->current_matrix);
else
row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
+ y0 = *y - row->y;
+ *y = row - MATRIX_FIRST_TEXT_ROW (w->current_matrix);
if (row->mode_line_p && row->enabled_p)
{
it's the one we were looking for. */
glyph = row->glyphs[TEXT_AREA];
end = glyph + row->used[TEXT_AREA];
- for (x0 = 0; glyph < end; x0 += glyph->pixel_width, ++glyph)
- if (x >= x0 && x < x0 + glyph->pixel_width)
- {
- string = glyph->object;
- *charpos = glyph->charpos;
- break;
- }
+ for (x0 = *x; glyph < end && x0 > glyph->pixel_width; ++glyph)
+ x0 -= glyph->pixel_width;
+ *x = glyph - row->glyphs[TEXT_AREA];
+ if (glyph < end)
+ {
+ string = glyph->object;
+ *charpos = glyph->charpos;
+ }
+ else
+ /* Add extra (default width) columns if clicked after EOL. */
+ *x += x0 / WINDOW_FRAME_COLUMN_WIDTH (w);
+ }
+ else
+ {
+ *x = 0;
+ x0 = 0;
+ }
+
+ if (dx)
+ {
+ *dx = x0;
+ *dy = y0;
}
return string;
the string returned. */
Lisp_Object
-marginal_area_string (w, x, y, part, charpos)
+marginal_area_string (w, x, y, dx, dy, part, charpos)
struct window *w;
- int x, y;
+ int *x, *y;
+ int *dx, *dy;
enum window_part part;
int *charpos;
{
struct glyph_row *row = w->current_matrix->rows;
struct glyph *glyph, *end;
- int x0, i, wy = y;
+ int x0, y0, i, wy = *y;
int area;
Lisp_Object string = Qnil;
for (i = 0; row->enabled_p && i < w->current_matrix->nrows; ++i, ++row)
if (wy >= row->y && wy < MATRIX_ROW_BOTTOM_Y (row))
break;
+ y0 = *y - row->y;
+ *y = row - MATRIX_FIRST_TEXT_ROW (w->current_matrix);
if (row->enabled_p)
{
/* Find the glyph under X. If we find one with a string object,
it's the one we were looking for. */
- glyph = row->glyphs[area];
- end = glyph + row->used[area];
-
if (area == RIGHT_MARGIN_AREA)
x0 = ((WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (w)
? WINDOW_LEFT_FRINGE_WIDTH (w)
? WINDOW_LEFT_FRINGE_WIDTH (w)
: 0);
- for (; glyph < end; x0 += glyph->pixel_width, ++glyph)
- if (x >= x0 && x < x0 + glyph->pixel_width)
- {
- string = glyph->object;
- *charpos = glyph->charpos;
- break;
- }
+ glyph = row->glyphs[area];
+ end = glyph + row->used[area];
+ for (x0 = *x - x0; glyph < end && x0 > glyph->pixel_width; ++glyph)
+ x0 -= glyph->pixel_width;
+ *x = glyph - row->glyphs[area];
+ if (glyph < end)
+ {
+ string = glyph->object;
+ *charpos = glyph->charpos;
+#ifdef HAVE_WINDOW_SYSTEM
+ if (glyph->type == IMAGE_GLYPH)
+ {
+ struct image *img;
+ img = IMAGE_FROM_ID (WINDOW_XFRAME (w), glyph->u.img_id);
+ if (img != NULL)
+ string = img->spec;
+ y0 -= row->ascent - glyph->ascent;
+ }
+#endif
+ }
+ else
+ /* Add extra (default width) columns if clicked after EOL. */
+ *x += x0 / WINDOW_FRAME_COLUMN_WIDTH (w);
+ }
+ else
+ {
+ x0 = 0;
+ *x = 0;
+ }
+
+ if (dx)
+ {
+ *dx = x0;
+ *dy = y0;
}
return string;
#endif
int old_errno = errno;
- get_frame_size (&width, &height);
-
- /* The frame size change obviously applies to a termcap-controlled
- frame. Find such a frame in the list, and assume it's the only
- one (since the redisplay code always writes to stdout, not a
- FILE * specified in the frame structure). Record the new size,
- but don't reallocate the data structures now. Let that be done
- later outside of the signal handler. */
+ struct tty_output *tty;
+
+ /* The frame size change obviously applies to a single
+ termcap-controlled terminal, but we can't decide which.
+ Therefore, we resize the frames corresponding to each tty.
+ */
+ for (tty = tty_list; tty; tty = tty->next) {
- {
- Lisp_Object tail, frame;
-
- FOR_EACH_FRAME (tail, frame)
- {
- if (FRAME_TERMCAP_P (XFRAME (frame)))
- {
- change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
- break;
- }
- }
+ if (! tty->term_initted)
+ continue;
+
+ get_tty_size (fileno (TTY_INPUT (tty)), &width, &height);
+
+ {
+ Lisp_Object tail, frame;
+
+ FOR_EACH_FRAME (tail, frame)
+ {
+ if (FRAME_TERMCAP_P (XFRAME (frame)) && FRAME_TTY (XFRAME (frame)) == tty)
+ {
+ /* Record the new sizes, but don't reallocate the data structures
+ now. Let that be done later outside of the signal handler. */
+ change_frame_size (XFRAME (frame), height, width, 0, 1, 0);
+ break;
+ }
+ }
+ }
}
-
+
signal (SIGWINCH, window_change_signal);
errno = old_errno;
}
{
Lisp_Object tail, frame;
- if (! FRAME_WINDOW_P (f))
+ if (FRAME_MSDOS_P (f))
{
- /* When using termcap, or on MS-DOS, all frames use
- the same screen, so a change in size affects all frames. */
+ /* On MS-DOS, all frames use the same screen, so a change in
+ size affects all frames. Termcap now supports multiple
+ ttys. */
FOR_EACH_FRAME (tail, frame)
if (! FRAME_WINDOW_P (XFRAME (frame)))
change_frame_size_1 (XFRAME (frame), newheight, newwidth,
newheight - FRAME_TOP_MARGIN (f), 0);
if (FRAME_TERMCAP_P (f) && !pretend)
- FrameRows = newheight;
+ FrameRows (FRAME_TTY (f)) = newheight;
}
if (new_frame_total_cols != FRAME_TOTAL_COLS (f))
set_window_width (FRAME_MINIBUF_WINDOW (f), new_frame_total_cols, 0);
if (FRAME_TERMCAP_P (f) && !pretend)
- FrameCols = newwidth;
+ FrameCols (FRAME_TTY (f)) = newwidth;
if (WINDOWP (f->tool_bar_window))
XSETFASTINT (XWINDOW (f->tool_bar_window)->total_cols, newwidth);
(file)
Lisp_Object file;
{
- if (termscript != 0) fclose (termscript);
- termscript = 0;
+ if (TTY_TERMSCRIPT (CURTTY ()) != 0)
+ fclose (TTY_TERMSCRIPT (CURTTY ()));
+ TTY_TERMSCRIPT (CURTTY ()) = 0;
if (! NILP (file))
{
file = Fexpand_file_name (file, Qnil);
- termscript = fopen (SDATA (file), "w");
- if (termscript == 0)
+ TTY_TERMSCRIPT (CURTTY ()) = fopen (SDATA (file), "w");
+ if (TTY_TERMSCRIPT (CURTTY ()) == 0)
report_file_error ("Opening termscript", Fcons (file, Qnil));
}
return Qnil;
{
/* ??? Perhaps we should do something special for multibyte strings here. */
CHECK_STRING (string);
- fwrite (SDATA (string), 1, SBYTES (string), stdout);
- fflush (stdout);
- if (termscript)
+ if (TTY_TERMSCRIPT (CURTTY ()))
{
fwrite (SDATA (string), 1, SBYTES (string),
- termscript);
- fflush (termscript);
+ TTY_TERMSCRIPT (CURTTY ()));
+ fflush (TTY_TERMSCRIPT (CURTTY ()));
}
+ fwrite (SDATA (string), 1, SBYTES (string),
+ TTY_OUTPUT (CURTTY ()));
+ fflush (TTY_OUTPUT (CURTTY ()));
return Qnil;
}
putchar (07);
else
ring_bell ();
- fflush (stdout);
+ fflush (TTY_OUTPUT (CURTTY ()));
}
else
bitch_at_user ();
error ("Keyboard macro terminated by a command ringing the bell");
else
ring_bell ();
- fflush (stdout);
+ fflush (TTY_OUTPUT (CURTTY ()));
}
Where the optional arg MILLISECONDS specifies an additional wait period,
in milliseconds; this was useful when Emacs was built without
floating point support.
-usage: (sit-for SECONDS &optional NODISP) */)
+usage: (sit-for SECONDS &optional NODISP OLD-NODISP) */)
+
+/* The `old-nodisp' stuff is there so that the arglist has the correct
+ length. Otherwise, `defdvice' will redefine it with fewer args. */
(seconds, milliseconds, nodisp)
Lisp_Object seconds, milliseconds, nodisp;
{
Initialization
***********************************************************************/
-char *terminal_type;
-
/* Initialization done when Emacs fork is started, before doing stty.
Determine terminal type and set terminal_driver. Then invoke its
decoding routine to set up variables in the terminal package. */
void
init_display ()
{
+ char *terminal_type;
+
#ifdef HAVE_X_WINDOWS
extern int display_arg;
#endif
SET_CHAR_GLYPH_FROM_GLYPH (space_glyph, ' ');
space_glyph.charpos = -1;
- meta_key = 0;
inverse_video = 0;
cursor_in_echo_area = 0;
terminal_type = (char *) 0;
}
#endif /* VMS */
- term_init (terminal_type);
-
+ {
+ struct tty_output *tty;
+
+ tty = term_init (selected_frame, 0, terminal_type);
+ change_frame_size (XFRAME (selected_frame), FrameRows (tty), FrameCols (tty), 0, 0, 0);
+ }
+
{
struct frame *sf = SELECTED_FRAME ();
int width = FRAME_TOTAL_COLS (sf);
Vwindow_system_version = Qnil;
}
}
+
+/* arch-tag: 8d812b1f-04a2-4195-a9c4-381f8457a413
+ (do not change this comment) */