#include <config.h>
#include <stdio.h>
#undef NULL
#include "lisp.h"
#include "frame.h"
#include "window.h"
#include "termchar.h"
#include "dispextern.h"
#include "buffer.h"
#include "charset.h"
#include "indent.h"
#include "commands.h"
#include "macros.h"
#include "disptab.h"
#include "termhooks.h"
#include "intervals.h"
#include "keyboard.h"
#include "coding.h"
#include "process.h"
#include "region-cache.h"
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
extern void set_frame_menubar ();
extern int pending_menu_activation;
#endif
extern int interrupt_input;
extern int command_loop_level;
extern int minibuffer_auto_raise;
extern Lisp_Object Qface;
extern Lisp_Object Voverriding_local_map;
extern Lisp_Object Voverriding_local_map_menu_flag;
Lisp_Object Qoverriding_local_map, Qoverriding_terminal_local_map;
Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions;
Lisp_Object Qredisplay_end_trigger_functions;
Lisp_Object Qinhibit_point_motion_hooks;
Lisp_Object Vinhibit_redisplay, Qinhibit_redisplay;
int noninteractive_need_newline;
static int message_log_need_newline;
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
#define minmax(floor, val, ceil) \
((val) < (floor) ? (floor) : (val) > (ceil) ? (ceil) : (val))
static int this_line_bufpos;
static int this_line_endpos;
static int this_line_vpos;
static int this_line_start_hpos;
static struct buffer *this_line_buffer;
char *previous_echo_glyphs;
int truncate_partial_width_windows;
int unibyte_display_via_language_environment;
int multiple_frames;
Lisp_Object Vglobal_mode_string;
Lisp_Object Voverlay_arrow_position;
Lisp_Object Voverlay_arrow_string;
static Lisp_Object last_arrow_position, last_arrow_string;
Lisp_Object Vframe_title_format;
Lisp_Object Vicon_title_format;
static Lisp_Object Vwindow_size_change_functions;
Lisp_Object Qmenu_bar_update_hook;
static int overlay_arrow_seen;
static int zv_strings_seen;
static int highlight_nonselected_windows;
static int scroll_step;
static int scroll_conservatively;
int scroll_margin;
static int minibuffer_scroll_overlap;
static int blank_end_of_window;
int buffer_shared;
static int cursor_vpos;
static int cursor_hpos;
static int debug_end_pos;
int mode_line_inverse_video;
static void redisplay_internal ();
static int message_log_check_duplicate ();
static void echo_area_display ();
void mark_window_display_accurate ();
static void redisplay_windows ();
static void redisplay_window ();
static void update_menu_bar ();
static void try_window ();
static int try_window_id ();
static struct position *display_text_line ();
static void display_mode_line ();
static int display_mode_element ();
static char *decode_mode_spec ();
static int display_string ();
static void display_menu_bar ();
static int display_count_lines ();
Lisp_Object minibuf_prompt;
int minibuf_prompt_width;
char *echo_area_glyphs;
int echo_area_glyphs_length;
Lisp_Object echo_area_window;
int message_enable_multibyte;
int update_mode_lines;
int beg_unchanged;
int end_unchanged;
int unchanged_modified;
int overlay_unchanged_modified;
int windows_or_buffers_changed;
int line_number_displayed;
static int line_number_display_limit;
Lisp_Object Vmessage_log_max;
#define COERCE_MARKER(X) \
(MARKERP ((X)) ? Fmarker_position (X) : (X))
static int pos_tab_offset P_ ((struct window *, int, int));
void
message_log_maybe_newline ()
{
if (message_log_need_newline)
message_dolog ("", 0, 1, 0);
}
void
message_dolog (m, len, nlflag, multibyte)
char *m;
int len, nlflag, multibyte;
{
if (!NILP (Vmessage_log_max))
{
struct buffer *oldbuf;
Lisp_Object oldpoint, oldbegv, oldzv;
int old_windows_or_buffers_changed = windows_or_buffers_changed;
int point_at_end = 0;
int zv_at_end = 0;
Lisp_Object old_deactivate_mark, tem;
struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
old_deactivate_mark = Vdeactivate_mark;
oldbuf = current_buffer;
Fset_buffer (Fget_buffer_create (build_string ("*Messages*")));
current_buffer->undo_list = Qt;
oldpoint = Fpoint_marker ();
oldbegv = Fpoint_min_marker ();
oldzv = Fpoint_max_marker ();
GCPRO4 (oldpoint, oldbegv, oldzv, old_deactivate_mark);
if (PT == Z)
point_at_end = 1;
if (ZV == Z)
zv_at_end = 1;
BEGV = BEG;
BEGV_BYTE = BEG_BYTE;
ZV = Z;
ZV_BYTE = Z_BYTE;
TEMP_SET_PT_BOTH (Z, Z_BYTE);
if (multibyte
&& NILP (current_buffer->enable_multibyte_characters))
{
int i, c, nbytes;
unsigned char work[1];
for (i = 0; i < len; i += nbytes)
{
c = STRING_CHAR_AND_LENGTH (m + i, len - i, nbytes);
work[0] = (SINGLE_BYTE_CHAR_P (c)
? c
: multibyte_char_to_unibyte (c, Qnil));
insert_1_both (work, 1, 1, 1, 0, 0);
}
}
else if (! multibyte
&& ! NILP (current_buffer->enable_multibyte_characters))
{
int i, c, nbytes;
unsigned char *msg = (unsigned char *) m;
unsigned char *str, work[4];
for (i = 0; i < len; i++)
{
c = unibyte_char_to_multibyte (msg[i]);
nbytes = CHAR_STRING (c, work, str);
insert_1_both (work, 1, nbytes, 1, 0, 0);
}
}
else if (len)
insert_1 (m, len, 1, 0, 0);
if (nlflag)
{
int this_bol, this_bol_byte, prev_bol, prev_bol_byte, dup;
insert_1 ("\n", 1, 1, 0, 0);
scan_newline (Z, Z_BYTE, BEG, BEG_BYTE, -2, 0);
this_bol = PT;
this_bol_byte = PT_BYTE;
if (this_bol > BEG)
{
scan_newline (PT, PT_BYTE, BEG, BEG_BYTE, -2, 0);
prev_bol = PT;
prev_bol_byte = PT_BYTE;
dup = message_log_check_duplicate (prev_bol, prev_bol_byte,
this_bol, this_bol_byte);
if (dup)
{
del_range_both (prev_bol, prev_bol_byte,
this_bol, this_bol_byte, 0);
if (dup > 1)
{
char dupstr[40];
int duplen;
sprintf (dupstr, " [%d times]", dup);
duplen = strlen (dupstr);
TEMP_SET_PT_BOTH (Z - 1, Z_BYTE - 1);
insert_1 (dupstr, duplen, 1, 0, 1);
}
}
}
if (NATNUMP (Vmessage_log_max))
{
scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
-XFASTINT (Vmessage_log_max) - 1, 0);
del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, 0);
}
}
BEGV = XMARKER (oldbegv)->charpos;
BEGV_BYTE = marker_byte_position (oldbegv);
if (zv_at_end)
{
ZV = Z;
ZV_BYTE = Z_BYTE;
}
else
{
ZV = XMARKER (oldzv)->charpos;
ZV_BYTE = marker_byte_position (oldzv);
}
if (point_at_end)
TEMP_SET_PT_BOTH (Z, Z_BYTE);
else
TEMP_SET_PT_BOTH (XMARKER (oldpoint)->charpos,
XMARKER (oldpoint)->bytepos);
UNGCPRO;
free_marker (oldpoint);
free_marker (oldbegv);
free_marker (oldzv);
tem = Fget_buffer_window (Fcurrent_buffer (), Qt);
set_buffer_internal (oldbuf);
if (NILP (tem))
windows_or_buffers_changed = old_windows_or_buffers_changed;
message_log_need_newline = !nlflag;
Vdeactivate_mark = old_deactivate_mark;
}
}
static int
message_log_check_duplicate (prev_bol, prev_bol_byte, this_bol, this_bol_byte)
int prev_bol, this_bol;
int prev_bol_byte, this_bol_byte;
{
int i;
int len = Z_BYTE - 1 - this_bol_byte;
int seen_dots = 0;
unsigned char *p1 = BUF_BYTE_ADDRESS (current_buffer, prev_bol_byte);
unsigned char *p2 = BUF_BYTE_ADDRESS (current_buffer, this_bol_byte);
for (i = 0; i < len; i++)
{
if (i >= 3 && p1[i-3] == '.' && p1[i-2] == '.' && p1[i-1] == '.'
&& p1[i] != '\n')
seen_dots = 1;
if (p1[i] != p2[i])
return seen_dots;
}
p1 += len;
if (*p1 == '\n')
return 2;
if (*p1++ == ' ' && *p1++ == '[')
{
int n = 0;
while (*p1 >= '0' && *p1 <= '9')
n = n * 10 + *p1++ - '0';
if (strncmp (p1, " times]\n", 8) == 0)
return n+1;
}
return 0;
}
void
message2 (m, len, multibyte)
char *m;
int len;
int multibyte;
{
message_log_maybe_newline ();
if (m)
message_dolog (m, len, 1, multibyte);
message2_nolog (m, len, multibyte);
}
void
message2_nolog (m, len, multibyte)
char *m;
int len;
{
message_enable_multibyte = multibyte;
if (noninteractive)
{
if (noninteractive_need_newline)
putc ('\n', stderr);
noninteractive_need_newline = 0;
if (m)
fwrite (m, len, 1, stderr);
if (cursor_in_echo_area == 0)
fprintf (stderr, "\n");
fflush (stderr);
}
else if (INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
{
Lisp_Object mini_window;
FRAME_PTR f;
mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
FRAME_SAMPLE_VISIBILITY (f);
if (FRAME_VISIBLE_P (selected_frame)
&& ! FRAME_VISIBLE_P (f))
Fmake_frame_visible (WINDOW_FRAME (XWINDOW (mini_window)));
if (m)
{
echo_area_glyphs = m;
echo_area_glyphs_length = len;
if (minibuffer_auto_raise)
Fraise_frame (WINDOW_FRAME (XWINDOW (mini_window)));
}
else
echo_area_glyphs = previous_echo_glyphs = 0;
do_pending_window_change ();
echo_area_display ();
update_frame (f, 1, 1);
do_pending_window_change ();
if (frame_up_to_date_hook != 0 && ! gc_in_progress)
(*frame_up_to_date_hook) (f);
}
}
void
message1 (m)
char *m;
{
message2 (m, (m ? strlen (m) : 0), 0);
}
void
message1_nolog (m)
char *m;
{
message2_nolog (m, (m ? strlen (m) : 0), 0);
}
void
message_with_string (m, string, log)
char *m;
Lisp_Object string;
int log;
{
if (noninteractive)
{
if (m)
{
if (noninteractive_need_newline)
putc ('\n', stderr);
noninteractive_need_newline = 0;
fprintf (stderr, m, XSTRING (string)->data);
if (cursor_in_echo_area == 0)
fprintf (stderr, "\n");
fflush (stderr);
}
}
else if (INTERACTIVE)
{
Lisp_Object mini_window;
FRAME_PTR f;
mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
if (FRAME_MESSAGE_BUF (f))
{
int len;
char *a[1];
a[0] = (char *) XSTRING (string)->data;
len = doprnt (FRAME_MESSAGE_BUF (f),
FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
if (log)
message2 (FRAME_MESSAGE_BUF (f), len,
STRING_MULTIBYTE (string));
else
message2_nolog (FRAME_MESSAGE_BUF (f), len,
STRING_MULTIBYTE (string));
message_buf_print = 0;
}
}
}
void
truncate_echo_area (len)
int len;
{
if (!noninteractive && INTERACTIVE && FRAME_MESSAGE_BUF (selected_frame))
echo_area_glyphs_length = len;
}
int message_buf_print;
void
message (m, a1, a2, a3)
char *m;
EMACS_INT a1, a2, a3;
{
if (noninteractive)
{
if (m)
{
if (noninteractive_need_newline)
putc ('\n', stderr);
noninteractive_need_newline = 0;
fprintf (stderr, m, a1, a2, a3);
if (cursor_in_echo_area == 0)
fprintf (stderr, "\n");
fflush (stderr);
}
}
else if (INTERACTIVE)
{
Lisp_Object mini_window;
FRAME_PTR f;
mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
if (FRAME_MESSAGE_BUF (f))
{
if (m)
{
int len;
#ifdef NO_ARG_ARRAY
char *a[3];
a[0] = (char *) a1;
a[1] = (char *) a2;
a[2] = (char *) a3;
len = doprnt (FRAME_MESSAGE_BUF (f),
FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3, a);
#else
len = doprnt (FRAME_MESSAGE_BUF (f),
FRAME_MESSAGE_BUF_SIZE (f), m, (char *)0, 3,
(char **) &a1);
#endif
message2 (FRAME_MESSAGE_BUF (f), len, 0);
}
else
message1 (0);
message_buf_print = 0;
}
}
}
void
message_nolog (m, a1, a2, a3)
char *m;
EMACS_INT a1, a2, a3;
{
Lisp_Object old_log_max;
old_log_max = Vmessage_log_max;
Vmessage_log_max = Qnil;
message (m, a1, a2, a3);
Vmessage_log_max = old_log_max;
}
void
update_echo_area ()
{
message2 (echo_area_glyphs, echo_area_glyphs_length,
! NILP (current_buffer->enable_multibyte_characters));
}
static void
echo_area_display ()
{
register int vpos;
FRAME_PTR f;
Lisp_Object mini_window;
mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
f = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
if (! FRAME_VISIBLE_P (f))
return;
if (frame_garbaged)
{
redraw_garbaged_frames ();
frame_garbaged = 0;
}
if (echo_area_glyphs || minibuf_level == 0)
{
int i;
echo_area_window = mini_window;
vpos = XFASTINT (XWINDOW (mini_window)->top);
get_display_line (f, vpos, 0);
for (i = 0; i < FRAME_LEFT_SCROLL_BAR_WIDTH (f); i++)
f->desired_glyphs->glyphs[vpos][i] = SPACEGLYPH;
display_string (XWINDOW (mini_window), vpos,
echo_area_glyphs ? echo_area_glyphs : "",
echo_area_glyphs ? echo_area_glyphs_length : -1,
FRAME_LEFT_SCROLL_BAR_WIDTH (f),
0, 0, 0,
FRAME_WIDTH (f) + FRAME_LEFT_SCROLL_BAR_WIDTH (f),
message_enable_multibyte);
#if 0
if (cursor_in_echo_area)
FRAME_CURSOR_Y (f) = vpos;
if (FRAME_CURSOR_Y (f) == vpos)
FRAME_CURSOR_X (f) = FRAME_DESIRED_GLYPHS (f)->used[vpos];
#endif
{
int i;
for (i = vpos + 1;
i < vpos + XFASTINT (XWINDOW (mini_window)->height); i++)
{
get_display_line (f, i, 0);
display_string (XWINDOW (mini_window), i,
"", 0,
0, 0, 0,
0, FRAME_WIDTH (f) + FRAME_SCROLL_BAR_WIDTH (f),
0);
}
}
}
else if (!EQ (mini_window, selected_window))
windows_or_buffers_changed++;
if (EQ (mini_window, selected_window))
this_line_bufpos = 0;
previous_echo_glyphs = echo_area_glyphs;
}
#ifdef HAVE_WINDOW_SYSTEM
static char frame_title_buf[512];
static char *frame_title_ptr;
static int
store_frame_title (str, mincol, maxcol)
char *str;
int mincol, maxcol;
{
char *limit;
if (maxcol < 0 || maxcol >= sizeof(frame_title_buf))
maxcol = sizeof (frame_title_buf);
limit = &frame_title_buf[maxcol];
while (*str != '\0' && frame_title_ptr < limit)
*frame_title_ptr++ = *str++;
while (frame_title_ptr < &frame_title_buf[mincol])
*frame_title_ptr++ = ' ';
return frame_title_ptr - frame_title_buf;
}
static void
x_consider_frame_title (frame)
Lisp_Object frame;
{
Lisp_Object fmt;
struct buffer *obuf;
int len;
FRAME_PTR f = XFRAME (frame);
if (!(FRAME_WINDOW_P (f) || FRAME_MINIBUF_ONLY_P (f) || f->explicit_name))
return;
{
Lisp_Object tail;
for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
{
FRAME_PTR tf = XFRAME (XCONS (tail)->car);
if (tf != f && FRAME_KBOARD (tf) == FRAME_KBOARD (f)
&& !FRAME_MINIBUF_ONLY_P (tf)
&& (FRAME_VISIBLE_P (tf) || FRAME_ICONIFIED_P (tf)))
break;
}
multiple_frames = CONSP (tail);
}
obuf = current_buffer;
Fset_buffer (XWINDOW (f->selected_window)->buffer);
fmt = (FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format);
frame_title_ptr = frame_title_buf;
len = display_mode_element (XWINDOW (f->selected_window), 0, 0, 0,
0, sizeof (frame_title_buf), fmt);
frame_title_ptr = 0;
set_buffer_internal (obuf);
if (! STRINGP (f->name) || STRING_BYTES (XSTRING (f->name)) != len
|| bcmp (frame_title_buf, XSTRING (f->name)->data, len) != 0)
x_implicitly_set_name (f, make_string (frame_title_buf, len), Qnil);
}
#else
#define frame_title_ptr ((char *)0)
#define store_frame_title(str, mincol, maxcol) 0
#endif
void
prepare_menu_bars ()
{
register struct window *w = XWINDOW (selected_window);
int all_windows;
struct gcpro gcpro1, gcpro2;
all_windows = (update_mode_lines || buffer_shared > 1
|| windows_or_buffers_changed);
#ifdef HAVE_WINDOW_SYSTEM
if (windows_or_buffers_changed || update_mode_lines)
{
Lisp_Object tail, frame;
FOR_EACH_FRAME (tail, frame)
if (FRAME_VISIBLE_P (XFRAME (frame))
|| FRAME_ICONIFIED_P (XFRAME (frame)))
x_consider_frame_title (frame);
}
#endif
if (all_windows)
{
Lisp_Object tail, frame;
int count = specpdl_ptr - specpdl;
record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
FOR_EACH_FRAME (tail, frame)
{
if (FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)))
{
Lisp_Object functions;
FRAME_WINDOW_SIZES_CHANGED (XFRAME (frame)) = 0;
functions = Vwindow_size_change_functions;
GCPRO2 (tail, functions);
while (CONSP (functions))
{
call1 (XCONS (functions)->car, frame);
functions = XCONS (functions)->cdr;
}
UNGCPRO;
}
GCPRO1 (tail);
update_menu_bar (XFRAME (frame), 0);
UNGCPRO;
}
unbind_to (count, Qnil);
}
else
update_menu_bar (selected_frame, 1);
#ifdef USE_X_TOOLKIT
pending_menu_activation = 0;
#endif
}
static int do_verify_charstarts;
static int clear_face_cache_count;
static FRAME_PTR previous_terminal_frame;
void
redisplay ()
{
redisplay_internal (0);
}
static void
redisplay_internal (preserve_echo_area)
int preserve_echo_area;
{
register struct window *w = XWINDOW (selected_window);
register int pause;
int must_finish = 0;
int all_windows;
register int tlbufpos, tlendpos;
struct position pos;
int number_of_visible_frames;
if (noninteractive)
return;
#ifdef USE_X_TOOLKIT
if (popup_activated ())
return;
#endif
if (! NILP (Vinhibit_redisplay))
return;
retry:
if (! FRAME_WINDOW_P (selected_frame)
&& previous_terminal_frame != selected_frame)
{
windows_or_buffers_changed++;
SET_FRAME_GARBAGED (selected_frame);
XSETFRAME (Vterminal_frame, selected_frame);
}
previous_terminal_frame = selected_frame;
{
Lisp_Object tail, frame;
number_of_visible_frames = 0;
FOR_EACH_FRAME (tail, frame)
{
FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
if (FRAME_VISIBLE_P (XFRAME (frame)))
number_of_visible_frames++;
init_desired_glyphs (XFRAME (frame));
}
}
do_pending_window_change ();
if (frame_garbaged)
{
redraw_garbaged_frames ();
frame_garbaged = 0;
}
prepare_menu_bars ();
if (windows_or_buffers_changed)
update_mode_lines++;
if ((SAVE_MODIFF < MODIFF) != !NILP (w->last_had_star))
{
w->update_mode_line = Qt;
if (buffer_shared > 1)
update_mode_lines++;
}
if (!NILP (w->column_number_displayed)
&& !(PT == XFASTINT (w->last_point)
&& XFASTINT (w->last_modified) >= MODIFF
&& XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
&& XFASTINT (w->column_number_displayed) != current_column ())
w->update_mode_line = Qt;
FRAME_SCROLL_BOTTOM_VPOS (XFRAME (w->frame)) = -1;
all_windows = update_mode_lines || buffer_shared > 1;
if (! EQ (COERCE_MARKER (Voverlay_arrow_position), last_arrow_position)
|| ! EQ (Voverlay_arrow_string, last_arrow_string))
all_windows = 1;
if (echo_area_glyphs || previous_echo_glyphs)
{
echo_area_display ();
must_finish = 1;
}
if (((!NILP (Vtransient_mark_mode)
&& !NILP (XBUFFER (w->buffer)->mark_active))
!= !NILP (w->region_showing))
|| (!NILP (w->region_showing)
&& !EQ (w->region_showing,
Fmarker_position (XBUFFER (w->buffer)->mark))))
this_line_bufpos = -1;
tlbufpos = this_line_bufpos;
tlendpos = this_line_endpos;
if (!all_windows && tlbufpos > 0 && NILP (w->update_mode_line)
&& !current_buffer->clip_changed
&& FRAME_VISIBLE_P (XFRAME (w->frame))
&& !FRAME_OBSCURED_P (XFRAME (w->frame))
&& this_line_buffer == current_buffer
&& current_buffer == XBUFFER (w->buffer)
&& NILP (w->force_start)
&& PT >= tlbufpos
&& PT <= Z - tlendpos
&& ((XFASTINT (w->last_modified) >= MODIFF
&& (XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF))
|| (beg_unchanged >= tlbufpos - 1
&& GPT >= tlbufpos
&& ((INTEGERP (current_buffer->selective_display)
&& XINT (current_buffer->selective_display) > 0
? (beg_unchanged >= tlbufpos
&& GPT > tlbufpos)
: 1))
&& end_unchanged >= tlendpos
&& Z - GPT >= tlendpos)))
{
int tlbufpos_byte = CHAR_TO_BYTE (tlbufpos);
if (tlbufpos > BEGV && FETCH_BYTE (tlbufpos_byte - 1) != '\n'
&& (tlbufpos == ZV
|| FETCH_BYTE (tlbufpos_byte) == '\n'))
goto cancel;
else if (XFASTINT (w->last_modified) < MODIFF
|| XFASTINT (w->last_overlay_modified) < OVERLAY_MODIFF
|| MINI_WINDOW_P (w))
{
struct position val;
int prevline;
int opoint = PT, opoint_byte = PT_BYTE;
scan_newline (tlbufpos, tlbufpos_byte, BEGV, BEGV_BYTE, -1, 1);
val = *compute_motion (PT, 0,
XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
0,
tlbufpos,
1 << (BITS_PER_SHORT - 1),
1 << (BITS_PER_SHORT - 1),
window_internal_width (w) - 1,
XINT (w->hscroll), 0, w);
TEMP_SET_PT_BOTH (opoint, opoint_byte);
if (val.hpos != this_line_start_hpos)
goto cancel;
cursor_vpos = -1;
overlay_arrow_seen = 0;
zv_strings_seen = 0;
display_text_line (w, tlbufpos, tlbufpos_byte,
this_line_vpos, this_line_start_hpos,
pos_tab_offset (w, tlbufpos, tlbufpos_byte), 0);
if (cursor_vpos >= 0 && this_line_bufpos
&& this_line_endpos == tlendpos)
{
if (this_line_vpos + 1
< XFASTINT (w->top) + window_internal_height (w))
{
int left = WINDOW_LEFT_MARGIN (w);
int *charstart_next_line
= FRAME_CURRENT_GLYPHS (XFRAME (WINDOW_FRAME (w)))->charstarts[this_line_vpos + 1];
int adjust;
if (Z - tlendpos == ZV)
adjust = Z - tlendpos - charstart_next_line[left];
else
adjust = Z - tlendpos + 1 - charstart_next_line[left];
adjust_window_charstarts (w, this_line_vpos, adjust);
}
if (!WINDOW_FULL_WIDTH_P (w))
preserve_other_columns (w);
goto update;
}
else
goto cancel;
}
else if (PT == XFASTINT (w->last_point)
&& XINT (w->top) <= FRAME_CURSOR_Y (selected_frame)
&& (XINT (w->top) + XINT (w->height)
> FRAME_CURSOR_Y (selected_frame)))
{
if (!must_finish)
{
do_pending_window_change ();
return;
}
goto update;
}
else if (! (!NILP (Vtransient_mark_mode)
&& !NILP (current_buffer->mark_active))
&& (w == XWINDOW (current_buffer->last_selected_window)
|| highlight_nonselected_windows)
&& NILP (w->region_showing)
&& !cursor_in_echo_area)
{
pos = *compute_motion (tlbufpos, 0,
XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0,
0,
PT, 2, - (1 << (BITS_PER_SHORT - 1)),
window_internal_width (w) - 1,
XINT (w->hscroll),
pos_tab_offset (w, tlbufpos, tlbufpos_byte),
w);
if (pos.vpos < 1)
{
int width = window_internal_width (w) - 1;
FRAME_CURSOR_X (selected_frame)
= WINDOW_LEFT_MARGIN (w) + minmax (0, pos.hpos, width);
FRAME_CURSOR_Y (selected_frame) = this_line_vpos;
goto update;
}
else
goto cancel;
}
cancel:
cancel_line (this_line_vpos, selected_frame);
}
this_line_bufpos = 0;
all_windows |= buffer_shared > 1;
clear_face_cache_count++;
if (all_windows)
{
Lisp_Object tail, frame;
#ifdef HAVE_FACES
if (clear_face_cache_count > 1000)
{
clear_face_cache ();
clear_face_cache_count = 0;
}
#endif
buffer_shared = 0;
FOR_EACH_FRAME (tail, frame)
{
FRAME_PTR f = XFRAME (frame);
if (FRAME_WINDOW_P (f) || f == selected_frame)
{
if (condemn_scroll_bars_hook)
(*condemn_scroll_bars_hook) (f);
if (FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
redisplay_windows (FRAME_ROOT_WINDOW (f), preserve_echo_area);
if (judge_scroll_bars_hook)
(*judge_scroll_bars_hook) (f);
}
}
}
else if (FRAME_VISIBLE_P (selected_frame) && !FRAME_OBSCURED_P (selected_frame))
{
redisplay_window (selected_window, 1, preserve_echo_area);
if (!WINDOW_FULL_WIDTH_P (w))
preserve_other_columns (w);
}
update:
if (interrupt_input)
unrequest_sigio ();
stop_polling ();
if (all_windows)
{
Lisp_Object tail;
pause = 0;
for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr)
{
FRAME_PTR f;
if (!FRAMEP (XCONS (tail)->car))
continue;
f = XFRAME (XCONS (tail)->car);
if ((FRAME_WINDOW_P (f) || f == selected_frame)
&& FRAME_VISIBLE_P (f) && !FRAME_OBSCURED_P (f))
{
pause |= update_frame (f, 0, 0);
if (!pause)
{
mark_window_display_accurate (f->root_window, 1);
if (frame_up_to_date_hook != 0)
(*frame_up_to_date_hook) (f);
}
}
}
}
else
{
if (FRAME_VISIBLE_P (selected_frame) && !FRAME_OBSCURED_P (selected_frame))
pause = update_frame (selected_frame, 0, 0);
else
pause = 0;
{
Lisp_Object mini_window;
FRAME_PTR mini_frame;
mini_window = FRAME_MINIBUF_WINDOW (selected_frame);
mini_frame = XFRAME (WINDOW_FRAME (XWINDOW (mini_window)));
if (mini_frame != selected_frame && FRAME_WINDOW_P (mini_frame))
pause |= update_frame (mini_frame, 0, 0);
}
}
if (pause)
{
this_line_bufpos = 0;
if (!NILP (last_arrow_position))
{
last_arrow_position = Qt;
last_arrow_string = Qt;
}
if (!WINDOW_FULL_WIDTH_P (w))
update_mode_lines = 1;
}
if (!pause)
{
register struct buffer *b = XBUFFER (w->buffer);
blank_end_of_window = 0;
unchanged_modified = BUF_MODIFF (b);
overlay_unchanged_modified = BUF_OVERLAY_MODIFF (b);
beg_unchanged = BUF_GPT (b) - BUF_BEG (b);
end_unchanged = BUF_Z (b) - BUF_GPT (b);
if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (selected_frame)
&& EQ (FRAME_MINIBUF_WINDOW (selected_frame), minibuf_window)))
{
XSETFASTINT (w->last_point, BUF_PT (b));
XSETFASTINT (w->last_point_x, FRAME_CURSOR_X (selected_frame));
XSETFASTINT (w->last_point_y, FRAME_CURSOR_Y (selected_frame));
}
else
XSETINT (w->last_point, -1);
if (all_windows)
mark_window_display_accurate (FRAME_ROOT_WINDOW (selected_frame), 1);
else
{
b->clip_changed = 0;
w->update_mode_line = Qnil;
XSETFASTINT (w->last_modified, BUF_MODIFF (b));
XSETFASTINT (w->last_overlay_modified, BUF_OVERLAY_MODIFF (b));
w->last_had_star
= (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
? Qt : Qnil);
w->region_showing = (!NILP (Vtransient_mark_mode)
&& (w == XWINDOW (current_buffer->last_selected_window)
|| highlight_nonselected_windows)
&& !NILP (XBUFFER (w->buffer)->mark_active)
? Fmarker_position (XBUFFER (w->buffer)->mark)
: Qnil);
w->window_end_valid = w->buffer;
last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
last_arrow_string = Voverlay_arrow_string;
if (do_verify_charstarts)
verify_charstarts (w);
if (frame_up_to_date_hook != 0)
(*frame_up_to_date_hook) (selected_frame);
}
update_mode_lines = 0;
windows_or_buffers_changed = 0;
}
if (interrupt_input)
request_sigio ();
start_polling ();
if (!pause)
{
Lisp_Object tail, frame;
int new_count = 0;
FOR_EACH_FRAME (tail, frame)
{
int this_is_visible = 0;
if (XFRAME (frame)->visible)
this_is_visible = 1;
FRAME_SAMPLE_VISIBILITY (XFRAME (frame));
if (XFRAME (frame)->visible)
this_is_visible = 1;
if (this_is_visible)
new_count++;
}
if (new_count != number_of_visible_frames)
windows_or_buffers_changed++;
}
do_pending_window_change ();
if (windows_or_buffers_changed && !pause)
goto retry;
}
void
redisplay_preserve_echo_area ()
{
if (echo_area_glyphs == 0 && previous_echo_glyphs != 0)
{
echo_area_glyphs = previous_echo_glyphs;
redisplay_internal (1);
echo_area_glyphs = 0;
}
else
redisplay_internal (1);
}
void
mark_window_display_accurate (window, flag)
Lisp_Object window;
int flag;
{
register struct window *w;
for (;!NILP (window); window = w->next)
{
if (!WINDOWP (window)) abort ();
w = XWINDOW (window);
if (!NILP (w->buffer))
{
XSETFASTINT (w->last_modified,
!flag ? 0 : BUF_MODIFF (XBUFFER (w->buffer)));
XSETFASTINT (w->last_overlay_modified,
!flag ? 0 : BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)));
w->last_had_star
= (BUF_MODIFF (XBUFFER (w->buffer)) > BUF_SAVE_MODIFF (XBUFFER (w->buffer))
? Qt : Qnil);
w->region_showing = (!NILP (Vtransient_mark_mode)
&& (w == XWINDOW (current_buffer->last_selected_window)
|| highlight_nonselected_windows)
&& !NILP (XBUFFER (w->buffer)->mark_active)
? Fmarker_position (XBUFFER (w->buffer)->mark)
: Qnil);
}
w->window_end_valid = w->buffer;
w->update_mode_line = Qnil;
if (!NILP (w->buffer) && flag)
XBUFFER (w->buffer)->clip_changed = 0;
if (!NILP (w->vchild))
mark_window_display_accurate (w->vchild, flag);
if (!NILP (w->hchild))
mark_window_display_accurate (w->hchild, flag);
}
if (flag)
{
last_arrow_position = COERCE_MARKER (Voverlay_arrow_position);
last_arrow_string = Voverlay_arrow_string;
}
else
{
last_arrow_position = Qt;
last_arrow_string = Qt;
}
}
static void
update_menu_bar (f, save_match_data)
FRAME_PTR f;
int save_match_data;
{
struct buffer *old = current_buffer;
Lisp_Object window;
register struct window *w;
window = FRAME_SELECTED_WINDOW (f);
w = XWINDOW (window);
if (update_mode_lines)
w->update_mode_line = Qt;
if (FRAME_WINDOW_P (f)
?
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
FRAME_EXTERNAL_MENU_BAR (f)
#else
FRAME_MENU_BAR_LINES (f) > 0
#endif
: FRAME_MENU_BAR_LINES (f) > 0)
{
if (windows_or_buffers_changed
|| !NILP (w->update_mode_line)
|| ((BUF_SAVE_MODIFF (XBUFFER (w->buffer))
< BUF_MODIFF (XBUFFER (w->buffer)))
!= !NILP (w->last_had_star))
|| ((!NILP (Vtransient_mark_mode)
&& !NILP (XBUFFER (w->buffer)->mark_active))
!= !NILP (w->region_showing)))
{
struct buffer *prev = current_buffer;
int count = specpdl_ptr - specpdl;
set_buffer_internal_1 (XBUFFER (w->buffer));
if (save_match_data)
record_unwind_protect (Fset_match_data, Fmatch_data (Qnil, Qnil));
if (NILP (Voverriding_local_map_menu_flag))
{
specbind (Qoverriding_terminal_local_map, Qnil);
specbind (Qoverriding_local_map, Qnil);
}
call1 (Vrun_hooks, Qactivate_menubar_hook);
if (! NILP (Vlucid_menu_bar_dirty_flag))
call0 (Qrecompute_lucid_menubar);
safe_run_hooks (Qmenu_bar_update_hook);
FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
if (FRAME_WINDOW_P (f))
set_frame_menubar (f, 0, 0);
else
w->update_mode_line = Qt;
#else
w->update_mode_line = Qt;
#endif
unbind_to (count, Qnil);
set_buffer_internal_1 (prev);
}
}
}
int do_id = 1;
static void
redisplay_windows (window, preserve_echo_area)
Lisp_Object window;
int preserve_echo_area;
{
for (; !NILP (window); window = XWINDOW (window)->next)
redisplay_window (window, 0, preserve_echo_area);
}
Lisp_Object
disp_char_vector (dp, c)
struct Lisp_Char_Table *dp;
int c;
{
int code[4], i;
Lisp_Object val;
if (SINGLE_BYTE_CHAR_P (c)) return (dp->contents[c]);
SPLIT_NON_ASCII_CHAR (c, code[0], code[1], code[2]);
if (code[0] != CHARSET_COMPOSITION)
{
if (code[1] < 32) code[1] = -1;
else if (code[2] < 32) code[2] = -1;
}
code[0] += 128;
code[3] = -1;
for (i = 0; code[i] >= 0; i++, dp = XCHAR_TABLE (val))
{
val = dp->contents[code[i]];
if (!SUB_CHAR_TABLE_P (val))
return (NILP (val) ? dp->defalt : val);
}
return (dp->defalt);
}
static void
redisplay_window (window, just_this_one, preserve_echo_area)
Lisp_Object window;
int just_this_one, preserve_echo_area;
{
register struct window *w = XWINDOW (window);
FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
int height;
int lpoint = PT;
int lpoint_byte = PT_BYTE;
struct buffer *old = current_buffer;
register int width = window_internal_width (w) - 1;
register int startp, startp_byte;
register int hscroll = XINT (w->hscroll);
struct position pos;
int opoint = PT;
int opoint_byte = PT_BYTE;
int tem;
int update_mode_line;
struct Lisp_Char_Table *dp = window_display_table (w);
int really_switched_buffer = 0;
int count = specpdl_ptr - specpdl;
if (Z == Z_BYTE && lpoint != lpoint_byte)
abort ();
if (lpoint_byte < lpoint)
abort ();
if (FRAME_HEIGHT (f) == 0) abort ();
if (!NILP (w->vchild))
{
redisplay_windows (w->vchild, preserve_echo_area);
return;
}
if (!NILP (w->hchild))
{
redisplay_windows (w->hchild, preserve_echo_area);
return;
}
if (NILP (w->buffer))
abort ();
specbind (Qinhibit_point_motion_hooks, Qt);
height = window_internal_height (w);
update_mode_line = (!NILP (w->update_mode_line) || update_mode_lines);
if (XBUFFER (w->buffer)->clip_changed)
update_mode_line = 1;
if (MINI_WINDOW_P (w))
{
if (w == XWINDOW (echo_area_window) && echo_area_glyphs)
goto finish_scroll_bars;
else if (w != XWINDOW (minibuf_window))
{
int vpos = XFASTINT (w->top);
int i;
for (i = 0; i < height; i++)
{
get_display_line (f, vpos + i, 0);
display_string (w, vpos + i, "", 0,
FRAME_LEFT_SCROLL_BAR_WIDTH (f),
0, 1, 0, width, 0);
}
goto finish_scroll_bars;
}
}
if (update_mode_line)
{
set_buffer_internal_1 (XBUFFER (w->buffer));
really_switched_buffer = 1;
}
else
set_buffer_temp (XBUFFER (w->buffer));
opoint = PT;
opoint_byte = PT_BYTE;
if (Z == Z_BYTE && opoint != opoint_byte)
abort ();
if (opoint_byte < opoint)
abort ();
if (!NILP (w->column_number_displayed)
&& !(PT == XFASTINT (w->last_point)
&& XFASTINT (w->last_modified) >= MODIFF
&& XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)
&& XFASTINT (w->column_number_displayed) != current_column ())
update_mode_line = 1;
if (!just_this_one)
{
struct buffer *current_base, *window_base;
current_base = current_buffer;
window_base = XBUFFER (XWINDOW (selected_window)->buffer);
if (current_base->base_buffer)
current_base = current_base->base_buffer;
if (window_base->base_buffer)
window_base = window_base->base_buffer;
if (current_base == window_base)
buffer_shared++;
}
if (!EQ (window, selected_window))
{
int new_pt = XMARKER (w->pointm)->charpos;
int new_pt_byte = marker_byte_position (w->pointm);
if (new_pt < BEGV)
{
new_pt = BEGV;
new_pt_byte = BEGV_BYTE;
set_marker_both (w->pointm, Qnil, BEGV, BEGV_BYTE);
}
else if (new_pt > (ZV - 1))
{
new_pt = ZV;
new_pt_byte = ZV_BYTE;
set_marker_both (w->pointm, Qnil, ZV, ZV_BYTE);
}
TEMP_SET_PT_BOTH (new_pt, new_pt_byte);
}
if (current_buffer->width_run_cache)
{
struct Lisp_Char_Table *disptab = buffer_display_table ();
if (! disptab_matches_widthtab (disptab,
XVECTOR (current_buffer->width_table)))
{
invalidate_region_cache (current_buffer,
current_buffer->width_run_cache,
BEG, Z);
recompute_width_table (current_buffer, disptab);
}
}
if (XMARKER (w->start)->buffer != current_buffer)
goto recenter;
startp = marker_position (w->start);
startp_byte = marker_byte_position (w->start);
if (!NILP (w->optional_new_start)
&& startp >= BEGV && startp <= ZV)
{
w->optional_new_start = Qnil;
pos = *compute_motion (startp, 0,
(((EQ (window, minibuf_window)
&& startp == BEG)
? minibuf_prompt_width : 0)
+ (hscroll ? 1 - hscroll : 0)),
0,
PT, height,
- (1 << (BITS_PER_SHORT - 1)),
width, hscroll,
pos_tab_offset (w, startp, startp_byte), w);
if (pos.bufpos == PT)
w->force_start = Qt;
}
if (!NILP (w->force_start))
{
w->force_start = Qnil;
w->base_line_number = Qnil;
w->window_end_valid = Qnil;
if (!update_mode_line
|| ! NILP (Vwindow_scroll_functions))
{
Lisp_Object temp[3];
if (!really_switched_buffer)
{
set_buffer_temp (old);
set_buffer_internal_1 (XBUFFER (w->buffer));
}
really_switched_buffer = 1;
update_mode_line = 1;
w->update_mode_line = Qt;
if (! NILP (Vwindow_scroll_functions))
{
run_hook_with_args_2 (Qwindow_scroll_functions, window,
make_number (startp));
startp = marker_position (w->start);
startp_byte = marker_byte_position (w->start);
}
}
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
if (startp < BEGV) startp = BEGV, startp_byte = BEGV_BYTE;
if (startp > ZV) startp = ZV, startp_byte = ZV_BYTE;
try_window (window, startp);
if (cursor_vpos < 0)
{
pos = *compute_motion (startp, 0,
(((EQ (window, minibuf_window)
&& startp == BEG)
? minibuf_prompt_width : 0)
+ (hscroll ? 1 - hscroll : 0)),
0,
ZV, height / 2,
- (1 << (BITS_PER_SHORT - 1)),
width, hscroll,
pos_tab_offset (w, startp, startp_byte),
w);
TEMP_SET_PT_BOTH (pos.bufpos, pos.bytepos);
if (w != XWINDOW (selected_window))
set_marker_both (w->pointm, Qnil, PT, PT_BYTE);
else
{
if (current_buffer == old)
{
lpoint = PT;
lpoint_byte = PT_BYTE;
}
FRAME_CURSOR_X (f) = (WINDOW_LEFT_MARGIN (w)
+ minmax (0, pos.hpos, width));
FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
}
if (!NILP (Vtransient_mark_mode)
&& !NILP (current_buffer->mark_active))
{
cancel_my_columns (XWINDOW (window));
try_window (window, startp);
}
}
goto done;
}
if (XFASTINT (w->last_modified) >= MODIFF
&& XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF
&& PT >= startp && !current_buffer->clip_changed
&& (just_this_one || WINDOW_FULL_WIDTH_P (w))
&& NILP (w->update_mode_line)
&& !(!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active))
&& NILP (w->region_showing)
&& INTEGERP (w->window_end_vpos)
&& XFASTINT (w->window_end_vpos) < XFASTINT (w->height)
&& !EQ (window, minibuf_window)
&& (!MARKERP (Voverlay_arrow_position)
|| current_buffer != XMARKER (Voverlay_arrow_position)->buffer))
{
int this_scroll_margin = scroll_margin;
int last_point_y = XFASTINT (w->last_point_y) - XINT (w->top);
int last_point_x = (XFASTINT (w->last_point_x) - WINDOW_LEFT_MARGIN (w));
if (PT == XFASTINT (w->last_point) && just_this_one
&& ! cursor_in_echo_area)
{
pos.hpos = last_point_x;
pos.vpos = last_point_y;
pos.bufpos = PT;
}
else if (PT > XFASTINT (w->last_point)
&& ! cursor_in_echo_area
&& XFASTINT (w->last_point) > startp && just_this_one
&& !(last_point_x <= 0 && hscroll))
{
int last_point = XFASTINT (w->last_point);
int last_point_byte = CHAR_TO_BYTE (last_point);
int tab_offset = (pos_tab_offset (w, last_point, last_point_byte)
- (last_point_x + hscroll - !! hscroll));
pos = *compute_motion (last_point, last_point_y, last_point_x, 1,
PT, height,
- (1 << (BITS_PER_SHORT - 1)),
width, hscroll,
tab_offset,
w);
}
else
{
pos = *compute_motion (startp, 0, (hscroll ? 1 - hscroll : 0), 0,
PT, height,
- (1 << (BITS_PER_SHORT - 1)),
width, hscroll,
pos_tab_offset (w, startp, startp_byte),
w);
}
if (this_scroll_margin < 0)
this_scroll_margin = 0;
if (XINT (w->height) < 4 * scroll_margin)
this_scroll_margin = XINT (w->height) / 4;
if (pos.vpos < height - this_scroll_margin
&& (pos.vpos >= this_scroll_margin || startp == BEGV))
{
if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
{
FRAME_CURSOR_X (f) = (WINDOW_LEFT_MARGIN (w)
+ minmax (0, pos.hpos, width));
FRAME_CURSOR_Y (f) = pos.vpos + XFASTINT (w->top);
}
if (current_buffer->clip_changed
&& ! NILP (Vwindow_scroll_functions))
run_hook_with_args_2 (Qwindow_scroll_functions, window,
make_number (marker_position (w->start)));
goto done;
}
}
else if (!NILP (w->start_at_line_beg)
&& !(startp <= BEGV
|| FETCH_BYTE (startp_byte - 1) == '\n'))
{
goto recenter;
}
else if (just_this_one && !MINI_WINDOW_P (w)
&& PT >= startp
&& XFASTINT (w->last_modified)
&& ! NILP (w->start_at_line_beg)
&& ! EQ (w->window_end_valid, Qnil)
&& do_id && !current_buffer->clip_changed
&& !blank_end_of_window
&& WINDOW_FULL_WIDTH_P (w)
&& !(!NILP (Vtransient_mark_mode)
&& !NILP (current_buffer->mark_active))
&& !(dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, '\n')))
&& NILP (w->region_showing)
&& EQ (last_arrow_position, COERCE_MARKER (Voverlay_arrow_position))
&& EQ (last_arrow_string, Voverlay_arrow_string)
&& (tem = try_window_id (FRAME_SELECTED_WINDOW (f)))
&& tem != -2)
{
if (tem > 0)
goto done;
}
else if (startp >= BEGV && startp <= ZV
&& (startp < ZV
#if 0
|| ! EQ (window, selected_window)
|| preserve_echo_area
#endif
|| startp == BEGV
|| (XFASTINT (w->last_modified) >= MODIFF
&& XFASTINT (w->last_overlay_modified) >= OVERLAY_MODIFF)))
{
try_window (window, startp);
if (cursor_vpos >= 0)
{
if (!just_this_one || current_buffer->clip_changed
|| beg_unchanged < startp)
w->base_line_number = Qnil;
if (current_buffer->clip_changed
&& ! NILP (Vwindow_scroll_functions))
run_hook_with_args_2 (Qwindow_scroll_functions, window,
make_number (marker_position (w->start)));
goto done;
}
else
cancel_my_columns (w);
}
XSETFASTINT (w->last_modified, 0);
XSETFASTINT (w->last_overlay_modified, 0);
if (!update_mode_line)
{
if (!really_switched_buffer)
{
set_buffer_temp (old);
set_buffer_internal_1 (XBUFFER (w->buffer));
}
update_mode_line = 1;
w->update_mode_line = Qt;
}
if ((scroll_conservatively || scroll_step)
&& !current_buffer->clip_changed
&& startp >= BEGV && startp <= ZV)
{
int this_scroll_margin = scroll_margin;
int scroll_margin_pos, scroll_margin_bytepos;
int scroll_max = scroll_step;
Lisp_Object ltemp;
if (scroll_conservatively)
scroll_max = scroll_conservatively;
if (this_scroll_margin < 0)
this_scroll_margin = 0;
if (XINT (w->height) < 4 * this_scroll_margin)
this_scroll_margin = XINT (w->height) / 4;
ltemp = Fwindow_end (window, Qt);
scroll_margin_pos = XINT (ltemp);
if (this_scroll_margin)
{
pos = *vmotion (scroll_margin_pos, -this_scroll_margin, w);
scroll_margin_pos = pos.bufpos;
scroll_margin_bytepos = pos.bytepos;
}
else
scroll_margin_bytepos = CHAR_TO_BYTE (scroll_margin_pos);
if (PT >= scroll_margin_pos)
{
struct position pos;
pos = *compute_motion (scroll_margin_pos, 0, 0, 0,
PT, XFASTINT (w->height), 0,
XFASTINT (w->width), XFASTINT (w->hscroll),
pos_tab_offset (w, scroll_margin_pos,
scroll_margin_bytepos),
w);
if (pos.vpos >= scroll_max)
goto scroll_fail_1;
pos = *vmotion (startp,
scroll_conservatively ? pos.vpos + 1 : scroll_step,
w);
w->window_end_valid = Qnil;
if (! NILP (Vwindow_scroll_functions))
{
set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos);
run_hook_with_args_2 (Qwindow_scroll_functions, window,
make_number (pos.bufpos));
pos.bufpos = marker_position (w->start);
}
try_window (window, pos.bufpos);
if (cursor_vpos >= 0)
{
if (!just_this_one || current_buffer->clip_changed
|| beg_unchanged < startp)
w->base_line_number = Qnil;
goto done;
}
else
cancel_my_columns (w);
}
scroll_margin_pos = startp;
if (this_scroll_margin)
{
pos = *vmotion (scroll_margin_pos, this_scroll_margin, w);
scroll_margin_pos = pos.bufpos;
}
if (PT < scroll_margin_pos)
{
struct position pos;
pos = *compute_motion (PT, 0, 0, 0,
scroll_margin_pos, XFASTINT (w->height), 0,
XFASTINT (w->width), XFASTINT (w->hscroll),
pos_tab_offset (w, PT, PT_BYTE),
w);
if (pos.vpos > scroll_max)
goto scroll_fail_1;
pos = *vmotion (startp,
scroll_conservatively ? -pos.vpos : - scroll_step,
w);
w->window_end_valid = Qnil;
if (! NILP (Vwindow_scroll_functions))
{
set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos);
run_hook_with_args_2 (Qwindow_scroll_functions, window,
make_number (pos.bufpos));
pos.bufpos = marker_position (w->start);
}
try_window (window, pos.bufpos);
if (cursor_vpos >= 0)
{
if (!just_this_one || current_buffer->clip_changed
|| beg_unchanged < startp)
w->base_line_number = Qnil;
goto done;
}
else
cancel_my_columns (w);
}
scroll_fail_1: ;
}
#if 0
if (scroll_step && ! scroll_margin && !current_buffer->clip_changed
&& startp >= BEGV && startp <= ZV)
{
if (margin_call == 0)
margin_call = (PT > startp ? 1 : -1);
if (margin_call > 0)
{
pos = *vmotion (Z - XFASTINT (w->window_end_pos), scroll_step, w);
if (pos.vpos >= height)
goto scroll_fail;
}
pos = *vmotion (startp, (margin_call < 0 ? - scroll_step : scroll_step),
w);
if (PT >= pos.bufpos)
{
w->window_end_valid = Qnil;
if (! NILP (Vwindow_scroll_functions))
{
set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos);
run_hook_with_args_2 (Qwindow_scroll_functions, window,
make_number (pos.bufpos));
pos.bufpos = marker_position (w->start);
}
try_window (window, pos.bufpos);
if (cursor_vpos >= 0)
{
if (!just_this_one || current_buffer->clip_changed
|| beg_unchanged < startp)
w->base_line_number = Qnil;
goto done;
}
else
cancel_my_columns (w);
}
scroll_fail: ;
}
#endif
recenter:
w->base_line_number = Qnil;
pos = *vmotion (PT, - (height / 2), w);
if (height == 1
&& (pos.bufpos >= PT - minibuffer_scroll_overlap
|| pos.bufpos < startp + width / 2)
&& PT > BEGV + minibuffer_scroll_overlap
&& FETCH_BYTE (pos.bytepos - 1) != '\n')
{
pos.bufpos = PT - minibuffer_scroll_overlap;
pos.bytepos = CHAR_TO_BYTE (pos.bufpos);
}
set_marker_both (w->start, Qnil, pos.bufpos, pos.bytepos);
w->window_end_valid = Qnil;
if (! NILP (Vwindow_scroll_functions))
{
run_hook_with_args_2 (Qwindow_scroll_functions, window,
make_number (pos.bufpos));
pos.bufpos = marker_position (w->start);
pos.bytepos = marker_byte_position (w->start);
}
try_window (window, pos.bufpos);
startp = marker_position (w->start);
startp_byte = marker_byte_position (w->start);
w->start_at_line_beg
= (startp == BEGV || FETCH_BYTE (startp_byte - 1) == '\n') ? Qt : Qnil;
done:
if ((update_mode_line
|| (!just_this_one && !WINDOW_FULL_WIDTH_P (w))
|| INTEGERP (w->base_line_pos)
|| (!NILP (w->column_number_displayed)
&& XFASTINT (w->column_number_displayed) != current_column ()))
&& height != XFASTINT (w->height))
{
FRAME_PTR oframe = selected_frame;
if (!really_switched_buffer)
{
set_buffer_temp (old);
set_buffer_internal_1 (XBUFFER (w->buffer));
really_switched_buffer = 1;
}
selected_frame = f;
display_mode_line (w);
selected_frame = oframe;
}
if (! line_number_displayed
&& ! BUFFERP (w->base_line_pos))
{
w->base_line_pos = Qnil;
w->base_line_number = Qnil;
}
if (update_mode_line
&& (FRAME_WINDOW_P (f)
?
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI)
FRAME_EXTERNAL_MENU_BAR (f)
#else
FRAME_MENU_BAR_LINES (f) > 0
#endif
: FRAME_MENU_BAR_LINES (f) > 0)
&& EQ (FRAME_SELECTED_WINDOW (f), window))
display_menu_bar (w);
finish_scroll_bars:
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
{
int start, end, whole;
if (! MINI_WINDOW_P (w)
|| (w == XWINDOW (minibuf_window) && ! echo_area_glyphs))
{
whole = ZV - BEGV;
start = marker_position (w->start) - BEGV;
end = (Z - XINT (w->window_end_pos)) - BEGV;
if (end < start) end = start;
if (whole < (end - start)) whole = end - start;
}
else
start = end = whole = 0;
(*set_vertical_scroll_bar_hook) (w, end - start, whole, start);
(*redeem_scroll_bar_hook) (w);
}
TEMP_SET_PT_BOTH (opoint, opoint_byte);
if (really_switched_buffer)
set_buffer_internal_1 (old);
else
set_buffer_temp (old);
TEMP_SET_PT_BOTH (lpoint, lpoint_byte);
unbind_to (count, Qnil);
}
static void
try_window (window, pos)
Lisp_Object window;
register int pos;
{
register struct window *w = XWINDOW (window);
register int height = window_internal_height (w);
register int vpos = XFASTINT (w->top);
register int last_text_vpos = vpos;
FRAME_PTR f = XFRAME (w->frame);
int width = window_internal_width (w) - 1;
struct position val;
if (pos < XBUFFER (w->buffer)->begv
|| pos > XBUFFER (w->buffer)->zv)
abort ();
if (XMARKER (w->start)->charpos != pos)
Fset_marker (w->start, make_number (pos), Qnil);
cursor_vpos = -1;
overlay_arrow_seen = 0;
zv_strings_seen = 0;
val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
val.ovstring_chars_done = 0;
val.bytepos = marker_byte_position (w->start);
val.tab_offset = pos_tab_offset (w, pos, val.bytepos);
while (--height >= 0)
{
val = *display_text_line (w, pos, val.bytepos, vpos,
val.hpos, val.tab_offset,
val.ovstring_chars_done);
#if 0
tab_offset += width;
if (val.vpos) tab_offset = 0;
#endif
vpos++;
if (pos != val.bufpos)
{
int invis = 0;
#ifdef USE_TEXT_PROPERTIES
Lisp_Object invis_prop;
invis_prop = Fget_char_property (make_number (val.bufpos - 1),
Qinvisible, window);
invis = TEXT_PROP_MEANS_INVISIBLE (invis_prop);
#endif
last_text_vpos
= vpos - (val.vpos
&& (FETCH_BYTE (val.bytepos - 1) != '\n' || invis));
}
pos = val.bufpos;
}
if (val.hpos < (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
pos++;
if (XFASTINT (w->window_end_pos) == 0
&& Z != pos)
w->update_mode_line = Qt;
XSETFASTINT (w->window_end_pos, Z - pos);
XSETFASTINT (w->window_end_vpos, last_text_vpos - XFASTINT (w->top));
w->window_end_valid = Qnil;
}
static int
try_window_id (window)
Lisp_Object window;
{
int pos, pos_byte;
int opoint, opoint_byte;
register struct window *w = XWINDOW (window);
register int height = window_internal_height (w);
FRAME_PTR f = XFRAME (w->frame);
int top = XFASTINT (w->top);
int start = marker_position (w->start);
int width = window_internal_width (w) - 1;
int hscroll = XINT (w->hscroll);
int lmargin = hscroll > 0 ? 1 - hscroll : 0;
int did_motion;
register int vpos;
register int i, tem;
int last_text_vpos = 0;
int stop_vpos;
int selective = (INTEGERP (current_buffer->selective_display)
? XINT (current_buffer->selective_display)
: !NILP (current_buffer->selective_display) ? -1 : 0);
struct position val, bp, ep, xp, pp;
int scroll_amount = 0;
int delta;
int epto, old_tick;
int start_byte = marker_byte_position (w->start);
if (GPT - BEG < beg_unchanged)
beg_unchanged = GPT - BEG;
if (Z - GPT < end_unchanged)
end_unchanged = Z - GPT;
if (beg_unchanged + BEG < start)
return 0;
bp = *compute_motion (start, 0, lmargin, 0,
min (ZV, beg_unchanged + BEG), height,
- (1 << (BITS_PER_SHORT - 1)),
width, hscroll,
pos_tab_offset (w, start, start_byte),
w);
if (bp.vpos >= height)
{
if (PT < bp.bufpos)
{
bp = *compute_motion (start, 0, lmargin, 0,
ZV, height,
- (1 << (BITS_PER_SHORT - 1)),
width, hscroll,
pos_tab_offset (w, start, start_byte), w);
XSETFASTINT (w->window_end_vpos, height);
XSETFASTINT (w->window_end_pos, Z - bp.bufpos);
goto findpoint;
}
return 0;
}
vpos = bp.vpos;
bp = *vmotion (bp.bufpos, 0, w);
pos = bp.bufpos;
pos_byte = bp.bytepos;
val.hpos = lmargin;
if (pos < start)
return -1;
did_motion = 0;
if ((bp.contin && bp.bufpos - 1 == beg_unchanged && vpos > 0)
||
(selective > 0 && bp.bufpos - 1 == beg_unchanged && vpos > 0))
{
bp = *vmotion (bp.bufpos, -1, w);
--vpos;
pos = bp.bufpos;
pos_byte = bp.bytepos;
}
val.tab_offset = bp.tab_offset;
if (bp.contin && bp.hpos != lmargin)
{
val.hpos = bp.prevhpos - width + lmargin;
val.tab_offset = bp.tab_offset + width - bp.prevhpos;
did_motion = 1;
DEC_BOTH (pos, pos_byte);
}
bp.vpos = vpos;
opoint = PT, opoint_byte = PT_BYTE;
TEMP_SET_PT (Z - max (end_unchanged, Z - ZV));
scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
if (selective > 0)
while (PT < ZV - 1 && indented_beyond_p (PT, PT_BYTE, selective))
scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
tem = PT;
TEMP_SET_PT_BOTH (opoint, opoint_byte);
ep = *compute_motion (pos, vpos, val.hpos, did_motion, tem,
height, - (1 << (BITS_PER_SHORT - 1)),
width, hscroll,
val.tab_offset, w);
if (ep.bufpos > Z - XFASTINT (w->window_end_pos))
stop_vpos = height;
else
stop_vpos = ep.vpos;
if (stop_vpos == ep.vpos
&& (ep.bufpos == BEGV
|| FETCH_BYTE (ep.bytepos - 1) != '\n'
|| ep.bufpos == Z - end_unchanged))
stop_vpos = ep.vpos + 1;
cursor_vpos = -1;
overlay_arrow_seen = 0;
zv_strings_seen = 0;
if (stop_vpos < height)
{
xp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
Z - XFASTINT (w->window_end_pos),
1 << (BITS_PER_SHORT - 1),
1 << (BITS_PER_SHORT - 1),
width, hscroll, ep.tab_offset, w);
scroll_amount = xp.vpos - XFASTINT (w->window_end_vpos);
for (i = ep.bytepos; i < xp.bytepos; i++)
{
tem = FETCH_BYTE (i);
if (tem != ' ' && tem != '\n' && tem != '\t')
break;
}
if (i == xp.bytepos)
return -2;
XSETFASTINT (w->window_end_vpos,
XFASTINT (w->window_end_vpos) + scroll_amount);
if (PT > ep.bufpos && !(PT <= xp.bufpos && xp.vpos < height))
{
if (PT <= xp.bufpos)
{
pp = *compute_motion (ep.bufpos, ep.vpos, ep.hpos, 1,
PT, height, - (1 << (BITS_PER_SHORT - 1)),
width, hscroll,
ep.tab_offset, w);
}
else
{
pp = *compute_motion (xp.bufpos, xp.vpos, xp.hpos, 1,
PT, height, - (1 << (BITS_PER_SHORT - 1)),
width, hscroll,
xp.tab_offset, w);
}
if (pp.bufpos < PT || pp.vpos == height)
return 0;
cursor_vpos = pp.vpos + top;
cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, pp.hpos, width);
}
if (stop_vpos - scroll_amount >= height
|| ep.bufpos == xp.bufpos)
{
if (scroll_amount < 0)
stop_vpos -= scroll_amount;
scroll_amount = 0;
blank_end_of_window = 1;
}
else if (!scroll_amount)
{
int oldpos = FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
int adjust = ep.bufpos - oldpos;
adjust_window_charstarts (w, ep.vpos + top - 1, adjust);
}
else if (bp.bufpos == Z - end_unchanged)
{
if (scroll_cost (f, bp.vpos + top - scroll_amount,
top + height - max (0, scroll_amount),
scroll_amount)
> xp.bufpos - bp.bufpos - 20)
return -2;
tem = scroll_frame_lines (f, bp.vpos + top - scroll_amount,
top + height - max (0, scroll_amount),
scroll_amount, bp.bufpos);
if (!tem)
stop_vpos = height;
else
{
int oldstart
= FRAME_CURRENT_GLYPHS (f)->charstarts[ep.vpos + top][0];
adjust_window_charstarts (w, ep.vpos + top - 1,
ep.bufpos - oldstart);
}
}
else if (scroll_amount)
{
if (scroll_cost (f, ep.vpos + top - scroll_amount,
top + height - max (0, scroll_amount),
scroll_amount)
> xp.bufpos - ep.bufpos - 20)
return -2;
tem = scroll_frame_lines (f, ep.vpos + top - scroll_amount,
top + height - max (0, scroll_amount),
scroll_amount, ep.bufpos);
if (!tem) stop_vpos = height;
}
}
if (stop_vpos >= height)
{
stop_vpos = height;
scroll_amount = 0;
}
if (vpos == 0 && pos < marker_position (w->start))
Fset_marker (w->start, make_number (pos), Qnil);
val.bytepos = pos_byte;
val.ovstring_chars_done = 0;
last_text_vpos = vpos;
#if 0
tab_offset = pos_tab_offset (w, pos, pos_byte);
if (val.hpos < lmargin)
tab_offset += width;
#endif
old_tick = MODIFF;
while (vpos < stop_vpos)
{
val = *display_text_line (w, pos, val.bytepos, top + vpos++,
val.hpos, val.tab_offset,
val.ovstring_chars_done);
if (old_tick != MODIFF)
stop_vpos = height;
#if 0
tab_offset += width;
if (val.vpos) tab_offset = 0;
#endif
if (pos != val.bufpos)
last_text_vpos
= vpos - (val.vpos && FETCH_BYTE (val.bytepos - 1) != '\n');
pos = val.bufpos;
}
if (vpos == height)
{
if (val.hpos < lmargin)
val.bufpos++;
XSETFASTINT (w->window_end_vpos, last_text_vpos);
XSETFASTINT (w->window_end_pos, Z - val.bufpos);
}
if (scroll_amount < 0)
{
FRAME_SCROLL_BOTTOM_VPOS (f) = xp.vpos;
vpos = xp.vpos;
pos = xp.bufpos;
pos_byte = xp.bytepos;
val.hpos = xp.hpos;
val.tab_offset = xp.tab_offset;
if (pos == ZV)
{
vpos = height + scroll_amount;
val.hpos = lmargin;
val.tab_offset = 0;
}
else if (xp.contin && xp.hpos != lmargin)
{
val.hpos = xp.prevhpos - width + lmargin;
val.tab_offset = xp.tab_offset + bp.prevhpos - width;
DEC_BOTH (pos, pos_byte);
}
blank_end_of_window = 1;
#if 0
tab_offset = pos_tab_offset (w, pos, pos_byte);
if (val.hpos < lmargin)
tab_offset += width;
#endif
val.bytepos = pos_byte;
while (vpos < height)
{
val = *display_text_line (w, pos, val.bytepos,
top + vpos++, val.hpos,
val.tab_offset, val.ovstring_chars_done);
#if 0
tab_offset += width;
if (val.vpos) tab_offset = 0;
#endif
pos = val.bufpos;
}
if (xp.bufpos == ZV
&& xp.bufpos == PT)
cursor_vpos = -1;
}
if (XFASTINT (w->window_end_pos) == 0
&& Z != val.bufpos)
w->update_mode_line = Qt;
if (scroll_amount)
{
delta = height - xp.vpos;
if (delta < 0
|| (delta > 0 && xp.bufpos <= ZV)
|| (delta == 0 && xp.hpos))
{
val = *vmotion (Z - XFASTINT (w->window_end_pos), delta, w);
XSETFASTINT (w->window_end_pos, Z - val.bufpos);
XSETFASTINT (w->window_end_vpos,
XFASTINT (w->window_end_vpos) + val.vpos);
}
}
w->window_end_valid = Qnil;
if (cursor_vpos < 0)
{
findpoint:
val = *compute_motion (start, 0, lmargin, 0, PT,
1 << (BITS_PER_SHORT - 1),
1 << (BITS_PER_SHORT - 1),
width, hscroll,
pos_tab_offset (w, start, start_byte),
w);
if (val.vpos >= height)
{
for (vpos = 0; vpos < height; vpos++)
cancel_line (vpos + top, f);
return 0;
}
cursor_vpos = val.vpos + top;
cursor_hpos = WINDOW_LEFT_MARGIN (w) + minmax (0, val.hpos, width);
}
FRAME_CURSOR_X (f) = cursor_hpos;
FRAME_CURSOR_Y (f) = cursor_vpos;
if (debug_end_pos)
{
val = *compute_motion (start, 0, lmargin, 0, ZV,
height, - (1 << (BITS_PER_SHORT - 1)),
width, hscroll,
pos_tab_offset (w, start, start_byte),
w);
if (val.vpos != XFASTINT (w->window_end_vpos))
abort ();
if (XFASTINT (w->window_end_pos)
!= Z - val.bufpos)
abort ();
}
return 1;
}
static GLYPH *
copy_part_of_rope (f, to, s, from, len, face)
FRAME_PTR f;
register GLYPH *to;
register GLYPH *s;
Lisp_Object *from;
int len;
int face;
{
int n = len;
register Lisp_Object *fp = from;
int last_code = -1;
int last_merged = 0;
#ifdef HAVE_FACES
if (! FRAME_TERMCAP_P (f))
while (n--)
{
GLYPH glyph = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
int facecode;
unsigned int c = FAST_GLYPH_CHAR (glyph);
if (c > MAX_CHAR)
c = ' ';
if (FAST_GLYPH_FACE (glyph) == 0)
facecode = face;
else if (FAST_GLYPH_FACE (glyph) == last_code)
facecode = last_merged;
else
{
last_code = FAST_GLYPH_FACE (glyph);
last_merged = facecode = compute_glyph_face (f, last_code, face);
}
if (to >= s)
*to = FAST_MAKE_GLYPH (c, facecode);
++to;
++fp;
}
else
#endif
while (n--)
{
if (to >= s) *to = (INTEGERP (*fp) ? XFASTINT (*fp) : 0);
++to;
++fp;
}
return to;
}
static GLYPH
fix_glyph (f, glyph, cface)
FRAME_PTR f;
GLYPH glyph;
int cface;
{
#ifdef HAVE_FACES
if (! FRAME_TERMCAP_P (f))
{
if (FAST_GLYPH_FACE (glyph) != 0)
cface = compute_glyph_face (f, FAST_GLYPH_FACE (glyph), cface);
glyph = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (glyph), cface);
}
#endif
return glyph;
}
static int
pos_tab_offset (w, pos, pos_byte)
struct window *w;
register int pos, pos_byte;
{
int opoint = PT;
int opoint_byte = PT_BYTE;
int col;
int width = window_internal_width (w) - 1;
if (pos == BEGV)
return MINI_WINDOW_P (w) ? -minibuf_prompt_width : 0;
if (FETCH_BYTE (pos_byte - 1) == '\n')
return 0;
TEMP_SET_PT_BOTH (pos, pos_byte);
col = current_column ();
TEMP_SET_PT_BOTH (opoint, opoint_byte);
return col;
}
struct position val_display_text_line;
static struct position *
display_text_line (w, start, start_byte, vpos, hpos, taboffset, ovstr_done)
struct window *w;
int start;
int vpos;
int hpos;
int taboffset;
int ovstr_done;
{
register int pos = start;
int pos_byte = start_byte;
register int c;
register GLYPH *p1;
int pause, limit_byte;
register unsigned char *p;
GLYPH *endp;
register GLYPH *leftmargin;
register GLYPH *p1prev;
register GLYPH *p1start;
GLYPH *p1_wide_column_end = (GLYPH *) 0;
int prevpos, prevpos_byte;
int *charstart;
FRAME_PTR f = XFRAME (w->frame);
int tab_width = XINT (current_buffer->tab_width);
int ctl_arrow = !NILP (current_buffer->ctl_arrow);
int width = window_internal_width (w) - 1;
struct position val;
int lastpos, lastpos_byte;
int invis;
int last_invis_skip = 0;
Lisp_Object last_invis_prop;
int hscroll = XINT (w->hscroll);
int truncate = (hscroll
|| (truncate_partial_width_windows
&& !WINDOW_FULL_WIDTH_P (w))
|| !NILP (current_buffer->truncate_lines));
int highlight_region
= (!NILP (Vtransient_mark_mode) && !NILP (current_buffer->mark_active)
&& XMARKER (current_buffer->mark)->buffer != 0);
int region_beg, region_end;
int selective = (INTEGERP (current_buffer->selective_display)
? XINT (current_buffer->selective_display)
: !NILP (current_buffer->selective_display) ? -1 : 0);
register struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
register struct Lisp_Char_Table *dp = window_display_table (w);
Lisp_Object default_invis_vector[3];
int selective_rlen
= (dp && VECTORP (DISP_INVIS_VECTOR (dp))
? XVECTOR (DISP_INVIS_VECTOR (dp))->size
: !NILP (current_buffer->selective_display_ellipses) ? 3 : 0);
Lisp_Object *invis_vector_contents
= (dp && VECTORP (DISP_INVIS_VECTOR (dp))
? XVECTOR (DISP_INVIS_VECTOR (dp))->contents
: default_invis_vector);
GLYPH truncator = (dp == 0 || !INTEGERP (DISP_TRUNC_GLYPH (dp))
|| !GLYPH_CHAR_VALID_P (XINT (DISP_TRUNC_GLYPH (dp)))
? '$' : XINT (DISP_TRUNC_GLYPH (dp)));
GLYPH continuer = (dp == 0 || !INTEGERP (DISP_CONTINUE_GLYPH (dp))
|| !GLYPH_CHAR_VALID_P (XINT (DISP_CONTINUE_GLYPH (dp)))
? '\\' : XINT (DISP_CONTINUE_GLYPH (dp)));
int multibyte = !NILP (current_buffer->enable_multibyte_characters);
int len;
GLYPH rev_dir_bit = (NILP (current_buffer->direction_reversed)
? 0 : GLYPH_MASK_REV_DIR);
int next_face_change;
int next_boundary;
int current_face = 0;
int i;
XSETFASTINT (default_invis_vector[2], '.');
default_invis_vector[0] = default_invis_vector[1] = default_invis_vector[2];
get_display_line (f, vpos, WINDOW_LEFT_MARGIN (w));
if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
if (highlight_region
&& (highlight_nonselected_windows
|| w == XWINDOW (selected_window)
|| (MINI_WINDOW_P (XWINDOW (selected_window))
&& w == XWINDOW (Vminibuf_scroll_window))))
{
region_beg = marker_position (current_buffer->mark);
if (PT < region_beg)
{
region_end = region_beg;
region_beg = PT;
}
else
region_end = PT;
w->region_showing = Qt;
}
else
{
region_beg = region_end = -1;
w->region_showing = Qnil;
}
if (MINI_WINDOW_P (w)
&& start == BEG
&& vpos == XFASTINT (w->top))
{
if (! NILP (minibuf_prompt))
{
int old_width = minibuf_prompt_width;
minibuf_prompt_width
= (display_string (w, vpos, XSTRING (minibuf_prompt)->data,
STRING_BYTES (XSTRING (minibuf_prompt)),
hpos + WINDOW_LEFT_MARGIN (w),
' ',
1, -1,
(XFASTINT (w->width) > 10
? XFASTINT (w->width) - 4 : -1),
STRING_MULTIBYTE (minibuf_prompt))
- hpos - WINDOW_LEFT_MARGIN (w));
hpos += minibuf_prompt_width;
taboffset -= minibuf_prompt_width - old_width;
}
else
minibuf_prompt_width = 0;
}
if (hpos < 0)
{
struct position *left_edge
= compute_motion (pos, vpos, hpos, 0,
ZV, vpos, 0,
width, hscroll, taboffset, w);
if ((left_edge->vpos > vpos
|| left_edge->hpos > 0)
&& left_edge->bufpos > pos)
{
pos = left_edge->bufpos;
pos_byte = left_edge->bytepos;
DEC_BOTH (pos, pos_byte);
hpos = left_edge->prevhpos;
}
else
{
pos = left_edge->bufpos;
pos_byte = left_edge->bytepos;
hpos = left_edge->hpos;
}
}
hpos += WINDOW_LEFT_MARGIN (w);
desired_glyphs->bufp[vpos] = start;
p1 = desired_glyphs->glyphs[vpos] + hpos;
p1start = p1;
charstart = desired_glyphs->charstarts[vpos] + hpos;
desired_glyphs->charstarts[vpos][WINDOW_LEFT_MARGIN (w)] = -1;
leftmargin = desired_glyphs->glyphs[vpos] + WINDOW_LEFT_MARGIN (w);
endp = leftmargin + width;
recenter_overlay_lists (current_buffer, pos);
pause = pos;
limit_byte = pos_byte;
next_face_change = pos;
next_boundary = pos;
p1prev = p1;
prevpos = pos;
prevpos_byte = pos_byte;
if (hscroll && start <= PT && PT < pos && cursor_vpos < 0)
{
cursor_vpos = vpos;
cursor_hpos = p1 - leftmargin;
}
while (p1 < endp)
{
if (pos >= pause)
{
int e_t_h;
while (pos == next_boundary)
{
Lisp_Object position, limit, prop, ww;
if (pos < ZV || !zv_strings_seen++)
{
int ovlen;
unsigned char *ovstr;
ovlen = overlay_strings (pos, w, &ovstr);
if (ovlen > 0)
{
ovstr += ovstr_done;
ovlen -= ovstr_done;
while (ovlen > 0 && p1 < endp)
{
int charset, cols;
GLYPH g;
if (multibyte)
{
c = STRING_CHAR_AND_LENGTH (ovstr, ovlen, len);
ovstr += len, ovlen -= len, ovstr_done += len;
charset = CHAR_CHARSET (c);
cols = (charset == CHARSET_COMPOSITION
? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
: CHARSET_WIDTH (charset));
}
else
{
c = *ovstr++, ovlen--, ovstr_done++;
cols = 1;
}
g = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
while (cols-- > 0)
{
if (p1 >= leftmargin && p1 < endp)
*p1 = g, g |= GLYPH_MASK_PADDING;
p1++;
}
}
if (ovlen == 0 && p1 < endp)
ovstr_done = 0;
}
}
if (pos == PT && cursor_vpos < 0)
{
cursor_vpos = vpos;
cursor_hpos = p1 - leftmargin;
}
if (pos >= ZV)
break;
XSETFASTINT (position, pos);
limit = Fnext_overlay_change (position);
#ifdef USE_TEXT_PROPERTIES
if (XFASTINT (limit) > pos + 50)
{
int limitpos = pos + 50;
XSETFASTINT (limit, limitpos);
}
limit = Fnext_single_property_change (position, Qinvisible,
Fcurrent_buffer (), limit);
#endif
next_boundary = XFASTINT (limit);
XSETWINDOW (ww, w);
prop = Fget_char_property (position, Qinvisible, ww);
if (TEXT_PROP_MEANS_INVISIBLE (prop))
{
if (pos < PT && next_boundary >= PT)
{
cursor_vpos = vpos;
cursor_hpos = p1 - leftmargin;
}
pos = next_boundary;
pos_byte = CHAR_TO_BYTE (pos);
last_invis_skip = pos;
last_invis_prop = prop;
}
}
if (pos == PT && cursor_vpos < 0)
{
cursor_vpos = vpos;
cursor_hpos = p1 - leftmargin;
}
if (pos >= ZV)
{
if (p1 >= leftmargin && p1 + 1 != endp)
{
int *p2x = &charstart[(p1 < leftmargin
? leftmargin : p1)
- p1start];
*p2x++ = pos;
}
break;
}
if (MARKERP (w->redisplay_end_trigger)
&& XMARKER (w->redisplay_end_trigger)->buffer != 0)
e_t_h = marker_position (w->redisplay_end_trigger);
else if (INTEGERP (w->redisplay_end_trigger))
e_t_h = XINT (w->redisplay_end_trigger);
else
e_t_h = ZV;
if (pos >= e_t_h && e_t_h != ZV)
{
Lisp_Object args[3];
args[0] = Qredisplay_end_trigger_functions;
XSETWINDOW (args[1], w);
XSETINT (args[2], e_t_h);
w->redisplay_end_trigger = Qnil;
Frun_hook_with_args (3, args);
e_t_h = ZV;
next_face_change = pos;
}
#ifdef HAVE_FACES
if (pos >= next_face_change
&& (FRAME_WINDOW_P (f) || FRAME_MSDOS_P (f)))
{
int limit = pos + 50;
current_face = compute_char_face (f, w, pos,
region_beg, region_end,
&next_face_change, limit, 0);
}
#endif
pause = ZV;
if (pos < next_boundary && next_boundary < pause)
pause = next_boundary;
if (pos < next_face_change && next_face_change < pause)
pause = next_face_change;
if (e_t_h < pause)
pause = e_t_h;
if (pos < PT && PT < pause)
pause = PT;
if (pos < GPT && GPT < pause)
pause = GPT;
limit_byte = ZV_BYTE;
if (pos < GPT && GPT_BYTE < limit_byte)
limit_byte = GPT_BYTE;
{
int temp = CHAR_TO_BYTE (pos);
p = BYTE_POS_ADDR (temp);
}
}
if (p1 >= endp)
break;
p1prev = p1;
p1_wide_column_end = (GLYPH *) 0;
if (multibyte)
c = STRING_CHAR_AND_LENGTH (p, limit_byte - pos_byte, len), p += len;
else
c = *p++, len = 1;
if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
{
p1 = copy_part_of_rope (f, p1, leftmargin,
XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
current_face, rev_dir_bit);
}
else if (c >= 040 && c < 0177)
{
if (p1 >= leftmargin)
*p1 = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
p1++;
}
else if (c == '\n')
{
#if 0
GLYPH *p1prev_modified;
#endif
invis = 0;
if (last_invis_skip == pos
&& TEXT_PROP_MEANS_INVISIBLE_WITH_ELLIPSIS (last_invis_prop))
invis = 1;
while (pos + 1 < ZV
&& selective > 0
&& indented_beyond_p (pos + 1, pos_byte + 1, selective))
{
int opoint = PT, opoint_byte = PT_BYTE;
invis = 1;
INC_BOTH (pos, pos_byte);
scan_newline (pos, pos_byte, ZV, ZV_BYTE, 1, 1);
pos = PT, pos_byte = PT_BYTE;
if (FETCH_BYTE (pos_byte - 1) == '\n')
{
pos--;
pos_byte--;
}
TEMP_SET_PT_BOTH (opoint, opoint_byte);
}
if (invis && selective_rlen > 0 && p1 >= leftmargin)
{
#if 0
GLYPH *cs, *csend;
cs = charstart + (p1 - p1start);
#endif
p1 += selective_rlen;
if (p1 - leftmargin > width)
p1 = endp;
#if 0
csend = charstart + (p1 - p1start);
while (cs != csend)
*cs++ = -2;
p1prev_modified = p1;
#endif
copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
(p1 - p1prev), current_face, rev_dir_bit);
}
if (p1 >= leftmargin && p1prev != endp)
{
int *p2x = &charstart[(p1prev < leftmargin
? leftmargin : p1prev)
- p1start];
int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
*p2x++ = pos;
while (p2x < p2)
*p2x++ = -1;
}
#ifdef HAVE_FACES
if (current_face)
{
if (p1 < leftmargin)
p1 = leftmargin;
while (p1 < endp)
*p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit;
}
#endif
break;
}
else if (c == '\t')
{
do
{
if (p1 >= leftmargin && p1 < endp)
*p1 = MAKE_GLYPH (f, ' ', current_face) | rev_dir_bit;
p1++;
}
while ((p1 - leftmargin + taboffset + hscroll - (hscroll > 0))
% tab_width);
}
else if (c == Ctl ('M') && selective == -1)
{
int opoint = PT, opoint_byte = PT_BYTE;
scan_newline (pos, pos_byte, ZV, ZV_BYTE, 1, 1);
pos = PT, pos_byte = PT_BYTE;
TEMP_SET_PT_BOTH (opoint, opoint_byte);
if (FETCH_BYTE (pos_byte - 1) == '\n')
pos--, pos_byte--;
if (selective_rlen > 0)
{
p1 += selective_rlen;
if (p1 - leftmargin > width)
p1 = endp;
copy_part_of_rope (f, p1prev, p1prev, invis_vector_contents,
(p1 - p1prev), current_face, rev_dir_bit);
}
#ifdef HAVE_FACES
if (current_face)
{
if (p1 < leftmargin)
p1 = leftmargin;
while (p1 < endp)
*p1++ = FAST_MAKE_GLYPH (' ', current_face) | rev_dir_bit;
}
#endif
if (p1 >= leftmargin && p1prev != endp)
{
int *p2x = &charstart[(p1prev < leftmargin
? leftmargin : p1prev)
- p1start];
int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
*p2x++ = pos;
while (p2x < p2)
*p2x++ = -1;
}
break;
}
else if (c < 0200 && ctl_arrow)
{
if (p1 >= leftmargin)
*p1 = (fix_glyph
(f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
&& GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp)))
? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
current_face)
| rev_dir_bit);
p1++;
if (p1 >= leftmargin && p1 < endp)
*p1 = MAKE_GLYPH (f, c ^ 0100, current_face) | rev_dir_bit;
p1++;
}
else
{
int remaining_bytes = len;
if (unibyte_display_via_language_environment
&& SINGLE_BYTE_CHAR_P (c)
&& (c >= 0240
|| (c >= 0200 && !NILP (Vnonascii_translation_table))))
c = unibyte_char_to_multibyte (c);
if (c >= 0400 && CHAR_VALID_P (c, 0))
{
int charset = CHAR_CHARSET (c);
int columns = (charset == CHARSET_COMPOSITION
? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
: CHARSET_WIDTH (charset));
GLYPH g = MAKE_GLYPH (f, c, current_face) | rev_dir_bit;
while (columns--)
{
if (p1 >= leftmargin && p1 < endp)
*p1 = g, g |= GLYPH_MASK_PADDING;
p1++;
}
p1_wide_column_end = p1;
remaining_bytes -= CHARSET_BYTES (charset);
}
while (remaining_bytes > 0)
{
c = *(p - remaining_bytes--);
if (p1 >= leftmargin && p1 < endp)
*p1 = (fix_glyph
(f,
(dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
&& GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp)))
? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
current_face)
| rev_dir_bit);
p1++;
if (p1 >= leftmargin && p1 < endp)
*p1 = (MAKE_GLYPH (f, (c >> 6) + '0', current_face)
| rev_dir_bit);
p1++;
if (p1 >= leftmargin && p1 < endp)
*p1 = (MAKE_GLYPH (f, (7 & (c >> 3)) + '0', current_face)
| rev_dir_bit);
p1++;
if (p1 >= leftmargin && p1 < endp)
*p1 = (MAKE_GLYPH (f, (7 & c) + '0', current_face)
| rev_dir_bit);
p1++;
}
}
prevpos = pos;
prevpos_byte = pos_byte;
pos++;
pos_byte += len;
if (p1 >= leftmargin)
{
if (p1 != p1prev)
{
int *p2x = &charstart[(p1prev < leftmargin
? leftmargin : p1prev)
- p1start];
int *p2 = &charstart[(p1 < endp ? p1 : endp) - p1start];
if (p2x < p2)
*p2x++ = prevpos;
while (p2x < p2)
*p2x++ = -1;
}
}
}
val.hpos = - XINT (w->hscroll);
if (val.hpos)
val.hpos++;
val.vpos = 1;
lastpos = pos;
lastpos_byte = pos_byte;
i = p1 - p1start + 1;
if (p1 < leftmargin)
i += leftmargin - p1;
for (; i < endp - p1start + 1; i++)
charstart[i] = 0;
if (p1 > endp)
{
if (p1prev)
{
pos = prevpos;
pos_byte = prevpos_byte;
if (p1_wide_column_end < endp)
val.hpos += p1prev - endp;
else
{
taboffset = taboffset + (p1prev - endp);
{
GLYPH g = fix_glyph (f, truncate ? truncator : continuer, 0);
while (p1prev < endp)
*p1prev++ = g;
}
lastpos = pos;
lastpos_byte = pos_byte;
if (PT == pos)
cursor_vpos = -1;
}
}
p1 = endp;
}
if (pos < ZV)
{
if (FETCH_BYTE (pos_byte) == '\n')
{
int opoint = PT, opoint_byte = PT_BYTE;
TEMP_SET_PT_BOTH (pos + 1, pos_byte + 1);
val.tab_offset = 0;
while (PT < ZV && selective > 0
&& indented_beyond_p (PT, PT_BYTE, selective))
scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
pos = PT, pos_byte = PT_BYTE;
TEMP_SET_PT_BOTH (opoint, opoint_byte);
}
else
{
if (truncate)
{
int opoint = PT, opoint_byte = PT_BYTE;
TEMP_SET_PT_BOTH (pos, pos_byte);
*p1++ = fix_glyph (f, truncator, 0);
do
scan_newline (PT, PT_BYTE, ZV, ZV_BYTE, 1, 1);
while (PT < ZV && selective > 0
&& indented_beyond_p (PT, PT_BYTE, selective));
pos = PT, pos_byte = PT_BYTE;
val.hpos = XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0;
TEMP_SET_PT_BOTH (opoint, opoint_byte);
lastpos = pos - (FETCH_BYTE (pos_byte - 1) == '\n');
lastpos_byte = CHAR_TO_BYTE (lastpos);
val.tab_offset = 0;
}
else
{
*p1++ = fix_glyph (f, continuer, 0);
val.vpos = 0;
DEC_BOTH (lastpos, lastpos_byte);
val.tab_offset = taboffset + width;
}
}
}
else
val.tab_offset = 0;
if (start <= PT && PT <= lastpos && cursor_vpos < 0)
{
cursor_vpos = vpos;
cursor_hpos = p1 - leftmargin;
}
if (cursor_vpos == vpos)
{
if (cursor_hpos < 0) cursor_hpos = 0;
if (cursor_hpos > width) cursor_hpos = width;
cursor_hpos += WINDOW_LEFT_MARGIN (w);
if (w == XWINDOW (FRAME_SELECTED_WINDOW (f)))
{
this_line_bufpos = 0;
if (!(cursor_in_echo_area && FRAME_HAS_MINIBUF_P (f)
&& EQ (FRAME_MINIBUF_WINDOW (f), minibuf_window)))
{
FRAME_CURSOR_Y (f) = cursor_vpos;
FRAME_CURSOR_X (f) = cursor_hpos;
if (w == XWINDOW (selected_window))
{
if ((hpos - WINDOW_LEFT_MARGIN (w)
== (XINT (w->hscroll) ? 1 - XINT (w->hscroll) : 0))
&& val.vpos)
{
this_line_bufpos = start;
this_line_buffer = current_buffer;
this_line_vpos = cursor_vpos;
this_line_start_hpos = hpos - WINDOW_LEFT_MARGIN (w);
this_line_endpos = Z - lastpos;
}
}
}
}
}
if (hscroll && lastpos != start)
{
GLYPH g = fix_glyph (f, truncator, 0);
*leftmargin = g;
if (p1 <= leftmargin)
p1 = leftmargin + 1;
else
{
p1prev = leftmargin + 1;
while (p1prev < p1 && *p1prev & GLYPH_MASK_PADDING)
*p1prev++ = g;
}
}
if (!WINDOW_RIGHTMOST_P (w))
{
endp++;
if (p1 < leftmargin) p1 = leftmargin;
while (p1 < endp) *p1++ = SPACEGLYPH;
if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
{
int i;
for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
*p1++ = SPACEGLYPH;
}
else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
*p1++ = (dp && INTEGERP (DISP_BORDER_GLYPH (dp))
? XINT (DISP_BORDER_GLYPH (dp))
: '|');
}
desired_glyphs->used[vpos] = max (desired_glyphs->used[vpos],
p1 - desired_glyphs->glyphs[vpos]);
desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
if (MARKERP (Voverlay_arrow_position)
&& current_buffer == XMARKER (Voverlay_arrow_position)->buffer
&& start == marker_position (Voverlay_arrow_position)
&& STRINGP (Voverlay_arrow_string)
&& ! overlay_arrow_seen)
{
int i, i_byte;
int len = XSTRING (Voverlay_arrow_string)->size;
int arrow_end;
if (len > width)
len = width;
for (i = 0, i_byte = 0; i < len; )
{
int c;
Lisp_Object face, ilisp;
int newface;
int idx = i;
if (STRING_MULTIBYTE (Voverlay_arrow_string))
FETCH_STRING_CHAR_ADVANCE (c, Voverlay_arrow_string, i, i_byte);
else
c = XSTRING (Voverlay_arrow_string)->data[i++];
XSETFASTINT (ilisp, i);
#ifdef HAVE_FACES
if (FRAME_WINDOW_P (f))
{
face = Fget_text_property (ilisp, Qface, Voverlay_arrow_string);
newface = compute_glyph_face_1 (f, face, 0);
c = FAST_MAKE_GLYPH (c, newface);
}
#endif
leftmargin[idx] = c;
}
arrow_end = (leftmargin - desired_glyphs->glyphs[vpos]) + len;
if (desired_glyphs->used[vpos] < arrow_end)
desired_glyphs->used[vpos] = arrow_end;
overlay_arrow_seen = 1;
}
val.bufpos = pos;
val.bytepos = pos_byte;
val.ovstring_chars_done = ovstr_done;
val_display_text_line = val;
return &val_display_text_line;
}
static void
display_menu_bar (w)
struct window *w;
{
Lisp_Object items, tail;
register int vpos = 0;
register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
int maxendcol = FRAME_WIDTH (f);
int hpos = 0;
int i;
#ifdef HAVE_NTGUI
if (!NILP (Vwindow_system))
return;
#endif
#ifdef USE_X_TOOLKIT
if (FRAME_X_P (f))
return;
#endif
get_display_line (f, vpos, 0);
items = FRAME_MENU_BAR_ITEMS (f);
for (i = 0; i < XVECTOR (items)->size; i += 4)
{
Lisp_Object pos, string;
string = XVECTOR (items)->contents[i + 1];
if (NILP (string))
break;
XSETFASTINT (XVECTOR (items)->contents[i + 3], hpos);
if (hpos < maxendcol)
hpos = display_string (w, vpos,
XSTRING (string)->data,
STRING_BYTES (XSTRING (string)),
hpos, 0, 0, hpos, maxendcol,
STRING_MULTIBYTE (string));
if (hpos < maxendcol)
{
int hpos1 = hpos + 1;
hpos = display_string (w, vpos, "", 0, hpos, 0, 0,
min (hpos1, maxendcol), maxendcol, 0);
}
}
FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
if (maxendcol > hpos)
hpos = display_string (w, vpos, "", 0, hpos, 0, 0, maxendcol, maxendcol, 0);
vpos++;
while (vpos < FRAME_MENU_BAR_LINES (f))
get_display_line (f, vpos++, 0);
}
static void
display_mode_line (w)
struct window *w;
{
register int vpos = XFASTINT (w->height) + XFASTINT (w->top) - 1;
register int left = WINDOW_LEFT_MARGIN (w);
register int right = WINDOW_RIGHT_MARGIN (w);
register FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
line_number_displayed = 0;
w->column_number_displayed = Qnil;
get_display_line (f, vpos, left);
push_frame_kboard (f);
display_mode_element (w, vpos, left, 0, right, right,
current_buffer->mode_line_format);
pop_frame_kboard ();
FRAME_DESIRED_GLYPHS (f)->bufp[vpos] = 0;
#ifdef HAVE_FACES
if (! FRAME_TERMCAP_P (f) && mode_line_inverse_video)
{
int i;
unsigned int padding;
GLYPH *ptr = FRAME_DESIRED_GLYPHS (f)->glyphs[vpos];
for (i = left; i < right; ++i)
{
padding = ptr[i] & GLYPH_MASK_PADDING;
ptr[i] = FAST_MAKE_GLYPH (FAST_GLYPH_CHAR (ptr[i]), 1) | padding;
}
}
else
#endif
if (WINDOW_FULL_WIDTH_P (w)
|| WINDOW_FULL_WIDTH_P (XWINDOW (w->parent)))
FRAME_DESIRED_GLYPHS (f)->highlight[vpos] = mode_line_inverse_video;
}
static int
display_mode_element (w, vpos, hpos, depth, minendcol, maxendcol, elt)
struct window *w;
register int vpos, hpos;
int depth;
int minendcol;
register int maxendcol;
register Lisp_Object elt;
{
tail_recurse:
if (depth > 10)
goto invalid;
depth++;
switch (SWITCH_ENUM_CAST (XTYPE (elt)))
{
case Lisp_String:
{
register unsigned char c;
register unsigned char *this = XSTRING (elt)->data;
while (hpos < maxendcol && *this)
{
unsigned char *last = this;
while ((c = *this++) != '\0' && c != '%')
;
if (this - 1 != last)
{
register int lim = --this - last + hpos;
if (frame_title_ptr)
hpos = store_frame_title (last, hpos, min (lim, maxendcol));
else
hpos = display_string (w, vpos, last, -1, hpos, 0, 1,
hpos, min (lim, maxendcol),
STRING_MULTIBYTE (elt));
}
else
{
register int minendcol;
register int spec_width = 0;
while ((c = *this++) >= '0' && c <= '9')
{
spec_width = spec_width * 10 + (c - '0');
}
minendcol = hpos + spec_width;
if (minendcol > maxendcol)
{
spec_width = maxendcol - hpos;
minendcol = maxendcol;
}
if (c == 'M')
hpos = display_mode_element (w, vpos, hpos, depth,
spec_width, maxendcol,
Vglobal_mode_string);
else if (c != 0)
{
char *spec = decode_mode_spec (w, c, spec_width,
maxendcol - hpos);
if (frame_title_ptr)
hpos = store_frame_title (spec, minendcol, maxendcol);
else
hpos = display_string (w, vpos, spec, -1,
hpos, 0, 1,
minendcol, maxendcol, -1);
}
}
}
}
break;
case Lisp_Symbol:
{
register Lisp_Object tem;
tem = Fboundp (elt);
if (!NILP (tem))
{
tem = Fsymbol_value (elt);
if (STRINGP (tem))
{
if (frame_title_ptr)
hpos = store_frame_title (XSTRING (tem)->data,
minendcol, maxendcol);
else
hpos = display_string (w, vpos, XSTRING (tem)->data,
STRING_BYTES (XSTRING (tem)),
hpos, 0, 1, minendcol, maxendcol,
STRING_MULTIBYTE (tem));
}
else if (!EQ (tem, elt))
{ elt = tem; goto tail_recurse; }
}
}
break;
case Lisp_Cons:
{
register Lisp_Object car, tem;
car = XCONS (elt)->car;
if (SYMBOLP (car))
{
tem = Fboundp (car);
elt = XCONS (elt)->cdr;
if (!CONSP (elt))
goto invalid;
if (!NILP (tem))
{
tem = Fsymbol_value (car);
if (!NILP (tem))
{ elt = XCONS (elt)->car; goto tail_recurse; }
}
elt = XCONS (elt)->cdr;
if (NILP (elt))
break;
else if (!CONSP (elt))
goto invalid;
elt = XCONS (elt)->car;
goto tail_recurse;
}
else if (INTEGERP (car))
{
register int lim = XINT (car);
elt = XCONS (elt)->cdr;
if (lim < 0)
maxendcol = min (maxendcol, hpos - lim);
else if (lim > 0)
{
lim += hpos;
if (lim > maxendcol)
lim = maxendcol;
if (lim > minendcol)
minendcol = lim;
}
goto tail_recurse;
}
else if (STRINGP (car) || CONSP (car))
{
register int limit = 50;
while (CONSP (elt) && --limit > 0
&& hpos < maxendcol)
{
hpos = display_mode_element (w, vpos, hpos, depth,
hpos, maxendcol,
XCONS (elt)->car);
elt = XCONS (elt)->cdr;
}
}
}
break;
default:
invalid:
if (frame_title_ptr)
hpos = store_frame_title ("*invalid*", minendcol, maxendcol);
else
hpos = display_string (w, vpos, "*invalid*", -1, hpos, 0, 1,
minendcol, maxendcol, 0);
return hpos;
}
if (minendcol > hpos)
if (frame_title_ptr)
hpos = store_frame_title ("", minendcol, maxendcol);
else
hpos = display_string (w, vpos, "", 0, hpos,
0, 1, minendcol, maxendcol, 0);
return hpos;
}
static void
pint2str (buf, width, d)
register char *buf;
register int width;
register int d;
{
register char *p = buf;
if (d <= 0)
*p++ = '0';
else
while (d > 0)
{
*p++ = d % 10 + '0';
d /= 10;
}
for (width -= (int) (p - buf); width > 0; --width) *p++ = ' ';
*p-- = '\0';
while (p > buf)
{
d = *buf;
*buf++ = *p;
*p-- = d;
}
}
static unsigned char invalid_eol_type[] = "(*invalid*)";
static char *
decode_mode_spec_coding (coding_system, buf, eol_flag)
Lisp_Object coding_system;
register char *buf;
int eol_flag;
{
Lisp_Object val;
int multibyte = !NILP (current_buffer->enable_multibyte_characters);
unsigned char *eol_str;
int eol_str_len;
Lisp_Object eoltype;
val = Fget (coding_system, Qcoding_system);
if (!VECTORP (val))
{
if (multibyte)
*buf++ = '-';
if (eol_flag)
eoltype = eol_mnemonic_undecided;
}
else
{
Lisp_Object eolvalue;
eolvalue = Fget (coding_system, Qeol_type);
if (multibyte)
*buf++ = XFASTINT (XVECTOR (val)->contents[1]);
if (eol_flag)
{
if (NILP (eolvalue))
eoltype = eol_mnemonic_undecided;
else if (VECTORP (eolvalue))
eoltype = eol_mnemonic_undecided;
else
eoltype = (XFASTINT (eolvalue) == 0
? eol_mnemonic_unix
: (XFASTINT (eolvalue) == 1
? eol_mnemonic_dos : eol_mnemonic_mac));
}
}
if (eol_flag)
{
if (STRINGP (eoltype))
{
eol_str = XSTRING (eoltype)->data;
eol_str_len = XSTRING (eoltype)->size;
}
else if (INTEGERP (eoltype)
&& CHAR_VALID_P (XINT (eoltype), 0))
{
int c = XINT (eoltype);
unsigned char work[4];
eol_str_len = CHAR_STRING (XINT (eoltype), work, eol_str);
}
else
{
eol_str = invalid_eol_type;
eol_str_len = sizeof (invalid_eol_type) - 1;
}
bcopy (eol_str, buf, eol_str_len);
buf += eol_str_len;
}
return buf;
}
static char lots_of_dashes[] = "--------------------------------------------------------------------------------------------------------------------------------------------";
static char *
decode_mode_spec (w, c, spec_width, maxwidth)
struct window *w;
register char c;
register int spec_width;
register int maxwidth;
{
Lisp_Object obj;
FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
char *decode_mode_spec_buf = (char *) FRAME_TEMP_GLYPHS (f)->total_contents;
struct buffer *b = XBUFFER (w->buffer);
obj = Qnil;
if (maxwidth > FRAME_WIDTH (f))
maxwidth = FRAME_WIDTH (f);
switch (c)
{
case '*':
if (!NILP (b->read_only))
return "%";
if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
return "*";
return "-";
case '+':
if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
return "*";
if (!NILP (b->read_only))
return "%";
return "-";
case '&':
if (BUF_MODIFF (b) > BUF_SAVE_MODIFF (b))
return "*";
return "-";
case '%':
return "%";
case '[':
{
int i;
char *p;
if (command_loop_level > 5)
return "[[[... ";
p = decode_mode_spec_buf;
for (i = 0; i < command_loop_level; i++)
*p++ = '[';
*p = 0;
return decode_mode_spec_buf;
}
case ']':
{
int i;
char *p;
if (command_loop_level > 5)
return " ...]]]";
p = decode_mode_spec_buf;
for (i = 0; i < command_loop_level; i++)
*p++ = ']';
*p = 0;
return decode_mode_spec_buf;
}
case '-':
{
register char *p;
register int i;
if (maxwidth < sizeof (lots_of_dashes))
return lots_of_dashes;
else
{
for (p = decode_mode_spec_buf, i = maxwidth; i > 0; i--)
*p++ = '-';
*p = '\0';
}
return decode_mode_spec_buf;
}
case 'b':
obj = b->name;
#if 0
if (maxwidth >= 3 && STRING_BYTES (XSTRING (obj)) > maxwidth)
{
bcopy (XSTRING (obj)->data, decode_mode_spec_buf, maxwidth - 1);
decode_mode_spec_buf[maxwidth - 1] = '\\';
decode_mode_spec_buf[maxwidth] = '\0';
return decode_mode_spec_buf;
}
#endif
break;
case 'c':
{
int col = current_column ();
XSETFASTINT (w->column_number_displayed, col);
pint2str (decode_mode_spec_buf, spec_width, col);
return decode_mode_spec_buf;
}
case 'F':
if (FRAME_WINDOW_P (f) && !NILP (f->title))
return (char *) XSTRING (f->title)->data;
if (f->explicit_name || ! FRAME_WINDOW_P (f))
return (char *) XSTRING (f->name)->data;
return "Emacs";
case 'f':
obj = b->filename;
#if 0
if (NILP (obj))
return "[none]";
else if (STRINGP (obj) && STRING_BYTES (XSTRING (obj)) > maxwidth)
{
bcopy ("...", decode_mode_spec_buf, 3);
bcopy (XSTRING (obj)->data + STRING_BYTES (XSTRING (obj)) - maxwidth + 3,
decode_mode_spec_buf + 3, maxwidth - 3);
return decode_mode_spec_buf;
}
#endif
break;
case 'l':
{
int startpos = XMARKER (w->start)->charpos;
int startpos_byte = marker_byte_position (w->start);
int line, linepos, linepos_byte, topline;
int nlines, junk;
Lisp_Object tem;
int height = XFASTINT (w->height);
if (EQ (w->base_line_pos, w->buffer))
goto no_value;
else if (BUFFERP (w->base_line_pos))
w->base_line_pos = Qnil;
if (BUF_ZV (b) - BUF_BEGV (b) > line_number_display_limit)
{
w->base_line_pos = Qnil;
w->base_line_number = Qnil;
goto no_value;
}
if (!NILP (w->base_line_number)
&& !NILP (w->base_line_pos)
&& XFASTINT (w->base_line_pos) <= startpos)
{
line = XFASTINT (w->base_line_number);
linepos = XFASTINT (w->base_line_pos);
linepos_byte = buf_charpos_to_bytepos (b, linepos);
}
else
{
line = 1;
linepos = BUF_BEGV (b);
linepos_byte = BUF_BEGV_BYTE (b);
}
nlines = display_count_lines (linepos, linepos_byte,
startpos_byte,
startpos, &junk);
topline = nlines + line;
if (startpos == BUF_BEGV (b))
{
XSETFASTINT (w->base_line_number, topline);
XSETFASTINT (w->base_line_pos, BUF_BEGV (b));
}
else if (nlines < height + 25 || nlines > height * 3 + 50
|| linepos == BUF_BEGV (b))
{
int limit = BUF_BEGV (b);
int limit_byte = BUF_BEGV_BYTE (b);
int position;
int distance = (height * 2 + 30) * 200;
if (startpos - distance > limit)
{
limit = startpos - distance;
limit_byte = CHAR_TO_BYTE (limit);
}
nlines = display_count_lines (startpos, startpos_byte,
limit_byte,
- (height * 2 + 30),
&position);
if (position == limit_byte && limit == startpos - distance)
{
w->base_line_pos = w->buffer;
w->base_line_number = Qnil;
goto no_value;
}
XSETFASTINT (w->base_line_number, topline - nlines);
XSETFASTINT (w->base_line_pos, BYTE_TO_CHAR (position));
}
nlines = display_count_lines (startpos, startpos_byte,
PT_BYTE, PT, &junk);
line_number_displayed = 1;
pint2str (decode_mode_spec_buf, spec_width, topline + nlines);
return decode_mode_spec_buf;
no_value:
{
char* p = decode_mode_spec_buf;
for (spec_width -= 2; spec_width > 0; --spec_width) *p++ = ' ';
strcpy (p, "??");
return decode_mode_spec_buf;
}
}
break;
case 'm':
obj = b->mode_name;
break;
case 'n':
if (BUF_BEGV (b) > BUF_BEG (b) || BUF_ZV (b) < BUF_Z (b))
return " Narrow";
break;
case 'p':
{
int pos = marker_position (w->start);
int total = BUF_ZV (b) - BUF_BEGV (b);
if (XFASTINT (w->window_end_pos) <= BUF_Z (b) - BUF_ZV (b))
{
if (pos <= BUF_BEGV (b))
return "All";
else
return "Bottom";
}
else if (pos <= BUF_BEGV (b))
return "Top";
else
{
if (total > 1000000)
total = ((pos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
else
total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total;
if (total == 100)
total = 99;
sprintf (decode_mode_spec_buf, "%2d%%", total);
return decode_mode_spec_buf;
}
}
case 'P':
{
int toppos = marker_position (w->start);
int botpos = BUF_Z (b) - XFASTINT (w->window_end_pos);
int total = BUF_ZV (b) - BUF_BEGV (b);
if (botpos >= BUF_ZV (b))
{
if (toppos <= BUF_BEGV (b))
return "All";
else
return "Bottom";
}
else
{
if (total > 1000000)
total = ((botpos - BUF_BEGV (b)) + (total / 100) - 1) / (total / 100);
else
total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total;
if (total == 100)
total = 99;
if (toppos <= BUF_BEGV (b))
sprintf (decode_mode_spec_buf, "Top%2d%%", total);
else
sprintf (decode_mode_spec_buf, "%2d%%", total);
return decode_mode_spec_buf;
}
}
case 's':
obj = Fget_buffer_process (w->buffer);
if (NILP (obj))
return "no process";
#ifdef subprocesses
obj = Fsymbol_name (Fprocess_status (obj));
#endif
break;
case 't':
#ifdef MODE_LINE_BINARY_TEXT
return MODE_LINE_BINARY_TEXT (b);
#else
return "T";
#endif
case 'z':
case 'Z':
{
int eol_flag = (c == 'Z');
char *p = decode_mode_spec_buf;
if (! FRAME_WINDOW_P (f))
{
p = decode_mode_spec_coding (keyboard_coding.symbol, p, 0);
p = decode_mode_spec_coding (terminal_coding.symbol, p, 0);
}
p = decode_mode_spec_coding (b->buffer_file_coding_system,
p, eol_flag);
#if 0
#ifdef subprocesses
obj = Fget_buffer_process (Fcurrent_buffer ());
if (PROCESSP (obj))
{
p = decode_mode_spec_coding (XPROCESS (obj)->decode_coding_system,
p, eol_flag);
p = decode_mode_spec_coding (XPROCESS (obj)->encode_coding_system,
p, eol_flag);
}
#endif
#endif
*p = 0;
return decode_mode_spec_buf;
}
}
if (STRINGP (obj))
return (char *) XSTRING (obj)->data;
else
return "";
}
static int
display_count_lines (start, start_byte, limit_byte, count, byte_pos_ptr)
int start, start_byte, limit_byte, count;
int *byte_pos_ptr;
{
register unsigned char *cursor;
unsigned char *base;
register int ceiling;
register unsigned char *ceiling_addr;
int orig_count = count;
int selective_display = (!NILP (current_buffer->selective_display)
&& !INTEGERP (current_buffer->selective_display));
if (count > 0)
{
while (start_byte < limit_byte)
{
ceiling = BUFFER_CEILING_OF (start_byte);
ceiling = min (limit_byte - 1, ceiling);
ceiling_addr = BYTE_POS_ADDR (ceiling) + 1;
base = (cursor = BYTE_POS_ADDR (start_byte));
while (1)
{
if (selective_display)
while (*cursor != '\n' && *cursor != 015 && ++cursor != ceiling_addr)
;
else
while (*cursor != '\n' && ++cursor != ceiling_addr)
;
if (cursor != ceiling_addr)
{
if (--count == 0)
{
start_byte += cursor - base + 1;
*byte_pos_ptr = start_byte;
return orig_count;
}
else
if (++cursor == ceiling_addr)
break;
}
else
break;
}
start_byte += cursor - base;
}
}
else
{
while (start_byte > limit_byte)
{
ceiling = BUFFER_FLOOR_OF (start_byte - 1);
ceiling = max (limit_byte, ceiling);
ceiling_addr = BYTE_POS_ADDR (ceiling) - 1;
base = (cursor = BYTE_POS_ADDR (start_byte - 1) + 1);
while (1)
{
if (selective_display)
while (--cursor != ceiling_addr
&& *cursor != '\n' && *cursor != 015)
;
else
while (--cursor != ceiling_addr && *cursor != '\n')
;
if (cursor != ceiling_addr)
{
if (++count == 0)
{
start_byte += cursor - base + 1;
*byte_pos_ptr = start_byte;
return - orig_count - 1;
}
}
else
break;
}
start_byte += cursor - base + 1;
}
}
*byte_pos_ptr = limit_byte;
if (count < 0)
return - orig_count + count;
return orig_count - count;
}
static int
display_string (w, vpos, string, length, hpos, truncate,
obey_window_width, mincol, maxcol, multibyte)
struct window *w;
unsigned char *string;
int length;
int vpos, hpos;
GLYPH truncate;
int obey_window_width;
int mincol, maxcol;
int multibyte;
{
register int c;
int truncated;
register GLYPH *p1;
int hscroll = XINT (w->hscroll);
int tab_width = XINT (XBUFFER (w->buffer)->tab_width);
register GLYPH *start;
register GLYPH *end;
FRAME_PTR f = XFRAME (WINDOW_FRAME (w));
struct frame_glyphs *desired_glyphs = FRAME_DESIRED_GLYPHS (f);
GLYPH *p1start = desired_glyphs->glyphs[vpos] + hpos;
int window_width = XFASTINT (w->width);
register struct Lisp_Char_Table *dp = 0;
int i;
if (multibyte == -1)
multibyte = !NILP (current_buffer->enable_multibyte_characters);
if (DISP_TABLE_P (Vstandard_display_table))
dp = XCHAR_TABLE (Vstandard_display_table);
if (tab_width <= 0 || tab_width > 1000) tab_width = 8;
p1 = p1start;
start = desired_glyphs->glyphs[vpos];
if (obey_window_width)
{
start += XFASTINT (w->left);
end = start + window_width - (truncate != 0);
if (!WINDOW_RIGHTMOST_P (w))
{
if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
{
int i;
for (i = 0; i < FRAME_SCROLL_BAR_COLS (f); i++)
*end-- = ' ';
}
else if (!FRAME_HAS_VERTICAL_SCROLL_BARS (f))
*end-- = '|';
}
}
if (! obey_window_width
|| (maxcol >= 0 && end - desired_glyphs->glyphs[vpos] > maxcol))
end = desired_glyphs->glyphs[vpos] + maxcol;
for (i = (hpos >= 0 ? hpos : 0); i < end - p1start + hpos; i++)
desired_glyphs->charstarts[vpos][i] = 0;
if (maxcol >= 0 && mincol > maxcol)
mincol = maxcol;
if (length < 0)
length = strlen (string);
truncated = 0;
while (1)
{
int len;
if (length <= 0)
break;
if (multibyte)
c = STRING_CHAR_AND_LENGTH (string, length, len);
else
c = *string, len = 1;
string += len, length -= len;
if (p1 >= end)
{
truncated = 1;
break;
}
if (dp != 0 && VECTORP (DISP_CHAR_VECTOR (dp, c)))
{
p1 = copy_part_of_rope (f, p1, start,
XVECTOR (DISP_CHAR_VECTOR (dp, c))->contents,
XVECTOR (DISP_CHAR_VECTOR (dp, c))->size,
0);
}
else if (c >= 040 && c < 0177)
{
if (p1 >= start)
*p1 = c;
p1++;
}
else if (c == '\t')
{
do
{
if (p1 >= start && p1 < end)
*p1 = SPACEGLYPH;
p1++;
}
while ((p1 - start + hscroll - (hscroll > 0)) % tab_width);
}
else if (c < 0200 && ! NILP (buffer_defaults.ctl_arrow))
{
if (p1 >= start)
*p1 = (fix_glyph
(f, (dp && INTEGERP (DISP_CTRL_GLYPH (dp))
&& GLYPH_CHAR_VALID_P (XINT (DISP_CTRL_GLYPH (dp)))
? XINT (DISP_CTRL_GLYPH (dp)) : '^'),
0));
p1++;
if (p1 >= start && p1 < end)
*p1 = c ^ 0100;
p1++;
}
else
{
int remaining_bytes = len;
if (c >= 0400 && CHAR_VALID_P (c, 0))
{
int charset = CHAR_CHARSET (c);
int columns = (charset == CHARSET_COMPOSITION
? cmpchar_table[COMPOSITE_CHAR_ID (c)]->width
: CHARSET_WIDTH (charset));
remaining_bytes -= CHARSET_BYTES (charset);
if (p1 < start)
{
columns -= start - p1;
p1 = start;
while (columns--)
{
if (p1 < end)
*p1 = SPACEGLYPH;
p1++;
}
}
else if (p1 + columns > end)
{
if (truncate)
{
while (p1 < end)
*p1++ = fix_glyph (f, truncate, 0);
truncated = 1;
}
break;
}
else
{
*p1++ = c;
while (--columns)
*p1++ = c | GLYPH_MASK_PADDING;
}
}
while (remaining_bytes > 0)
{
c = *(string - remaining_bytes--);
if (p1 >= start)
*p1 = (fix_glyph
(f, (dp && INTEGERP (DISP_ESCAPE_GLYPH (dp))
&& GLYPH_CHAR_VALID_P (XINT (DISP_ESCAPE_GLYPH (dp)))
? XINT (DISP_ESCAPE_GLYPH (dp)) : '\\'),
0));
p1++;
if (p1 >= start && p1 < end)
*p1 = (c >> 6) + '0';
p1++;
if (p1 >= start && p1 < end)
*p1 = (7 & (c >> 3)) + '0';
p1++;
if (p1 >= start && p1 < end)
*p1 = (7 & c) + '0';
p1++;
}
}
}
if (truncated)
{
p1 = end;
if (truncate) *p1++ = fix_glyph (f, truncate, 0);
}
else if (mincol >= 0)
{
end = desired_glyphs->glyphs[vpos] + mincol;
while (p1 < end)
*p1++ = SPACEGLYPH;
}
{
register int len = p1 - desired_glyphs->glyphs[vpos];
if (len > desired_glyphs->used[vpos])
desired_glyphs->used[vpos] = len;
desired_glyphs->glyphs[vpos][desired_glyphs->used[vpos]] = 0;
return len;
}
}
int
invisible_p (propval, list)
register Lisp_Object propval;
Lisp_Object list;
{
register Lisp_Object tail, proptail;
for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
{
register Lisp_Object tem;
tem = XCONS (tail)->car;
if (EQ (propval, tem))
return 1;
if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
return 1;
}
if (CONSP (propval))
for (proptail = propval; CONSP (proptail);
proptail = XCONS (proptail)->cdr)
{
Lisp_Object propelt;
propelt = XCONS (proptail)->car;
for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
{
register Lisp_Object tem;
tem = XCONS (tail)->car;
if (EQ (propelt, tem))
return 1;
if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
return 1;
}
}
return 0;
}
int
invisible_ellipsis_p (propval, list)
register Lisp_Object propval;
Lisp_Object list;
{
register Lisp_Object tail, proptail;
for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
{
register Lisp_Object tem;
tem = XCONS (tail)->car;
if (CONSP (tem) && EQ (propval, XCONS (tem)->car))
return ! NILP (XCONS (tem)->cdr);
}
if (CONSP (propval))
for (proptail = propval; CONSP (proptail);
proptail = XCONS (proptail)->cdr)
{
Lisp_Object propelt;
propelt = XCONS (proptail)->car;
for (tail = list; CONSP (tail); tail = XCONS (tail)->cdr)
{
register Lisp_Object tem;
tem = XCONS (tail)->car;
if (CONSP (tem) && EQ (propelt, XCONS (tem)->car))
return ! NILP (XCONS (tem)->cdr);
}
}
return 0;
}
void
syms_of_xdisp ()
{
staticpro (&Qinhibit_redisplay);
Qinhibit_redisplay = intern ("inhibit-redisplay");
staticpro (&Qmenu_bar_update_hook);
Qmenu_bar_update_hook = intern ("menu-bar-update-hook");
staticpro (&Qoverriding_terminal_local_map);
Qoverriding_terminal_local_map = intern ("overriding-terminal-local-map");
staticpro (&Qoverriding_local_map);
Qoverriding_local_map = intern ("overriding-local-map");
staticpro (&Qwindow_scroll_functions);
Qwindow_scroll_functions = intern ("window-scroll-functions");
staticpro (&Qredisplay_end_trigger_functions);
Qredisplay_end_trigger_functions = intern ("redisplay-end-trigger-functions");
staticpro (&Qinhibit_point_motion_hooks);
Qinhibit_point_motion_hooks = intern ("inhibit-point-motion-hooks");
staticpro (&last_arrow_position);
staticpro (&last_arrow_string);
last_arrow_position = Qnil;
last_arrow_string = Qnil;
DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay,
"Non-nil means don't actually do any redisplay.\n\
This is used for internal purposes.");
Vinhibit_redisplay = Qnil;
DEFVAR_LISP ("global-mode-string", &Vglobal_mode_string,
"String (or mode line construct) included (normally) in `mode-line-format'.");
Vglobal_mode_string = Qnil;
DEFVAR_LISP ("overlay-arrow-position", &Voverlay_arrow_position,
"Marker for where to display an arrow on top of the buffer text.\n\
This must be the beginning of a line in order to work.\n\
See also `overlay-arrow-string'.");
Voverlay_arrow_position = Qnil;
DEFVAR_LISP ("overlay-arrow-string", &Voverlay_arrow_string,
"String to display as an arrow. See also `overlay-arrow-position'.");
Voverlay_arrow_string = Qnil;
DEFVAR_INT ("scroll-step", &scroll_step,
"*The number of lines to try scrolling a window by when point moves out.\n\
If that fails to bring point back on frame, point is centered instead.\n\
If this is zero, point is always centered after it moves off frame.");
DEFVAR_INT ("scroll-conservatively", &scroll_conservatively,
"*Scroll up to this many lines, to bring point back on screen.");
scroll_conservatively = 0;
DEFVAR_INT ("scroll-margin", &scroll_margin,
"*Number of lines of margin at the top and bottom of a window.\n\
Recenter the window whenever point gets within this many lines\n\
of the top or bottom of the window.");
scroll_margin = 0;
DEFVAR_INT ("debug-end-pos", &debug_end_pos, "Don't ask");
DEFVAR_BOOL ("truncate-partial-width-windows",
&truncate_partial_width_windows,
"*Non-nil means truncate lines in all windows less than full frame wide.");
truncate_partial_width_windows = 1;
DEFVAR_BOOL ("mode-line-inverse-video", &mode_line_inverse_video,
"*Non-nil means use inverse video for the mode line.");
mode_line_inverse_video = 1;
DEFVAR_INT ("line-number-display-limit", &line_number_display_limit,
"*Maximum buffer size (in characters) for line number display\n\
If the buffer is bigger than this, the line number does not appear\n\
in the mode line.");
line_number_display_limit = 1000000;
DEFVAR_BOOL ("highlight-nonselected-windows", &highlight_nonselected_windows,
"*Non-nil means highlight region even in nonselected windows.");
highlight_nonselected_windows = 0;
DEFVAR_BOOL ("multiple-frames", &multiple_frames,
"Non-nil if more than one frame is visible on this display.\n\
Minibuffer-only frames don't count, but iconified frames do.\n\
This variable is not guaranteed to be accurate except while processing\n\
`frame-title-format' and `icon-title-format'.");
DEFVAR_LISP ("frame-title-format", &Vframe_title_format,
"Template for displaying the titlebar of visible frames.\n\
\(Assuming the window manager supports this feature.)\n\
This variable has the same structure as `mode-line-format' (which see),\n\
and is used only on frames for which no explicit name has been set\n\
\(see `modify-frame-parameters').");
DEFVAR_LISP ("icon-title-format", &Vicon_title_format,
"Template for displaying the titlebar of an iconified frame.\n\
\(Assuming the window manager supports this feature.)\n\
This variable has the same structure as `mode-line-format' (which see),\n\
and is used only on frames for which no explicit name has been set\n\
\(see `modify-frame-parameters').");
Vicon_title_format
= Vframe_title_format
= Fcons (intern ("multiple-frames"),
Fcons (build_string ("%b"),
Fcons (Fcons (build_string (""),
Fcons (intern ("invocation-name"),
Fcons (build_string ("@"),
Fcons (intern ("system-name"),
Qnil)))),
Qnil)));
DEFVAR_LISP ("message-log-max", &Vmessage_log_max,
"Maximum number of lines to keep in the message log buffer.\n\
If nil, disable message logging. If t, log messages but don't truncate\n\
the buffer when it becomes large.");
XSETFASTINT (Vmessage_log_max, 50);
DEFVAR_LISP ("window-size-change-functions", &Vwindow_size_change_functions,
"Functions called before redisplay, if window sizes have changed.\n\
The value should be a list of functions that take one argument.\n\
Just before redisplay, for each frame, if any of its windows have changed\n\
size since the last redisplay, or have been split or deleted,\n\
all the functions in the list are called, with the frame as argument.");
Vwindow_size_change_functions = Qnil;
DEFVAR_LISP ("window-scroll-functions", &Vwindow_scroll_functions,
"List of functions to call before redisplaying a window with scrolling.\n\
Each function is called with two arguments, the window\n\
and its new display-start position. Note that the value of `window-end'\n\
is not valid when these functions are called.");
Vwindow_scroll_functions = Qnil;
DEFVAR_INT ("minibuffer-scroll-overlap", &minibuffer_scroll_overlap,
"*Number of characters of overlap when scrolling a one-line window.\n\
This commonly affects the minibuffer window, hence the name of the variable.");
minibuffer_scroll_overlap = 20;
DEFVAR_BOOL ("unibyte-display-via-language-environment",
&unibyte_display_via_language_environment,
"*Non-nil means display unibyte text according to language environment.\n\
Specifically this means that unibyte non-ASCII characters\n\
are displayed by converting them to the equivalent multibyte characters\n\
according to the current language environment. As a result, they are\n\
displayed according to the current fontset.");
unibyte_display_via_language_environment = 0;
}
void
init_xdisp ()
{
Lisp_Object root_window;
#ifndef COMPILER_REGISTER_BUG
register
#endif
struct window *mini_w;
this_line_bufpos = 0;
mini_w = XWINDOW (minibuf_window);
root_window = FRAME_ROOT_WINDOW (XFRAME (WINDOW_FRAME (mini_w)));
echo_area_glyphs = 0;
previous_echo_glyphs = 0;
if (!noninteractive)
{
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (root_window)));
XSETFASTINT (XWINDOW (root_window)->top, FRAME_MENU_BAR_LINES (f));
set_window_height (root_window,
FRAME_HEIGHT (f) - 1 - FRAME_MENU_BAR_LINES (f),
0);
XSETFASTINT (mini_w->top, FRAME_HEIGHT (f) - 1);
set_window_height (minibuf_window, 1, 0);
XSETFASTINT (XWINDOW (root_window)->width, FRAME_WIDTH (f));
XSETFASTINT (mini_w->width, FRAME_WIDTH (f));
}
}