This is screen.c in view mode; [Download] [Up]
/*
* Copyright (c) 1992, 1995 John E. Davis (davis@space.mit.edu)
* All Rights Reserved.
*/
#include <config.h>
#include <stdio.h>
#include <slang.h>
#include <string.h>
#ifdef pc_system
#include <dos.h>
#endif
#include "buffer.h"
#include "screen.h"
#include "window.h"
#include "paste.h"
#include "ins.h"
#include "ledit.h"
#include "display.h"
#include "sysdep.h"
#include "misc.h"
#include "vterm.h"
#include "file.h"
#include "hooks.h"
#ifdef HAS_SUBPROCESSES
#include "jprocess.h"
#endif
#ifdef FLOAT_TYPE
# define JED_VERSION "0.F97.14"
#else
# define JED_VERSION "0.97.14"
#endif
int Jed_Version_Number = 9714;
#define fputs(s,f) write(fileno(f), s, strlen(s))
Screen_Type JScreen[MAX_SCREEN_SIZE];
int Screen_Row = 1;
int Screen_Col = 1;
int Cursor_Motion; /* indicates cursor movement only -1 ^ v +1 < > */
int Scroll_Region_1;
int Scroll_Region_2;
int Scroll_Lines;
int Jed_Dollar = '$';
int User_Prefers_Line_Numbers = 0;
int Mode_Has_Syntax_Highlight;
int Wants_Syntax_Highlight; /* if non-zero, highlight the syntax.
*/
int Wants_Attributes = 1;
int Wants_HScroll = 20; /* controls automatic horizontal
* scrolling. If positive, scroll
* only line, if negative, whole wind
*/
int Term_Supports_Color = 1; /* optimistic assumption */
static Line *HScroll_Line;
static int HScroll; /* amount to scroll line by */
static int Absolute_Column;
static int Message_Color;
void (*X_Update_Open_Hook)(void); /* hooks called when starting */
void (*X_Update_Close_Hook)(void); /* and finishing update */
int Goal_Column;
int Display_Eight_Bit = 0;
int JED_CSI = -1;
unsigned short Point_On_Char; /* character at cursor position */
static int Point_Cursor_Flag = 1; /* if non-zero, point cursor */
static Line Eob_Line =
{
NULL, NULL, (unsigned char *) "[EOB]", 5
#ifdef KEEP_SPACE_INFO
,5
#endif
};
int Want_Eob = 0;
int Display_Time = 1; /* Turn on %t processing in status line */
void blank_line(int row)
{
int n = JWindow->width;
register unsigned short *p, *pmax;
p = JScreen[row].old;
if (p == NULL) return;
pmax = p + n;
while (p < pmax)
{
*p = 32; *(p + 1) = 32; *(p + 2) = 32; *(p + 3) = 32;
p += 4;
}
}
static void update_screen_txt(int row)
{
unsigned short *tmp;
tmp = JScreen[row].neew;
JScreen[row].neew = JScreen[row].old;
JScreen[row].old = tmp;
}
static unsigned char char_width[256];
static int dis8bit = -100;
static int j_csi = -1;
static int Selective_Display = -0x7FFF;
#define FIX_CHAR_WIDTH \
if ((Display_Eight_Bit != dis8bit) || (JED_CSI != j_csi)\
|| (Selective_Display != Buffer_Local.sd)) fix_char_width()
static int fix_attributes(register unsigned short *p, register unsigned short *pmax,
unsigned int color)
{
if (pmax == NULL) pmax = p + JWindow->width;
if (p >= pmax) return(0);
color = color << 8;
while (p < pmax)
{
*p = color | (*p & 0xFF);
p++;
}
return(1);
}
#ifdef HAS_DISPLAY_TABLE
unsigned char Output_Display_Table[256];
#endif
static int output(unsigned char *line, int len, int row, register int max_col,
register int column_offset, unsigned char *hi_beg, unsigned char *hi_end,
Line *buffer_line)
{
register unsigned char ch, *p, *pmax, *b;
register unsigned short *outp;
register int count;
unsigned char expb[80];
unsigned short *out, *mark, *hi0_outp = NULL, *hi1_outp = NULL, *sp, *spmax;
int tab, tabsize, visible, i, mini, w;
int done = 0;
unsigned short dollar = Jed_Dollar & 0xFF;
#if !defined(pc_system) && !defined(__os2__)
dollar |= 0x20; /* prevent control character */
if (*tt_Use_Ansi_Colors && Term_Supports_Color)
{
#endif
dollar |= JDOLLAR_COLOR << 8;
#if !defined(pc_system) && !defined(__os2__)
}
#endif
outp = out = JScreen[row - 1].neew;
if (outp == NULL) return 1;
tab = Buffer_Local.tab;
if (Buffer_Local.sd < 0)
*(char_width + (unsigned int) '\r') = 3;
else
*(char_width + (unsigned int) '\r') = 2;
count = 0;
visible = 0;
mini = 1;
while(mini >= 0)
{
/* deal with mini_buffer prompt */
if (mini && (IS_MINIBUFFER) && Mini_Info.prompt_len)
{
p = (unsigned char *) Mini_Info.prompt;
pmax = p + Mini_Info.prompt_len;
mini = 0;
}
else
{
p = line;
pmax = p + len;
mini = -1;
}
while (p < pmax)
{
if (p == hi_beg) hi0_outp = outp;
if (p == hi_end) hi1_outp = outp;
ch = (unsigned char) *p++;
b = expb;
/* expand char to display form */
#ifdef HAS_DISPLAY_TABLE
ch = Output_Display_Table[(unsigned int) ch];
#endif
w = *(char_width + (unsigned int) ch);
if (w == 1)
{
/* try to optimize this by putting this here */
count++;
if ((count < max_col) && (count >= column_offset))
{
*outp++ = (unsigned short) ch;
}
else if (count >= max_col)
{
done = 1;
p = pmax;
}
continue;
}
else if (w == 3)
{
if (ch == '\r')
{
*b++ = '.'; *b++ = '.'; *b++ = '.';
done = -1;
p = pmax;
}
else
{
*b++ = '~';
*b++ = '^';
/* Be better to replace following by:
* *b++ = ch - '@';
*/
ch &= 0x7F;
*b++ = (ch == 127) ? '?' : ch + 'A' - 1;
}
}
else if (w == 2)
{
if ((ch == '\t') && (tab > 0))
{
tabsize = tab * (count / tab + 1) - count;
i = 0; while (i++ < tabsize) *b++ = ' ';
w = tabsize;
}
else if (ch & 0x80)
{
*b++ = '~'; *b++ = ch & 0x7F;
}
else
{
*b++ = '^';
/* Be better to replace following by:
* *b++ = (ch | 0x80) - '@';
*/
*b++ = (ch == 127) ? '?' : ch + 'A' - 1;
}
}
else /* w = 0 */
{
ch = *p++; /* skip next char */
continue;
}
b = expb;
while (w--)
{
count++;
if (count >= max_col)
{
done = 1;
p = pmax;
}
else if (count >= column_offset)
{
*outp++ = (unsigned short) *b;
}
b++;
}
}
}
sp = out;
while (sp < outp)
{
if (*sp++ != ' ')
{
visible++;
break;
}
}
#if !defined(pc_system) && !defined(__os2__)
if (*tt_Use_Ansi_Colors && Term_Supports_Color)
{
#endif
if (Wants_Syntax_Highlight && Mode_Has_Syntax_Highlight
&& (line != Eob_Line.data)) syntax_highlight (out, outp);
else if (Message_Color)
{
unsigned short *ppp = out;
while (ppp < outp) *ppp++ |= Message_Color;
}
#if !defined(pc_system) && !defined(__os2__)
}
#endif
if (outp == out)
{
*outp++ = dollar;
visible = 1;
}
else if (column_offset > 1)
{
*out = dollar;
visible++;
}
mark = outp;
sp = outp;
spmax = out + JWindow->width;
#if defined(msdos) && !defined(__WATCOMC__) && !defined(__WIN32__)
asm mov bx, di
asm mov cx, word ptr spmax
asm sub cx, word ptr outp
asm shr cx, 1
asm mov ax, 32
asm les di, dword ptr outp
asm cld
asm rep stosw
asm mov di, bx
/* Note that outp is not updated here! */
#else
/* MEMSET((char *) sp, (char) ' ', sizeof(short) * (int) (spmax - sp)); */
/* This line burns some CPU */
while (sp < spmax) {*sp++ = 0x0020; *sp++ = 0x0020; *sp++ = 0x0020; *sp++ = 0x0020;
}
#endif
#ifdef JED_LINE_ATTRIBUTES
if ((buffer_line != NULL)
&& (buffer_line->flags & JED_LINE_MARK))
{
register unsigned short *ppp = out;
while (ppp < spmax) *ppp++ |= JLINE_COLOR << 8;
visible++;
}
#endif
if (done == 1)
{
mark = out + (JWindow->width - 1);
*mark = dollar;
visible += 1;
if ((hi_beg != NULL) && (hi0_outp == NULL)) hi0_outp = mark;
mark = NULL;
}
out[JWindow->width] = '\0';
/* fix highlighting on this line */
if ((Wants_Attributes) && (hi0_outp != NULL))
{
if (hi1_outp == NULL) hi1_outp = outp + 1;
visible += fix_attributes(hi0_outp, hi1_outp, JREGION_COLOR);
}
if (visible)
{
#if defined(msdos) && !defined(MSWINDOWS)
(void) mark;
/* 2nd and last parameters not used in msdos smartputs so they do
not need to be valid */
tt_smart_puts(out, out, *tt_Screen_Cols, row - 1);
#else
tt_smart_puts(out, JScreen[row-1].old, *tt_Screen_Cols, row - 1);
#endif
JScreen[row-1].n = visible;
Point_Cursor_Flag = 1;
}
/* else take care of it in calling routine */
return(visible);
}
static void display_line(Line *line, int row)
{
int len, cofs = JWindow->column;
Screen_Type *s = &JScreen[row - 1];
if (line != NULL)
{
len = line->len;
if (len && (row != *tt_Screen_Rows)
&& (line->data[len - 1] == '\n'))
{
if ((s->hi1 != NULL) && (s->hi1 == line->data + len)) s->hi1--;
len--;
}
if ((len > 0) || (cofs > 1)
|| ((row == *tt_Screen_Rows) && Mini_Info.prompt_len))
{
if (Wants_HScroll && (line == HScroll_Line) && HScroll)
{
cofs += HScroll;
}
len = output(line->data, len, row,
cofs + JWindow->width - 1, cofs,
s->hi0, s->hi1, line);
}
}
else len = 0;
if (len <= 0)
{
if (s->n)
{
tt_goto_rc(row - 1, 0);
Screen_Row = row;
tt_del_eol();
}
blank_line(row - 1);
s->n = 0;
}
s->line = line;
s->flags = 0;
/* s->hi0 = s->hi1 = NULL; */
if (len > 0) update_screen_txt(row-1);
}
static void mark_window_attributes(int wa)
{
register Screen_Type *s = &JScreen[JWindow->top - 1],
*smax = s + JWindow->rows, *s1, *s2;
Mark *m;
register Line *l = JWindow->beg.line, *ml;
unsigned char *hi0, *hi1;
int mn, pn, dn;
s1 = s;
if ((CBuf->vis_marks == 0) || (wa == 0) || (Wants_Attributes == 0))
{
s2 = s;
goto done; /* I hate gotos but they are convenient */
}
m = CBuf->marks;
while ((m->flags & VISIBLE_MARK) == 0) m = m->next;
ml = m->line;
mn = m->n; /* already in canonical form */
pn = LineNum + CBuf->nup; /* not in canonical form */
dn = pn - mn;
while (l != CLine) /* find pos of point in window */
{
s1++;
l = l->next;
}
/* s1 now points at current line */
/* The whole point of all of this is to preserve the screen flags without
touching the screen. */
if (dn > 0) /* mark on prev lines */
{
s2 = s1 + 1;
hi0 = l->data;
hi1 = l->data + Point;
if ((s1->hi0 != hi0) || (s1->hi1 != hi1))
{
s1->hi0 = hi0; s1->hi1 = hi1;
s1->flags = 1;
}
l = l->prev; s1--;
while ((s1 >= s) && (l != ml))
{
hi0 = l->data;
hi1 = l->data + l->len;
if ((s1->hi0 != hi0) || (s1->hi1 != hi1))
{
s1->hi0 = hi0; s1->hi1 = hi1;
s1->flags = 1;
}
l = l->prev; s1--;
}
if (s1 >= s)
{
hi0 = ml->data + m->point;
hi1 = ml->data + ml->len;
if ((s1->hi0 != hi0) || (s1->hi1 != hi1))
{
s1->hi0 = hi0; s1->hi1 = hi1;
s1->flags = 1;
}
s1--;
}
}
else if (dn < 0) /* mark ahead of point */
{
s2 = s1;
s1--;
hi0 = l->data + Point;
hi1 = l->data + l->len;
if ((s2->hi0 != hi0) || (s2->hi1 != hi1))
{
s2->hi0 = hi0; s2->hi1 = hi1;
s2->flags = 1;
}
l = l->next;
s2++;
while ((s2 < smax) && (l != ml))
{
hi0 = l->data;
hi1 = l->data + l->len;
if ((s2->hi0 != hi0) || (s2->hi1 != hi1))
{
s2->hi0 = hi0; s2->hi1 = hi1;
s2->flags = 1;
}
l = l->next;
s2++;
}
if (s2 < smax)
{
hi0 = ml->data;
hi1 = ml->data + m->point;
if ((s2->hi0 != hi0) || (s2->hi1 != hi1))
{
s2->hi0 = hi0; s2->hi1 = hi1;
s2->flags = 1;
}
s2++;
}
}
else /* same line */
{
if (Point < m->point)
{
s1->hi0 = l->data + Point;
s1->hi1 = l->data + m->point;
}
else
{
s1->hi1 = l->data + Point;
s1->hi0 = l->data + m->point;
}
s1->flags = 1;
s2 = s1 + 1;
s1--;
}
done: /* reached if there is no mark */
/* now do area outside the region */
while (s1 >= s)
{
if (s1->hi0 != NULL)
{
s2->hi1 = s1->hi0 = NULL;
s1->flags = 1;
}
s1--;
}
while (s2 < smax)
{
if (s2->hi0 != NULL)
{
s2->hi1 = s2->hi0 = NULL;
s2->flags = 1;
}
s2++;
}
}
static void open_scroll(void)
{
Scroll_Region_1 = 1;
Scroll_Region_2 = *tt_Screen_Rows;
Scroll_Lines = 0;
}
static void do_scroll_up(int n)
{
tt_goto_rc(0,0);
tt_delete_nlines(n);
}
static void do_scroll_down(int n)
{
tt_goto_rc(0, 0);
tt_reverse_index(n);
}
static void execute_scroll(void)
{
if (Scroll_Lines > 0)
{
tt_set_scroll_region(Scroll_Region_1 - 1, Scroll_Region_2 - 1);
execute_vscroll_up(Scroll_Region_1, Scroll_Region_2, Scroll_Lines);
do_scroll_up(Scroll_Lines);
}
else if (Scroll_Lines < 0)
{
tt_set_scroll_region(Scroll_Region_1 - 1, Scroll_Region_2 - 1);
execute_vscroll_down(Scroll_Region_1, Scroll_Region_2, -Scroll_Lines);
do_scroll_down(-Scroll_Lines);
}
Scroll_Lines = 0;
}
static void queue_scroll(int n, int r1, int r2)
{
if ((r1 != Scroll_Region_1) || (r2 != Scroll_Region_2))
{
/* if ((n == -1) && (Scroll_Region_1 == r1 + Scroll_Lines)
&& (Scroll_Region_2 == r2)) */
if ((n == -1) && (Scroll_Region_1 == r1 + Scroll_Lines)
&& (Scroll_Region_2 == r2)) Scroll_Lines--;
else if ((n == -1) && (Scroll_Region_1 == r1 + Scroll_Lines)
&& (Scroll_Region_2 == r2 - 1))
{
Scroll_Region_2 = r2;
Scroll_Lines--;
}
else
{
execute_scroll();
Scroll_Region_1 = r1;
Scroll_Region_2 = r2;
Scroll_Lines = n;
}
}
else Scroll_Lines += n;
}
static void close_scroll(void)
{
if (Scroll_Lines) execute_scroll();
if ((Scroll_Region_1 != 1) || (Scroll_Region_2 != *tt_Screen_Rows))
tt_reset_scroll_region();
}
/* Here a scrolling region (t,b) is used to scroll line t + n to t. All
that is assumed is that the line at t + n exists! */
int scroll_up(int n, int t, int b)
{
int i, necess;
if (n == 0) return(0);
/* t = JWindow->top - 1 + t;
b = JWindow->top - 1 + b; */
/* check to see if this is really necessary */
necess = 0;
for (i = t - 1; i < b; i++)
{
if (JScreen[i].n)
{
necess = 1;
break;
}
}
if (!necess) return(0);
queue_scroll(n, t, b);
vscroll_up(t,b,n);
return(necess);
}
/* Here a scrolling region (t,b) is used to scroll line t + n to t. */
void scroll_down(int n, int t, int b)
{
if (n == 0) return;
/* t = JWindow->top - 1 + t;
b = JWindow->top - 1 + b; */
tt_set_scroll_region(t - 1,b - 1);
tt_reverse_index(n);
tt_reset_scroll_region();
vscroll_down(t,b,n);
}
static int update_insert_line(int r1, Line *line)
{
int i, r2, r, necess;
Line *bot;
/* normalize r1: */
/* r1 = JWindow->top - 1 + r1; */
/* find the first one that is blank to delimit the region so that the
loss will be minimal */
r = r1; /* not r1 + 1 as obvious (but naive) as it seems */
r2 = JWindow->rows + JWindow->top - 1;
while (r < r2)
{
bot = JScreen[r - 1].line;
if ((bot == NULL) || (bot == &Eob_Line)) break;
r++;
}
if ((r1 != r2) && (r == r2))
/* we may have failed so check the bottom up so we don't push linesoff. */
{
bot = line;
for (r = r1 + 1; r <= r2; r++)
{
bot = bot->next;
if (bot == NULL) break;
if (JScreen[r-1].line == bot) break;
}
if ((bot != NULL) && (r <= r2)) r--;
if (r > r2) r = r2;
}
if (r < r1) r = r1;
r2 = r;
/* check to see if we gain by doing this */
necess = 0;
for (i = r1 - 1; i < r2; i++)
{
if (JScreen[i].n)
{
necess = 1;
break;
}
}
if (r1 == r2) return(0);
if (!necess) return(0);
queue_scroll(-1, r1, r2);
vscroll_down(r1, r2, 1);
return(1);
}
Line *find_top()
{
int n, i;
Line *line, *next, *prev, *tthis;
n = JWindow->rows - 1;
if (n <= 0) return(CLine);
/* Check the top window line. Chances are that one of the lines
above CLine will match in usual situations */
line = JScreen[JWindow->top - 1].line;
prev = CLine;
if (line != NULL) for (i = 0; i < JWindow->rows; i++)
{
if (prev == line) return(line);
tthis = prev->prev;
if (tthis == NULL) break;
else prev = tthis;
}
/* That was the obvious choice now try some others */
/* try bottom (or punt) */
if (*tt_Term_Cannot_Scroll)
{
if (*tt_Term_Cannot_Scroll == -1)
{
if ((line != NULL) && (CLine->next == line)) return (CLine);
if (CLine->prev != JScreen[JWindow->rows + JWindow->top - 2].line) n = n / 2;
}
else n = n / 2;
goto no_scroll;
}
line = JScreen[JWindow->rows + JWindow->top - 2].line;
next = CLine;
if (line != NULL) for (i = 0; i < JWindow->rows; i++)
{
if (next == line)
{
line = CLine;
while(i < JWindow->rows - 1)
{
prev = line->prev;
if (prev == NULL) return(line);
line = prev;
i++;
}
return(line);
}
next = next->next;
if (next == NULL) break;
}
/* try to find CLine somewhere in the window */
next = CLine->next;
prev = CLine->prev;
for (i = JWindow->top - 1; i < JWindow->top - 1 + JWindow->rows; i++)
{
tthis = JScreen[i].line;
if (tthis == CLine)
{
line = CLine;
while(i > JWindow->top - 1)
{
i--;
line = line->prev;
if (line == NULL) return(CLine);
}
return(line);
}
else if ((tthis == prev) && (tthis != NULL))
{
i--;
while(i-- > JWindow->top - 1)
{
if (prev->prev == NULL) return(prev);
prev = prev->prev;
}
return(prev);
}
else if ((tthis == next) && (tthis != NULL))
{
i++;
while(i-- > JWindow->top - 1)
{
if (next->prev == NULL) return(next);
next = next->prev;
}
return(next);
}
}
/* not found so check neighbors */
line = CLine->next;
if ((line != NULL) && (line == JScreen[JWindow->top - 1].line)) return(CLine);
line = CLine->prev;
if ((line == NULL) || (line != JScreen[n + JWindow->top - 1].line))
{
n = n / 2;
}
no_scroll: /* on terms that cannot scroll */
line = prev = CLine;
while(n--)
{
line = line->prev;
if (line == NULL) return(prev);
prev = line;
}
return(line);
}
static void do_scroll(register Line *top)
{
Line *bot, *middle1, *middle2, *s;
register Line *sline;
int r1, r, r2, match, overwrite = 1, scroll_region_set = 0, srs, nrows;
int n1, n2, n3 = 0;
/* unsigned short sh; */
nrows = JWindow->rows;
r1 = JWindow->top;
r2 = r1 + nrows - 1;
/* Actually it might be more benificial to extend r2 to a status line.
The status line is easy to detect since it begins with a highlighted
minus sign. */
/*
r = r2;
while (r < *tt_Screen_Rows - 1)
{
sh = JScreen[r].old[0];
if (((sh & 0xFF) == '-') && (sh >> 8)) break;
r++;
}
nrows = r - r1 + 1;
r2 = r;
*/
open_scroll();
if (top != NULL) bot = top->next; else bot = NULL;
middle1 = middle2 = NULL;
r = 1;
bot = top;
n1 = nrows / 3;
n2 = 2 * n1;
/* I do not want to use CLine and the previous one as a basis
* for determining scroll region since we may have just created it.
* There is nothing right or wrong about it--- just a feeling that
* results in optimization of screen update. */
while (r++ < nrows)
{
if ((r >= n1) && (middle1 == NULL) && (bot != NULL)
&& (bot != CLine) && (bot != CLine->prev)) middle1 = bot;
if ((r >= n2) && (middle2 == NULL) && (bot != NULL)
&& (bot != CLine) && (bot != CLine->prev))
{
middle2 = bot;
n2 = bot->len;
}
if (bot != NULL) bot = bot -> next;
}
/* if the middle or the bottom lines match, we do not overwrite */
if (bot != NULL) n3 = bot->len;
if (middle1 == NULL) overwrite = 0;
else
{
n1 = middle1->len;
/* I do not want to scroll if only 1 thing matches */
for (r = r1; r <= r2; r++)
{
s = JScreen[r - 1].line;
if (((middle1 == s) && (n1 == s->len)
&& n1 && (middle1->data[n1 / 2] == s->data[n1 / 2]))
|| ((middle2 == s) && (middle2 != NULL) && (n2 == s->len)
&& n2 && (middle2->data[n2 / 2] == s->data[n2 / 2]))
|| ((bot != NULL) && (bot == s) && (n3 > 4) && (n3 == s->len)
&& n3 && (bot->data[n3/2] == s->data[n3 / 2])))
{
overwrite = 0;
break;
}
}
}
while(r1 <= r2)
{
if (top == NULL) break;
match = 0;
for(r = r1; r <= r2; r++)
{
sline = JScreen[r - 1].line;
if (sline == top)
{
if (r != r1)
{
scroll_region_set = 0;
scroll_up(r - r1, r1, r2);
}
r1++;
match = 1;
if (top != NULL) top = top->next;
break;
}
}
if (match) continue;
/* not found so insert it */
if ((top != NULL) && (!overwrite))
{
srs = update_insert_line(r1, top);
if (!scroll_region_set) scroll_region_set = srs;
}
if (top != NULL) top = top->next;
r1++;
}
/* if (scroll_region_set) reset_scroll_region(); */
close_scroll();
if (overwrite) touch_window();
}
static void fix_char_width(void)
{
int i;
for (i = 0; i < 32; i++)
{
char_width[i] = 2;
char_width[i + 128] = 3;
}
for (i = 32; i < 127; i++)
{
char_width[i] = 1;
char_width[i + 128] = 2;
}
char_width[127] = 2;
char_width[255] = 3;
if (Display_Eight_Bit > 0)
{
for (i = (Display_Eight_Bit > 127 ? Display_Eight_Bit : 128);
i < 256; i++)
{
char_width[i] = 1;
}
}
dis8bit = Display_Eight_Bit;
if ((Selective_Display = Buffer_Local.sd) < 0)
{
char_width[(unsigned char) '\r'] = 3;
}
if (JED_CSI > 0) char_width[(unsigned char) JED_CSI] = 0;
j_csi = JED_CSI;
}
void point_column(int n)
{
register unsigned char *p, *pmax;
register int i;
int tab, w, sd;
FIX_CHAR_WIDTH;
if (IS_MINIBUFFER) n -= Mini_Info.effective_prompt_len;
if (CLine->len == 0)
{
Point = 0;
return;
}
p = CLine->data;
pmax = p + (CLine->len - 1);
if (*pmax != '\n') pmax++;
tab = Buffer_Local.tab;
sd = (Buffer_Local.sd < 0);
i = 0;
n--; /* start at 0 */
while(p < pmax)
{
if ((*p == '\t') && tab)
{
i = tab * (i / tab + 1);
}
else
{
w = char_width[*p];
i += w;
if (w == 0) p++;
}
if ((i > n) || (sd && (*p == '\r'))) break;
p++;
}
Point = (int) (p - CLine->data);
}
/* given a position in a line, return apparant distance from bol
* expanding tabs, etc... up to pos.
*
* ****Note****
* !! misc.c calls this using the minibuffer prompt. This routine
* !! can only depend on Point and CLine->data but not CLine->len!!
*/
int calculate_column()
{
register int i;
int tab, w;
register unsigned char *cw = char_width;
register unsigned char ch, *pos, *this_pos;
int sd;
FIX_CHAR_WIDTH;
pos = CLine->data;
this_pos = pos + Point;
i = 1;
tab = Buffer_Local.tab;
sd = Buffer_Local.sd;
while(pos < this_pos)
{
ch = *pos++;
if ((ch == '\t') && tab)
{
i = tab * ((i - 1)/tab + 1) + 1; /* tab column tabs */
}
else
{
w = cw[ch];
/* w = char_width[ch]; */
i += w;
if (w == 0) pos++;
}
if ((ch == '\r') && sd) break;
}
Absolute_Column = i;
if (IS_MINIBUFFER) i += Mini_Info.effective_prompt_len;
Screen_Col = i;
return (i);
}
void point_cursor(int c)
{
int r, row;
Line *tthis;
if (JWindow->trashed) return;
r = 0;
Point_Cursor_Flag = 0;
for (row = JWindow->top; row < JWindow->top + JWindow->rows; row++)
{
tthis = JScreen[row-1].line;
if (tthis == NULL) break;
if ((tthis == CLine) || (tthis == &Eob_Line))
{
r = row;
break;
}
}
if (Point >= CLine->len)
{
Point = CLine->len - 1;
if (Point < 0) Point = 0;
else if ((*(CLine->data + Point) != '\n')
|| (CBuf == MiniBuffer)) Point++;
}
if (r)
{
if (!c) c = calculate_column();
c = c - JWindow->column + 1;
if (CLine == HScroll_Line) c -= HScroll;
if (c < 1) c = 1; else if (c > JWindow->width) c = JWindow->width;
Point_On_Char = JScreen[r - 1].old[c - 1];
tt_goto_rc (r - 1 , c - 1);
Screen_Row = r;
Screen_Col = c;
}
else
{
/* msg_error("Point not visible in Window."); */
c = 1;
}
flush_output ();
if (!Cursor_Motion) Goal_Column = c;
}
static unsigned short *stat_cpy(register unsigned short *s1,
register unsigned char *v,
register unsigned short *smax)
{
register unsigned char ch;
if (v == NULL) return (s1);
while ((s1 < smax) && ((ch = *v++) != 0))
{
if (((unsigned int)(ch & 0x7F) < 32)
|| (ch == 127))
{
if (ch & 0x80)
{
*s1++ = (unsigned short) '~';
if (s1 == smax) break;
ch = ch & 0x7F;
}
*s1++ = (unsigned short) '^';
if (s1 < smax)
{
if (ch == 127) *s1++ = (unsigned short) '?';
else
*s1++ = (unsigned short) (ch + '@');
}
}
else *s1++ = ch;
}
return (s1);
}
/* site.sl should modify this */
char Default_Status_Line[80] =
" ^Ke: quit, ^Kg: get file, ^K^W: write file | %b (%m%n%o) %p";
static unsigned long Status_Last_Time;
static unsigned long Status_This_Time;
static char *status_get_time(void)
{
static char status_time[10];
register char *t, ch, *t1;
char am;
int n;
if (Display_Time == 0) return (NULL);
if (Status_This_Time == 0) Status_This_Time = sys_time();
if (Status_This_Time - Status_Last_Time >= 30)
{
Status_Last_Time = Status_This_Time;
am = 'a';
t = SLcurrent_time_string ();
/* returns a string like: "Tue Nov 2 13:18:19 1993" */
t1 = status_time;
while (ch = *t, (ch <= '0') || (ch > '9')) t++;
/* on date number, skip it */
while (*t++ != ' ');
if (*t == '0') t++;
if (Display_Time > 0)
{
n = 0;
while ((ch = *t++) != ':')
{
n = 10 * n + (int) (ch - '0');
}
if (n >= 12) am = 'p';
n = n % 12;
if (n == 0) n = 12;
if (n >= 10)
{
n -= 10;
*t1++ = '1';
}
*t1++ = '0' + n;
*t1++ = ':';
while ((*t1++ = *t++) != ':');
*(t1 - 1) = am; *t1++ = 'm'; *t1 = 0;
}
else
{
*t1++ = '[';
while ((*t1++ = *t++) != ':');
while ((*t1++ = *t++) != ':');
*--t1 = ']'; *++t1 = 0;
}
}
return (status_time);
}
static unsigned short *finish_status(unsigned short *s1, unsigned short *smax, int col_flag)
{
unsigned int line, maxline;
register char *v, ch;
Line *l;
int top, rows;
char pstr[20], *str, col_buf[20];
unsigned short *s1_save = s1;
/* line = w->mark.n - buf->nup; */
line = LineNum;
maxline = Max_LineNum;
if (!User_Prefers_Line_Numbers)
{
top = JWindow->top - 1; rows = JWindow->rows - 1;
l = JScreen[top + rows].line;
if (l == CBuf->end) l = NULL;
if (JScreen[top].line == CBuf->beg)
{
if (l == NULL) strcpy(pstr,"All");
else strcpy(pstr,"Top");
}
else if (l == NULL) strcpy(pstr, "Bot");
else
{
sprintf(pstr, "%d%%",
(int) ((line * 100L) / (long) maxline));
}
}
else sprintf(pstr, "%d/%d", line, maxline);
v = CBuf->status_line;
if (*v == 0) v = Default_Status_Line;
while (((ch = *v++) != 0) && (s1 < smax))
{
if (ch != '%') *s1++ = ch;
else
{
ch = *v++;
switch (ch)
{
case 'a':
if (CBuf->flags & ABBREV_MODE) str = " abbrev"; else str = NULL;
break;
case 'f': str = CBuf->file; break;
case 'n':
if (CBuf->narrow != NULL) str = " Narrow"; else str = NULL;
break;
case 'o':
if (CBuf->flags & OVERWRITE_MODE) str = " Ovwrt"; else str = NULL;
break;
case 'b': str = CBuf->name; break;
case 'p': str = pstr; break;
case 'v': str = JED_VERSION; break;
case 'm': str = CBuf->mode_str; break;
case 't': str = status_get_time(); break;
case 'c': if (User_Prefers_Line_Numbers > 1)
{
if (col_flag) (void) calculate_column ();
sprintf(col_buf, "%d", Absolute_Column);
str = col_buf;
}
else
{
/* 100 to 1 that there is punctuation before this, kill it */
if (s1 > s1_save) s1--;
str = NULL;
}
break;
case '%': str = "%"; break;
default: return(s1);
}
if (str != NULL) s1 = stat_cpy(s1, (unsigned char *) str, smax);
}
}
return (s1);
}
void set_status_format(char *f, int *local)
{
char *s;
if (*local) s = Default_Status_Line; else s = CBuf->status_line;
strncpy(s, f, 79);
s[79] = 0;
}
static void make_status_line(int col_flag)
{
unsigned short mrk, flag, spot, star, ubit = '-';
register unsigned short *s1, *s, *smax;
if (JWindow->top == *tt_Screen_Rows) return; /* minibuffer ? */
s = JScreen[JWindow->rows + JWindow->top - 1].neew;
smax = s + JWindow->width;
mrk = flag = spot = star = '-';
if (CBuf->marks != NULL) mrk = 'm';
if (CBuf->flags & FILE_MODIFIED) flag = 'd';
if (CBuf->spots != NULL) spot = 's';
if (CBuf->flags & BUFFER_TRASHED) star = '*';
if (CBuf->flags & READ_ONLY) star = '%';
if (CBuf->flags & UNDO_ENABLED) ubit = '+';
s1 = s;
if (JWindow->column != 1) *s1++ = '<'; else *s1++ = '-';
*s1++ = star; *s1++ = star; *s1++ = mrk; *s1++ = flag;
*s1++ = spot;
if (CBuf->flags & BINARY_FILE) *s1++ = 'B';
#ifdef pc_system
else if ((CBuf->flags & ADD_CR_ON_WRITE_FLAG) == 0) *s1++ = 'L';
#else
#ifdef unix
else if (CBuf->flags & ADD_CR_ON_WRITE_FLAG) *s1++ = 'C';
#endif
#endif
else *s1++ = '-';
*s1++ = ubit;
s1 = finish_status(s1, smax, col_flag);
if (Defining_Keyboard_Macro) s1 = stat_cpy(s1, (unsigned char *) " [Macro]", smax);
while (s1 < smax) *s1++ = '-';
*smax = 0;
(void) fix_attributes (s, smax, JSTATUS_COLOR);
}
static int update_status_line(int col_flag)
{
int r;
if (JWindow->top == *tt_Screen_Rows) return(0); /* minibuffer ? */
r = JWindow->rows + JWindow->top - 1;
make_status_line(col_flag);
tt_smart_puts(JScreen[r].neew, JScreen[r].old, *tt_Screen_Cols, r);
Point_Cursor_Flag = 1;
update_screen_txt(r);
JScreen[r].n = *tt_Screen_Cols;
return(1);
}
/* if force then do update otherwise return 1 if update or 0 if not */
static int update_1(Line *top, int force)
{
int i;
Window_Type *w;
int did_eob = 0, time_has_expired = 0;
if (Batch ||
(!force
&& (Executing_Keyboard_Macro || (Repeat_Factor != NULL)
|| Input_Buffer_Len || input_pending(&Number_Zero)
|| (Read_This_Character != NULL)))
|| (CBuf != JWindow->buffer))
{
return(0);
}
if (Suspend_Screen_Update != 0)
{
Suspend_Screen_Update = 0;
touch_screen ();
}
JWindow->mark.line = CLine;
JWindow->mark.point = Point;
JWindow->mark.n = LineNum + CBuf->nup;
CBuf->linenum = LineNum;
CBuf->max_linenum = Max_LineNum;
if (Wants_Attributes && CBuf->vis_marks)
{
JWindow->trashed = 1;
}
/* Do not bother setting this unless it is really needed */
if (Display_Time)
{
Status_This_Time = sys_time();
time_has_expired = (Status_This_Time > Status_Last_Time + 45);
}
/* if cursor moves just left right, do not update status line */
if (!force && !JWindow->trashed &&
((JWindow == JWindow->next) || (User_Prefers_Line_Numbers && Cursor_Motion))
/* if % wanted, assume user is like me and gets annoyed with
screen updates */
&& (User_Prefers_Line_Numbers || time_has_expired))
{
update_status_line(0);
return(1);
}
if (!JWindow->trashed && Cursor_Motion) return(1);
w = JWindow;
do
{
/* #define HANDLE_CTRL_L */
#ifdef HANDLE_CTRL_L
int cline_found = 0;
#endif
if (Wants_Syntax_Highlight) init_syntax_highlight ();
did_eob = 0;
if (top == NULL) top = find_top();
if (top == NULL) top = CLine;
JWindow->beg.line = top;
/* scroll the screen to optimal location */
if (0 == *tt_Term_Cannot_Scroll) do_scroll(top);
mark_window_attributes((w == JWindow) || (w->buffer != CBuf));
for (i = JWindow->top - 1; i < JWindow->rows + JWindow->top - 1; i++)
{
/* the next line is really optional */
#ifndef pc_system
if (!force && (Exit_From_MiniBuffer ||
input_pending(&Number_Zero))) break;
#endif
#ifdef HANDLE_CTRL_L
if (CLine == top)
{
cline_found = 1;
}
#endif
if ((JScreen[i].line != top) || (JScreen[i].flags)
|| (Want_Eob
&& !did_eob
&& (i != *tt_Screen_Rows - 1)
&& (top == NULL)))
{
if (((top == NULL) || (top->len == 0))
&& (Want_Eob && !did_eob && !(CBuf->flags & READ_ONLY)))
{
display_line(&Eob_Line, i + 1);
/* JScreen[i].line = top; */
did_eob = 1;
}
else display_line(top, i + 1);
}
if (top != NULL)
{
#ifdef HANDLE_CTRL_L
if (cline_found && (*top->data == 0xC))
{
cline_found = -1;
top = NULL;
}
else
#endif
top = top->next;
}
}
HScroll_Line = NULL;
Mode_Has_Syntax_Highlight = 0;
if (!force && input_pending(&Number_Zero))
{
while(JWindow != w) other_window();
JWindow->trashed = 1; /* since cursor not pointed */
return(0);
}
else update_status_line(w != JWindow);
JWindow->trashed = 0;
other_window();
top = NULL;
/* if (!JWindow->trashed) top = JWindow->beg.line; else top = NULL; */
}
while(JWindow != w);
return(1);
}
int Mini_Ghost = 0;
static void update_minibuffer(void)
{
Window_Type *w;
if (Executing_Keyboard_Macro) return;
if (MiniBuffer != NULL)
{
w = JWindow;
while (!IS_MINIBUFFER) other_window();
if ((*Message_Buffer) && JScreen[*tt_Screen_Rows - 1].n) (void) input_pending(&Number_Ten);
JWindow->beg.line = CLine;
mark_window_attributes(1);
display_line(CLine, *tt_Screen_Rows);
while (w != JWindow) other_window();
Mini_Ghost = 1;
}
else if (Mini_Ghost && !*Error_Buffer && !*Message_Buffer)
{
/* if < 0, it is a result of flush message so let it pass this round */
if (Mini_Ghost < 0) Mini_Ghost = 1;
else
{
display_line(NULL, *tt_Screen_Rows);
if (!JWindow->trashed) point_cursor(0);
Mini_Ghost = 0;
}
}
else Mini_Ghost = ((*Message_Buffer) || (*Error_Buffer));
}
void do_dialog(char *b)
{
int len = 0, dout, row = *tt_Screen_Rows - 1;
char *quit = "Quit!";
if (Batch) return;
FIX_CHAR_WIDTH;
if (! *b)
{
if(!SLKeyBoard_Quit) return;
b = quit;
}
if (MiniBuffer)
{
len = Mini_Info.prompt_len;
Mini_Info.prompt_len = 0;
}
if ((b == Error_Buffer) || (b == quit))
{
Message_Color = JERROR_COLOR << 8;
touch_screen();
}
else Message_Color = JMESSAGE_COLOR << 8;
dout = output((unsigned char *) b, strlen(b),
*tt_Screen_Rows, *tt_Screen_Cols, 1, NULL, NULL, NULL);
Message_Color = 0;
if (MiniBuffer) Mini_Info.prompt_len = len;
if ((b == Error_Buffer) || (SLKeyBoard_Quit))
{
beep();
flush_input();
}
if (!dout)
{
if (JScreen[row].n)
{
tt_goto_rc(*tt_Screen_Rows - 1, 0);
tt_del_eol();
}
blank_line(row);
JScreen[row].n = 0;
}
else
{
update_screen_txt(row);
if (MiniBuffer != NULL)
{
flush_output ();
(void) input_pending(&Number_Ten);
}
}
Mini_Ghost = -dout;
}
static void set_hscroll(int col)
{
int hdiff, whs = abs(Wants_HScroll), wc = JWindow->column - 1,
sw = *tt_Screen_Cols - 1;
static Line *last;
Line *tmp;
/* take care of last effect of horizontal scroll */
if (last != NULL)
{
tmp = CLine;
CLine = last;
register_change(0);
CLine = tmp;
if (last != CLine)
{
#if 0
/* I need to think about this more */
if (Wants_HScroll < 0)
{
if (wc != 0)
{
JWindow->column = 1;
wc = 0;
touch_window ();
}
}
#endif
HScroll = 0;
}
last = NULL;
}
col--; /* use 0 origin */
hdiff = col - wc;
if ((HScroll >= hdiff)
|| (HScroll <= hdiff - sw))
{
if (hdiff >= sw)
{
HScroll = hdiff - sw + whs;
}
else if ((hdiff == 0) && (wc == 0)) HScroll = 0;
else if (hdiff <= 1)
{
HScroll = hdiff - whs - 1;
}
else HScroll = 0;
}
if (HScroll)
{
if (wc + HScroll < 0) HScroll = -wc;
if (Wants_HScroll < 0)
{
JWindow->column += HScroll;
touch_window();
HScroll = 0;
}
else
{
register_change(0);
last = HScroll_Line = CLine;
}
}
}
static char Top_Screen_Line_Buffer[132] = "If you see this, you have an installation problem.";
void define_top_screen_line (char *neew)
{
SLang_push_string (Top_Screen_Line_Buffer);
strncpy (Top_Screen_Line_Buffer, neew, 130);
Top_Screen_Line_Buffer[131] = 0;
JScreen[0].flags = 1;
}
static void update_top_screen_line (void)
{
register unsigned short *s, *smax, *s1;
register unsigned char ch, *chp;
if (Top_Window_Row == 1) return;
chp = (unsigned char *) Top_Screen_Line_Buffer;
s = s1 = JScreen[0].neew;
smax = s + JWindow->width;
while ((s1 < smax) && ((ch = *chp++) != 0))
{
*s1++ = (unsigned short) ch;
}
while (s1 < smax) *s1++ = ' ';
*smax = 0;
(void) fix_attributes (s, smax, JMENU_COLOR);
tt_smart_puts(JScreen[0].neew, JScreen[0].old, *tt_Screen_Cols, 0);
Point_Cursor_Flag = 1;
update_screen_txt(0);
JScreen[0].n = *tt_Screen_Cols;
JScreen[0].flags = 0;
}
/* if flag is non-zero, do not touch the message/error buffers */
void update(Line *line, int force, int flag)
{
int pc_flag = 1;
int col;
static unsigned long last_time;
Line *hscroll_line_save;
#ifdef HAS_SUBPROCESSES
if (Child_Status_Changed_Flag)
{
jed_get_child_status ();
force = 1;
}
#endif
if (Batch) return;
if (!force && !SLang_Error && !SLKeyBoard_Quit && (!*Error_Buffer))
{
if (Input_Buffer_Len || input_pending (&Number_Zero))
{
JWindow->trashed = 1;
return;
}
}
if (last_time + 30 < Status_This_Time)
{
if (last_time == 0) last_time = Status_This_Time;
else
{
last_time = Status_This_Time;
if (SLang_run_hooks ("update_timer_hook", NULL, NULL))
flag = 0;
}
}
if (Suspend_Screen_Update != 0)
{
Suspend_Screen_Update = 0;
touch_screen ();
}
if (X_Update_Open_Hook != NULL) (*X_Update_Open_Hook) ();
FIX_CHAR_WIDTH;
col = calculate_column();
HScroll_Line = NULL;
if (Wants_HScroll) set_hscroll(col); else HScroll = 0;
hscroll_line_save = HScroll_Line;
if (SLang_Error) flag = 0; /* update hook invalidates flag */
if (SLang_Error && !(*Error_Buffer || SLKeyBoard_Quit)) SLang_doerror(NULL);
if (!flag && (*Error_Buffer || SLKeyBoard_Quit))
{
do_dialog(Error_Buffer);
SLKeyBoard_Quit = 0;
SLang_restart(0);
SLang_Error = 0;
flag = 0;
Mini_Ghost = 1;
(void) update_1(line, 1);
update_minibuffer();
}
else if (!flag && *Message_Buffer)
{
if (!update_1(line, force))
{
/* *Message_Buffer = 0; */
goto done;
}
Mini_Ghost = 1;
do_dialog(Message_Buffer);
update_minibuffer();
}
else
{
pc_flag = JWindow->trashed || (JWindow != JWindow->next) || Cursor_Motion;
if (!flag) update_minibuffer();
if (!update_1(line, force)) goto done;
}
if (!flag) *Error_Buffer = *Message_Buffer = 0;
if ((Top_Window_Row != 1) && JScreen[0].flags)
{
update_top_screen_line ();
}
done:
HScroll_Line = hscroll_line_save;
if (Point_Cursor_Flag || pc_flag) point_cursor(col);
if (X_Update_Close_Hook != NULL) (*X_Update_Close_Hook) ();
flush_output ();
}
/* search for the CLine in the SCreen and flag it as changed */
/* n = 0 means line was changed, n = 1 means it was destroyed */
void register_change(int n)
{
Window_Type *w;
register Screen_Type *s, *smax;
register Line *cl = CLine;
JWindow->trashed = 1;
if (Suspend_Screen_Update) return;
if (No_Screen_Update)
{
No_Screen_Update = 0;
if (((n == CINSERT) || (n == CDELETE)) && (JWindow->next == JWindow))
{
/* Since no screen update, we are probably safe to do: */
/* JScreen[Screen_Row - 1].flags = 1; */
return;
}
w = JWindow->next; /* skip this window */
}
else w = JWindow;
do
{
s = &JScreen[w->top - 1];
smax = s + w->rows;
while (s < smax)
{
if (s->line == cl)
{
s->flags = 1;
if ((n == NLDELETE) || (n == LDELETE)) s->line = NULL;
w->trashed = 1;
}
s++;
}
w = w->next;
}
while(w != JWindow);
}
static int Display_Initialized;
void reset_display()
{
int i;
unsigned short *p;
if (Display_Initialized == 0) return;
if (Batch) return;
Display_Initialized = 0;
tt_reset_video ();
/* tt_del_eol ();
flush_output (); */
for (i = 0; i < *tt_Screen_Rows; i++)
{
p = JScreen[i].old; if (p != NULL) SLFREE(p); JScreen[i].old = NULL;
p = JScreen[i].neew; if (p != NULL) SLFREE(p); JScreen[i].neew = NULL;
}
}
void init_display(int g)
{
int i, r, c;
unsigned short *old, *neew = NULL;
if (Batch) return;
if (g)
{
get_term_dimensions(&c, &r);
if (r > MAX_SCREEN_SIZE) r = MAX_SCREEN_SIZE;
if (r <= 4) r = 4;
if (c <= 4) c = 4;
if (JWindow != NULL)
{
/* Note that this next call will call this routine again
with g = 0. */
change_screen_size (c, r);
return;
}
*tt_Screen_Cols = c;
*tt_Screen_Rows = r;
}
tt_init_video();
for (i = 0; i < *tt_Screen_Rows; i++)
{
/* these are bigger to handle overflow in output routine in case
* special char occurs at end as well as allowing code as in blank_line*/
if ((NULL == (old = (unsigned short *) SLCALLOC(*tt_Screen_Cols + 3, sizeof(short))))
|| (NULL == (neew = (unsigned short *) SLCALLOC(*tt_Screen_Cols + 3, sizeof(short)))))
{
exit_error("init_display(): malloc error.", 0);
}
JScreen[i].line = NULL;
JScreen[i].flags = 1;
JScreen[i].n = 0;
JScreen[i].old = old;
JScreen[i].neew = neew;
neew = old + *tt_Screen_Cols;
while (old < neew) *old++ = ' ';
}
Display_Initialized = 1;
}
void redraw_screen(int force)
{
int row, center;
Window_Type *w;
Line *l;
if (Batch) return;
#ifndef msdos
/* send_string_to_term("\033[?6h"); */ /* relative origin mode */
tt_reset_scroll_region();
tt_end_insert();
#endif
tt_normal_video ();
tt_cls();
for (row = 0; row < *tt_Screen_Rows; row++)
{
JScreen[row].line = NULL;
JScreen[row].n = 0;
JScreen[row].flags = 1;
blank_line(row);
}
w = JWindow;
center = JWindow->trashed;
do
{
w->trashed = 1;
w = w->next;
}
while(w != JWindow);
if (center)
{
for (row = 0; row < JWindow->rows; row++)
{
JScreen[row + JWindow->top - 1].line = NULL;
}
l = NULL;
}
else l = JWindow->beg.line;
update(l, force, 0);
}
int redraw ()
{
redraw_screen(0);
return 0;
}
void recenter(int *np)
{
Line *l = CLine;
int i, n = *np;
JWindow->trashed = 1;
if (n == 0)
{
n = JWindow->rows / 2;
for (i = 0; i < n; i++)
{
if (l->prev == NULL) break;
l = l->prev;
}
JWindow->beg.line = l;
JWindow->beg.n -= i;
JWindow->beg.point = 0;
redraw();
return;
}
if (CBuf != JWindow->buffer) return;
if ((n <= 0) || (n > JWindow->rows)) n = JWindow->rows / 2;
while (--n)
{
l = l->prev;
if (l == NULL)
{
l = CBuf->beg;
break;
}
}
update(l, 0, 0);
}
int window_line(void)
{
Line *top = find_top();
int n = 1;
if (CBuf != JWindow->buffer) return(0);
while ((top != NULL) && (top != CLine))
{
n++;
top = top->next;
}
return(n);
}
void touch_window()
{
int i;
if (Suspend_Screen_Update) return;
for (i = 0; i < JWindow->rows; i++)
{
JScreen[i + JWindow->top - 1].flags = 1;
}
JWindow->trashed = 1;
}
void touch_screen()
{
Window_Type *w;
No_Screen_Update = 0;
if (Suspend_Screen_Update) return;
w = JWindow;
do
{
touch_window();
JWindow = JWindow->next;
}
while(w != JWindow);
if (Top_Window_Row != 1) JScreen[0].flags = 1;
}
void exit_error(char *str, int severity)
{
SLang_Error = SLKeyBoard_Quit = 0;
auto_save_all();
reset_display();
reset_tty();
fprintf(stderr,"\007\rJED (%s): Fatal Error: %s\n", JED_VERSION, str);
if (*Error_Buffer) fprintf (stderr, "%s\n", Error_Buffer);
if (CBuf != NULL)
{
if (Batch == 0)
{
fprintf(stderr, "CBuf: %p, CLine: %p, Point %d\n", CBuf, CLine, Point);
if (CLine != NULL) fprintf(stderr, "CLine: data: %p, len = %d, next: %p, prev %p\n",
CLine->data, CLine->len, CLine->next, CLine->prev);
fprintf(stderr, "Max_LineNum: %d, LineNum: %d\n", Max_LineNum, LineNum);
if (JWindow != NULL) fprintf(stderr, "JWindow: %p, top: %d, rows: %d, buffer: %p\n",
JWindow, JWindow->top, JWindow->rows, JWindow->buffer);
}
auto_save_all();
}
if (severity)
{
#ifdef unix
fprintf(stderr, "Dumping Core.");
abort ();
#endif
}
exit(-1);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.