/*************************************************************************
* This program is copyright (C) 1985, 1986 by Jonathan Payne. It is *
* provided to you without charge for use only on a licensed Unix *
* system. You may copy JOVE provided that this notice is included with *
* the copy. You may not sell copies of this program or versions *
* modified for use on microcomputer systems, unless the copies are *
* included with a Unix system distribution and the source is provided. *
*************************************************************************/
/* Kludge windows gets called by the routines that delete lines from the
buffer. If the w->w_line or w->w_top are deleted and this procedure
is not called, the redisplay routine will barf. */
register Window
*w
= fwind
;
for (lp
= line1
->l_next
; lp
!= line2
->l_next
; lp
= lp
->l_next
) {
register Window
*w
= fwind
;
register struct scrimage
*des_p
,
curwind
->w_line
= curwind
->w_bufp
->b_dot
;
curwind
->w_char
= curwind
->w_bufp
->b_char
;
if (InputPending
= charp())
for (lineno
= 0, w
= fwind
; lineno
< ILI
; w
= w
->w_next
) {
for (i
= 0; i
< ILI
; i
++, des_p
++, phys_p
++) {
if (!done_ID
&& (des_p
->s_id
!= phys_p
->s_id
)) {
if ((des_p
->s_flags
& (DIRTY
| L_MOD
)) ||
(des_p
->s_id
!= phys_p
->s_id
) ||
(des_p
->s_vln
!= phys_p
->s_vln
) ||
(des_p
->s_offset
!= phys_p
->s_offset
))
Placur(LI
- 1, min(CO
- 2, calc_pos(mesgbuf
, Asking
)));
/* find_pos() returns the position on the line, that c_char represents
return calc_pos(lcontents(line
), c_char
);
while ((--c_char
>= 0) && ((c
= *lp
++) & 0177) != 0) {
pos
+= (tabstop
- (pos
% tabstop
));
register struct scrimage
*des_p
= &DesiredScreen
[start
];
struct scrimage
*phys_p
= &PhysScreen
[start
];
/* Some changes have been made. Try for insert or delete lines.
If either case has happened, Addlines and/or DelLines will do
necessary scrolling, also CONVERTING PhysScreen to account for the
physical changes. The comparison continues from where the
insertion/deletion takes place; this doesn't happen very often,
usually it happens with more than one window with the same
return; /* We should never have been called! */
for (i
= start
; i
< ILI
; i
++, des_p
++, phys_p
++)
if (des_p
->s_id
!= phys_p
->s_id
)
for (j
= i
+ 1; j
< ILI
; j
++) {
des_p
= &DesiredScreen
[j
];
if (des_p
->s_id
!= 0 && des_p
->s_id
== phys_p
->s_id
)
if (des_p
->s_id
== PhysScreen
[i
].s_id
) {
if (AddLines(i
, j
- i
)) {
if ((des_p
= &DesiredScreen
[i
])->s_id
== phys_p
->s_id
) {
if (DelLines(i
, j
- i
)) {
/* Make DesiredScreen reflect what the screen should look like when we are done
with the redisplay. This deals with horizontal scrolling. Also makes
sure the current line of the Window is in the window. */
upper
, /* Top of window */
lower
, /* Bottom of window */
ntries
= 0; /* # of tries at updating window. */
register struct scrimage
*des_p
,
if (w
->w_flags
& CURGONE
) {
if (w
->w_flags
& TOPGONE
)
CentWind(w
); /* Reset topline of screen */
for (i
= w
->w_height
, lp
= w
->w_top
; --i
> 0 && lp
!= 0; lp
= lp
->l_next
)
if (i
== 0 || lp
== 0) { /* Current line not in window */
} else if (ntries
== 2) {
w
->w_top
= w
->w_line
= w
->w_bufp
->b_first
;
f_mess("ERROR in redisplay: I got hopelessly lost!");
} else if (ntries
== 3) {
printf("\rOops, still lost, quitting ...\r\n");
lower
= upper
+ w
->w_height
- 1; /* Don't include modeline */
des_p
= &DesiredScreen
[upper
];
phys_p
= &PhysScreen
[upper
];
for (i
= upper
, lp
= w
->w_top
; lp
!= 0 && i
< lower
; i
++, des_p
++, phys_p
++, lp
= lp
->l_next
) {
des_p
->s_id
= lp
->l_dline
& ~DIRTY
;
des_p
->s_flags
= isdirty(lp
) ? L_MOD
: 0;
des_p
->s_vln
= w
->w_topnum
+ (i
- upper
);
int diff
= w
->w_numlines
? 8 : 0,
strt_col
= phys_p
->s_offset
,
end_col
= strt_col
+ (CO
- 2) - diff
;
/* Right now we are displaying from strt_col to
end_col of the buffer line. These are PRINT
colums, not actual characters. */
w
->w_dotcol
= find_pos(lp
, w
->w_char
);
/* if the new dotcol is out of range, reselect
if (w
->w_dotcol
< strt_col
|| w
->w_dotcol
>= end_col
) {
if (w
->w_dotcol
< ((CO
- 2) - diff
))
strt_col
= w
->w_dotcol
- (CO
/ 2);
des_p
->s_offset
= strt_col
;
f_mess("DotNotHere is impossible!");
/* Is structure assignment faster than copy each field seperately */
static struct scrimage dirty_plate
= { 0, DIRTY
, 0, 0, 0, 0 },
clean_plate
= { 0, 0, 0, 0, 0, 0 };
for (; i
< lower
; i
++, des_p
++, phys_p
++)
if (((des_p
->s_id
= (int) w
->w_bufp
) != phys_p
->s_id
) || UpdModLine
)
des_p
->s_flags
= MODELINE
| DIRTY
;
/* Write whatever is in mesgbuf (maybe we are Asking, or just printed
a message). Turns off the UpdateMesg line flag. */
if (swrite(mesgbuf
, NIL
, abortable
)) {
/* Goto the current position in the current window. Presumably redisplay()
has already been called, and curwind->{w_dotline,w_dotcol} have been set
Placur(curwind
->w_dotline
, curwind
->w_dotcol
-
PhysScreen
[curwind
->w_dotline
].s_offset
);
register struct scrimage
*des_p
= &DesiredScreen
[start
],
*phys_p
= &PhysScreen
[start
];
while ((start
< ILI
) && (des_p
->s_id
!= phys_p
->s_id
)) {
/* Calls the routine to do the physical changes, and changes PhysScreen to
reflect those changes. */
int bottom
= UntilEqual(at
+ num
);
if (num
== 0 || num
>= ((bottom
- 1) - at
))
return 0; /* We did nothing */
v_ins_line(num
, at
, bottom
- 1);
/* Now change PhysScreen to account for the physical change. */
for (i
= bottom
- 1; i
- num
>= at
; i
--)
PhysScreen
[i
] = PhysScreen
[i
- num
];
for (i
= 0; i
< num
; i
++)
PhysScreen
[at
+ i
].s_id
= 0;
return 1; /* We did something. */
int bottom
= UntilEqual(at
+ num
);
if (num
== 0 || num
>= ((bottom
- 1) - at
))
v_del_line(num
, at
, bottom
- 1);
for (i
= at
; num
+ i
< bottom
; i
++)
PhysScreen
[i
] = PhysScreen
[num
+ i
];
for (i
= bottom
- num
; i
< bottom
; i
++)
/* Update line linenum in window w. Only set PhysScreen to DesiredScreen
if the swrite or cl_eol works, that is nothing is interupted by
register struct scrimage
*des_p
= &DesiredScreen
[linenum
];
register Window
*w
= des_p
->s_window
;
if (des_p
->s_flags
& MODELINE
)
des_p
->s_lp
->l_dline
&= ~DIRTY
;
des_p
->s_flags
&= ~(DIRTY
| L_MOD
);
if (!UseIC
&& w
->w_numlines
)
(void) swrite(sprint("%6d ", des_p
->s_vln
), NIL
, YES
);
int fromcol
= w
->w_numlines
? 8 : 0;
sprintf(outbuf
, "%6d ", des_p
->s_vln
);
lptr
= lcontents(des_p
->s_lp
);
DeTab(des_p
->s_offset
, lptr
, outbuf
+ fromcol
,
(sizeof outbuf
) - 1 - fromcol
,
des_p
->s_window
->w_visspace
);
if (IDchar(outbuf
, linenum
, 0))
PhysScreen
[linenum
] = *des_p
;
else if (i_set(linenum
, 0), swrite(outbuf
, NIL
, YES
))
PhysScreen
[linenum
].s_id
= -1;
PhysScreen
[linenum
].s_id
= -1;
} else if (PhysScreen
[linenum
].s_id
) /* Not the same ... make sure */
PhysScreen
[linenum
] = DesiredScreen
[linenum
];
/* From here to the end of the file is code that tries to utilize the
insert/delete character feature on some terminals. It is very confusing
and not so well written code, AND there is a lot of it. You may want
to use the space for something else. */
extern struct screenline
*Screen
;
DClen
= DC
? strlen(DC
) : 0;
MDClen
= M_DC
? strlen(M_DC
) : 9999;
IClen
= IC
? strlen(IC
) : 0;
MIClen
= M_IC
? strlen(M_IC
) : 9999;
IMlen
= IM
? strlen(IM
) : 0;
CElen
= CE
? strlen(CE
) : 0;
UseIC
= (IC
|| IM
|| M_IC
);
} else if (!on
&& IN_INSmode
) {
DeTab(s_offset
, buf
, outbuf
, limit
, visspace
)
register char *phys_p
= outbuf
,
char *limitp
= &outbuf
[limit
];
#define OkayOut(ch) if ((pos++ >= s_offset) && (phys_p < limitp))\
int nchars
= (tabstop
- (pos
% tabstop
));
OkayOut(c
== 0177 ? '?' : c
+ '@');
if (visspace
&& c
== ' ')
if (pos
- s_offset
>= CO
) {
phys_p
= &outbuf
[CO
- 1];
/* ID character routines full of special cases and other fun stuff like that.
It actually works though ...
Returns Non-Zero if you are finished (no differences left). */
register struct screenline
*sline
= &Screen
[lineno
];
oldlen
= sline
->s_length
- sline
->s_line
;
for (i
= col
; i
< oldlen
&& new[i
] != 0; i
++)
if (sline
->s_line
[i
] != new[i
])
if (new[i
] == 0 || i
== oldlen
)
return (new[i
] == 0 && i
== oldlen
);
for (j
= i
+ 1; j
< oldlen
&& new[j
]; j
++) {
if (new[j
] == sline
->s_line
[i
]) {
NumSaved
= IDcomp(new + j
, sline
->s_line
+ i
,
strlen(new)) + NumSimilar(new + i
,
sline
->s_line
+ i
, j
- i
);
if (OkayInsert(NumSaved
, j
- i
)) {
InsChar(lineno
, i
, j
- i
, new);
return(IDchar(new, lineno
, j
));
for (j
= i
+ 1; j
< oldlen
&& new[i
]; j
++) {
if (new[i
] == sline
->s_line
[j
]) {
NumSaved
= IDcomp(new + i
, sline
->s_line
+ j
,
if (OkayDelete(NumSaved
, j
- i
, new[oldlen
] == 0)) {
DelChar(lineno
, i
, j
- i
);
return(IDchar(new, lineno
, j
));
for (i
= 0; i
< len
; i
++) {
OkayDelete(Saved
, num
, samelength
)
/* If the old and the new are the same length, then we don't
* have to clear to end of line. We take that into consideration.
return ((Saved
+ (!samelength
? CElen
: 0))
> min(MDClen
, DClen
* num
));
if (IC
) /* Per character prefixes */
n
= min(num
* IClen
, MIClen
);
/* Good terminal. Fewer characters in this case */
n
+= num
; /* The characters themselves */
extern struct screenline
*Curline
;
DelChar(lineno
, col
, num
)
struct screenline
*sp
= (&Screen
[lineno
]);
sprintf(minibuf
, M_DC
, num
);
for (i
= num
; --i
>= 0; )
byte_copy(from
, to
, sp
->s_length
- from
+ 1);
clrline(sp
->s_length
- num
, sp
->s_length
);
InsChar(lineno
, col
, num
, new)
*sp2
, /* To push over the array. */
*sp3
; /* Last character to push over. */
sp2
= Curline
->s_length
+ num
;
i_set(lineno
, CO
- num
- 1);
sp3
= Curline
->s_line
+ col
;
byte_copy(new, sp3
, num
);
/* The internal screen is correct, and now we have to do
} else if (M_IC
&& num
> 1) {
sprintf(minibuf
, M_IC
, num
);
for (i
= 0; i
< num
; i
++)
for (i
= 0; i
< num
; i
++) {
/* chkmail() returns nonzero if there is new mail since the
char Mailbox
[128]; /* initialized in main */
int MailInt
= 60; /* check no more often than 60 seconds */
int BiffChk
= NO
; /* whether or not to turn off biff while in JOVE */
static time_t last_chk
= 0;
static int value
= FALSE
;
static off_t last_size
= 0;
if (!force
&& (now
< last_chk
+ MailInt
))
if (stat(Mailbox
, &stbuf
) < 0)
value
= ((stbuf
.st_mtime
> time0
) &&
(stbuf
.st_size
> last_size
) &&
(stbuf
.st_mtime
+ 5 > stbuf
.st_atime
));
last_size
= stbuf
.st_size
;
if (value
== TRUE
&& value
!= last_val
)
/* Print the mode line. */
int BriteMode
= 1; /* modeline should standout */
while ((mode_p
< mend_p
) && (*mode_p
++ = *str
++))
mode_p
--; /* back over the null */
char ModeFmt
[120] = "%3c %[%sJOVE (%M) Buffer: %b \"%f\" %]%s%m %((%t)%s%)%e";
register Buffer
*thisbuf
= w
->w_bufp
;
mend_p
= &line
[(sizeof line
) - 1];
if (BriteMode
!= 0 && SO
== 0)
fillc
= BriteMode
? ' ' : '-';
c
= *fmt
++; /* Character after the percent! */
if (ign_some
&& c
!= ')')
if (c
>= '0' && c
<= '9') {
while (c
>= '0' && c
<= '9') {
if (w
->w_next
!= fwind
) /* Not bottom window. */
char *strs
= (c
== '[') ? "[[[[[[[[[[" : "]]]]]]]]]]";
mode_app(strs
+ 10 - RecDepth
);
static char *mmodes
[] = {
mode_app(mmodes
[thisbuf
->b_major
]);
if (BufMinorMode(thisbuf
, Fill
))
if (BufMinorMode(thisbuf
, Abbrev
))
if (BufMinorMode(thisbuf
, OverWrite
))
if (BufMinorMode(thisbuf
, Indent
))
if (KeyMacro
.m_flags
& DEFINE
)
mode_p
--; /* Back over the extra space. */
mode_app(thisbuf
->b_name
);
if (thisbuf
->b_fname
== 0)
mode_app(pr_name(thisbuf
->b_fname
));
mode_app(basename(thisbuf
->b_fname
));
for (bp
= world
, n
= 1; bp
!= 0; bp
= bp
->b_next
, n
++)
if (IsModified(w
->w_bufp
))
mode_app(get_time((time_t *) 0, timestr
, 11, 16));
theavg
+= .005; /* round to nearest .01 */
sprintf(minibuf
, "%d.%02d",
(int)((theavg
- (int) theavg
) * 100));
case 'C': /* check mail here */
case 'd': /* print working directory */
mode_app(pr_name(pwd()));
/* 2 space pad pluss padding for magic cookies */
char *last_p
= &line
[CO
- 2 - (2 * SG
)];
goto outahere
; /* %e means we're done! */
/* Highlight mode line. */
if (swrite(line
, BriteMode
, YES
))
Line
*newtop
= prev_line((curwind
->w_line
= curline
), exp_p
?
if (newtop
== curwind
->w_top
)
v_clear(FLine(curwind
), FLine(curwind
) + SIZE(curwind
));
register struct scrimage
*phys_p
, *des_p
;
phys_p
= &PhysScreen
[line1
];
des_p
= &DesiredScreen
[line1
];
phys_p
->s_id
= des_p
->s_id
= 0;
if (in_window(curwind
, curwind
->w_bufp
->b_last
) != -1) {
newline
= next_line(curwind
->w_top
, max(1, SIZE(curwind
) - 1));
SetTop(curwind
, curwind
->w_line
= newline
);
if (curwind
->w_bufp
== curbuf
)
newline
= prev_line(curwind
->w_top
, max(1, SIZE(curwind
) - 1));
SetTop(curwind
, curwind
->w_line
= newline
);
if (curwind
->w_bufp
== curbuf
)
SetTop(curwind
, next_line(curwind
->w_top
, exp
));
if ((curwind
->w_bufp
== curbuf
) &&
(in_window(curwind
, curline
) == -1))
SetTop(curwind
, prev_line(curwind
->w_top
, exp
));
if ((curwind
->w_bufp
== curbuf
) &&
(in_window(curwind
, curline
) == -1))
RingBell
= 0; /* So if we have a lot of errors ...
ring the bell only ONCE */
/* Message prints the null terminated string onto the bottom line of the
null_ncpy(mesgbuf
, str
, (sizeof mesgbuf
) - 1);
SetLine(next_line(curwind
->w_top
, SIZE(curwind
) - 1 -
min(SIZE(curwind
) - 1, exp
- 1)));
/* Beginning of Window */
SetLine(next_line(curwind
->w_top
, min(SIZE(curwind
) - 1, exp
- 1)));
private Window
*old_wind
; /* save the window we were in BEFORE
before we were called, if UseBuffers
/* This initializes the typeout. If send-typeout-to-buffers is set
the buffer NAME is created (emptied if it already exists) and output
goes to the buffer. Otherwise output is drawn on the screen and
TOstart(name
, auto_newline
)
pop_wind(name
, YES
, B_SCRATCH
);
TOabort
= LineNo
= last_col
= 0;
if (!UseBuffers
&& (LineNo
== ILI
- 1)) {
if ((c
= getchar()) != ' ') {
if (c
!= CTL(G
) && c
!= RUBOUT
)
format(string
, sizeof string
, fmt
, ap
);
(void) swrite(string
, NIL
, YES
);
PhysScreen
[LineNo
].s_id
= -1;
if (fmt
== 0 || DoAutoNL
!= 0) {
} else if (fmt
== 0 || DoAutoNL
!= 0)