/*
* histlist.cc
*
* Turbo Vision - Version 2.0
*
* Copyright (c) 1994 by Borland International
* All Rights Reserved.
*
* Modified by Sergio Sigala <sergio@sigala.it>
*/
#include <tvision/tv.h>
#include <stdlib.h>
#include <string.h>
class HistRec
{
public:
HistRec( uchar nId, const char *nStr );
uchar id;
uchar len;
char str[1];
};
inline HistRec::HistRec( uchar nId, const char *nStr ) :
id( nId ),
len( strlen( nStr ) + 3 )
{
strcpy( str, nStr );
}
inline HistRec *advance( HistRec *ptr, size_t s )
{
return (HistRec *)((char *)ptr + s);
}
inline HistRec *backup( HistRec *ptr, size_t s )
{
return (HistRec *)((char *)ptr - s);
}
inline HistRec *next( HistRec *ptr )
{
return advance( ptr, ptr->len );
}
inline HistRec *prev( HistRec *ptr )
{
return backup( ptr, ptr->len );
}
/**
* Specifies the size of the history block used by the history list manager
* to store values entered into input lines. The size is fixed by
* initHistory() at program startup.
*
* The default size of the block is 1K, but may be changed before
* initHistory() is called. The value should not be changed after the call to
* initHistory().
* @see initHistory
*/
ushort historySize = 1024; // initial size of history block
static uchar curId;
static HistRec *curRec;
/**
* Points to a buffer called the history block used to store history strings.
* The size of the block is defined by historySize. The pointer is 0 until set
* by the THistory constructor, and its value should not be altered.
* @see THistory
*/
static HistRec *historyBlock;
static HistRec *lastRec;
void advanceStringPointer()
{
curRec = next( curRec );
while( curRec < lastRec && curRec->id != curId )
curRec = next( curRec );
if( curRec >= lastRec )
curRec = 0;
}
void deleteString()
{
size_t len = curRec->len;
#ifndef __UNPATCHED
// BUG FIX - EFW - Mon 10/30/95
// This insures that if n = lastRec, no bytes are copied and
// a GPF is prevented.
HistRec *n = next(curRec);
memcpy(curRec, n, size_t((char *)lastRec - (char *)n));
#else
memcpy(curRec, next(curRec), size_t( (char *)lastRec - (char *)curRec ) );
#endif
lastRec = backup( lastRec, len );
}
void insertString( uchar id, const char *str )
{
ushort len = strlen( str ) + 3;
while( len > historySize - ( (char *)lastRec - (char *)historyBlock ) )
{
ushort firstLen = historyBlock->len;
HistRec *dst = historyBlock;
HistRec *src = next( historyBlock );
memcpy( dst, src, size_t( (char *)lastRec - (char *)src ) );
lastRec = backup( lastRec, firstLen );
}
new( lastRec ) HistRec( id, str );
lastRec = next( lastRec );
}
void startId( uchar id )
{
curId = id;
curRec = historyBlock;
}
ushort historyCount( uchar id )
{
startId( id );
ushort count = 0;
advanceStringPointer();
while( curRec != 0 )
{
count++;
advanceStringPointer();
}
return count;
}
void historyAdd( uchar id, const char *str )
{
if( str[0] == EOS )
return;
startId( id );
advanceStringPointer();
while( curRec != 0 )
{
if( strcmp( str, curRec->str ) == 0 )
deleteString();
advanceStringPointer();
}
insertString( id, str );
}
const char *historyStr( uchar id, int index )
{
startId( id );
for( short i = 0; i <= index; i++ )
advanceStringPointer();
if( curRec != 0 )
return curRec->str;
else
return 0;
}
void clearHistory()
{
new (historyBlock) HistRec( 0, "" );
lastRec = next( historyBlock );
}
/**
* Called by TApplication constructor to allocate a block of memory on the
* heap for use by the history list manager. The size of the block is
* determined by the historySize variable. After initHistory() is called, the
* historyBlock variable points to the beginning of the block.
* @see TApplication
*/
void initHistory()
{
historyBlock = (HistRec *) new char[historySize];
clearHistory();
}
void doneHistory()
{
delete historyBlock;
}
syntax highlighted by Code2HTML, v. 0.9.1