#include <signal.h>
#include <config.h>
#include <stdio.h>
#include <ctype.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "lisp.h"
#include "termchar.h"
#include "termopts.h"
#include "termhooks.h"
#include "dispextern.h"
#include "cm.h"
#include "buffer.h"
#include "charset.h"
#include "frame.h"
#include "window.h"
#include "commands.h"
#include "disptab.h"
#include "indent.h"
#include "intervals.h"
#include "blockinput.h"
#include "process.h"
#include "keyboard.h"
#include "syssignal.h"
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif
#ifdef HAVE_NTGUI
#include "w32term.h"
#endif
#include "systime.h"
#include <errno.h>
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define minmax(floor, val, ceil) \
((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
#ifdef __GNU_LIBRARY__
#ifdef GNU_LIBRARY_PENDING_OUTPUT_COUNT
#define PENDING_OUTPUT_COUNT GNU_LIBRARY_PENDING_OUTPUT_COUNT
#else
#undef PENDING_OUTPUT_COUNT
#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->__bufp - (FILE)->__buffer)
#endif
#else
#ifndef PENDING_OUTPUT_COUNT
#define PENDING_OUTPUT_COUNT(FILE) ((FILE)->_ptr - (FILE)->_base)
#endif
#endif
static void change_frame_size_1 ();
int frame_garbaged;
int display_completed;
int visible_bell;
int inverse_video;
int baud_rate;
Lisp_Object Vwindow_system;
Lisp_Object Vwindow_system_version;
Lisp_Object Vglyph_table;
Lisp_Object Vstandard_display_table;
int cursor_in_echo_area;
Lisp_Object Qdisplay_table;
FRAME_PTR selected_frame;
FRAME_PTR last_nonminibuf_frame;
struct frame_glyphs **ophys_lines;
int ophys_lines_length;
FILE *termscript;
struct cm Wcm;
int delayed_size_change;
DEFUN ("redraw-frame", Fredraw_frame, Sredraw_frame, 1, 1, 0,
"Clear frame FRAME and output again what is supposed to appear on it.")
(frame)
Lisp_Object frame;
{
FRAME_PTR f;
CHECK_LIVE_FRAME (frame, 0);
f = XFRAME (frame);
if (FRAME_CURRENT_GLYPHS (f) != 0)
{
update_begin (f);
if (FRAME_MSDOS_P (f))
set_terminal_modes ();
clear_frame ();
clear_frame_records (f);
update_end (f);
fflush (stdout);
}
windows_or_buffers_changed++;
mark_window_display_accurate (FRAME_ROOT_WINDOW (f), 0);
f->garbaged = 0;
return Qnil;
}
void
redraw_frame (f)
FRAME_PTR f;
{
Lisp_Object frame;
XSETFRAME (frame, f);
Fredraw_frame (frame);
}
DEFUN ("redraw-display", Fredraw_display, Sredraw_display, 0, 0, "",
"Clear and redisplay all visible frames.")
()
{
Lisp_Object tail, frame;
FOR_EACH_FRAME (tail, frame)
if (FRAME_VISIBLE_P (XFRAME (frame)))
Fredraw_frame (frame);
return Qnil;
}
void
redraw_garbaged_frames ()
{
Lisp_Object tail, frame;
FOR_EACH_FRAME (tail, frame)
if (FRAME_VISIBLE_P (XFRAME (frame))
&& FRAME_GARBAGED_P (XFRAME (frame)))
Fredraw_frame (frame);
}
static struct frame_glyphs *
make_frame_glyphs (frame, empty)
register FRAME_PTR frame;
int empty;
{
register int i;
register int width = FRAME_WINDOW_WIDTH (frame);
register int height = FRAME_HEIGHT (frame);
register struct frame_glyphs *new
= (struct frame_glyphs *) xmalloc (sizeof (struct frame_glyphs));
SET_GLYPHS_FRAME (new, frame);
new->height = height;
new->width = width;
new->used = (int *) xmalloc (height * sizeof (int));
new->glyphs = (GLYPH **) xmalloc (height * sizeof (GLYPH *));
new->charstarts = (int **) xmalloc (height * sizeof (int *));
new->highlight = (char *) xmalloc (height * sizeof (char));
new->enable = (char *) xmalloc (height * sizeof (char));
bzero (new->enable, height * sizeof (char));
new->bufp = (int *) xmalloc (height * sizeof (int));
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (frame))
{
new->top_left_x = (short *) xmalloc (height * sizeof (short));
new->top_left_y = (short *) xmalloc (height * sizeof (short));
new->pix_width = (short *) xmalloc (height * sizeof (short));
new->pix_height = (short *) xmalloc (height * sizeof (short));
new->max_ascent = (short *) xmalloc (height * sizeof (short));
}
#endif
if (empty)
{
unsigned int total_glyphs = (width + 2) * sizeof (GLYPH);
unsigned int total_charstarts = (width + 2) * sizeof (int);
new->total_contents = (GLYPH *) xmalloc (total_glyphs);
bzero (new->total_contents, total_glyphs);
new->total_charstarts = (int *) xmalloc (total_charstarts);
bzero (new->total_charstarts, total_charstarts);
}
else
{
unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
new->total_contents = (GLYPH *) xmalloc (total_glyphs);
bzero (new->total_contents, total_glyphs);
for (i = 0; i < height; i++)
new->glyphs[i] = new->total_contents + i * (width + 2) + 1;
if (!FRAME_TERMCAP_P (frame))
{
unsigned int total_charstarts = height * (width + 2) * sizeof (int);
new->total_charstarts = (int *) xmalloc (total_charstarts);
bzero (new->total_charstarts, total_charstarts);
for (i = 0; i < height; i++)
new->charstarts[i] = new->total_charstarts + i * (width + 2) + 1;
}
else
{
new->total_charstarts = (int *) xmalloc ((width + 2) * sizeof (int));
for (i = 0; i < height; i++)
new->charstarts[i] = new->total_charstarts;
}
}
return new;
}
void
free_frame_glyphs (frame, glyphs)
FRAME_PTR frame;
struct frame_glyphs *glyphs;
{
if (glyphs->total_contents)
xfree (glyphs->total_contents);
if (glyphs->total_charstarts)
xfree (glyphs->total_charstarts);
xfree (glyphs->used);
xfree (glyphs->glyphs);
xfree (glyphs->highlight);
xfree (glyphs->enable);
xfree (glyphs->bufp);
if (glyphs->charstarts)
xfree (glyphs->charstarts);
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (frame))
{
xfree (glyphs->top_left_x);
xfree (glyphs->top_left_y);
xfree (glyphs->pix_width);
xfree (glyphs->pix_height);
xfree (glyphs->max_ascent);
}
#endif
xfree (glyphs);
}
void
remake_frame_glyphs (frame)
FRAME_PTR frame;
{
if (FRAME_CURRENT_GLYPHS (frame))
free_frame_glyphs (frame, FRAME_CURRENT_GLYPHS (frame));
if (FRAME_DESIRED_GLYPHS (frame))
free_frame_glyphs (frame, FRAME_DESIRED_GLYPHS (frame));
if (FRAME_TEMP_GLYPHS (frame))
free_frame_glyphs (frame, FRAME_TEMP_GLYPHS (frame));
if (FRAME_MESSAGE_BUF (frame))
{
char *old_message_buf = FRAME_MESSAGE_BUF (frame);
FRAME_MESSAGE_BUF (frame)
= (char *) xrealloc (FRAME_MESSAGE_BUF (frame),
FRAME_MESSAGE_BUF_SIZE (frame) + 1);
if (echo_area_glyphs == old_message_buf)
echo_area_glyphs = FRAME_MESSAGE_BUF (frame);
if (previous_echo_glyphs == old_message_buf)
previous_echo_glyphs = FRAME_MESSAGE_BUF (frame);
}
else
FRAME_MESSAGE_BUF (frame)
= (char *) xmalloc (FRAME_MESSAGE_BUF_SIZE (frame) + 1);
FRAME_CURRENT_GLYPHS (frame) = make_frame_glyphs (frame, 0);
FRAME_DESIRED_GLYPHS (frame) = make_frame_glyphs (frame, 0);
FRAME_TEMP_GLYPHS (frame) = make_frame_glyphs (frame, 1);
if (FRAME_WINDOW_P (frame) || frame == selected_frame)
SET_FRAME_GARBAGED (frame);
}
static int
line_hash_code (m, vpos)
register struct frame_glyphs *m;
int vpos;
{
register GLYPH *body, *end;
register int h = 0;
if (!m->enable[vpos])
return 0;
if (m->highlight[vpos])
return -1;
body = m->glyphs[vpos];
if (must_write_spaces)
while (1)
{
GLYPH g = *body++;
if (g == 0)
break;
h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g - SPACEGLYPH;
}
else
while (1)
{
GLYPH g = *body++;
if (g == 0)
break;
h = (((h << 4) + (h >> 24)) & 0x0fffffff) + g;
}
if (h)
return h;
return 1;
}
static unsigned int
line_draw_cost (m, vpos)
struct frame_glyphs *m;
int vpos;
{
register GLYPH *beg = m->glyphs[vpos];
register GLYPH *end = m->glyphs[vpos] + m->used[vpos];
register int i;
register int tlen = GLYPH_TABLE_LENGTH;
register Lisp_Object *tbase = GLYPH_TABLE_BASE;
if (!must_write_spaces)
{
while ((end != beg) && (*end == SPACEGLYPH))
--end;
if (end == beg)
return (0);
while (*beg == SPACEGLYPH)
++beg;
}
if (tbase == 0)
return end - beg;
i = 0;
while ((beg <= end) && *beg)
{
register GLYPH g = *beg++;
if (GLYPH_SIMPLE_P (tbase, tlen, g))
i += 1;
else
i += GLYPH_LENGTH (tbase, g);
}
return i;
}
void
cancel_line (vpos, frame)
int vpos;
register FRAME_PTR frame;
{
FRAME_DESIRED_GLYPHS (frame)->enable[vpos] = 0;
}
void
clear_frame_records (frame)
register FRAME_PTR frame;
{
bzero (FRAME_CURRENT_GLYPHS (frame)->enable, FRAME_HEIGHT (frame));
}
void
init_desired_glyphs (frame)
register FRAME_PTR frame;
{
register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
int vpos;
int height = FRAME_HEIGHT (frame);
for (vpos = 0; vpos < height; vpos++)
desired_glyphs->enable[vpos] = 0;
}
void
get_display_line (frame, vpos, hpos)
register FRAME_PTR frame;
int vpos;
register int hpos;
{
register struct frame_glyphs *glyphs;
register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (frame);
register GLYPH *p;
if (vpos < 0)
abort ();
if (! desired_glyphs->enable[vpos])
{
desired_glyphs->used[vpos] = 0;
desired_glyphs->highlight[vpos] = 0;
desired_glyphs->enable[vpos] = 1;
}
if (hpos > desired_glyphs->used[vpos])
{
GLYPH *g = desired_glyphs->glyphs[vpos] + desired_glyphs->used[vpos];
GLYPH *end = desired_glyphs->glyphs[vpos] + hpos;
desired_glyphs->used[vpos] = hpos;
while (g != end)
*g++ = SPACEGLYPH;
}
}
void
safe_bcopy (from, to, size)
char *from, *to;
int size;
{
if (size <= 0 || from == to)
return;
if (to < from || from + size <= to)
bcopy (from, to, size);
else
{
register char *endf = from + size;
register char *endt = to + size;
if (to - from < 64)
{
do
*--endt = *--endf;
while (endf != from);
}
else
{
for (;;)
{
endt -= (to - from);
endf -= (to - from);
if (endt < to)
break;
bcopy (endf, endt, to - from);
}
bcopy (from, to, endt - from);
}
}
}
static void
rotate_vector (vector, size, distance)
char *vector;
int size;
int distance;
{
char *temp = (char *) alloca (size);
if (distance < 0)
distance += size;
bcopy (vector, temp + distance, size - distance);
bcopy (vector + size - distance, temp, distance);
bcopy (temp, vector, size);
}
int
scroll_frame_lines (frame, from, end, amount, newpos)
register FRAME_PTR frame;
int from, end, amount, newpos;
{
register int i;
register struct frame_glyphs *current_frame
= FRAME_CURRENT_GLYPHS (frame);
int pos_adjust;
int width = FRAME_WINDOW_WIDTH (frame);
if (!line_ins_del_ok)
return 0;
if (amount == 0)
return 1;
if (amount > 0)
{
update_begin (frame);
set_terminal_window (end + amount);
if (!scroll_region_ok)
ins_del_lines (end, -amount);
ins_del_lines (from, amount);
set_terminal_window (0);
rotate_vector (current_frame->glyphs + from,
sizeof (GLYPH *) * (end + amount - from),
amount * sizeof (GLYPH *));
rotate_vector (current_frame->charstarts + from,
sizeof (int *) * (end + amount - from),
amount * sizeof (int *));
safe_bcopy (current_frame->used + from,
current_frame->used + from + amount,
(end - from) * sizeof current_frame->used[0]);
safe_bcopy (current_frame->highlight + from,
current_frame->highlight + from + amount,
(end - from) * sizeof current_frame->highlight[0]);
safe_bcopy (current_frame->enable + from,
current_frame->enable + from + amount,
(end - from) * sizeof current_frame->enable[0]);
pos_adjust = newpos - current_frame->charstarts[from + amount][0];
for (i = from + amount; i < end + amount; i++)
{
int *line = current_frame->charstarts[i];
int col;
for (col = 0; col < width; col++)
if (line[col] > 0)
line[col] += pos_adjust;
}
for (i = from; i < from + amount; i++)
{
int *line = current_frame->charstarts[i];
int col;
line[0] = -1;
for (col = 0; col < width; col++)
line[col] = 0;
}
bzero (current_frame->used + from,
amount * sizeof current_frame->used[0]);
bzero (current_frame->highlight + from,
amount * sizeof current_frame->highlight[0]);
for (i = from; i < from + amount; i++)
{
current_frame->glyphs[i][0] = '\0';
current_frame->charstarts[i][0] = -1;
current_frame->enable[i] = 1;
}
safe_bcopy (current_frame->bufp + from,
current_frame->bufp + from + amount,
(end - from) * sizeof current_frame->bufp[0]);
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (frame))
{
safe_bcopy (current_frame->top_left_x + from,
current_frame->top_left_x + from + amount,
(end - from) * sizeof current_frame->top_left_x[0]);
safe_bcopy (current_frame->top_left_y + from,
current_frame->top_left_y + from + amount,
(end - from) * sizeof current_frame->top_left_y[0]);
safe_bcopy (current_frame->pix_width + from,
current_frame->pix_width + from + amount,
(end - from) * sizeof current_frame->pix_width[0]);
safe_bcopy (current_frame->pix_height + from,
current_frame->pix_height + from + amount,
(end - from) * sizeof current_frame->pix_height[0]);
safe_bcopy (current_frame->max_ascent + from,
current_frame->max_ascent + from + amount,
(end - from) * sizeof current_frame->max_ascent[0]);
}
#endif
update_end (frame);
}
if (amount < 0)
{
update_begin (frame);
set_terminal_window (end);
ins_del_lines (from + amount, amount);
if (!scroll_region_ok)
ins_del_lines (end + amount, -amount);
set_terminal_window (0);
rotate_vector (current_frame->glyphs + from + amount,
sizeof (GLYPH *) * (end - from - amount),
amount * sizeof (GLYPH *));
rotate_vector (current_frame->charstarts + from + amount,
sizeof (int *) * (end - from - amount),
amount * sizeof (int *));
safe_bcopy (current_frame->used + from,
current_frame->used + from + amount,
(end - from) * sizeof current_frame->used[0]);
safe_bcopy (current_frame->highlight + from,
current_frame->highlight + from + amount,
(end - from) * sizeof current_frame->highlight[0]);
safe_bcopy (current_frame->enable + from,
current_frame->enable + from + amount,
(end - from) * sizeof current_frame->enable[0]);
pos_adjust = newpos - current_frame->charstarts[from + amount][0];
for (i = from + amount; i < end + amount; i++)
{
int *line = current_frame->charstarts[i];
int col;
for (col = 0; col < width; col++)
if (line[col] > 0)
line[col] += pos_adjust;
}
for (i = end + amount; i < end; i++)
{
int *line = current_frame->charstarts[i];
int col;
line[0] = -1;
for (col = 0; col < width; col++)
line[col] = 0;
}
bzero (current_frame->used + end + amount,
- amount * sizeof current_frame->used[0]);
bzero (current_frame->highlight + end + amount,
- amount * sizeof current_frame->highlight[0]);
for (i = end + amount; i < end; i++)
{
current_frame->glyphs[i][0] = '\0';
current_frame->charstarts[i][0] = 0;
current_frame->enable[i] = 1;
}
safe_bcopy (current_frame->bufp + from,
current_frame->bufp + from + amount,
(end - from) * sizeof current_frame->bufp[0]);
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (frame))
{
safe_bcopy (current_frame->top_left_x + from,
current_frame->top_left_x + from + amount,
(end - from) * sizeof current_frame->top_left_x[0]);
safe_bcopy (current_frame->top_left_y + from,
current_frame->top_left_y + from + amount,
(end - from) * sizeof current_frame->top_left_y[0]);
safe_bcopy (current_frame->pix_width + from,
current_frame->pix_width + from + amount,
(end - from) * sizeof current_frame->pix_width[0]);
safe_bcopy (current_frame->pix_height + from,
current_frame->pix_height + from + amount,
(end - from) * sizeof current_frame->pix_height[0]);
safe_bcopy (current_frame->max_ascent + from,
current_frame->max_ascent + from + amount,
(end - from) * sizeof current_frame->max_ascent[0]);
}
#endif
update_end (frame);
}
return 1;
}
void
preserve_other_columns (w)
struct window *w;
{
register int vpos;
register struct frame_glyphs *current_frame, *desired_frame;
register FRAME_PTR frame = XFRAME (w->frame);
int start = WINDOW_LEFT_MARGIN (w);
int end = WINDOW_RIGHT_EDGE (w);
int bot = XFASTINT (w->top) + XFASTINT (w->height);
current_frame = FRAME_CURRENT_GLYPHS (frame);
desired_frame = FRAME_DESIRED_GLYPHS (frame);
for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
{
if (current_frame->enable[vpos] && desired_frame->enable[vpos])
{
if (start > 0)
{
int len;
bcopy (current_frame->glyphs[vpos],
desired_frame->glyphs[vpos],
start * sizeof (current_frame->glyphs[vpos][0]));
bcopy (current_frame->charstarts[vpos],
desired_frame->charstarts[vpos],
start * sizeof (current_frame->charstarts[vpos][0]));
len = min (start, current_frame->used[vpos]);
if (desired_frame->used[vpos] < len)
desired_frame->used[vpos] = len;
}
if (current_frame->used[vpos] > end
&& desired_frame->used[vpos] < current_frame->used[vpos])
{
while (desired_frame->used[vpos] < end)
{
int used = desired_frame->used[vpos]++;
desired_frame->glyphs[vpos][used] = SPACEGLYPH;
desired_frame->glyphs[vpos][used] = 0;
}
bcopy (current_frame->glyphs[vpos] + end,
desired_frame->glyphs[vpos] + end,
((current_frame->used[vpos] - end)
* sizeof (current_frame->glyphs[vpos][0])));
bcopy (current_frame->charstarts[vpos] + end,
desired_frame->charstarts[vpos] + end,
((current_frame->used[vpos] - end)
* sizeof (current_frame->charstarts[vpos][0])));
desired_frame->used[vpos] = current_frame->used[vpos];
}
}
}
}
#if 0
preserve_my_columns (w)
struct window *w;
{
register int vpos, fin;
register struct frame_glyphs *l1, *l2;
register FRAME_PTR frame = XFRAME (w->frame);
int start = WINDOW_LEFT_MARGIN (w);
int end = WINDOW_RIGHT_EDGE (w);
int bot = XFASTINT (w->top) + XFASTINT (w->height);
for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
{
if ((l1 = FRAME_DESIRED_GLYPHS (frame)->glyphs[vpos + 1])
&& (l2 = FRAME_PHYS_GLYPHS (frame)->glyphs[vpos + 1]))
{
if (l2->length > start && l1->length < l2->length)
{
fin = l2->length;
if (fin > end) fin = end;
while (l1->length < start)
l1->body[l1->length++] = ' ';
bcopy (l2->body + start, l1->body + start, fin - start);
l1->length = fin;
}
}
}
}
#endif
void
adjust_window_charstarts (w, vpos, adjust)
struct window *w;
int vpos;
int adjust;
{
int left = WINDOW_LEFT_MARGIN (w);
int top = XFASTINT (w->top);
int right = left + window_internal_width (w);
int bottom = top + window_internal_height (w);
int i;
for (i = vpos + 1; i < bottom; i++)
{
int *charstart
= FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[i];
int j;
for (j = left; j < right; j++)
if (charstart[j] > 0)
charstart[j] += adjust;
}
}
void
verify_charstarts (w)
struct window *w;
{
FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
int i;
int top = XFASTINT (w->top);
int bottom = top + window_internal_height (w);
int left = WINDOW_LEFT_MARGIN (w);
int right = left + window_internal_width (w);
int next_line;
int truncate = (XINT (w->hscroll)
|| (truncate_partial_width_windows
&& !WINDOW_FULL_WIDTH_P (w))
|| !NILP (XBUFFER (w->buffer)->truncate_lines));
for (i = top; i < bottom; i++)
{
int j;
int last;
int *charstart = FRAME_CURRENT_GLYPHS (f)->charstarts[i];
if (i != top)
{
if (truncate)
{
if (charstart[left] < next_line)
abort ();
}
else
{
if (charstart[left] != next_line)
abort ();
}
}
for (j = left; j < right; j++)
if (charstart[j] > 0)
last = charstart[j];
next_line = last;
if (BUF_ZV (XBUFFER (w->buffer)) != last)
{
int endchar = *BUF_CHAR_ADDRESS (XBUFFER (w->buffer), last);
if (endchar == '\n')
next_line++;
}
}
}
void
cancel_my_columns (w)
struct window *w;
{
register int vpos;
register struct frame_glyphs *desired_glyphs
= FRAME_DESIRED_GLYPHS (XFRAME (w->frame));
register int start = WINDOW_LEFT_MARGIN (w);
register int bot = XFASTINT (w->top) + XFASTINT (w->height);
for (vpos = XFASTINT (w->top); vpos < bot; vpos++)
if (desired_glyphs->enable[vpos]
&& desired_glyphs->used[vpos] >= start)
desired_glyphs->used[vpos] = start;
}
int
direct_output_for_insert (g)
int g;
{
register FRAME_PTR frame = selected_frame;
register struct frame_glyphs *current_frame
= FRAME_CURRENT_GLYPHS (frame);
#ifndef COMPILER_REGISTER_BUG
register
#endif
struct window *w = XWINDOW (selected_window);
#ifndef COMPILER_REGISTER_BUG
register
#endif
int hpos = FRAME_CURSOR_X (frame);
#ifndef COMPILER_REGISTER_BUG
register
#endif
int vpos = FRAME_CURSOR_Y (frame);
if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1
|| (XINT (w->hscroll) && hpos == WINDOW_LEFT_MARGIN (w))
|| cursor_in_echo_area
|| FRAME_CURSOR_Y (frame) < XFASTINT (w->top)
|| FRAME_CURSOR_Y (frame) >= XFASTINT (w->top) + XFASTINT (w->height)
|| !display_completed
|| buffer_shared > 1
#ifdef USE_TEXT_PROPERTIES
|| ! NILP (Ftext_properties_at (make_number (PT - 1), Qnil))
#endif
|| (MINI_WINDOW_P (w) && echo_area_glyphs))
return 0;
{
int face = 0;
#ifdef HAVE_FACES
int dummy;
if (FRAME_WINDOW_P (frame) || FRAME_MSDOS_P (frame))
face = compute_char_face (frame, w, PT - 1, -1, -1, &dummy, PT, 0);
#endif
current_frame->glyphs[vpos][hpos] = MAKE_GLYPH (frame, g, face);
current_frame->charstarts[vpos][hpos] = PT - 1;
current_frame->charstarts[vpos][hpos + 1] = PT;
adjust_window_charstarts (w, vpos, 1);
}
unchanged_modified = MODIFF;
beg_unchanged = GPT - BEG;
XSETFASTINT (w->last_point, PT);
XSETFASTINT (w->last_point_x, hpos + 1);
XSETFASTINT (w->last_modified, MODIFF);
XSETFASTINT (w->last_overlay_modified, OVERLAY_MODIFF);
reassert_line_highlight (0, vpos);
write_glyphs (¤t_frame->glyphs[vpos][hpos], 1);
fflush (stdout);
++FRAME_CURSOR_X (frame);
if (hpos == current_frame->used[vpos])
{
current_frame->used[vpos] = hpos + 1;
current_frame->glyphs[vpos][hpos + 1] = 0;
}
return 1;
}
int
direct_output_forward_char (n)
int n;
{
register FRAME_PTR frame = selected_frame;
register struct window *w = XWINDOW (selected_window);
Lisp_Object position;
int hpos = FRAME_CURSOR_X (frame);
if (hpos >= WINDOW_LEFT_MARGIN (w) + window_internal_width (w) - 1)
return 0;
if (!NILP (XBUFFER(w->buffer)->direction_reversed))
return 0;
if ((FRAME_CURSOR_X (frame) == WINDOW_LEFT_MARGIN (w)
&& (XINT (w->hscroll) || n < 0))
|| (n > 0
&& (FRAME_CURSOR_X (frame) + 1
>= XFASTINT (w->left) + window_internal_width (w) - 1))
|| cursor_in_echo_area)
return 0;
if (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
return 0;
if (overlay_touches_p (PT) || overlay_touches_p (PT - n))
return 0;
#ifdef USE_TEXT_PROPERTIES
XSETFASTINT (position, PT);
if (XFASTINT (position) < ZV
&& ! NILP (Fget_char_property (position,
Qinvisible,
selected_window)))
return 0;
XSETFASTINT (position, PT - 1);
if (XFASTINT (position) >= BEGV
&& ! NILP (Fget_char_property (position,
Qinvisible,
selected_window)))
return 0;
#endif
FRAME_CURSOR_X (frame) += n;
XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (frame));
XSETFASTINT (w->last_point, PT);
cursor_to (FRAME_CURSOR_Y (frame), FRAME_CURSOR_X (frame));
fflush (stdout);
return 1;
}
static void update_line ();
int
update_frame (f, force, inhibit_hairy_id)
FRAME_PTR f;
int force;
int inhibit_hairy_id;
{
register struct frame_glyphs *current_frame;
register struct frame_glyphs *desired_frame = 0;
register int i;
int pause;
int preempt_count = baud_rate / 2400 + 1;
extern int input_pending;
#ifdef HAVE_WINDOW_SYSTEM
register int downto, leftmost;
#endif
if (baud_rate != FRAME_COST_BAUD_RATE (f))
calculate_costs (f);
if (preempt_count <= 0)
preempt_count = 1;
if (FRAME_HEIGHT (f) == 0) abort ();
detect_input_pending ();
if (input_pending && !force)
{
pause = 1;
goto do_pause;
}
update_begin (f);
if (!line_ins_del_ok)
inhibit_hairy_id = 1;
current_frame = FRAME_CURRENT_GLYPHS (f);
desired_frame = FRAME_DESIRED_GLYPHS (f);
for (i = 0; i < FRAME_HEIGHT (f); i++)
if (desired_frame->enable[i])
break;
if (!inhibit_hairy_id && i < FRAME_HEIGHT (f))
force |= scrolling (f);
if (desired_frame->enable[FRAME_HEIGHT (f) - 1])
update_line (f, FRAME_HEIGHT (f) - 1);
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (f))
{
leftmost = downto = FRAME_INTERNAL_BORDER_WIDTH (f);
if (desired_frame->enable[0])
{
current_frame->top_left_x[FRAME_HEIGHT (f) - 1] = leftmost;
current_frame->top_left_y[FRAME_HEIGHT (f) - 1]
= PIXEL_HEIGHT (f) - FRAME_INTERNAL_BORDER_WIDTH (f)
- current_frame->pix_height[FRAME_HEIGHT (f) - 1];
current_frame->top_left_x[0] = leftmost;
current_frame->top_left_y[0] = downto;
}
}
#endif
for (i = 0; i < FRAME_HEIGHT (f) - 1 && (force || !input_pending); i++)
{
if (desired_frame->enable[i])
{
if (FRAME_TERMCAP_P (f))
{
int outq = PENDING_OUTPUT_COUNT (stdout);
if (outq > 900
|| (outq > 20 && ((i - 1) % preempt_count == 0)))
{
fflush (stdout);
if (preempt_count == 1)
{
#ifdef EMACS_OUTQSIZE
if (EMACS_OUTQSIZE (0, &outq) < 0)
outq = PENDING_OUTPUT_COUNT (stdout);
#endif
outq *= 10;
if (baud_rate <= outq && baud_rate > 0)
sleep (outq / baud_rate);
}
}
}
if ((i - 1) % preempt_count == 0)
detect_input_pending ();
update_line (f, i);
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (f))
{
current_frame->top_left_y[i] = downto;
current_frame->top_left_x[i] = leftmost;
}
#endif
}
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (f))
downto += current_frame->pix_height[i];
#endif
}
pause = (i < FRAME_HEIGHT (f) - 1) ? i : 0;
if (!pause)
{
if ((cursor_in_echo_area
|| (EQ (minibuf_window, selected_window)
&& EQ (minibuf_window, echo_area_window)
&& echo_area_glyphs != 0))
&& FRAME_HAS_MINIBUF_P (f)
&& EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
{
int top = XINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top);
int row, col;
if (cursor_in_echo_area < 0)
{
row = top;
col = 0;
}
else
{
row = FRAME_HEIGHT (f);
do
{
row--;
if (current_frame->enable[row])
col = current_frame->used[row];
else
col = 0;
}
while (row > top && col == 0);
if (col >= FRAME_CURSOR_X_LIMIT (f))
{
if (row < FRAME_HEIGHT (f) - 1)
{
col = FRAME_LEFT_SCROLL_BAR_WIDTH (f);
row++;
}
else
col = FRAME_CURSOR_X_LIMIT (f) - 1;
}
}
cursor_to (row, col);
}
else
cursor_to (FRAME_CURSOR_Y (f),
minmax (0, FRAME_CURSOR_X (f),
FRAME_CURSOR_X_LIMIT (f) - 1));
}
update_end (f);
if (termscript)
fflush (termscript);
fflush (stdout);
do_pause:
if (FRAME_HEIGHT (f) == 0) abort ();
display_completed = !pause;
bzero (FRAME_DESIRED_GLYPHS (f)->enable, FRAME_HEIGHT (f));
return pause;
}
void
quit_error_check ()
{
#if 0
if (FRAME_DESIRED_GLYPHS (selected_frame) == 0)
return;
if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[0])
abort ();
if (FRAME_DESIRED_GLYPHS (selected_frame)->enable[FRAME_HEIGHT (selected_frame) - 1])
abort ();
#endif
}
extern void scrolling_1 ();
int
scrolling (frame)
FRAME_PTR frame;
{
int unchanged_at_top, unchanged_at_bottom;
int window_size;
int changed_lines;
int *old_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
int *new_hash = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
int *draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
int *old_draw_cost = (int *) alloca (FRAME_HEIGHT (frame) * sizeof (int));
register int i;
int free_at_end_vpos = FRAME_HEIGHT (frame);
register struct frame_glyphs *current_frame = FRAME_CURRENT_GLYPHS (frame);
register struct frame_glyphs *desired_frame = FRAME_DESIRED_GLYPHS (frame);
changed_lines = 0;
unchanged_at_top = 0;
unchanged_at_bottom = FRAME_HEIGHT (frame);
for (i = 0; i < FRAME_HEIGHT (frame); i++)
{
if (!current_frame->enable[i])
return 0;
old_hash[i] = line_hash_code (current_frame, i);
if (! desired_frame->enable[i])
{
new_hash[i] = old_hash[i];
#define INFINITY 1000000
draw_cost[i] = INFINITY;
}
else
{
new_hash[i] = line_hash_code (desired_frame, i);
draw_cost[i] = line_draw_cost (desired_frame, i);
}
if (old_hash[i] != new_hash[i])
{
changed_lines++;
unchanged_at_bottom = FRAME_HEIGHT (frame) - i - 1;
}
else if (i == unchanged_at_top)
unchanged_at_top++;
old_draw_cost[i] = line_draw_cost (current_frame, i);
}
if (!scroll_region_ok && changed_lines < baud_rate / 2400
|| unchanged_at_bottom == FRAME_HEIGHT (frame))
return 1;
window_size = (FRAME_HEIGHT (frame) - unchanged_at_top
- unchanged_at_bottom);
if (scroll_region_ok)
free_at_end_vpos -= unchanged_at_bottom;
else if (memory_below_frame)
free_at_end_vpos = -1;
if (!scroll_region_ok && window_size >= 18 && baud_rate > 2400
&& (window_size >=
10 * scrolling_max_lines_saved (unchanged_at_top,
FRAME_HEIGHT (frame) - unchanged_at_bottom,
old_hash, new_hash, draw_cost)))
return 0;
scrolling_1 (frame, window_size, unchanged_at_top, unchanged_at_bottom,
draw_cost + unchanged_at_top - 1,
old_draw_cost + unchanged_at_top - 1,
old_hash + unchanged_at_top - 1,
new_hash + unchanged_at_top - 1,
free_at_end_vpos - unchanged_at_top);
return 0;
}
int
buffer_posn_from_coords (window, col, line)
struct window *window;
int col, line;
{
int hscroll = XINT (window->hscroll);
int window_left = WINDOW_LEFT_MARGIN (window);
int window_width = window_internal_width (window) - 1;
int startp = marker_position (window->start);
struct buffer *old_current_buffer = current_buffer;
struct position *posn;
current_buffer = XBUFFER (window->buffer);
if (startp < BEGV)
startp = BEGV;
posn = compute_motion (startp, 0,
((window == XWINDOW (minibuf_window) && startp == BEG
? minibuf_prompt_width : 0)
+ (hscroll ? 1 - hscroll : 0)),
0,
ZV, line, col,
window_width, hscroll, 0, window);
current_buffer = old_current_buffer;
if (posn->vpos > line)
return posn->bufpos - 1;
else
return posn->bufpos;
}
static int
count_blanks (r)
register GLYPH *r;
{
register GLYPH *p = r;
while (*p++ == SPACEGLYPH);
return p - r - 1;
}
static int
count_match (str1, str2)
GLYPH *str1, *str2;
{
register GLYPH *p1 = str1;
register GLYPH *p2 = str2;
while (*p1++ == *p2++);
return p1 - str1 - 1;
}
extern int *char_ins_del_vector;
#define char_ins_del_cost(f) (&char_ins_del_vector[FRAME_WINDOW_WIDTH((f))])
static void
update_line (frame, vpos)
register FRAME_PTR frame;
int vpos;
{
register GLYPH *obody, *nbody, *op1, *op2, *np1, *temp;
int *temp1;
int tem;
int osp, nsp, begmatch, endmatch, olen, nlen;
GLYPH save;
register struct frame_glyphs *current_frame
= FRAME_CURRENT_GLYPHS (frame);
register struct frame_glyphs *desired_frame
= FRAME_DESIRED_GLYPHS (frame);
if (desired_frame->highlight[vpos]
!= (current_frame->enable[vpos] && current_frame->highlight[vpos]))
{
change_line_highlight (desired_frame->highlight[vpos], vpos,
(current_frame->enable[vpos] ?
current_frame->used[vpos] : 0));
current_frame->enable[vpos] = 0;
}
else
reassert_line_highlight (desired_frame->highlight[vpos], vpos);
if (! current_frame->enable[vpos])
{
olen = 0;
}
else
{
obody = current_frame->glyphs[vpos];
olen = current_frame->used[vpos];
if (! current_frame->highlight[vpos])
{
if (!must_write_spaces)
while (olen > 0 && obody[olen - 1] == SPACEGLYPH)
olen--;
}
else
{
while (olen < FRAME_WINDOW_WIDTH (frame) - 1)
obody[olen++] = SPACEGLYPH;
}
}
current_frame->enable[vpos] = 1;
current_frame->used[vpos] = desired_frame->used[vpos];
current_frame->highlight[vpos] = desired_frame->highlight[vpos];
current_frame->bufp[vpos] = desired_frame->bufp[vpos];
#ifdef HAVE_WINDOW_SYSTEM
if (FRAME_WINDOW_P (frame))
{
current_frame->pix_width[vpos]
= current_frame->used[vpos]
* FONT_WIDTH (FRAME_FONT (frame));
current_frame->pix_height[vpos]
= FRAME_LINE_HEIGHT (frame);
}
#endif
if (!desired_frame->enable[vpos])
{
nlen = 0;
goto just_erase;
}
nbody = desired_frame->glyphs[vpos];
nlen = desired_frame->used[vpos];
if (! desired_frame->highlight[vpos])
{
if (!must_write_spaces)
while (nbody[nlen - 1] == SPACEGLYPH)
nlen--;
}
else
{
while (nlen < FRAME_WINDOW_WIDTH (frame) - 1)
nbody[nlen++] = SPACEGLYPH;
}
if (!char_ins_del_ok)
{
int i,j;
#if 0
if (FRAME_X_P (frame))
{
for (i = 0; i < nlen; i++)
if (i >= olen || nbody[i] != obody[i])
break;
cursor_to (vpos, i);
if (i != olen)
clear_end_of_line (olen);
write_glyphs (nbody + i, nlen - i);
}
else
{}
#endif
for (i = 0; i < nlen; i++)
{
if (i >= olen || nbody[i] != obody[i])
{
cursor_to (vpos, i);
for (j = 1;
(i + j < nlen
&& (i + j >= olen || nbody[i + j] != obody[i + j]
|| (nbody[i + j] & GLYPH_MASK_PADDING)));
j++);
write_glyphs (nbody + i, j);
i += j - 1;
}
}
if (olen > nlen)
{
cursor_to (vpos, nlen);
clear_end_of_line (olen);
}
temp = desired_frame->glyphs[vpos];
desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
current_frame->glyphs[vpos] = temp;
temp1 = desired_frame->charstarts[vpos];
desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
current_frame->charstarts[vpos] = temp1;
return;
}
if (!olen)
{
nsp = (must_write_spaces || desired_frame->highlight[vpos])
? 0 : count_blanks (nbody);
if (nlen > nsp)
{
cursor_to (vpos, nsp);
write_glyphs (nbody + nsp, nlen - nsp);
}
temp = desired_frame->glyphs[vpos];
desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
current_frame->glyphs[vpos] = temp;
temp1 = desired_frame->charstarts[vpos];
desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
current_frame->charstarts[vpos] = temp1;
return;
}
obody[olen] = 1;
save = nbody[nlen];
nbody[nlen] = 0;
osp = count_blanks (obody);
if (!desired_frame->highlight[vpos])
nsp = count_blanks (nbody);
else
nsp = 0;
begmatch = count_match (obody + osp, nbody + nsp);
if (!must_write_spaces && osp + begmatch == olen)
{
np1 = nbody + nsp;
while (np1[begmatch] == SPACEGLYPH)
begmatch++;
}
if (begmatch == 0 && osp != nsp)
osp = nsp = min (osp, nsp);
op1 = obody + olen;
np1 = nbody + nlen;
op2 = op1 + begmatch - min (olen - osp, nlen - nsp);
while (op1 > op2 && op1[-1] == np1[-1])
{
op1--;
np1--;
}
endmatch = obody + olen - op1;
nbody[nlen] = save;
obody[olen] = 0;
tem = (nlen - nsp) - (olen - osp);
if (endmatch && tem
&& (!char_ins_del_ok || endmatch <= char_ins_del_cost (frame)[tem]))
endmatch = 0;
if (nsp != osp
&& (!char_ins_del_ok
|| begmatch + endmatch <= char_ins_del_cost (frame)[nsp - osp]))
{
begmatch = 0;
endmatch = 0;
osp = nsp = min (osp, nsp);
}
if (osp > nsp)
{
cursor_to (vpos, nsp);
delete_glyphs (osp - nsp);
}
else if (nsp > osp)
{
if (endmatch && nlen < olen + nsp - osp)
{
cursor_to (vpos, nlen - endmatch + osp - nsp);
delete_glyphs (olen + nsp - osp - nlen);
olen = nlen - (nsp - osp);
}
cursor_to (vpos, osp);
insert_glyphs ((GLYPH *) 0, nsp - osp);
}
olen += nsp - osp;
tem = nsp + begmatch + endmatch;
if (nlen != tem || olen != tem)
{
cursor_to (vpos, nsp + begmatch);
if (!endmatch || nlen == olen)
{
if (nlen == FRAME_WINDOW_WIDTH (frame))
olen = 0;
write_glyphs (nbody + nsp + begmatch, nlen - tem);
#ifdef obsolete
if (nlen == FRAME_WINDOW_WIDTH (frame) && fast_clear_end_of_line && olen > nlen)
{
write_glyphs (nbody + tem, nlen - tem - 1);
clear_end_of_line (olen);
olen = 0;
write_glyphs (nbody + nlen - 1, 1);
}
else
write_glyphs (nbody + nsp + begmatch, nlen - tem);
#endif
}
else if (nlen > olen)
{
int out = olen - tem;
int del;
while (nbody[nsp + begmatch + out] & GLYPH_MASK_PADDING) out--;
write_glyphs (nbody + nsp + begmatch, out);
del = olen - tem - out;
if (del > 0) delete_glyphs (del);
insert_glyphs (nbody + nsp + begmatch + out, nlen - olen + del);
olen = nlen;
}
else if (olen > nlen)
{
write_glyphs (nbody + nsp + begmatch, nlen - tem);
delete_glyphs (olen - nlen);
olen = nlen;
}
}
just_erase:
if (olen > nlen)
{
cursor_to (vpos, nlen);
clear_end_of_line (olen);
}
temp = desired_frame->glyphs[vpos];
desired_frame->glyphs[vpos] = current_frame->glyphs[vpos];
current_frame->glyphs[vpos] = temp;
temp1 = desired_frame->charstarts[vpos];
desired_frame->charstarts[vpos] = current_frame->charstarts[vpos];
current_frame->charstarts[vpos] = temp1;
}
static Lisp_Object frame_and_buffer_state;
DEFUN ("frame-or-buffer-changed-p", Fframe_or_buffer_changed_p,
Sframe_or_buffer_changed_p, 0, 0, 0,
"Return non-nil if the frame and buffer state appears to have changed.\n\
The state variable is an internal vector containing all frames and buffers,\n\
aside from buffers whose names start with space,\n\
along with the buffers' read-only and modified flags, which allows a fast\n\
check to see whether the menu bars might need to be recomputed.\n\
If this function returns non-nil, it updates the internal vector to reflect\n\
the current state.\n")
()
{
Lisp_Object tail, frame, buf;
Lisp_Object *vecp;
int n;
vecp = XVECTOR (frame_and_buffer_state)->contents;
FOR_EACH_FRAME (tail, frame)
{
if (!EQ (*vecp++, frame))
goto changed;
if (!EQ (*vecp++, XFRAME (frame)->name))
goto changed;
}
for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
{
buf = XCONS (XCONS (tail)->car)->cdr;
if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
continue;
if (!EQ (*vecp++, buf))
goto changed;
if (!EQ (*vecp++, XBUFFER (buf)->read_only))
goto changed;
if (!EQ (*vecp++, Fbuffer_modified_p (buf)))
goto changed;
}
if (EQ (*vecp, Qlambda))
return Qnil;
changed:
n = 1;
FOR_EACH_FRAME (tail, frame)
n += 2;
for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
n += 3;
if (n > XVECTOR (frame_and_buffer_state)->size
|| n + 20 < XVECTOR (frame_and_buffer_state)->size / 2)
frame_and_buffer_state = Fmake_vector (make_number (n + 20), Qlambda);
vecp = XVECTOR (frame_and_buffer_state)->contents;
FOR_EACH_FRAME (tail, frame)
{
*vecp++ = frame;
*vecp++ = XFRAME (frame)->name;
}
for (tail = Vbuffer_alist; CONSP (tail); tail = XCONS (tail)->cdr)
{
buf = XCONS (XCONS (tail)->car)->cdr;
if (XSTRING (XBUFFER (buf)->name)->data[0] == ' ')
continue;
*vecp++ = buf;
*vecp++ = XBUFFER (buf)->read_only;
*vecp++ = Fbuffer_modified_p (buf);
}
*vecp++ = Qlambda;
while (vecp - XVECTOR (frame_and_buffer_state)->contents
< XVECTOR (frame_and_buffer_state)->size)
*vecp++ = Qlambda;
if (vecp - XVECTOR (frame_and_buffer_state)->contents
> XVECTOR (frame_and_buffer_state)->size)
abort ();
return Qt;
}
DEFUN ("open-termscript", Fopen_termscript, Sopen_termscript,
1, 1, "FOpen termscript file: ",
"Start writing all terminal output to FILE as well as the terminal.\n\
FILE = nil means just close any termscript file currently open.")
(file)
Lisp_Object file;
{
if (termscript != 0) fclose (termscript);
termscript = 0;
if (! NILP (file))
{
file = Fexpand_file_name (file, Qnil);
termscript = fopen (XSTRING (file)->data, "w");
if (termscript == 0)
report_file_error ("Opening termscript", Fcons (file, Qnil));
}
return Qnil;
}
#ifdef SIGWINCH
SIGTYPE
window_change_signal (signalnum)
int signalnum;
{
int width, height;
extern int errno;
int old_errno = errno;
get_frame_size (&width, &height);
{
Lisp_Object tail, frame;
FOR_EACH_FRAME (tail, frame)
{
if (FRAME_TERMCAP_P (XFRAME (frame)))
{
change_frame_size (XFRAME (frame), height, width, 0, 1);
break;
}
}
}
signal (SIGWINCH, window_change_signal);
errno = old_errno;
}
#endif
void
do_pending_window_change ()
{
while (delayed_size_change)
{
Lisp_Object tail, frame;
delayed_size_change = 0;
FOR_EACH_FRAME (tail, frame)
{
FRAME_PTR f = XFRAME (frame);
int height = FRAME_NEW_HEIGHT (f);
int width = FRAME_NEW_WIDTH (f);
if (height != 0 || width != 0)
change_frame_size (f, height, width, 0, 0);
}
}
}
void
change_frame_size (f, newheight, newwidth, pretend, delay)
register FRAME_PTR f;
int newheight, newwidth, pretend, delay;
{
Lisp_Object tail, frame;
if (! FRAME_WINDOW_P (f))
{
FOR_EACH_FRAME (tail, frame)
if (! FRAME_WINDOW_P (XFRAME (frame)))
change_frame_size_1 (XFRAME (frame), newheight, newwidth,
pretend, delay);
}
else
change_frame_size_1 (f, newheight, newwidth, pretend, delay);
}
static void
change_frame_size_1 (frame, newheight, newwidth, pretend, delay)
register FRAME_PTR frame;
int newheight, newwidth, pretend, delay;
{
int new_frame_window_width;
unsigned int total_glyphs;
int count = specpdl_ptr - specpdl;
if (delay)
{
FRAME_NEW_HEIGHT (frame) = newheight;
FRAME_NEW_WIDTH (frame) = newwidth;
delayed_size_change = 1;
return;
}
FRAME_NEW_HEIGHT (frame) = 0;
FRAME_NEW_WIDTH (frame) = 0;
if (newheight == 0)
newheight = FRAME_HEIGHT (frame);
if (newwidth == 0)
newwidth = FRAME_WIDTH (frame);
new_frame_window_width = FRAME_WINDOW_WIDTH_ARG (frame, newwidth);
total_glyphs = newheight * (newwidth + 2) * sizeof (GLYPH);
if (total_glyphs / sizeof (GLYPH) / newheight != newwidth + 2)
return;
check_frame_size (frame, &newheight, &newwidth);
if (newheight == FRAME_HEIGHT (frame)
&& new_frame_window_width == FRAME_WINDOW_WIDTH (frame))
return;
BLOCK_INPUT;
#ifdef MSDOS
dos_set_window_size (&newheight, &newwidth);
#endif
if (newheight != FRAME_HEIGHT (frame))
{
if (FRAME_HAS_MINIBUF_P (frame)
&& ! FRAME_MINIBUF_ONLY_P (frame))
{
set_window_height (FRAME_ROOT_WINDOW (frame),
newheight - 1 - FRAME_MENU_BAR_LINES (frame), 0);
XSETFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (frame))->top,
newheight - 1);
set_window_height (FRAME_MINIBUF_WINDOW (frame), 1, 0);
}
else
set_window_height (FRAME_ROOT_WINDOW (frame),
newheight - FRAME_MENU_BAR_LINES (frame), 0);
if (FRAME_TERMCAP_P (frame) && !pretend)
FrameRows = newheight;
#if 0
if (frame->output_method == output_termcap)
{
frame_height = newheight;
if (!pretend)
FrameRows = newheight;
}
#endif
}
if (new_frame_window_width != FRAME_WINDOW_WIDTH (frame))
{
set_window_width (FRAME_ROOT_WINDOW (frame), new_frame_window_width, 0);
if (FRAME_HAS_MINIBUF_P (frame))
set_window_width (FRAME_MINIBUF_WINDOW (frame), new_frame_window_width, 0);
if (FRAME_TERMCAP_P (frame) && !pretend)
FrameCols = newwidth;
#if 0
if (frame->output_method == output_termcap)
{
frame_width = newwidth;
if (!pretend)
FrameCols = newwidth;
}
#endif
}
FRAME_HEIGHT (frame) = newheight;
SET_FRAME_WIDTH (frame, newwidth);
if (FRAME_CURSOR_X (frame) >= FRAME_CURSOR_X_LIMIT (frame))
FRAME_CURSOR_X (frame) = FRAME_CURSOR_X_LIMIT (frame) - 1;
if (FRAME_CURSOR_Y (frame) >= FRAME_HEIGHT (frame))
FRAME_CURSOR_Y (frame) = FRAME_HEIGHT (frame) - 1;
remake_frame_glyphs (frame);
calculate_costs (frame);
UNBLOCK_INPUT;
record_unwind_protect (Fset_buffer, Fcurrent_buffer ());
Fset_window_buffer (FRAME_SELECTED_WINDOW (frame),
XWINDOW (FRAME_SELECTED_WINDOW (frame))->buffer);
unbind_to (count, Qnil);
}
DEFUN ("send-string-to-terminal", Fsend_string_to_terminal,
Ssend_string_to_terminal, 1, 1, 0,
"Send STRING to the terminal without alteration.\n\
Control characters in STRING will have terminal-dependent effects.")
(string)
Lisp_Object string;
{
CHECK_STRING (string, 0);
fwrite (XSTRING (string)->data, 1, STRING_BYTES (XSTRING (string)), stdout);
fflush (stdout);
if (termscript)
{
fwrite (XSTRING (string)->data, 1, STRING_BYTES (XSTRING (string)),
termscript);
fflush (termscript);
}
return Qnil;
}
DEFUN ("ding", Fding, Sding, 0, 1, 0,
"Beep, or flash the screen.\n\
Also, unless an argument is given,\n\
terminate any keyboard macro currently executing.")
(arg)
Lisp_Object arg;
{
if (!NILP (arg))
{
if (noninteractive)
putchar (07);
else
ring_bell ();
fflush (stdout);
}
else
bitch_at_user ();
return Qnil;
}
void
bitch_at_user ()
{
if (noninteractive)
putchar (07);
else if (!INTERACTIVE)
error ("Keyboard macro terminated by a command ringing the bell");
else
ring_bell ();
fflush (stdout);
}
DEFUN ("sleep-for", Fsleep_for, Ssleep_for, 1, 2, 0,
"Pause, without updating display, for SECONDS seconds.\n\
SECONDS may be a floating-point value, meaning that you can wait for a\n\
fraction of a second. Optional second arg MILLISECONDS specifies an\n\
additional wait period, in milliseconds; this may be useful if your\n\
Emacs was built without floating point support.\n\
\(Not all operating systems support waiting for a fraction of a second.)")
(seconds, milliseconds)
Lisp_Object seconds, milliseconds;
{
int sec, usec;
if (NILP (milliseconds))
XSETINT (milliseconds, 0);
else
CHECK_NUMBER (milliseconds, 1);
usec = XINT (milliseconds) * 1000;
#ifdef LISP_FLOAT_TYPE
{
double duration = extract_float (seconds);
sec = (int) duration;
usec += (duration - sec) * 1000000;
}
#else
CHECK_NUMBER (seconds, 0);
sec = XINT (seconds);
#endif
#ifndef EMACS_HAS_USECS
if (sec == 0 && usec != 0)
error ("millisecond `sleep-for' not supported on %s", SYSTEM_TYPE);
#endif
if (usec < 0)
{
if (-1000000 < usec)
sec--, usec += 1000000;
else
sec -= -usec / 1000000, usec = 1000000 - (-usec % 1000000);
}
else
sec += usec / 1000000, usec %= 1000000;
if (sec < 0 || (sec == 0 && usec == 0))
return Qnil;
{
Lisp_Object zero;
XSETFASTINT (zero, 0);
wait_reading_process_input (sec, usec, zero, 0);
}
#if 0
immediate_quit = 1;
QUIT;
#ifdef VMS
sys_sleep (sec);
#else
#ifdef HAVE_SELECT
EMACS_GET_TIME (end_time);
EMACS_SET_SECS_USECS (timeout, sec, usec);
EMACS_ADD_TIME (end_time, end_time, timeout);
while (1)
{
EMACS_GET_TIME (timeout);
EMACS_SUB_TIME (timeout, end_time, timeout);
if (EMACS_TIME_NEG_P (timeout)
|| !select (1, 0, 0, 0, &timeout))
break;
}
#else
sleep (sec);
#endif
#endif
immediate_quit = 0;
#endif
return Qnil;
}
Lisp_Object
sit_for (sec, usec, reading, display, initial_display)
int sec, usec, reading, display, initial_display;
{
Lisp_Object read_kbd;
swallow_events (display);
if (detect_input_pending_run_timers (display))
return Qnil;
if (initial_display)
redisplay_preserve_echo_area ();
if (sec == 0 && usec == 0)
return Qt;
#ifdef SIGIO
gobble_input (0);
#endif
XSETINT (read_kbd, reading ? -1 : 1);
wait_reading_process_input (sec, usec, read_kbd, display);
return detect_input_pending () ? Qnil : Qt;
}
DEFUN ("sit-for", Fsit_for, Ssit_for, 1, 3, 0,
"Perform redisplay, then wait for SECONDS seconds or until input is available.\n\
SECONDS may be a floating-point value, meaning that you can wait for a\n\
fraction of a second. Optional second arg MILLISECONDS specifies an\n\
additional wait period, in milliseconds; this may be useful if your\n\
Emacs was built without floating point support.\n\
\(Not all operating systems support waiting for a fraction of a second.)\n\
Optional third arg NODISP non-nil means don't redisplay, just wait for input.\n\
Redisplay is preempted as always if input arrives, and does not happen\n\
if input is available before it starts.\n\
Value is t if waited the full time with no input arriving.")
(seconds, milliseconds, nodisp)
Lisp_Object seconds, milliseconds, nodisp;
{
int sec, usec;
if (NILP (milliseconds))
XSETINT (milliseconds, 0);
else
CHECK_NUMBER (milliseconds, 1);
usec = XINT (milliseconds) * 1000;
#ifdef LISP_FLOAT_TYPE
{
double duration = extract_float (seconds);
sec = (int) duration;
usec += (duration - sec) * 1000000;
}
#else
CHECK_NUMBER (seconds, 0);
sec = XINT (seconds);
#endif
#ifndef EMACS_HAS_USECS
if (usec != 0 && sec == 0)
error ("millisecond `sit-for' not supported on %s", SYSTEM_TYPE);
#endif
return sit_for (sec, usec, 0, NILP (nodisp), NILP (nodisp));
}
char *terminal_type;
void
init_display ()
{
#ifdef HAVE_X_WINDOWS
extern int display_arg;
#endif
meta_key = 0;
inverse_video = 0;
cursor_in_echo_area = 0;
terminal_type = (char *) 0;
Vwindow_system = Qnil;
#ifdef HAVE_X_WINDOWS
if (! display_arg)
{
char *display;
#ifdef VMS
display = getenv ("DECW$DISPLAY");
#else
display = getenv ("DISPLAY");
#endif
display_arg = (display != 0 && *display != 0);
}
if (!inhibit_window_system && display_arg
#ifndef CANNOT_DUMP
&& initialized
#endif
)
{
Vwindow_system = intern ("x");
#ifdef HAVE_X11
Vwindow_system_version = make_number (11);
#else
Vwindow_system_version = make_number (10);
#endif
#if defined (LINUX) && defined (HAVE_LIBNCURSES)
{ char b[2044]; tgetent (b, "xterm");}
#endif
return;
}
#endif
#ifdef HAVE_NTGUI
if (!inhibit_window_system)
{
Vwindow_system = intern ("w32");
Vwindow_system_version = make_number (1);
return;
}
#endif
if (! isatty (0))
{
fatal ("standard input is not a tty");
exit (1);
}
terminal_type = (char *) getenv ("TERM");
if (!terminal_type)
{
#ifdef VMS
fprintf (stderr, "Please specify your terminal type.\n\
For types defined in VMS, use set term /device=TYPE.\n\
For types not defined in VMS, use define emacs_term \"TYPE\".\n\
\(The quotation marks are necessary since terminal types are lower case.)\n");
#else
fprintf (stderr, "Please set the environment variable TERM; see tset(1).\n");
#endif
exit (1);
}
#ifdef VMS
{
char *new = (char *) xmalloc (strlen (terminal_type) + 1);
char *p;
strcpy (new, terminal_type);
for (p = new; *p; p++)
if (isupper (*p))
*p = tolower (*p);
terminal_type = new;
}
#endif
term_init (terminal_type);
{
int width = FRAME_WINDOW_WIDTH (selected_frame);
int height = FRAME_HEIGHT (selected_frame);
unsigned int total_glyphs = height * (width + 2) * sizeof (GLYPH);
if (total_glyphs / sizeof (GLYPH) / height != width + 2)
fatal ("screen size %dx%d too big", width, height);
}
remake_frame_glyphs (selected_frame);
calculate_costs (selected_frame);
FRAME_CURSOR_X (selected_frame) = 0;
FRAME_CURSOR_Y (selected_frame) = 0;
#ifdef SIGWINCH
#ifndef CANNOT_DUMP
if (initialized)
#endif
signal (SIGWINCH, window_change_signal);
#endif
}
void
syms_of_display ()
{
defsubr (&Sredraw_frame);
defsubr (&Sredraw_display);
defsubr (&Sframe_or_buffer_changed_p);
defsubr (&Sopen_termscript);
defsubr (&Sding);
defsubr (&Ssit_for);
defsubr (&Ssleep_for);
defsubr (&Ssend_string_to_terminal);
frame_and_buffer_state = Fmake_vector (make_number (20), Qlambda);
staticpro (&frame_and_buffer_state);
Qdisplay_table = intern ("display-table");
staticpro (&Qdisplay_table);
DEFVAR_INT ("baud-rate", &baud_rate,
"*The output baud rate of the terminal.\n\
On most systems, changing this value will affect the amount of padding\n\
and the other strategic decisions made during redisplay.");
DEFVAR_BOOL ("inverse-video", &inverse_video,
"*Non-nil means invert the entire frame display.\n\
This means everything is in inverse video which otherwise would not be.");
DEFVAR_BOOL ("visible-bell", &visible_bell,
"*Non-nil means try to flash the frame to represent a bell.");
DEFVAR_BOOL ("no-redraw-on-reenter", &no_redraw_on_reenter,
"*Non-nil means no need to redraw entire frame after suspending.\n\
A non-nil value is useful if the terminal can automatically preserve\n\
Emacs's frame display when you reenter Emacs.\n\
It is up to you to set this variable if your terminal can do that.");
DEFVAR_LISP ("window-system", &Vwindow_system,
"A symbol naming the window-system under which Emacs is running\n\
\(such as `x'), or nil if emacs is running on an ordinary terminal.");
DEFVAR_LISP ("window-system-version", &Vwindow_system_version,
"The version number of the window system in use.\n\
For X windows, this is 10 or 11.");
DEFVAR_BOOL ("cursor-in-echo-area", &cursor_in_echo_area,
"Non-nil means put cursor in minibuffer, at end of any message there.");
DEFVAR_LISP ("glyph-table", &Vglyph_table,
"Table defining how to output a glyph code to the frame.\n\
If not nil, this is a vector indexed by glyph code to define the glyph.\n\
Each element can be:\n\
integer: a glyph code which this glyph is an alias for.\n\
string: output this glyph using that string (not impl. in X windows).\n\
nil: this glyph mod 256 is char code to output,\n\
and this glyph / 256 is face code for X windows (see `face-id').");
Vglyph_table = Qnil;
DEFVAR_LISP ("standard-display-table", &Vstandard_display_table,
"Display table to use for buffers that specify none.\n\
See `buffer-display-table' for more information.");
Vstandard_display_table = Qnil;
#ifdef CANNOT_DUMP
if (noninteractive)
#endif
{
Vwindow_system = Qnil;
Vwindow_system_version = Qnil;
}
}