/*************************************************************************
* 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. *
*************************************************************************/
/* Make a newline after AFTER in buffer BUF, UNLESS after is 0,
in which case we insert the newline before after. */
register Line
*newline
= nbufline();
if (after
== 0) { /* Before the first line */
newline
->l_next
= buf
->b_first
;
newline
->l_next
= after
->l_next
;
newline
->l_next
->l_prev
= newline
;
if (buf
&& buf
->b_dot
== 0)
/* Divide the current line and move the current line to the next one */
newdot
= listput(curbuf
, newdot
);
SavLine(newdot
, NullStr
);
strcpy(newline
, &linebuf
[curchar
]);
linebuf
[curchar
] = '\0'; /* Shorten this line */
SavLine(curline
, linebuf
);
strcpy(linebuf
, newline
);
} else { /* Redisplay optimization */
newdot
->l_dline
= curline
->l_dline
;
SavLine(curline
, NullStr
);
IFixMarks(olddot
, oldchar
, curline
, curchar
);
DoTimes(Insert('\t'), (goal
/ tabstop
));
DoTimes(Insert(' '), (goal
% tabstop
));
if (MinorMode(Abbrev
) && !ismword(LastKeyStruck
) &&
!bolp() && ismword(linebuf
[curchar
- 1]))
if (MinorMode(OverWrite
)) {
for (i
= 0, num
= exp
, exp
= 1; i
< num
; i
++) {
int pos
= calc_pos(linebuf
, curchar
);
if (linebuf
[curchar
] == '\t') {
if ((pos
+ 1) == ((pos
+ tabstop
) - (pos
% tabstop
)))
if (MinorMode(Fill
) && (curchar
>= RMargin
||
(calc_pos(linebuf
, curchar
) >= RMargin
)))
DoJustify(curline
, 0, curline
,
curchar
+ strlen(&linebuf
[curchar
]), 1, LMargin
);
ins_c(c
, linebuf
, curchar
, exp
, LBSIZE
);
IFixMarks(curline
, curchar
, curline
, curchar
+ exp
);
/* Tab in to the right place for C mode */
if (MajorMode(LISPMODE
)) {
Mark
*m
= bolp() ? 0 : MakeMark(curline
, curchar
, FLOATER
);
if (MajorMode(CMODE
) && strlen(linebuf
) == 0)
(void) c_indent(CIndIncrmt
);
extern int alarmed
; /* If waitfor had to wait. */
/* Insert the paren. If in C mode and c is a '}' then insert the
'}' in the "right" place for C indentation; that is indented
the same amount as the matching '{' is indented. */
int PDelay
= 5, /* 1/2 a second */
Bufpos
*bp
= (Bufpos
*) -1;
if (MajorMode(CMODE
) && c
== '}' && blnkp(linebuf
)) {
if (MajorMode(LISPMODE
) && c
== ')' && blnkp(linebuf
)) {
if (MinorMode(ShowMatch
) && !charp() && !in_macro()) {
BackChar(); /* Back onto the ')' */
bp
= m_paren(c
, BACKWARD
, NO
, YES
);
nx
= in_window(curwind
, bp
->p_line
);
if (nx
!= -1) { /* is visible */
s_mess("%s", lcontents(bp
->p_line
));
mp_error(); /* display error message */
DoNewline(MinorMode(Indent
));
/* first we calculate the indent of the current line */
indent
= calc_pos(linebuf
, curchar
);
/* If there is more than 2 blank lines in a row then don't make
a newline, just move down one. */
if (MinorMode(Abbrev
) && !ismword(LastKeyStruck
) &&
!bolp() && ismword(linebuf
[curchar
- 1]))
if (exp
== 1 && eolp() && TwoBlank())
SetLine(curline
->l_next
);
n_indent((LMargin
== 0) ? indent
: LMargin
);
if (c
== '\n' || (ok_nl
&& llen
>= LBSIZE
- 2)) {
IFixMarks(save
.p_line
, save
.p_char
, curline
, curchar
);
ins_c(c
, linebuf
, curchar
++, 1, LBSIZE
);
IFixMarks(save
.p_line
, save
.p_char
, curline
, curchar
);
LineInsert(); /* Open the lines... */
/* Take the region FLINE/FCHAR to TLINE/TCHAR and insert it at
ATLINE/ATCHAR in WHATBUF. */
DoYank(fline
, fchar
, tline
, tchar
, atline
, atchar
, whatbuf
)
Line
*startline
= atline
;
(void) ltobuf(atline
, genbuf
);
strcpy(save
, &genbuf
[atchar
]);
(void) ltobuf(fline
, buf
);
linecopy(genbuf
, atchar
, &buf
[fchar
]);
atline
->l_dline
= putline(genbuf
);
while (fline
!= tline
->l_next
) {
newline
= listput(whatbuf
, atline
);
newline
->l_dline
= fline
->l_dline
;
(void) getline(atline
->l_dline
, genbuf
);
linecopy(genbuf
, atchar
, save
);
atline
->l_dline
= putline(genbuf
);
IFixMarks(startline
, startchar
, atline
, atchar
);
getDOT(); /* Whatever used to be in linebuf */
int dir
= -1; /* Direction to rotate the ring */
complain("Yank something first!");
lfreelist(reg_delete(mp
->m_line
, mp
->m_char
, curline
, curchar
));
/* Now must find a recently killed region. */
else if (killptr
>= NUMKILLS
)
dot
= DoYank(line
, 0, last
, length(last
), curline
, curchar
, curbuf
);
MarkSet(CurMark(), curline
, curchar
);
/* This is an attempt to reduce the amount of memory taken up by each line.
Without this each malloc of a line uses sizeof (line) + sizeof(HEADER)
where line is 3 words and HEADER is 1 word.
This is going to allocate memory in chucks of CHUNKSIZE * sizeof (line)
and divide each chuck into lineS. A line is free in a chunk when its
line->l_dline == 0, so freeline sets dline to 0. */
int c_nlines
; /* Number of lines in this chunk (so they
don't all have to be CHUNKSIZE long). */
Line
*c_block
; /* Chunk of memory */
struct chunk
*c_nextfree
; /* Next chunk of lines */
static struct chunk
*fchunk
= 0;
static Line
*ffline
= 0; /* First free line */
lfreereg(first
, lastline(first
));
/* Append region from line1 to line2 onto the free list of lines */
f
= (struct chunk
*) emalloc(sizeof (struct chunk
));
if ((f
->c_block
= (Line
*) malloc((unsigned) (sizeof (Line
) * nlines
))) == 0) {
f
->c_block
= (Line
*) malloc((unsigned) (sizeof (Line
) * nlines
));
for (i
= 0, newline
= f
->c_block
; i
< nlines
; newline
++, i
++)
if (ffline
== 0) /* No free list */
complain("[Out of lines] ");
/* Remove the free lines, in chunk c, from the free list because they are
register struct chunk
*c
;
for (lp
= c
->c_block
, i
= 0; i
< c
->c_nlines
; i
++, lp
++) {
lp
->l_prev
->l_next
= lp
->l_next
;
lp
->l_next
->l_prev
= lp
->l_prev
;
/* This is used to garbage collect the chunks of lines when malloc fails
and we are NOT looking for a new buffer line. This goes through each
chunk, and if every line in a given chunk is not allocated, the entire
chunk is `free'd by "free()". */
register struct chunk
*cp
;
for (cp
= fchunk
; cp
!= 0; cp
= next
) {
for (i
= 0, newline
= cp
->c_block
; i
< cp
->c_nlines
; newline
++, i
++)
if (newline
->l_dline
!= 0)
if (i
== cp
->c_nlines
) { /* Unlink it!!! */
prev
->c_nextfree
= cp
->c_nextfree
;
free((char *) cp
->c_block
);
if (linebuf
[curchar
] != '(')
if (curline
== end
.p_line
)
/* lisp_indent() indents a new line in Lisp Mode, according to where
the matching close-paren would go if we typed that (sort of). */
bp
= m_paren(')', BACKWARD
, NO
, YES
);
* Otherwise, we indent to the first argument of
* the current s-expression. This is done by
* starting at the matching paren, skipping
* to a word (atom), skipping over it, and
* skipping to the next one.
if (linebuf
[curchar
] != '(') {
static char *specials
[] = {
*cp2
= &linebuf
[curchar
];
if (Upper(*cp1
++) != Upper(*cp2
++))
if (index(&linebuf
[curchar
], ' ') != 0) {
WITH_TABLE(curbuf
->b_major
)
while (linebuf
[curchar
] == ' ')
goal
= calc_pos(linebuf
, curchar
);