topic.cpp

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 1,642 行 · 第 1/3 页

CPP
1,642
字号
    }
    }
}


//  HFTopic::dumpBrowse --Add binary browse sequence info to all topics.

void HFTopic::dumpBrowse()
{
    StringNode  *current = _bhead;
    StringNode  *lastlocal = NULL;
    StringNode  *lastglobal = NULL;
    char    *colonpos;
    int     seqlen;

    while( current != NULL ){
    colonpos = strchr( current->_string, ':' );
    seqlen = colonpos - current->_string + 1;
    if( colonpos == NULL ){
        if( lastlocal != NULL ){
        lastlocal->nextBrowse() = ~0;
        }
        lastlocal = NULL;
        if( lastglobal != NULL ){
        lastglobal->nextBrowse() = current->_charOffset;
        current->prevBrowse() = lastglobal->_charOffset;
        } else {
        current->prevBrowse() = ~0;
        }
        lastglobal = current;
    } else {
        if( lastlocal != NULL ){
        if( !strncmp( lastlocal->_string, current->_string, seqlen ) ){
            lastlocal->nextBrowse() = current->_charOffset;
            current->prevBrowse() = lastlocal->_charOffset;
        } else {
            lastlocal->nextBrowse() = ~0;
            current->prevBrowse() = ~0;
        }
        } else {
        current->prevBrowse() = ~0;
        }
        lastlocal = current;
    }

    current = current->_next;
    }
    if( lastlocal != NULL ){
    lastlocal->nextBrowse() = ~0;
    }
    if( lastglobal != NULL ){
    lastglobal->nextBrowse() = ~0;
    }
}


//  HFTopic::newNode    --Start a new current node.  Also dump the old one,
//            update the linked list, check the compression, ...

void HFTopic::newNode( int is_new_topic )
{
    int     forget_node = 0;
    int     i;
    int     j,k,zero_pos;
    FontFlags   the_flag;

    if( _curNode->_recordType == TOP_TEXT &&
        _curPar->_numAttribs == _curText->_size ){
    for( i=0; i<_curPar->_numAttribs; i++ ){
        the_flag = _curPar->_attribs[i]._type;
        if( the_flag == TOP_NEW_LINE ||
            the_flag == TOP_NEW_PAR  ||
        the_flag == TOP_HTAB ){
        break;
        }
    }
    if( i == _curPar->_numAttribs ){
        forget_node = 1;
    }
    }

    if( forget_node ){
    delete _curNode;
    } else {
    // Clean up the current text block and record its size.
    if( _curNode->_recordType != TOP_HEADER ){
        // See if any successive font changes can be combined into
        // a single change.
        for( i=0; i<_curText->_numZeroes-1; i++ ){
        if( _curPar->_attribs[i]._type != TOP_FONT_CHANGE ){
            continue;
        }
        zero_pos = _curText->_zeroes[i];
        j = i+1;
        while( j < _curText->_numZeroes &&
               _curPar->_attribs[j]._type == TOP_FONT_CHANGE &&
               _curText->_zeroes[j]-zero_pos == j-i ){
            j++;
        }
        if( j > i+1 ){
            memmove( &_curPar->_attribs[i], &_curPar->_attribs[j-1],
                     (_curPar->_numAttribs-j+1)*sizeof(TextAttr) );
            _curPar->_numAttribs -= (j-1-i);
            _curPar->_size -= (j-1-i)*3;
            memmove( _curText->_text+_curText->_zeroes[i]+1,
                     _curText->_text+_curText->_zeroes[j-1]+1,
                 _curText->_size-_curText->_zeroes[j-1]-1 );
            _curText->_size -= j-1-i;
            _curText->_uncompSize -= j-1-i;
            _curText->_numZeroes -= j-1-i;
            for( k=i; k<_curText->_numZeroes; k++ ){
            _curText->_zeroes[k] = (uint_16) (_curText->_zeroes[k+j-1-i]-j+1+i);
            }
        }
        }
        addAttr( TOP_END );
        _curPar->_size += _curPar->_parAttrSize;
        _curPar->_textSize = (uint_16) _curText->_size;
        _curPar->_headerSize = (uint_16) (_curPar->_size-3);
        if( _curPar->_textSize >= INT_SMALL_LIMIT ){
        _curPar->_size += 1;
        }
    }
    _curNode->_dataSize = _curText->_uncompSize;

    // Create memory for the current node.
    TopicLink   *first, *second, *third;

    first = new TopicLink( _curNode->_size );
    _curNode->_myLink = first;
    if( _curNode->_recordType == TOP_HEADER ){
        second = new TopicLink( _curTopic->_size );
        _curTopic->_myLink = second;
    } else {
        second = new TopicLink( _curPar->_size );
        _curPar->dumpTo( second );
    }
    third = new TopicLink( _curText->_size );
    _curText->dumpTo( third );

    // Update a few more size and linked list variables.
    _curNode->_topicSize = first->_size + second->_size + third->_size;
    _curNode->_dataOffset = first->_size + second->_size;
    _curTopic->_totalSize += first->_size + second->_size + third->_size;

    // See if the current page can hold this node.
    if( _useCompress ){
        if( _curNode->_recordType == TOP_HEADER ){
        _size += _myReader->skip( first->_size + second->_size );
        } else {
        _size += _myReader->skip( first->_size );
        _size += _myReader->compress( second->_myData, second->_size );
        }
        _size += _myReader->compress( third->_myData, third->_size );
    } else {
        _size += first->_size + second->_size + third->_size;
    }

    // Create a new page, if necessary.
    if( _size>= _numPages * COMP_PAGE_SIZE ){
        _ptail->_next = new PageHeader;
        _ptail->_next->nextNode() = _ptail->nextNode() + (COMP_PAGE_SIZE<<2);
        _ptail = _ptail->_next;
        _ptail->lastNode() = _lastLink;
        _ptail->lastTopic() = _lastTopic;
        if( _curTopic->_startNonScroll == _curOffset ){
        _curTopic->_startNonScroll = _ptail->nextNode();
        }
        if( _curTopic->_startScroll == _curOffset ){
        _curTopic->_startScroll = _ptail->nextNode();
        }
        _curOffset = _ptail->nextNode();
        if( _browseOffset == _curCharOffset ){
        _browseOffset = ( _curOffset & ~((COMP_PAGE_SIZE<<2)-1) ) << 1;
        }
        _curCharOffset = ( _curOffset & ~((COMP_PAGE_SIZE<<2)-1) ) << 1;
        _size = (_numPages++) * COMP_PAGE_SIZE + PAGE_HEADER_SIZE;
        if( _useCompress ){
        _myReader->flush();
        if( _curNode->_recordType == TOP_HEADER ){
            _size += _myReader->skip( first->_size + second->_size );
        } else {
            _size += _myReader->skip( first->_size );
            _size += _myReader->compress( second->_myData, second->_size );
        }
        _size += _myReader->compress( third->_myData, third->_size );
        } else {
        _size += first->_size + second->_size + third->_size;
        }
        first->_isFirstLink = 1;
    }

    // Update linked list pointers in old nodes we've been saving,
    // and dump them at last.

    _lastLink = _curOffset;
    if( _lastNode != NULL ){
        _lastNode->_nextNode = _curOffset;
        _lastNode->dumpTo( _lastNode->_myLink );
        delete _lastNode;
    }
    _lastNode = _curNode;
    if( _curNode->_recordType == TOP_HEADER ){
        _lastTopic = _curOffset;
        if( _lastHeader != NULL ){
        _lastHeader->_nextTopic = _curOffset;
        _lastHeader->dumpTo( _lastHeader->_myLink );
        delete _lastHeader;
        }
        _lastHeader = _curTopic;
    }

    // Increment the 'current location' counters.
    _curOffset += first->_size + second->_size + third->_size;
    if( _curNode->_recordType != TOP_HEADER ){
        _curCharOffset += third->_size;
    }

    // Add the new data blocks to the linked list of such blocks.
    if( _tail != NULL ){
        _tail->_next = first;
    } else {
        _head = first;
    }
    first->_next = second;
    second->_next = third;
    third->_next = NULL;
    _tail = third;
    }

    // Create the new current node.
    _curNode = new GenericNode( _lastLink );
    if( is_new_topic ){
    if( _lastHeader != NULL && _browseStr != NULL ){
        recordBrowse( _lastHeader->_myLink );
        _browseStr = NULL;
    }
    _curTopic = new TopicHeader( _numTopics++ );
    _curNode->_recordType = TOP_HEADER;
    } else {
    _curPar->reset();
    _curNode->_recordType = TOP_TEXT;
    }
    _curText->reset();
}


//  HFTopic::addText    --Adds text (assumed to be zero-terminated)
//            to the |TOPIC file.

void HFTopic::addText( char const source[], int use_phr )
{
    int length;
    if( source[0] == '\0' ){
    length = 1;
    } else {
    length = strlen( source );
    }
    if( length + _curText->_size > _curText->_maxSize ){
    _curText->_maxSize = (length + _curText->_size) / TEXT_BLOCK_SIZE + 1;
    _curText->_maxSize *= TEXT_BLOCK_SIZE;
    _curText->_text.resize( _curText->_maxSize );
    }

    _curText->_uncompSize += length;

    // Use phrase replacement, if appropriate.
    if( use_phr && _useCompress ){
    _phFile->replace( _curText->_text+_curText->_size, source, length );
    } else {
    memcpy( _curText->_text + _curText->_size, source, length );
    }

    if( length + _curText->_size > COMP_PAGE_SIZE ){
    HCError( TOP_TOOLARGE );
    }
    _curText->_size += length;
}


//  HFTopic::addZero    --Add a 0x00 byte (to signal a format change) to
//            the current text buffer.

void HFTopic::addZero( int index )
{
    int zero_pos;
    if( _curText->_size == COMP_PAGE_SIZE ){
    HCError( TOP_TOOLARGE );
    }
    if( _curText->_numZeroes == _curText->_maxZeroes ){
    _curText->_maxZeroes += TEXT_ZERO_SIZE;
    _curText->_zeroes.resize( _curText->_maxZeroes );
    }
    if( _curText->_size == _curText->_maxSize ){
    _curText->_maxSize += TEXT_BLOCK_SIZE;
    _curText->_text.resize( _curText->_maxSize );
    }
    if( index < _curText->_numZeroes ){
    zero_pos = _curText->_zeroes[index] + 1;
    char    *position = _curText->_text + zero_pos;
    memmove( position+1, position, _curText->_size - zero_pos );
    memmove( _curText->_zeroes+index+2, _curText->_zeroes+index+1,
             (_curText->_numZeroes-index-1)*2 );
    _curText->_zeroes[index+1] = (uint_16) zero_pos;
    } else {
    zero_pos = _curText->_size;
    _curText->_zeroes[_curText->_numZeroes] = (uint_16) zero_pos;
    }
    _curText->_text[ zero_pos ] = '\0';
    _curText->_size += 1;
    _curText->_uncompSize += 1;
    _curText->_numZeroes += 1;
}


//  HFTopic::presentSize    --Access function.

uint_32 HFTopic::presentSize()
{
    uint_32 result = _curNode->_size + _curText->_size;
    if( _curNode->_recordType == TOP_HEADER ){
    result += _curTopic->_size;
    } else {
    result += _curPar->_size + _curPar->_parAttrSize;
    }
    return result;
}


//  What follows are several HFTopic member functions used as front
//  ends to the corresponding TextHeader member functions.

int HFTopic::addAttr( FontFlags type, uint_32 val )
{
    if( _curNode->_recordType == TOP_HEADER ){
    HCError( HLP_ATTR );
    }

    // This had better not be a variable length attribute.
    switch( type ){
    case TOP_MACRO_LINK:
    case TOP_MACRO_INVIS:
    case TOP_POPUP_FILE:
    case TOP_JUMP_FILE:
    case TOP_POPUP_FILE_INVIS:
    case TOP_JUMP_FILE_INVIS:
    HCError( HLP_ATTR );
    }
    addZero( _curPar->_numAttribs );
    return _curPar->addAttr( type, val, NULL, 0 );
}

int HFTopic::addAttr( FontFlags type, char const str[], uint_16 len )
{
    if( _curNode->_recordType == TOP_HEADER ){
    HCError( HLP_ATTR );
    }

    switch( type ){
    case TOP_MACRO_LINK:
    case TOP_MACRO_INVIS:
    break;

    default:
    HCError( HLP_ATTR );
    }

    addZero( _curPar->_numAttribs );
    return _curPar->addAttr( type, 0, str, len );
}

int HFTopic::addAttr( FontFlags type, char const str[], uint_16 len, uint_32 val )
{
    if( _curNode->_recordType == TOP_HEADER ){
    HCError( HLP_ATTR );
    }

    switch( type ){
    case TOP_JUMP_FILE:
    case TOP_POPUP_FILE:
    case TOP_JUMP_FILE_INVIS:
    case TOP_POPUP_FILE_INVIS:
    break;

    default:
    HCError( HLP_ATTR );
    }

    addZero( _curPar->_numAttribs );
    return _curPar->addAttr( type, val, str, len );
}

int HFTopic::appendAttr( int index, FontFlags type, uint_32 val )
{
    if( _curNode->_recordType == TOP_HEADER ){
    HCError( HLP_ATTR );
    }

    // This had better not be a variable length attribute.
    switch( type ){
    case TOP_POPUP_LINK:
    case TOP_JUMP_LINK:
    case TOP_POPUP_INVIS:
    case TOP_JUMP_INVIS:
    break;

    default:
    HCError( HLP_ATTR );
    }

    int result = _curPar->appendAttr( index, type, val, NULL, 0 );
    addZero( index );
    return result;
}

int HFTopic::appendAttr( int index, FontFlags type, char const str[], uint_16 len )
{
    if( _curNode->_recordType == TOP_HEADER ){
    HCError( HLP_ATTR );
    }

    switch( type ){
    case TOP_MACRO_LINK:
    case TOP_MACRO_INVIS:
    break;

    default:
    HCError( HLP_ATTR );
    }

    int result = _curPar->appendAttr( index, type, 0, str, len );
    addZero( index );
    return result;
}

int HFTopic::appendAttr( int index, FontFlags type, char const str[], uint_16 len,
                       uint_32 val )
{
    if( _curNode->_recordType == TOP_HEADER ){
    HCError( HLP_ATTR );
    }

    switch( type ){
    case TOP_JUMP_FILE:
    case TOP_POPUP_FILE:
    case TOP_JUMP_FILE_INVIS:
    case TOP_POPUP_FILE_INVIS:
    break;

    default:
    HCError( HLP_ATTR );
    }

    int result = _curPar->appendAttr( index, type, val, str, len );
    addZero( index );
    return result;
}

void HFTopic::chgAttr( int index, FontFlags type, uint_32 val )
{
    if( _curNode->_recordType == TOP_HEADER ){
    HCError( HLP_ATTR );
    }

    // This had better not be a variable length attribute.
    switch( type ){
    case TOP_MACRO_LINK:
    case TOP_MACRO_INVIS:
    case TOP_POPUP_FILE:
    case TOP_JUMP_FILE:
    case TOP_POPUP_FILE_INVIS:
    case TOP_JUMP_FILE_INVIS:
    HCError( HLP_ATTR );
    }

    _curPar->chgAttr( index, type, val, NULL, 0 );
}

void HFTopic::chgAttr( int index, FontFlags type, char const str[], uint_16 len )
{
    if( _curNode->_recordType == TOP_HEADER ){
    HCError( HLP_ATTR );
    }

    switch( type ){
    case TOP_MACRO_LINK:
    case TOP_MACRO_INVIS:
    break;

    default:
    HCError( HLP_ATTR );
    }

    _curPar->chgAttr( index, type, 0, str, len );
}

void HFTopic::chgAttr( int index, FontFlags type, char const str[], uint_16 len,
                        uint_32 val )
{
    if( _curNode->_recordType == TOP_HEADER ){
    HCError( HLP_ATTR );
    }

    switch( type ){
    case TOP_POPUP_FILE:
    case TOP_JUMP_FILE:
    case TOP_POPUP_FILE_INVIS:
    case TOP_JUMP_FILE_INVIS:
    break;

    default:
    HCError( HLP_ATTR );
    }

    _curPar->chgAttr( index, type, val, str, len );
}

uint_32 HFTopic::attrData( int index )
{
    if( _curNode->_recordType == TOP_HEADER ){
    HCError( HLP_ATTR );
    }

    return _curPar->attrData( index );
}

int HFTopic::setTab( int val, TabTypes flag )
{
    return _curPar->setTab( val, (uint_8) flag );
}

int HFTopic::setPar( ParFlags type, int val )
{
    return _curPar->setPar( type, val );
}

void HFTopic::unsetPar( ParFlags type )
{
    _curPar->unsetPar( type );
}

void HFTopic::clearPar()
{
    _curPar->clearPar();
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?