teacl/src/insstr.c

112 lines
3.7 KiB
C

/*****************************************************************************
InsStr()
This function is called to insert text into the edit buffer. The
edit buffer is expanded to make room for the text if necessary.
*****************************************************************************/
#include "zport.h" /* define portability identifiers */
#include "tecoc.h" /* define general identifiers */
#include "defext.h" /* define external global variables */
#include "deferr.h" /* define identifiers for error messages */
/*
* The edit buffer gap needs to be expanded. If there's room in the input
* buffer, then we can shuffle memory to steal some room from the input
* buffer. If there's not room to steal from the input buffer, we have to
* re-allocate the whole edit/input buffer and then adjust the pointers to
* reflect the movement.
*/
#if USE_PROTOTYPES
static DEFAULT expand_gap(ptrdiff_t length)
#else
static DEFAULT expand_gap(length)
ptrdiff_t length; /* amount of gap room needed */
#endif
{
SIZE_T TmpSiz;
SIZE_T NewSiz;
charptr NewBeg;
DBGFEN(3,"expand_gap",NULL);
/*
* If the size of the input buffer exceeds IBFMIN, make it IBFMIN and
* add the leftover space to the edit buffer gap.
*
* from: EbfBeg...GapBeg...GapEnd...EBfEnd<TmpSiz><IBFMIN>IBfEnd
* to: EbfBeg...GapBeg...<TmpSiz>GapEnd...EBfEnd<IBFMIN>IBfEnd
*/
TmpSiz = IBfEnd-EBfEnd;
if (TmpSiz > IBFMIN) {
TmpSiz -= IBFMIN;
MEMMOVE(GapEnd+1+TmpSiz, GapEnd+1, (SIZE_T)(EBfEnd-GapEnd));
GapEnd += TmpSiz;
EBfEnd += TmpSiz;
}
/*
* If there's still not enough room in the edit buffer gap, expand the gap
* by reallocating the edit buffer. Since reallocating is expensive, take
* this opportunity to expand it by EBFEXP bytes more than what we need.
*
* from: EbfBeg...GapBeg<GapSiz>GapEnd...EBfEnd...IBfEnd
* to: EbfBeg...GapBeg<length-GapSiz+EBFEXP>GapEnd...EBfEnd...IBfEnd
*/
TmpSiz = GapEnd-GapBeg+1;
if (TmpSiz < length) { /* str length > GapSiz */
TmpSiz = (length - TmpSiz) + EBFEXP; /* amt to expand EBf */
NewSiz = (IBfEnd-EBfBeg+1) + TmpSiz; /* new size of EBf */
NewBeg = (charptr)ZRaloc(EBfBeg, NewSiz); /* reallocate EBf */
if (NewBeg == NULL) { /* if failure */
ErrMsg(ERR_MEM); /* memory overflow */
DBGFEX(3,DbgFNm,"FAILURE, couldn't ZRaloc more gap room");
return FAILURE;
}
/*
* Make sure all the pointers reference the new memory area.
*/
if (NewBeg != EBfBeg) {
GapBeg = NewBeg + (GapBeg - EBfBeg);
GapEnd = NewBeg + (GapEnd - EBfBeg);
EBfEnd = NewBeg + (EBfEnd - EBfBeg);
IBfEnd = NewBeg + (IBfEnd - EBfBeg);
EBfBeg = NewBeg;
}
/*
* Now open up the gap by moving the second half of the edit buffer
* down the amount we expanded the edit buffer (TmpSiz), then update the
* pointers again.
*/
MEMMOVE(GapEnd+1+TmpSiz, GapEnd+1, (SIZE_T)(EBfEnd - GapEnd));
GapEnd += TmpSiz;
EBfEnd += TmpSiz;
IBfEnd += TmpSiz;
}
DBGFEX(3,DbgFNm,NULL);
return SUCCESS;
}
DEFAULT InsStr(string, length) /* insert string into edit buffer */
charptr string;
ptrdiff_t length;
{
#if DEBUGGING
static char *DbgFNm = "InsStr";
sprintf(DbgSBf,"length = %d", length);
DbgFEn(3,DbgFNm,DbgSBf);
#endif
RefLen = -length; /* ^S = -length of last string */
/*
* Before trying to insert the text, we have to be sure there's enough room
* in the edit buffer gap for the text.
*/
if ((GapEnd-GapBeg+1) < length) {
if (expand_gap(length) == FAILURE) {
DBGFEX(3,DbgFNm,"FAILURE, expand_gap() failed");
return FAILURE;
}
}
/*
* Copy the new text into the edit buffer gap, and adjust GapBeg to make the
* text part of the edit buffer.
*/
MEMMOVE(GapBeg, string, (SIZE_T)length);
GapBeg += length;
DBGFEX(3,DbgFNm,"SUCCESS");
return SUCCESS;
}