home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d1xx
/
d166
/
stevie.lha
/
Stevie
/
source
/
misccmds.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-11-22
|
9KB
|
413 lines
/*
* STEVIE - Simply Try this Editor for VI Enthusiasts
*
* Code Contributions By : Tim Thompson twitch!tjt
* Tony Andrews onecom!wldrdg!tony
* G. R. (Fred) Walter watmath!watcgl!grwalter
*/
#include "stevie.h"
static bool_t
openfwd(), openbwd();
extern int did_ai;
/*
* opencmd
*
* Add a blank line above or below the current line.
*/
bool_t
opencmd(dir, can_ai)
int dir;
int can_ai; /* if true, consider auto-indent */
{
if (dir == FORWARD)
return (openfwd(can_ai));
else
return (openbwd(can_ai));
}
static bool_t
openfwd(can_ai)
int can_ai;
{
LINE *l;
LPTR *next;
char *s; /* string to be moved to new line, if any */
/*
* If we're in insert mode, we need to move the remainder of the current
* line onto the new line. Otherwise the new line is left blank.
*/
if (State == INSERT)
s = &Curschar->linep->s[Curschar->index];
else
s = "";
if ((next = nextline(Curschar)) == NULL) /* open on last line */
next = Fileend;
/*
* By asking for as much space as the prior line had we make sure that
* we'll have enough space for any auto-indenting.
*/
if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL) {
emsg("out of memory");
beep();
sleep(2);
return (FALSE);
}
if (*s != NUL)
strcpy(l->s, s); /* copy string to new line */
#ifdef AUTO_INDENT
else if (can_ai && P(P_AI)) {
/*
* Auto-indent removed due to buggy implementation...
*/
did_ai = TRUE;
}
#endif
if (State == INSERT) /* truncate current line at cursor */
*s = NUL;
Curschar->linep->next = l; /* link neighbors to new line */
next->linep->prev = l;
l->prev = Curschar->linep; /* link new line to neighbors */
l->next = next->linep;
if (next == Fileend) /* new line at end */
l->num = Curschar->linep->num + LINEINC;
else if ((l->prev->num) + 1 == l->next->num) /* no gap, renumber */
renum();
else { /* stick it in the middle */
long lnum;
lnum = (l->prev->num + l->next->num) / 2;
l->num = lnum;
}
*Curschar = *nextline(Curschar); /* cursor moves down */
Curschar->index = 0;
s_ins(Cursrow + 1, 1); /* insert a physical line */
updateNextscreen(); /* because Botchar is now invalid */
cursupdate(); /* update Cursrow before insert */
return (TRUE);
}
static bool_t
openbwd(can_ai)
int can_ai;
{
LINE *l;
LPTR *prev;
prev = prevline(Curschar);
if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL) {
emsg("out of memory");
beep();
sleep(2);
return (FALSE);
}
Curschar->linep->prev = l; /* link neighbors to new line */
if (prev != NULL)
prev->linep->next = l;
l->next = Curschar->linep; /* link new line to neighbors */
if (prev != NULL)
l->prev = prev->linep;
#ifdef AUTO_INDENT
if (can_ai && P(P_AI)) {
/*
* Auto-indent removed due to buggy implementation...
*/
did_ai = TRUE;
}
#endif
*Curschar = *prevline(Curschar); /* cursor moves up */
Curschar->index = 0;
if (prev == NULL) /* new start of file */
Filemem->linep = l;
renum(); /* keep it simple - we don't do this often */
cursupdate(); /* update Cursrow before insert */
if (Cursrow != 0)
s_ins(Cursrow, 1); /* insert a physical line */
updateNextscreen();
return (TRUE);
}
int
cntllines(pbegin, pend)
LPTR *pbegin, *pend;
{
register LINE *lp;
register int lnum = 1;
for (lp = pbegin->linep; lp != pend->linep; lp = lp->next)
lnum++;
return (lnum);
}
/*
* plines(p) - return the number of physical screen lines taken by line 'p'
*/
int
plines(p)
LPTR *p;
{
int col;
char *s;
if (p == NULL) {
fprintf(stderr, "plines(p) : p == NULL ????");
return (0);
}
s = p->linep->s;
if (*s == NUL) /* empty line */
return 1;
/*
* If list mode is on, then the '$' at the end of the line takes up one
* extra column.
*/
col = P(P_LS) ? 1 : 0;
for (; *s != NUL; s++) {
if (*s == TAB && !P(P_LS))
col += P(P_TS) - (col % P(P_TS));
else
col += chars[*s].ch_size;
}
return ((col + (Columns - 1)) / Columns);
}
void
fileinfo()
{
long l1, l2;
char buf[MAX_COLUMNS + 1];
if (bufempty()) {
msg("Buffer Empty");
return;
}
l1 = cntllines(Filemem, Curschar);
l2 = cntllines(Filemem, Fileend) - 1;
sprintf(buf, "\"%s\"%s line %ld of %ld -- %ld %% --",
(Filename != NULL) ? Filename : "No File",
Changed ? " [Modified]" : "",
l1, l2, (l1 * 100) / l2);
msg(buf);
}
/*
* gotoline(n) - return a pointer to line 'n'
*
* Returns a pointer to the last line of the file if n is zero, or beyond the
* end of the file.
*/
LPTR *
gotoline(n)
int n;
{
static LPTR l;
l.index = 0;
if (n == 0)
l = *prevline(Fileend);
else {
LPTR *p;
for (l = *Filemem; --n > 0; l = *p)
if ((p = nextline(&l)) == NULL)
break;
}
return &l;
}
void
inschar(c)
char c;
{
char *p;
char *pend;
/* make room for the new char. */
if (!canincrease(1))
return;
p = &Curschar->linep->s[strlen(Curschar->linep->s) + 1];
pend = &Curschar->linep->s[Curschar->index];
for (; p > pend; p--)
*p = *(p - 1);
*p = c;
if (RedrawingDisabled) {
inc(Curschar);
return;
}
/*
* If we're in insert mode and showmatch mode is set, then check for
* right parens and braces. If there isn't a match, then beep. If there
* is a match AND it's on the screen, then flash to it briefly. If it
* isn't on the screen, don't do anything.
*/
if (P(P_SM) && State == INSERT && (c == ')' || c == '}' || c == ']')) {
LPTR *lpos, csave;
if ((lpos = showmatch()) == NULL) /* no match, so beep */
beep();
else if (LINEOF(lpos) >= LINEOF(Topchar)) {
updateNextscreen(); /* show the new char first */
updateRealscreen();
csave = *Curschar;
*Curschar = *lpos; /* move to matching char */
cursupdate();
windgoto(Cursrow, Curscol);
delay(); /* brief pause */
*Curschar = csave; /* restore cursor position */
cursupdate();
}
}
inc(Curschar);
}
void
insstr(s)
char *s;
{
char *p, *endp;
int k, n = strlen(s);
/* Move everything in the file over to make */
/* room for the new string. */
if (!canincrease(n))
return;
endp = &Curschar->linep->s[Curschar->index];
p = Curschar->linep->s + strlen(Curschar->linep->s) + 1 + n;
for (; p > endp; p--)
*p = *(p - n);
p = &Curschar->linep->s[Curschar->index];
for (k = 0; k < n; k++) {
*p++ = *s++;
inc(Curschar);
}
}
bool_t
delchar(fixpos, undo)
bool_t fixpos; /* if TRUE fix the cursor position when done */
bool_t undo; /* if TRUE put char deleted into Undo buffer */
{
int i;
/* Check for degenerate case; there's nothing in the file. */
if (bufempty())
return FALSE;
if (lineempty(Curschar)) /* can't do anything */
return FALSE;
if (undo)
AppendToUndobuff(mkstr(gchar(Curschar)));
/* Delete the char. at Curschar by shifting everything in the line down. */
for (i = Curschar->index + 1; i < Curschar->linep->size; i++)
Curschar->linep->s[i - 1] = Curschar->linep->s[i];
/*
* If we just took off the last character of a non-blank line, we don't
* want to end up positioned at the newline.
*/
if (fixpos) {
if (gchar(Curschar) == NUL && Curschar->index > 0 && State != INSERT)
Curschar->index--;
}
return TRUE;
}
void
delline(nlines)
{
LINE *p, *q;
int doscreen = TRUE; /* if true, update the screen */
/*
* There's no point in keeping the screen updated if we're deleting more
* than a screen's worth of lines.
*/
if (nlines > (Rows - 1)) {
doscreen = FALSE;
s_del(Cursrow, Rows - 1); /* flaky way to clear rest of screen */
}
while (nlines-- > 0) {
if (bufempty()) /* nothing to delete */
break;
if (buf1line()) { /* just clear the line */
Curschar->linep->s[0] = NUL;
Curschar->index = 0;
break;
}
p = Curschar->linep->prev;
q = Curschar->linep->next;
if (p == NULL) { /* first line of file so... */
Filemem->linep = q; /* adjust start of file */
Topchar->linep = q; /* and screen */
} else
p->next = q;
q->prev = p;
clrmark(Curschar->linep); /* clear marks for the line */
/*
* Delete the correct number of physical lines on the screen
*/
if (doscreen)
s_del(Cursrow, plines(Curschar));
/*
* If deleting the top line on the screen, adjust Topchar
*/
if (Topchar->linep == Curschar->linep)
Topchar->linep = q;
free(Curschar->linep->s);
free((char *) (Curschar->linep));
Curschar->linep = q;
Curschar->index = 0; /* is this right? */
/* If we delete the last line in the file, back up */
if (Curschar->linep == Fileend->linep) {
Curschar->linep = Curschar->linep->prev;
/* and don't try to delete any more lines */
break;
}
}
}