version 1.3, 2000/04/13 06:12:15 |
version 1.4, 2000/09/01 14:59:09 |
|
|
/* |
/* |
* Text line handling. |
* Text line handling. |
* The functions in this file |
* |
* are a general set of line management |
* The functions in this file are a general set of line management |
* utilities. They are the only routines that |
* utilities. They are the only routines that touch the text. They |
* touch the text. They also touch the buffer |
* also touch the buffer and window structures to make sure that the |
* and window structures, to make sure that the |
* necessary updating gets done. There are routines in this file that |
* necessary updating gets done. There are routines |
* handle the kill buffer too. It isn't here for any good reason. |
* in this file that handle the kill buffer too. |
|
* It isn't here for any good reason. |
|
* |
* |
* Note that this code only updates the dot and |
* Note that this code only updates the dot and mark values in the window |
* mark values in the window list. Since all the code |
* list. Since all the code acts on the current window, the buffer that |
* acts on the current window, the buffer that we |
* we are editing must be displayed, which means that "b_nwnd" is non-zero, |
* are editing must be being displayed, which means |
* which means that the dot and mark values in the buffer headers are |
* that "b_nwnd" is non zero, which means that the |
|
* dot and mark values in the buffer headers are |
|
* nonsense. |
* nonsense. |
*/ |
*/ |
#include "def.h" |
|
|
|
/* number of bytes member is from start of structure type */ |
#include "def.h" |
/* should be computed at compile time */ |
|
|
|
|
/* |
|
* The number of bytes member from the start of the structure type should be |
|
* computed at compile time. |
|
*/ |
|
|
#ifndef OFFSET |
#ifndef OFFSET |
#define OFFSET(type,member) ((char *)&(((type *)0)->member)-(char *)((type *)0)) |
#define OFFSET(type,member) ((char *)&(((type *)0)->member)-(char *)((type *)0)) |
#endif |
#endif |
|
|
#define KBLOCK 256 /* Kill buffer block size. */ |
#define KBLOCK 256 /* Kill buffer block size. */ |
#endif |
#endif |
|
|
static char *kbufp = NULL; /* Kill buffer data. */ |
static char *kbufp = NULL; /* Kill buffer data. */ |
static RSIZE kused = 0; /* # of bytes used in KB. */ |
static RSIZE kused = 0; /* # of bytes used in KB. */ |
static RSIZE ksize = 0; /* # of bytes allocated in KB. */ |
static RSIZE ksize = 0; /* # of bytes allocated in KB. */ |
static RSIZE kstart = 0; /* # of first used byte in KB. */ |
static RSIZE kstart = 0; /* # of first used byte in KB. */ |
|
|
|
static int kgrow __P((int)); |
|
|
/* |
/* |
* This routine allocates a block of memory large enough to hold a LINE |
* This routine allocates a block of memory large enough to hold a LINE |
* containing "used" characters. The block is rounded up to whatever |
* containing "used" characters. The block is rounded up to whatever |
* needs to be allocated. (use lallocx for lines likely to grow.) |
* needs to be allocated. (use lallocx for lines likely to grow.) |
* Return a pointer to the new block, or NULL if there isn't |
* Return a pointer to the new block, or NULL if there isn't any memory |
* any memory left. Print a message in the message line if no space. |
* left. Print a message in the message line if no space. |
*/ |
*/ |
LINE * |
LINE * |
lalloc(used) |
lalloc(used) |
int used; |
int used; |
{ |
{ |
LINE *lp; |
LINE *lp; |
int size; |
int size; |
|
|
/* any padding at the end of the structure is used */ |
/* any padding at the end of the structure is used */ |
if ((size = used + OFFSET(LINE, l_text[0])) < sizeof(LINE)) |
if ((size = used + OFFSET(LINE, l_text[0])) < sizeof(LINE)) |
size = sizeof(LINE); |
size = sizeof(LINE); |
#ifdef MALLOCROUND |
#ifdef MALLOCROUND |
MALLOCROUND(size); /* round up to a size optimal to malloc */ |
MALLOCROUND(size); /* round up to a size optimal to malloc */ |
#endif |
#endif |
if ((lp = (LINE *) malloc((unsigned) size)) == NULL) { |
if ((lp = (LINE *)malloc((unsigned)size)) == NULL) { |
ewprintf("Can't get %d bytes", size); |
ewprintf("Can't get %d bytes", size); |
return (LINE *) NULL; |
return (LINE *)NULL; |
} |
} |
lp->l_size = size - OFFSET(LINE, l_text[0]); |
lp->l_size = size - OFFSET(LINE, l_text[0]); |
lp->l_used = used; |
lp->l_used = used; |
|
|
*/ |
*/ |
LINE * |
LINE * |
lallocx(used) |
lallocx(used) |
int used; |
int used; |
{ |
{ |
int size; |
int size; |
LINE *lp; |
LINE *lp; |
|
|
size = (NBLOCK + used) & ~(NBLOCK - 1); |
size = (NBLOCK + used) & ~(NBLOCK - 1); |
if ((lp = lalloc(size)) != NULL) |
if ((lp = lalloc(size)) != NULL) |
|
|
} |
} |
|
|
/* |
/* |
* Delete line "lp". Fix all of the |
* Delete line "lp". Fix all of the links that might point to it (they are |
* links that might point at it (they are |
* moved to offset 0 of the next line. Unlink the line from whatever buffer |
* moved to offset 0 of the next line. |
* it might be in, and release the memory. The buffers are updated too; the |
* Unlink the line from whatever buffer it |
* magic conditions described in the above comments don't hold here. |
* might be in. Release the memory. The |
|
* buffers are updated too; the magic conditions |
|
* described in the above comments don't hold |
|
* here. |
|
*/ |
*/ |
VOID |
VOID |
lfree(lp) |
lfree(lp) |
register LINE *lp; |
LINE *lp; |
{ |
{ |
register BUFFER *bp; |
BUFFER *bp; |
register MGWIN *wp; |
MGWIN *wp; |
|
|
for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { |
for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { |
if (wp->w_linep == lp) |
if (wp->w_linep == lp) |
|
|
} |
} |
lp->l_bp->l_fp = lp->l_fp; |
lp->l_bp->l_fp = lp->l_fp; |
lp->l_fp->l_bp = lp->l_bp; |
lp->l_fp->l_bp = lp->l_bp; |
free((char *) lp); |
free((char *)lp); |
} |
} |
|
|
/* |
/* |
* This routine gets called when |
* This routine is called when a character changes in place in the current |
* a character is changed in place in the |
* buffer. It updates all of the required flags in the buffer and window |
* current buffer. It updates all of the required |
* system. The flag used is passed as an argument; if the buffer is being |
* flags in the buffer and window system. The flag |
* displayed in more than 1 window we change EDIT to HARD. Set MODE if the |
* used is passed as an argument; if the buffer is being |
* mode line needs to be updated (the "*" has to be set). |
* displayed in more than 1 window we change EDIT to |
|
* HARD. Set MODE if the mode line needs to be |
|
* updated (the "*" has to be set). |
|
*/ |
*/ |
VOID |
VOID |
lchange(flag) |
lchange(flag) |
register int flag; |
int flag; |
{ |
{ |
register MGWIN *wp; |
MGWIN *wp; |
|
|
if ((curbp->b_flag & BFCHG) == 0) { /* First change, so */ |
/* update mode lines if this is the first change. */ |
flag |= WFMODE; /* update mode lines. */ |
if ((curbp->b_flag & BFCHG) == 0) { |
|
flag |= WFMODE; |
curbp->b_flag |= BFCHG; |
curbp->b_flag |= BFCHG; |
} |
} |
for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { |
for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { |
|
|
} |
} |
|
|
/* |
/* |
* Insert "n" copies of the character "c" |
* Insert "n" copies of the character "c" at the current location of dot. |
* at the current location of dot. In the easy case |
* In the easy case all that happens is the text is stored in the line. |
* all that happens is the text is stored in the line. |
* In the hard case, the line has to be reallocated. When the window list |
* In the hard case, the line has to be reallocated. |
* is updated, take special care; I screwed it up once. You always update |
* When the window list is updated, take special |
* dot in the current window. You update mark and a dot in another window |
* care; I screwed it up once. You always update dot |
* if it is greater than the place where you did the insert. Return TRUE |
* in the current window. You update mark, and a |
|
* dot in another window, if it is greater than |
|
* the place where you did the insert. Return TRUE |
|
* if all is well, and FALSE on errors. |
* if all is well, and FALSE on errors. |
*/ |
*/ |
|
int |
linsert(n, c) |
linsert(n, c) |
int n; |
int n, c; |
{ |
{ |
register char *cp1; |
LINE *lp1, *lp2, *lp3; |
register char *cp2; |
MGWIN *wp; |
register LINE *lp1; |
RSIZE i; |
LINE *lp2; |
int doto; |
LINE *lp3; |
char *cp1, *cp2; |
register int doto; |
|
register RSIZE i; |
|
MGWIN *wp; |
|
|
|
lchange(WFEDIT); |
lchange(WFEDIT); |
lp1 = curwp->w_dotp; /* Current line */ |
|
if (lp1 == curbp->b_linep) { /* At the end: special */ |
/* current line */ |
/* (now should only happen in empty buffer */ |
lp1 = curwp->w_dotp; |
|
|
|
/* special case for the end */ |
|
if (lp1 == curbp->b_linep) { |
|
/* now should only happen in empty buffer */ |
if (curwp->w_doto != 0) { |
if (curwp->w_doto != 0) { |
ewprintf("bug: linsert"); |
ewprintf("bug: linsert"); |
return FALSE; |
return FALSE; |
} |
} |
if ((lp2 = lallocx(n)) == NULL) /* Allocate new line */ |
/* allocate a new line */ |
|
if ((lp2 = lallocx(n)) == NULL) |
return FALSE; |
return FALSE; |
lp3 = lp1->l_bp;/* Previous line */ |
/* previous line */ |
lp3->l_fp = lp2;/* Link in */ |
lp3 = lp1->l_bp; |
|
/* link in */ |
|
lp3->l_fp = lp2; |
lp2->l_fp = lp1; |
lp2->l_fp = lp1; |
lp1->l_bp = lp2; |
lp1->l_bp = lp2; |
lp2->l_bp = lp3; |
lp2->l_bp = lp3; |
|
|
curwp->w_doto = n; |
curwp->w_doto = n; |
return TRUE; |
return TRUE; |
} |
} |
doto = curwp->w_doto; /* Save for later. */ |
/* save for later */ |
|
doto = curwp->w_doto; |
/* NOSTRICT (2) */ |
/* NOSTRICT (2) */ |
if (lp1->l_used + n > lp1->l_size) { /* Hard: reallocate */ |
/* Hard case: reallocate */ |
|
if (lp1->l_used + n > lp1->l_size) { |
if ((lp2 = lallocx(lp1->l_used + n)) == NULL) |
if ((lp2 = lallocx(lp1->l_used + n)) == NULL) |
return FALSE; |
return FALSE; |
cp1 = &lp1->l_text[0]; |
cp1 = &lp1->l_text[0]; |
|
|
lp2->l_fp = lp1->l_fp; |
lp2->l_fp = lp1->l_fp; |
lp1->l_fp->l_bp = lp2; |
lp1->l_fp->l_bp = lp2; |
lp2->l_bp = lp1->l_bp; |
lp2->l_bp = lp1->l_bp; |
free((char *) lp1); |
free((char *)lp1); |
} else { /* Easy: in place */ |
/* Easy case: in place */ |
lp2 = lp1; /* Pretend new line */ |
} else { |
|
/* pretend there's a new line */ |
|
lp2 = lp1; |
/* NOSTRICT */ |
/* NOSTRICT */ |
lp2->l_used += n; |
lp2->l_used += n; |
cp2 = &lp1->l_text[lp1->l_used]; |
cp2 = &lp1->l_text[lp1->l_used]; |
|
|
while (cp1 != &lp1->l_text[doto]) |
while (cp1 != &lp1->l_text[doto]) |
*--cp2 = *--cp1; |
*--cp2 = *--cp1; |
} |
} |
for (i = 0; i < n; ++i) /* Add the characters */ |
/* Add the characters */ |
|
for (i = 0; i < n; ++i) |
lp2->l_text[doto + i] = c; |
lp2->l_text[doto + i] = c; |
|
|
for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { |
for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { |
|
|
} |
} |
|
|
/* |
/* |
* Insert a newline into the buffer |
* Insert a newline into the buffer at the current location of dot in the |
* at the current location of dot in the current |
* current window. The funny ass-backwards way is no longer used. |
* window. The funny ass-backwards way is no longer used. |
|
*/ |
*/ |
|
int |
lnewline() |
lnewline() |
{ |
{ |
register LINE *lp1; |
LINE *lp1, *lp2; |
register LINE *lp2; |
int doto, nlen; |
register int doto; |
MGWIN *wp; |
register int nlen; |
|
MGWIN *wp; |
|
|
|
lchange(WFHARD); |
lchange(WFHARD); |
lp1 = curwp->w_dotp; /* Get the address and */ |
|
doto = curwp->w_doto; /* offset of "." */ |
/* Get the address and offset of "." */ |
if (doto == 0) { /* avoid unnessisary copying */ |
lp1 = curwp->w_dotp; |
if ((lp2 = lallocx(0)) == NULL) /* new first part */ |
doto = curwp->w_doto; |
|
|
|
/* avoid unnecessary copying */ |
|
if (doto == 0) { |
|
/* new first part */ |
|
if ((lp2 = lallocx(0)) == NULL) |
return FALSE; |
return FALSE; |
lp2->l_bp = lp1->l_bp; |
lp2->l_bp = lp1->l_bp; |
lp1->l_bp->l_fp = lp2; |
lp1->l_bp->l_fp = lp2; |
|
|
wp->w_linep = lp2; |
wp->w_linep = lp2; |
return TRUE; |
return TRUE; |
} |
} |
nlen = llength(lp1) - doto; /* length of new part */ |
|
if ((lp2 = lallocx(nlen)) == NULL) /* New second half line */ |
/* length of new part */ |
|
nlen = llength(lp1) - doto; |
|
|
|
/* new second half line */ |
|
if ((lp2 = lallocx(nlen)) == NULL) |
return FALSE; |
return FALSE; |
if (nlen != 0) |
if (nlen != 0) |
bcopy(&lp1->l_text[doto], &lp2->l_text[0], nlen); |
bcopy(&lp1->l_text[doto], &lp2->l_text[0], nlen); |
|
|
lp2->l_fp = lp1->l_fp; |
lp2->l_fp = lp1->l_fp; |
lp1->l_fp = lp2; |
lp1->l_fp = lp2; |
lp2->l_fp->l_bp = lp2; |
lp2->l_fp->l_bp = lp2; |
for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { /* Windows */ |
/* Windows */ |
|
for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { |
if (wp->w_dotp == lp1 && wp->w_doto >= doto) { |
if (wp->w_dotp == lp1 && wp->w_doto >= doto) { |
wp->w_dotp = lp2; |
wp->w_dotp = lp2; |
wp->w_doto -= doto; |
wp->w_doto -= doto; |
|
|
} |
} |
|
|
/* |
/* |
* This function deletes "n" bytes, |
* This function deletes "n" bytes, starting at dot. It understands how to |
* starting at dot. It understands how do deal |
* deal with end of lines, etc. It returns TRUE if all of the characters |
* with end of lines, etc. It returns TRUE if all |
* were deleted, and FALSE if they were not (because dot ran into the end |
* of the characters were deleted, and FALSE if |
* of the buffer. The "kflag" indicates either no insertion, or direction |
* they were not (because dot ran into the end of |
* of insertion into the kill buffer. |
* the buffer. The "kflag" indicates either no insertion, |
|
* or direction of insertion into the kill buffer. |
|
*/ |
*/ |
|
int |
ldelete(n, kflag) |
ldelete(n, kflag) |
RSIZE n; |
RSIZE n; |
|
int kflag; |
{ |
{ |
register char *cp1; |
LINE *dotp; |
register char *cp2; |
RSIZE chunk; |
register LINE *dotp; |
MGWIN *wp; |
register int doto; |
int doto; |
register RSIZE chunk; |
char *cp1, *cp2; |
MGWIN *wp; |
|
|
|
/* |
/* |
* HACK - doesn't matter, and fixes back-over-nl bug for empty |
* HACK - doesn't matter, and fixes back-over-nl bug for empty |
|
|
while (n != 0) { |
while (n != 0) { |
dotp = curwp->w_dotp; |
dotp = curwp->w_dotp; |
doto = curwp->w_doto; |
doto = curwp->w_doto; |
if (dotp == curbp->b_linep) /* Hit end of buffer. */ |
/* Hit the end of the buffer */ |
|
if (dotp == curbp->b_linep) |
return FALSE; |
return FALSE; |
chunk = dotp->l_used - doto; /* Size of chunk. */ |
/* Size of the chunk */ |
|
chunk = dotp->l_used - doto; |
if (chunk > n) |
if (chunk > n) |
chunk = n; |
chunk = n; |
if (chunk == 0) { /* End of line, merge. */ |
/* End of line, merge */ |
|
if (chunk == 0) { |
if (dotp == lback(curbp->b_linep)) |
if (dotp == lback(curbp->b_linep)) |
return FALSE; /* End of buffer. */ |
/* End of buffer */ |
|
return FALSE; |
lchange(WFHARD); |
lchange(WFHARD); |
if (ldelnewline() == FALSE |
if (ldelnewline() == FALSE || |
|| (kflag != KNONE && kinsert('\n', kflag) == FALSE)) |
(kflag != KNONE && kinsert('\n', kflag) == FALSE)) |
return FALSE; |
return FALSE; |
--n; |
--n; |
continue; |
continue; |
} |
} |
lchange(WFEDIT); |
lchange(WFEDIT); |
cp1 = &dotp->l_text[doto]; /* Scrunch text. */ |
/* Scrunch text */ |
|
cp1 = &dotp->l_text[doto]; |
cp2 = cp1 + chunk; |
cp2 = cp1 + chunk; |
if (kflag == KFORW) { |
if (kflag == KFORW) { |
while (ksize - kused < chunk) |
while (ksize - kused < chunk) |
if (kgrow(FALSE) == FALSE) |
if (kgrow(FALSE) == FALSE) |
return FALSE; |
return FALSE; |
bcopy(cp1, &(kbufp[kused]), (int) chunk); |
bcopy(cp1, &(kbufp[kused]), (int)chunk); |
kused += chunk; |
kused += chunk; |
} else if (kflag == KBACK) { |
} else if (kflag == KBACK) { |
while (kstart < chunk) |
while (kstart < chunk) |
if (kgrow(TRUE) == FALSE) |
if (kgrow(TRUE) == FALSE) |
return FALSE; |
return FALSE; |
bcopy(cp1, &(kbufp[kstart - chunk]), (int) chunk); |
bcopy(cp1, &(kbufp[kstart - chunk]), (int)chunk); |
kstart -= chunk; |
kstart -= chunk; |
} else if (kflag != KNONE) |
} else if (kflag != KNONE) |
panic("broken ldelete call"); |
panic("broken ldelete call"); |
while (cp2 != &dotp->l_text[dotp->l_used]) |
while (cp2 != &dotp->l_text[dotp->l_used]) |
*cp1++ = *cp2++; |
*cp1++ = *cp2++; |
dotp->l_used -= (int) chunk; |
dotp->l_used -= (int)chunk; |
for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { |
for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { |
if (wp->w_dotp == dotp && wp->w_doto >= doto) { |
if (wp->w_dotp == dotp && wp->w_doto >= doto) { |
/* NOSTRICT */ |
/* NOSTRICT */ |
|
|
} |
} |
|
|
/* |
/* |
* Delete a newline. Join the current line |
* Delete a newline and join the current line with the next line. If the next |
* with the next line. If the next line is the magic |
* line is the magic header line always return TRUE; merging the last line |
* header line always return TRUE; merging the last line |
* with the header line can be thought of as always being a successful |
* with the header line can be thought of as always being a |
* operation. Even if nothing is done, this makes the kill buffer work |
* successful operation, even if nothing is done, and this makes |
* "right". Easy cases can be done by shuffling data around. Hard cases |
* the kill buffer work "right". Easy cases can be done by |
* require that lines be moved about in memory. Return FALSE on error and |
* shuffling data around. Hard cases require that lines be moved |
* TRUE if all looks ok. |
* about in memory. Return FALSE on error and TRUE if all |
|
* looks ok. |
|
*/ |
*/ |
|
int |
ldelnewline() |
ldelnewline() |
{ |
{ |
register LINE *lp1; |
LINE *lp1, *lp2, *lp3; |
register LINE *lp2; |
MGWIN *wp; |
register MGWIN *wp; |
|
LINE *lp3; |
|
|
|
lp1 = curwp->w_dotp; |
lp1 = curwp->w_dotp; |
lp2 = lp1->l_fp; |
lp2 = lp1->l_fp; |
if (lp2 == curbp->b_linep) /* At the buffer end. */ |
/* at the end of the buffer */ |
|
if (lp2 == curbp->b_linep) |
return TRUE; |
return TRUE; |
if (lp2->l_used <= lp1->l_size - lp1->l_used) { |
if (lp2->l_used <= lp1->l_size - lp1->l_used) { |
bcopy(&lp2->l_text[0], &lp1->l_text[lp1->l_used], lp2->l_used); |
bcopy(&lp2->l_text[0], &lp1->l_text[lp1->l_used], lp2->l_used); |
|
|
lp1->l_used += lp2->l_used; |
lp1->l_used += lp2->l_used; |
lp1->l_fp = lp2->l_fp; |
lp1->l_fp = lp2->l_fp; |
lp2->l_fp->l_bp = lp1; |
lp2->l_fp->l_bp = lp1; |
free((char *) lp2); |
free((char *)lp2); |
return TRUE; |
return TRUE; |
} |
} |
if ((lp3 = lalloc(lp1->l_used + lp2->l_used)) == NULL) |
if ((lp3 = lalloc(lp1->l_used + lp2->l_used)) == NULL) |
|
|
wp->w_marko += lp1->l_used; |
wp->w_marko += lp1->l_used; |
} |
} |
} |
} |
free((char *) lp1); |
free((char *)lp1); |
free((char *) lp2); |
free((char *)lp2); |
return TRUE; |
return TRUE; |
} |
} |
|
|
/* |
/* |
* Replace plen characters before dot with argument string. |
* Replace plen characters before dot with argument string. Control-J |
* Control-J characters in st are interpreted as newlines. |
* characters in st are interpreted as newlines. There is a casehack |
* There is a casehack disable flag (normally it likes to match |
* disable flag (normally it likes to match case of replacement to what |
* case of replacement to what was there). |
* was there). |
*/ |
*/ |
|
int |
lreplace(plen, st, f) |
lreplace(plen, st, f) |
register RSIZE plen; /* length to remove */ |
RSIZE plen; /* length to remove */ |
char *st; /* replacement string */ |
char *st; /* replacement string */ |
int f; /* case hack disable */ |
int f; /* case hack disable */ |
{ |
{ |
register RSIZE rlen; /* replacement length */ |
RSIZE rlen; /* replacement length */ |
register int rtype; /* capitalization */ |
int rtype; /* capitalization */ |
register int c; /* used for random characters */ |
int c; /* used for random characters */ |
register int doto; /* offset into line */ |
int doto; /* offset into line */ |
|
|
/* |
/* |
* Find the capitalization of the word that was found. |
* Find the capitalization of the word that was found. f says use |
* f says use exact case of replacement string (same thing that |
* exact case of replacement string (same thing that happens with |
* happens with lowercase found), so bypass check. |
* lowercase found), so bypass check. |
*/ |
*/ |
/* NOSTRICT */ |
/* NOSTRICT */ |
(VOID) backchar(FFARG | FFRAND, (int) plen); |
(VOID)backchar(FFARG | FFRAND, (int)plen); |
rtype = _L; |
rtype = _L; |
c = lgetc(curwp->w_dotp, curwp->w_doto); |
c = lgetc(curwp->w_dotp, curwp->w_doto); |
if (ISUPPER(c) != FALSE && f == FALSE) { |
if (ISUPPER(c) != FALSE && f == FALSE) { |
|
|
rlen = strlen(st); |
rlen = strlen(st); |
doto = curwp->w_doto; |
doto = curwp->w_doto; |
if (plen > rlen) |
if (plen > rlen) |
(VOID) ldelete((RSIZE) (plen - rlen), KNONE); |
(VOID)ldelete((RSIZE) (plen - rlen), KNONE); |
else if (plen < rlen) { |
else if (plen < rlen) { |
if (linsert((int) (rlen - plen), ' ') == FALSE) |
if (linsert((int)(rlen - plen), ' ') == FALSE) |
return FALSE; |
return FALSE; |
} |
} |
curwp->w_doto = doto; |
curwp->w_doto = doto; |
|
|
rtype = _L; |
rtype = _L; |
if (c == CCHR('J')) { |
if (c == CCHR('J')) { |
if (curwp->w_doto == llength(curwp->w_dotp)) |
if (curwp->w_doto == llength(curwp->w_dotp)) |
(VOID) forwchar(FFRAND, 1); |
(VOID)forwchar(FFRAND, 1); |
else { |
else { |
if (ldelete((RSIZE) 1, KNONE) != FALSE) |
if (ldelete((RSIZE) 1, KNONE) != FALSE) |
(VOID) lnewline(); |
(VOID)lnewline(); |
} |
} |
} else if (curwp->w_dotp == curbp->b_linep) { |
} else if (curwp->w_dotp == curbp->b_linep) { |
(VOID) linsert(1, c); |
(VOID)linsert(1, c); |
} else if (curwp->w_doto == llength(curwp->w_dotp)) { |
} else if (curwp->w_doto == llength(curwp->w_dotp)) { |
if (ldelete((RSIZE) 1, KNONE) != FALSE) |
if (ldelete((RSIZE) 1, KNONE) != FALSE) |
(VOID) linsert(1, c); |
(VOID)linsert(1, c); |
} else |
} else |
lputc(curwp->w_dotp, curwp->w_doto++, c); |
lputc(curwp->w_dotp, curwp->w_doto++, c); |
} |
} |
|
|
} |
} |
|
|
/* |
/* |
* Delete all of the text |
* Delete all of the text saved in the kill buffer. Called by commands when |
* saved in the kill buffer. Called by commands |
* a new kill context is created. The kill buffer array is released, just in |
* when a new kill context is being created. The kill |
* case the buffer has grown to an immense size. No errors. |
* buffer array is released, just in case the buffer has |
|
* grown to immense size. No errors. |
|
*/ |
*/ |
VOID |
VOID |
kdelete() |
kdelete() |
{ |
{ |
|
|
if (kbufp != NULL) { |
if (kbufp != NULL) { |
free((char *) kbufp); |
free((char *)kbufp); |
kbufp = NULL; |
kbufp = NULL; |
kstart = kused = ksize = 0; |
kstart = kused = ksize = 0; |
} |
} |
} |
} |
|
|
/* |
/* |
* Insert a character to the kill buffer, |
* Insert a character to the kill buffer, enlarging the buffer if there |
* enlarging the buffer if there isn't any room. Always |
* isn't any room. Always grow the buffer in chunks, on the assumption |
* grow the buffer in chunks, on the assumption that if you |
* that if you put something in the kill buffer you are going to put more |
* put something in the kill buffer you are going to put |
* stuff there too later. Return TRUE if all is well, and FALSE on errors. |
* more stuff there too later. Return TRUE if all is |
* Print a message on errors. Dir says whether to put it at back or front. |
* well, and FALSE on errors. Print a message on |
|
* errors. Dir says whether to put it at back or front. |
|
*/ |
*/ |
|
int |
kinsert(c, dir) |
kinsert(c, dir) |
|
int c, dir; |
{ |
{ |
|
|
if (kused == ksize && dir == KFORW && kgrow(FALSE) == FALSE) |
if (kused == ksize && dir == KFORW && kgrow(FALSE) == FALSE) |
return FALSE; |
return FALSE; |
if (kstart == 0 && dir == KBACK && kgrow(TRUE) == FALSE) |
if (kstart == 0 && dir == KBACK && kgrow(TRUE) == FALSE) |
|
|
* kgrow - just get more kill buffer for the callee. back is true if |
* kgrow - just get more kill buffer for the callee. back is true if |
* we are trying to get space at the beginning of the kill buffer. |
* we are trying to get space at the beginning of the kill buffer. |
*/ |
*/ |
|
static int |
kgrow(back) |
kgrow(back) |
|
int back; |
{ |
{ |
register int nstart; |
int nstart; |
register char *nbufp; |
char *nbufp; |
|
|
if ((unsigned) (ksize + KBLOCK) <= (unsigned) ksize) { |
if ((unsigned)(ksize + KBLOCK) <= (unsigned)ksize) { |
/* probably 16 bit unsigned */ |
/* probably 16 bit unsigned */ |
ewprintf("Kill buffer size at maximum"); |
ewprintf("Kill buffer size at maximum"); |
return FALSE; |
return FALSE; |
} |
} |
if ((nbufp = malloc((unsigned) (ksize + KBLOCK))) == NULL) { |
if ((nbufp = malloc((unsigned)(ksize + KBLOCK))) == NULL) { |
ewprintf("Can't get %ld bytes", (long) (ksize + KBLOCK)); |
ewprintf("Can't get %ld bytes", (long)(ksize + KBLOCK)); |
return FALSE; |
return FALSE; |
} |
} |
nstart = (back == TRUE) ? (kstart + KBLOCK) : (KBLOCK / 4); |
nstart = (back == TRUE) ? (kstart + KBLOCK) : (KBLOCK / 4); |
bcopy(&(kbufp[kstart]), &(nbufp[nstart]), (int) (kused - kstart)); |
bcopy(&(kbufp[kstart]), &(nbufp[nstart]), (int)(kused - kstart)); |
if (kbufp != NULL) |
if (kbufp != NULL) |
free((char *) kbufp); |
free((char *)kbufp); |
kbufp = nbufp; |
kbufp = nbufp; |
ksize += KBLOCK; |
ksize += KBLOCK; |
kused = kused - kstart + nstart; |
kused = kused - kstart + nstart; |
|
|
} |
} |
|
|
/* |
/* |
* This function gets characters from |
* This function gets characters from the kill buffer. If the character |
* the kill buffer. If the character index "n" is |
* index "n" is off the end, it returns "-1". This lets the caller just |
* off the end, it returns "-1". This lets the caller |
* scan along until it gets a "-1" back. |
* just scan along until it gets a "-1" back. |
|
*/ |
*/ |
|
int |
kremove(n) |
kremove(n) |
|
int n; |
{ |
{ |
if (n < 0 || n + kstart >= kused) |
if (n < 0 || n + kstart >= kused) |
return -1; |
return -1; |