home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Frozen Fish 1: Amiga
/
FrozenFish-Apr94.iso
/
bbs
/
alib
/
d8xx
/
d832
/
term.lha
/
Term
/
term-3.1-Source.lha
/
termBuffer.c
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-18
|
11KB
|
638 lines
/*
** termBuffer.c
**
** Auxilary routines for text buffer/capture management.
**
** Copyright © 1990-1993 by Olaf `Olsen' Barthel & MXM
** All Rights Reserved
*/
#include "termGlobal.h"
/* Maximum size of an allocated line string. */
#define STRING_SIZE (1 + 255 + 1)
/* How many strings to include in a single puddle. */
#define STRING_COUNT 10
/* The number of lines the buffer will grow. */
#define BUFFER_GROW 100
/* Memory allocation routines. */
STATIC STRPTR (* __regargs AllocString)(STRPTR,LONG);
STATIC VOID (* __regargs FreeString)(STRPTR);
/* Memory pool header (Kickstart 3.0 required). */
STATIC APTR BufferPoolHeader;
/* OldAllocString(STRPTR String,WORD Len):
*
+ Allocate space for a string, old flavour.
*/
STATIC STRPTR __regargs
OldAllocString(STRPTR String,LONG Len)
{
STRPTR Mem;
if(Len > 255)
Len = 255;
if(Mem = (STRPTR)AllocMem(1 + Len + 1,MEMF_ANY | MEMF_PUBLIC))
{
*Mem++ = Len;
memcpy(Mem,String,Len);
Mem[Len] = 0;
return((STRPTR)Mem);
}
else
return(NULL);
}
/* OldFreeString(STRPTR String):
*
* Free the space occupied by a string, old flavour.
*/
STATIC VOID __regargs
OldFreeString(STRPTR String)
{
FreeMem(&String[-1],1 + String[-1] + 1);
}
/* NewAllocString(STRPTR String,WORD Len):
*
+ Allocate space for a string, new pooled version.
*/
STATIC STRPTR __regargs
NewAllocString(STRPTR String,LONG Len)
{
STRPTR Mem;
if(Len > 255)
Len = 255;
if(Mem = (STRPTR)AllocPooled(BufferPoolHeader,1 + Len + 1))
{
*Mem++ = Len;
memcpy(Mem,String,Len);
Mem[Len] = 0;
return((STRPTR)Mem);
}
else
return(NULL);
}
/* NewFreeString(STRPTR String):
*
* Free the space occupied by a string, new pooled version.
*/
STATIC VOID __regargs
NewFreeString(STRPTR String)
{
FreePooled(BufferPoolHeader,&String[-1],1 + String[-1] + 1);
}
/* AddLine(STRPTR Line,LONG Size):
*
* Add a line to the display buffer.
*/
STATIC VOID __regargs
AddLine(register STRPTR Line,register LONG Size)
{
/* Are we still to update the buffer contents? */
if(!BufferClosed)
{
/* Remove trailing spaces. */
while(Size > 0 && Line[Size - 1] == ' ')
Size--;
/* Is the buffer array initialized? */
if(BufferLines)
{
ULONG Signals = 0;
/* Pick up the global access semaphore
* (two tasks are sharing the data).
*/
ObtainSemaphore(BufferSemaphore);
/* Check for limit. */
if(Config -> CaptureConfig -> MaxBufferSize && BufferSpace >= Config -> CaptureConfig -> MaxBufferSize)
{
register LONG i;
BufferSpace -= BufferLines[0][-1];
(*FreeString)(BufferLines[0]);
for(i = 1 ; i < MaxLines ; i++)
BufferLines[i - 1] = BufferLines[i];
Lines--;
/* Tell the buffer task to
* refresh the display.
*/
Signals = SIG_MOVEUP;
}
else
{
/* We've reached the last line in the buffer. */
if(Lines == MaxLines)
{
STRPTR *MoreBuffer;
/* Allocate space for some more lines. */
if(MoreBuffer = (STRPTR *)AllocVec((MaxLines + BUFFER_GROW) * sizeof(STRPTR),MEMF_ANY | MEMF_CLEAR))
{
register LONG i;
BufferChanged = TRUE;
/* Copy the old lines to the new
* buffer.
*/
for(i = 0 ; i < Lines ; i++)
MoreBuffer[i] = BufferLines[i];
/* Free the old lines. */
FreeVec(BufferLines);
/* Set the new buffer. */
MaxLines += BUFFER_GROW;
BufferLines = MoreBuffer;
}
else
{
BufferChanged = TRUE;
/* We couldn't get enough memory
* to extend the number of lines
* in the buffer, so we'll have
* to wrap the contents of the
* buffer around.
*/
if(Lines)
{
register LONG i;
BufferSpace -= BufferLines[0][-1];
(*FreeString)(BufferLines[0]);
for(i = 1 ; i < MaxLines ; i++)
BufferLines[i - 1] = BufferLines[i];
Lines--;
/* Tell the buffer task to
* refresh the display.
*/
Signals = SIG_MOVEUP;
}
}
}
}
/* Allocate a new line and copy the buffer contents
* into it.
*/
if(BufferLines[Lines] = (*AllocString)(Line,Size))
{
BufferChanged = TRUE;
Lines++;
BufferSpace += Size;
}
ReleaseSemaphore(BufferSemaphore);
/* Tell the buffer task to update the display. */
if(!Signals)
{
Signals = SIG_UPDATE;
UpdateReview(FALSE);
}
else
UpdateReview(TRUE);
if(BufferProcess)
Signal(BufferProcess,Signals);
}
}
}
/* StoreBuffer(APTR Buffer,LONG Size):
*
* Store data in the display buffer.
*/
VOID __regargs
StoreBuffer(register STRPTR Buffer,register LONG Size)
{
STATIC UBYTE LineBuffer[BUFFER_LINE_WIDTH];
STATIC LONG BufferCount = 0;
register UBYTE c;
while(Size--)
{
/* Look which char we are to handle. */
switch(c = *Buffer++)
{
/* Move the cursor one step back. */
case BKS:
if(BufferCount)
BufferCount--;
break;
/* Move the cursor to the next tab
* stop.
*/
case TAB:
if(((BufferCount + 8) & ~7) < LastColumn)
{
register LONG Delta = ((BufferCount + 8) & ~7) - BufferCount;
memset(&LineBuffer[BufferCount],' ',Delta);
BufferCount += Delta;
}
else
{
AddLine(LineBuffer,BufferCount);
BufferCount = 0;
}
break;
/* Terminate the current line. */
case ENT:
AddLine(LineBuffer,BufferCount);
BufferCount = 0;
break;
/* Stuff the character into the buffer. */
default:
if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
{
if(IsPrintable[c])
LineBuffer[BufferCount++] = c;
}
else
{
if(c)
LineBuffer[BufferCount++] = c;
}
break;
}
/* The line is full, add it to the display buffer. */
if(BufferCount >= LastColumn || BufferCount == BUFFER_LINE_WIDTH)
{
AddLine(LineBuffer,BufferCount);
BufferCount = 0;
}
}
}
/* DeleteBuffer():
*
* Delete buffer resources.
*/
VOID
DeleteBuffer()
{
if(BufferLines)
{
if(!BufferPoolHeader)
{
LONG i;
for(i = 0 ; i < Lines ; i++)
{
if(BufferLines[i])
(*FreeString)(BufferLines[i]);
}
}
FreeVec(BufferLines);
BufferLines = NULL;
}
if(BufferPoolHeader)
{
DeletePool(BufferPoolHeader);
BufferPoolHeader = NULL;
}
if(BufferSemaphore)
{
FreeVec(BufferSemaphore);
BufferSemaphore = NULL;
}
}
/* CreateBuffer():
*
* Allocate buffer resources.
*/
BYTE
CreateBuffer()
{
if(BufferLines = (STRPTR *)AllocVec(MaxLines * sizeof(STRPTR),MEMF_ANY | MEMF_CLEAR | MEMF_PUBLIC))
{
if(BufferSemaphore = (struct SignalSemaphore *)AllocVec(sizeof(struct SignalSemaphore),MEMF_ANY | MEMF_PUBLIC))
{
InitSemaphore(BufferSemaphore);
/* Create a memory pool header if possible. */
if(SysBase -> LibNode . lib_Version >= 39)
{
if(BufferPoolHeader = CreatePool(MEMF_ANY | MEMF_PUBLIC,STRING_SIZE * STRING_COUNT,STRING_SIZE * STRING_COUNT))
{
AllocString = NewAllocString;
FreeString = NewFreeString;
return(TRUE);
}
}
AllocString = OldAllocString;
FreeString = OldFreeString;
return(TRUE);
}
FreeVec(BufferLines);
BufferLines = NULL;
}
return(FALSE);
}
/* FreeBuffer():
*
* Release the contents of the text buffer.
*/
VOID
FreeBuffer()
{
BufferChanged = FALSE;
/* Free the contents of the display buffer. */
if(BufferLines)
{
APTR NewPoolHeader;
/* Simple, create another pool header if possible. */
if(BufferPoolHeader)
NewPoolHeader = CreatePool(MEMF_ANY | MEMF_PUBLIC,STRING_SIZE * STRING_COUNT,STRING_SIZE * STRING_COUNT);
else
NewPoolHeader = NULL;
/* If a new pool header is available, free the old
* pool and replace it with the new pool, else
* do it again by hand.
*/
if(NewPoolHeader)
{
DeletePool(BufferPoolHeader);
BufferPoolHeader = NewPoolHeader;
}
else
{
LONG i;
for(i = 0 ; i < Lines ; i++)
{
if(BufferLines[i])
(*FreeString)(BufferLines[i]);
}
}
FreeVec(BufferLines);
Lines = 0;
MaxLines = BUFFER_GROW;
BufferLines = (STRPTR *)AllocVec(MaxLines * sizeof(STRPTR),MEMF_ANY|MEMF_CLEAR);
UpdateReview(TRUE);
}
BufferSpace = 0;
BufferChanged = FALSE;
}
/* CreateSearchInfo(STRPTR Pattern):
*
* Create auxilary data required by SearchTextBuffer().
*/
struct SearchInfo * __regargs
CreateSearchInfo(STRPTR Pattern)
{
struct SearchInfo *Info;
/* Allocate the buffer. */
if(Info = (struct SearchInfo *)AllocVec(sizeof(struct SearchInfo),MEMF_ANY | MEMF_PUBLIC))
{
WORD i;
/* Determine pattern width. */
Info -> PatternWidth = strlen(Pattern);
/* Turn the pattern into upper case characters. */
for(i = 0 ; i <= Info -> PatternWidth ; i++)
Info -> Pattern[i] = ToUpper(Pattern[i]);
/* Fill the entire range with the maximum pattern width. */
for(i = 0 ; i < 256 ; i++)
Info -> Distance[i] = Info -> PatternWidth;
/* Fill in the matching distances. */
for(i = 0 ; i < Info -> PatternWidth - 1 ; i++)
Info -> Distance[Info -> Pattern[i]] = Info -> PatternWidth - i - 1;
/* Restart from scratch. */
Info -> FoundY = -1;
}
return(Info);
}
/* DeleteSearchInfo(struct SearchInfo *Info):
*
* Free buffer allocated by CreateSearchInfo().
*/
VOID __regargs
DeleteSearchInfo(struct SearchInfo *Info)
{
if(Info)
FreeVec(Info);
}
/* SearchTextBuffer():
*
* String search function, based on the Boyer-Moore search
* algorithm.
*/
LONG __regargs
SearchTextBuffer(struct SearchInfo *Info)
{
if(BufferLines)
{
UBYTE *Distance,
*Pattern;
WORD LineWidth,
PatternWidth;
STRPTR Line;
LONG i;
WORD j,k,l,Index;
/* Extract relevant data. */
Distance = Info -> Distance;
Pattern = Info -> Pattern;
PatternWidth = Info -> PatternWidth;
/* Update the search positions. */
if(Info -> FoundY == -1)
{
Info -> FoundX = 0;
Info -> FoundY = 0;
Index = 0;
}
else
{
if(!(Index = Info -> Index))
Info -> FoundY = (Info -> FoundY + 1) % Lines;
}
/* Run down the buffer. */
for(i = Info -> FoundY ; i < Lines ; i++)
{
Line = BufferLines[i];
/* Is there anything to search for? */
if((LineWidth = Line[-1]) >= PatternWidth)
{
/* Cast the magic spell of Boyer-Moore... */
if(Index)
j = Index;
else
j = PatternWidth;
do
{
k = PatternWidth - 1;
l = j - 1;
while(k >= 0 && Pattern[k] == ToUpper(Line[l]))
{
l--;
k--;
}
j += Distance[ToUpper(Line[j - 1])];
if(k < 0)
{
Info -> FoundX = l + 1;
Info -> FoundY = i;
if(j <= LineWidth)
Info -> Index = j;
else
Info -> Index = 0;
return(i);
}
}
while(j <= LineWidth);
Index = 0;
}
}
}
return(-1);
}