#include "info.h"
#include "display.h"
extern int info_any_buffered_input_p ();
static void free_display ();
static DISPLAY_LINE **make_display ();
DISPLAY_LINE **the_display = (DISPLAY_LINE **)NULL;
int display_inhibited = 0;
void
display_initialize_display (width, height)
int width, height;
{
free_display (the_display);
the_display = make_display (width, height);
display_clear_display (the_display);
}
void
display_clear_display (display)
DISPLAY_LINE **display;
{
register int i;
register DISPLAY_LINE *display_line;
for (i = 0; (display_line = display[i]); i++)
{
display[i]->text[0] = '\0';
display[i]->textlen = 0;
display[i]->inverse = 0;
}
}
int display_was_interrupted_p = 0;
void
display_update_display (window)
WINDOW *window;
{
register WINDOW *win;
display_was_interrupted_p = 0;
for (win = window; win; win = win->next)
{
if (((win->flags & W_WindowVisible) == 0) ||
((win->flags & W_UpdateWindow) == 0) ||
(win->height == 0))
continue;
display_update_one_window (win);
if (display_was_interrupted_p)
break;
}
display_update_one_window (the_echo_area);
}
void
display_update_one_window (win)
WINDOW *win;
{
register char *nodetext;
register char *last_node_char;
register int i;
char *printed_line;
int pl_index = 0;
int line_index = 0;
DISPLAY_LINE **display = the_display;
if (display_inhibited)
display_was_interrupted_p = 1;
if (!win->height || display_inhibited)
return;
if ((win->first_row < 0) || (win->first_row > the_screen->height))
return;
printed_line = (char *)xmalloc (1 + win->width);
if (!win->node || !win->line_starts)
goto done_with_node_display;
nodetext = win->line_starts[win->pagetop];
last_node_char = win->node->contents + win->node->nodelen;
for (; nodetext < last_node_char; nodetext++)
{
char *rep, *rep_carried_over, rep_temp[2];
int replen;
if (isprint (*nodetext))
{
rep_temp[0] = *nodetext;
replen = 1;
rep_temp[1] = '\0';
rep = rep_temp;
}
else
{
if (*nodetext == '\r' || *nodetext == '\n')
{
replen = win->width - pl_index;
}
else
{
rep = printed_representation (*nodetext, pl_index);
replen = strlen (rep);
}
}
if (replen + pl_index < win->width)
{
if (replen == 1)
{
printed_line[pl_index++] = *rep;
}
else
{
for (i = 0; i < replen; i++)
printed_line[pl_index++] = rep[i];
}
}
else
{
DISPLAY_LINE *entry;
if (*nodetext == '\n' || *nodetext == '\r' || *nodetext == '\t')
{
printed_line[pl_index] = '\0';
rep_carried_over = (char *)NULL;
}
else
{
for (i = 0; pl_index < (win->width - 1);)
printed_line[pl_index++] = rep[i++];
rep_carried_over = rep + i;
if (1 + line_index + win->first_row < the_screen->height)
{
if (win->flags & W_NoWrap)
printed_line[pl_index++] = '$';
else
printed_line[pl_index++] = '\\';
}
printed_line[pl_index] = '\0';
}
entry = display[line_index + win->first_row];
if (entry->inverse)
{
terminal_goto_xy (0, line_index + win->first_row);
terminal_clear_to_eol ();
entry->inverse = 0;
entry->text[0] = '\0';
entry->textlen = 0;
}
for (i = 0; i < pl_index; i++)
if (printed_line[i] != entry->text[i])
break;
if ((i != pl_index) || (pl_index != entry->textlen))
{
terminal_goto_xy (i, line_index + win->first_row);
if (i != pl_index)
terminal_put_text (printed_line + i);
if ((pl_index < win->width && pl_index < entry->textlen) ||
(entry->inverse))
terminal_clear_to_eol ();
fflush (stdout);
strcpy (entry->text + i, printed_line + i);
entry->textlen = pl_index;
entry->inverse = 0;
}
if (++line_index == win->height)
break;
if (info_any_buffered_input_p ())
{
free (printed_line);
display_was_interrupted_p = 1;
return;
}
pl_index = 0;
if (rep_carried_over)
for (; rep[pl_index]; pl_index++)
printed_line[pl_index] = rep[pl_index];
if (pl_index && (win->flags & W_NoWrap))
{
char *begin;
pl_index = 0;
printed_line[0] = '\0';
begin = nodetext;
while ((nodetext < last_node_char) && (*nodetext != '\n'))
nodetext++;
}
}
}
done_with_node_display:
for (; line_index < win->height; line_index++)
{
DISPLAY_LINE *entry = display[line_index + win->first_row];
if (entry && entry->textlen)
{
entry->textlen = 0;
entry->text[0] = '\0';
terminal_goto_xy (0, line_index + win->first_row);
terminal_clear_to_eol ();
}
}
if ((win->flags & W_InhibitMode) == 0)
{
window_make_modeline (win);
line_index = win->first_row + win->height;
if ((!display[line_index]->inverse) ||
(strcmp (display[line_index]->text, win->modeline) != 0))
{
terminal_goto_xy (0, line_index);
terminal_begin_inverse ();
terminal_put_text (win->modeline);
terminal_end_inverse ();
strcpy (display[line_index]->text, win->modeline);
display[line_index]->inverse = 1;
display[line_index]->textlen = strlen (win->modeline);
fflush (stdout);
}
}
win->flags &= ~W_UpdateWindow;
free (printed_line);
fflush (stdout);
}
void
display_scroll_display (start, end, amount)
int start, end, amount;
{
register int i, last;
DISPLAY_LINE *temp;
if (!terminal_can_scroll)
return;
if (!the_display[0])
return;
if (info_any_buffered_input_p ())
return;
terminal_scroll_terminal (start, end, amount);
if (amount > 0)
{
last = end + amount;
for (i = 0; i < (end - start); i++)
{
temp = the_display[last - i];
the_display[last - i] = the_display[end - i];
the_display[end - i] = temp;
}
for (i = start; i != (start + amount); i++)
{
the_display[i]->text[0] = '\0';
the_display[i]->textlen = 0;
the_display[i]->inverse = 0;
}
}
if (amount < 0)
{
last = start + amount;
for (i = 0; i < (end - start); i++)
{
temp = the_display[last + i];
the_display[last + i] = the_display[start + i];
the_display[start + i] = temp;
}
for (i = end + amount; i != end; i++)
{
the_display[i]->text[0] = '\0';
the_display[i]->textlen = 0;
the_display[i]->inverse = 0;
}
}
}
void
display_scroll_line_starts (window, old_pagetop, old_starts, old_count)
WINDOW *window;
int old_pagetop, old_count;
char **old_starts;
{
register int i, old, new;
int last_new, last_old;
int old_first, new_first;
int unchanged_at_top = 0;
int already_scrolled = 0;
old_first = old_pagetop;
new_first = window->pagetop;
last_new = window->pagetop + (window->height - 1);
if (last_new > window->line_count)
last_new = window->line_count - 1;
last_old = old_pagetop + (window->height - 1);
if (last_old > old_count)
last_old = old_count - 1;
for (old = old_first, new = new_first;
old < last_old && new < last_new;
old++, new++)
if (old_starts[old] != window->line_starts[new])
break;
else
unchanged_at_top++;
for (old = old_first + unchanged_at_top; old < last_old; old++)
{
for (new = new_first; new < last_new; new++)
if (old_starts[old] == window->line_starts[new])
{
for (i = 0; (old + i) < last_old; i++)
if (old_starts[old + i] != window->line_starts[new + i])
break;
{
int start, end, amount;
start = (window->first_row
+ ((old + already_scrolled) - old_pagetop));
amount = new - (old + already_scrolled);
end = window->first_row + window->height;
if (amount > 0)
end -= amount;
if ((end - start) > 0)
{
display_scroll_display (start, end, amount);
old += i;
already_scrolled += amount;
}
}
}
}
}
void
display_cursor_at_point (window)
WINDOW *window;
{
int vpos, hpos;
vpos = window_line_of_point (window) - window->pagetop + window->first_row;
hpos = window_get_cursor_column (window);
terminal_goto_xy (hpos, vpos);
fflush (stdout);
}
static DISPLAY_LINE **
make_display (width, height)
int width, height;
{
register int i;
DISPLAY_LINE **display;
display = (DISPLAY_LINE **)xmalloc ((1 + height) * sizeof (DISPLAY_LINE *));
for (i = 0; i < height; i++)
{
display[i] = (DISPLAY_LINE *)xmalloc (sizeof (DISPLAY_LINE));
display[i]->text = (char *)xmalloc (1 + width);
display[i]->textlen = 0;
display[i]->inverse = 0;
}
display[i] = (DISPLAY_LINE *)NULL;
return (display);
}
static void
free_display (display)
DISPLAY_LINE **display;
{
register int i;
register DISPLAY_LINE *display_line;
if (!display)
return;
for (i = 0; (display_line = display[i]); i++)
{
free (display_line->text);
free (display_line);
}
free (display);
}