topic.cpp
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 1,642 行 · 第 1/3 页
CPP
1,642 行
// used to calculate the size of a text attribute.
const int TextHeader::_attrSizes[] = { 3, 1, 1, 1, 9, 9, 9, 1, 3, 3,
5, 5, 5, 5, 7, 7, 7, 7, 1
};
// TextHeader::addAttr --Add a text attribute.
int TextHeader::addAttr( FontFlags type, uint_32 val, char const str[],
int length )
{
int result = _numAttribs;
if( _numAttribs == _maxAttribs ){
_maxAttribs += TEXT_ATTR_MAX;
_attribs.resize( _maxAttribs );
}
_attribs[ _numAttribs ]._type = type;
_attribs[ _numAttribs ]._data = val;
if( length > 0 ){
_attribs[ _numAttribs ]._stringDat = new char[length];
memcpy( _attribs[ _numAttribs ]._stringDat, str, length );
} else {
_attribs[ _numAttribs ]._stringDat = NULL;
}
_attribs[ _numAttribs ]._size = _attrSizes[ type ];
if( type == TOP_MACRO_LINK || type == TOP_MACRO_INVIS ||
( type >= TOP_POPUP_FILE && type <= TOP_JUMP_FILE_INVIS ) ){
_attribs[ _numAttribs ]._size += length;
}
_size += _attribs[ _numAttribs ]._size;
++_numAttribs;
return result;
}
// TextHeader::appendAttr --Append a text attribute after a given one.
int TextHeader::appendAttr( int index, FontFlags type, uint_32 val,
char const str[], int length )
{
if( index >= _numAttribs ){
HCError( HLP_ATTR );
}
int result = index+1;
if( _numAttribs == _maxAttribs ){
_maxAttribs += TEXT_ATTR_MAX;
_attribs.resize( _maxAttribs );
}
if( result < _numAttribs ){
memmove( &_attribs[result+1], &_attribs[result],
(_numAttribs-result)*sizeof( TextAttr ) );
}
_attribs[ result ]._type = type;
_attribs[ result ]._data = val;
if( length > 0 ){
_attribs[ result ]._stringDat = new char[length];
memcpy( _attribs[ result ]._stringDat, str, length );
} else {
_attribs[ result ]._stringDat = NULL;
}
_attribs[ result ]._size = _attrSizes[ type ];
if( type == TOP_MACRO_LINK || type == TOP_MACRO_INVIS ||
( type >= TOP_POPUP_FILE && type <= TOP_JUMP_FILE_INVIS ) ){
_attribs[ result ]._size += length;
}
_size += _attribs[ result ]._size;
++_numAttribs;
return result;
}
// TextHeader::chgAttr --Modify a text attribute.
void TextHeader::chgAttr( int index, FontFlags type, uint_32 val,
char const str[], int length )
{
if( index >= _numAttribs ){
HCError( HLP_ATTR );
}
_size -= _attribs[ index ]._size;
_attribs[ index ]._type = type;
_attribs[ index ]._data = val;
if( _attribs[ index ]._stringDat != NULL ){
delete _attribs[ index ]._stringDat;
}
if( length > 0 ){
_attribs[ index ]._stringDat = new char[length];
memcpy( _attribs[ index ]._stringDat, str, length );
} else {
_attribs[ index ]._stringDat = NULL;
}
_attribs[ index ]._size = _attrSizes[ type ];
if( type == TOP_MACRO_LINK || type == TOP_MACRO_INVIS ||
( type >= TOP_POPUP_FILE && type <= TOP_JUMP_FILE_INVIS ) ){
_attribs[ index ]._size += length;
}
_size += _attribs[ index ]._size;
}
// TextHeader::attrData --Read the data from an attribute.
uint_32 TextHeader::attrData( int index )
{
if( index >= _numAttribs ){
HCError( HLP_ATTR );
}
return _attribs[ index ]._data;
}
// TextHeader::DumpTo --Convert the node to it's binary form.
// Complicated, thanks to many variable-length fields.
void TextHeader::dumpTo( TopicLink *dest )
{
char *location = dest->_myData;
int i;
*( (uint_16*) location ) = (uint_16) ( (2*_headerSize) | 0x8000 );
location += sizeof( uint_16 );
if( _textSize < INT_SMALL_LIMIT ){
*location++ = (uint_8) (_textSize*2);
} else {
*( (uint_16*) location ) = (uint_16) (_textSize*2+1) ;
location += sizeof( uint_16 );
}
*location++ = _numColumns;
*location++ = 0x80; // magic byte
*((uint_32*) location ) = _flags;
location += sizeof( uint_32 );
// Print out the paragraph attributes.
for( i=0; i < TOP_BORDER; i++ ){
if( _flags & _parBits[i] ){
if( _spacing[i] & 0x1 ){
*((uint_16*) location) = _spacing[i];
location += sizeof( uint_16 );
} else {
*location++ = (uint_8) _spacing[i];
}
}
}
if( _flags & _parBits[ TOP_BORDER ] ){
*((uint_16*) location) = (uint_16) _border;
location += sizeof( uint_16 );
*location++ = (uint_8) (_border >> 16);
}
// Dump the tab stops, converting them into WinHelp's integer format.
if( _flags & _parBits[ TOP_TAB_STOPS ] ){
uint_16 stops_num = _numStops;
stops_num <<= 1;
if( stops_num < INT_SMALL_LIMIT ){
stops_num |= 0x80;
*location++ = (uint_8) stops_num;
} else {
stops_num |= 0x8001;
*((uint_16*) location) = stops_num;
location += sizeof( uint_16 );
}
for( i=0; i<_numStops; i++ ){
if( _tabStops[i] & 0x1 ){
*((uint_16*) location) = _tabStops[i];
location += sizeof( uint_16 );
if( _tabStops[i] & 0x8000 ){
*location++ = _tabFlags[i];
}
} else {
*location++ = (uint_8) _tabStops[i];
if( _tabStops[i] & 0x80 ){
*location++ = _tabFlags[i];
}
}
}
}
// Now the text attributes.
uint_16 length;
for( i=0; i < _numAttribs; i++ ){
*location++ = _attrBits[ _attribs[i]._type ];
switch( _attribs[i]._type ){
// deliberate fall-through
case TOP_NEW_LINE:
case TOP_NEW_PAR:
case TOP_HTAB:
case TOP_END_LINK:
case TOP_END:
// No argument for these flags.
break;
case TOP_CENT_BITMAP:
case TOP_LEFT_BITMAP:
case TOP_RIGHT_BITMAP:
// Right now these numbers are mostly magic.
*((uint_32*) location) = 0x02800822;
location += sizeof( uint_32 );
*((uint_16*) location) = (uint_16) 0;
location += sizeof( uint_16 );
*((uint_16*) location) = (uint_16) _attribs[i]._data;
location += sizeof( uint_16 );
break;
case TOP_FONT_CHANGE:
*((uint_16*) location) = (uint_16) _attribs[i]._data;
location += sizeof( uint_16 );
break;
// more fall-through
case TOP_POPUP_LINK:
case TOP_JUMP_LINK:
case TOP_POPUP_INVIS:
case TOP_JUMP_INVIS:
*((uint_32*) location) = _attribs[i]._data;
location += sizeof( uint_32 );
break;
case TOP_MACRO_LINK:
case TOP_MACRO_INVIS:
length = (uint_16) (_attribs[i]._size-3);
*((uint_16*) location) = length;
location += sizeof( uint_16 );
memcpy( location, _attribs[i]._stringDat, length );
location += length;
break;
default:
length = (uint_16) (_attribs[i]._size-_attrSizes[_attribs[i]._type]);
*((uint_16*) location) = (uint_16) (length+4);
location += sizeof( uint_16 );
*location++ = _attribs[i]._stringDat[0];
*((uint_32*) location) = _attribs[i]._data;
location += sizeof( uint_32 );
memcpy( location, _attribs[i]._stringDat+1, length-1 );
location += length-1;
}
}
dest->_size = _size;
}
// TextHolder::TextHolder
TextHolder::TextHolder()
: _text( TEXT_BLOCK_SIZE+1 ),
_zeroes( TEXT_ZERO_SIZE ),
_size( 0 ),
_uncompSize( 0 ),
_maxSize( TEXT_BLOCK_SIZE ),
_numZeroes( 0 ),
_maxZeroes( TEXT_ZERO_SIZE )
{
// empty
}
// TextHolder::DumpTo --Convert the node to it's binary form.
void TextHolder::dumpTo( TopicLink *dest )
{
if( _size > 0 ){
memcpy( dest->_myData, _text, _size );
}
dest->_size = _size;
}
// HFTopic::HFTopic
HFTopic::HFTopic( HFSDirectory * d_file, HFPhrases *ph )
: _size( PAGE_HEADER_SIZE ), // The initial 3-DWORD page header.
_numPages( 1 ),
_numTopics( 0 ),
_haveCleanedUp( 0 ),
_phFile( ph ),
_head( NULL ),
_tail( NULL ),
_browseStr( NULL ),
_bhead( NULL ),
_btail( NULL ),
_curOffset( PAGE_HEADER_SIZE ),
_curCharOffset( 0 ),
_lastTopic( ~0 ),
_lastLink( ~0 ),
_lastNode( NULL ),
_lastHeader( NULL )
{
_size = PAGE_HEADER_SIZE;
_useCompress = (ph != NULL);
_phead = new PageHeader;
_ptail = _phead;
// Set up the text-compression facilities, if necessary.
// Note the initial writer is a dummy, used just to get the size
// of the compressed data.
if( _useCompress ){
_myWriter = new CompWriter;
_myReader = new CompReader( _myWriter );
} else {
_myWriter = NULL;
_myReader = NULL;
}
// Create an initial linked-list node to work with.
_curNode = new GenericNode( ~0 );
_curNode->_recordType = TOP_HEADER;
_curTopic = new TopicHeader( _numTopics++ );
_curText = new TextHolder;
_curPar = new TextHeader;
// Set the initial page header.
_phead->lastNode() = _lastTopic;
_phead->nextNode() = _curOffset;
_phead->lastTopic() = 0;
// Register ourself with the directory.
d_file->addFile( this, "|TOPIC" );
}
// HFTopic::~HFTopic
HFTopic::~HFTopic()
{
if( _myWriter ) delete _myWriter;
if( _myReader ) delete _myReader;
if( _lastNode != _curNode ){
delete _lastNode;
}
if( _lastHeader != _curTopic ){
delete _lastHeader;
}
delete _curNode;
delete _curTopic;
delete _curPar;
delete _curText;
// Lotsa linked lists to delete.
TopicLink *current = _head;
TopicLink *temp;
while( current != NULL ){
temp = current;
current = current->_next;
delete temp;
}
PageHeader *pcurrent = _phead;
PageHeader *ptemp;
while( pcurrent != NULL ){
ptemp = pcurrent;
pcurrent = pcurrent->_next;
delete ptemp;
}
StringNode *bcurrent = _bhead;
StringNode *btemp;
while( bcurrent != NULL ){
btemp = bcurrent;
bcurrent = bcurrent->_next;
delete[] btemp->_string;
delete btemp;
}
}
// HFTopic::size --Overridden from Dumpable.
uint_32 HFTopic::size()
{
if( !_haveCleanedUp ){
// Dump the last linked-list node, if necessary.
newNode();
_haveCleanedUp = 1;
}
return _size;
}
// HFTopic::dump --Overridden from Dumpable.
int HFTopic::dump( OutFile * dest )
{
// Write the last few blocks of binary data.
if( _lastNode != NULL ){
_lastNode->dumpTo( _lastNode->_myLink );
}
if( _lastHeader != NULL ){
_lastHeader->dumpTo( _lastHeader->_myLink );
}
// Put in browse sequence information.
dumpBrowse();
// If we're compressing, stop the dummy compressor and start
// the real thing.
if( _useCompress ){
CompWriter *temp = new CompOutFile( dest );
_myReader->reset( temp );
if( _myWriter ) delete _myWriter;
_myWriter = temp;
}
TopicLink *current = _head;
PageHeader *cur_page = _phead->_next;
dest->writebuf( _phead->_pageNums, sizeof( uint_32 ), 3 );
uint_32 page_size = PAGE_HEADER_SIZE;
// Write the linked list nodes in order.
int i;
while( current != NULL ){
// At the start of a page, flush the compressor and
// write a page header.
if( current->_isFirstLink ){
HCTick();
if( _useCompress ){
_myReader->flush();
}
while( page_size < COMP_PAGE_SIZE ){
dest->writech( 0 );
page_size++;
}
page_size = PAGE_HEADER_SIZE;
dest->writebuf( cur_page->_pageNums, sizeof( uint_32 ), 3 );
cur_page = cur_page->_next;
}
if( _useCompress ){
page_size += _myReader->add( current->_myData, current->_size );
// "Magic" check to see if the current node is a topic header
// or a text header. This is the only way to do it since
// at this stage the node is just a binary data block.
if( current->_myData[20] == 0x02 ){
current = current->_next;
page_size += _myReader->add( current->_myData, current->_size );
} else {
current = current->_next;
page_size += _myReader->compress( current->_myData, current->_size );
}
current = current->_next;
page_size += _myReader->compress( current->_myData, current->_size );
current = current->_next;
} else {
for( i=0; i<3; i++, current=current->_next ){
page_size += current->_size;
dest->writebuf( current->_myData, 1, current->_size );
}
}
}
// If we're compressing, a few bytes may be left in the writer.
if( _useCompress ){
_myReader->flush();
}
return 1;
}
// HFTopic::startNonScroll --Signal the start of a non-scrolling
// region of text.
void HFTopic::startNonScroll()
{
_lastHeader->_startNonScroll = _curOffset;
}
// HFTopic::startScroll --Signal the start of a scrolling
// region of text.
void HFTopic::startScroll()
{
_lastHeader->_startScroll = _curOffset;
if( _lastHeader->_startNonScroll == _curOffset ){
_lastHeader->_startNonScroll = ~0;
}
}
// HFTopic::addBrowse --Add browse sequence information.
void HFTopic::addBrowse( char const str[] )
{
if( _browseStr != NULL ){
HCWarning( TOP_TWOBROWSE, _browseStr, str );
delete[] _browseStr;
}
int length = strlen( str );
_browseStr = new char[length+1];
strncpy( _browseStr, str, length+1 );
_browseOffset = _curCharOffset;
}
// HFTopic::recordBrowse --Get the browse sequence info, in
// binary form.
void HFTopic::recordBrowse( TopicLink *me )
{
StringNode *current = _bhead;
StringNode *prev = NULL;
StringNode *newnode = new StringNode;
newnode->_me= me;
newnode->_charOffset = _browseOffset;
newnode->_string = _browseStr;
strlwr( newnode->_string );
_browseStr = NULL;
while( current != NULL ){
if( strcmp( current->_string, newnode->_string ) > 0 ) break;
prev = current;
current = current->_next;
}
if( current == NULL ){
if( prev == NULL ){
_bhead = _btail = newnode;
newnode->_next = newnode->_prev = NULL;
} else {
prev->_next = newnode;
newnode->_prev = prev;
newnode->_next = NULL;
_btail = newnode;
}
} else {
newnode->_next = current;
newnode->_prev = current->_prev;
current->_prev = newnode;
if( prev == NULL ){
_bhead = newnode;
} else {
prev->_next = newnode;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?