topic.cpp
来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 1,642 行 · 第 1/3 页
CPP
1,642 行
/****************************************************************************
*
* Open Watcom Project
*
* Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
* ========================================================================
*
* This file contains Original Code and/or Modifications of Original
* Code as defined in and that are subject to the Sybase Open Watcom
* Public License version 1.0 (the 'License'). You may not use this file
* except in compliance with the License. BY USING THIS FILE YOU AGREE TO
* ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
* provided with the Original Code and Modifications, and is also
* available at www.sybase.com/developer/opensource.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
* ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
* NON-INFRINGEMENT. Please see the License for the specific language
* governing rights and limitations under the License.
*
* ========================================================================
*
* Description: Write help text in .hlp format.
*
****************************************************************************/
#include <string.h>
#include "topic.h"
#define COMP_PAGE_SIZE 4096
//
// TextAttr --Structure to record changes to text.
//
struct TextAttr
{
FontFlags _type;
uint_32 _data;
int _size;
char *_stringDat;
};
//
// TopicLink --Linked list record to store binary topic data
// once it's generated.
//
struct TopicLink
{
TopicLink *_next;
uint_32 _size;
int _isFirstLink;
Buffer<char> _myData;
TopicLink( uint_32 s );
};
//
// StringNode --A linked list record to keep track of browse sequences.
//
struct StringNode
{
char *_string;
TopicLink *_me;
uint_32 _charOffset;
StringNode *_next, *_prev;
// Handy access functions used by HFTopic::dumpBrowse().
uint_32 & prevBrowse() { return *((uint_32*) (_me->_myData+4)); };
uint_32 & nextBrowse() { return *((uint_32*) (_me->_myData+8)); };
};
//
// PageHeader --Structure to store paging-related information.
//
#define PAGE_HEADER_SIZE 12
struct PageHeader
{
PageHeader *_next;
uint_32 _pageNums[3];
// Some mnemonic access functions for accessing _pageNums.
uint_32 & lastNode() { return *_pageNums; };
uint_32 & nextNode() { return *(_pageNums+1); };
uint_32 & lastTopic() { return *(_pageNums+2); };
PageHeader();
};
// NOTE: every node in the |TOPIC linked list consistes of three parts:
// a node header, a type-specific header, and the text. There are three
// different type-specific headers, two of which are implemented here.
//
// GenericNode --Class to represent the 'node header'.
//
#define GENERIC_NODE_SIZE 21
class GenericNode
{
uint_32 _topicSize;
uint_32 _dataSize;
uint_32 _prevNode;
uint_32 _nextNode;
uint_32 _dataOffset;
uint_8 _recordType;
uint_32 _size;
TopicLink *_myLink;
GenericNode( uint_32 prev );
void dumpTo( TopicLink *dest );
friend class HFTopic;
};
//
// TopicHeader --Class to store topic headers, one kind of
// type-specific header.
//
#define TOPIC_HEADER_SIZE 28
class TopicHeader
{
uint_32 _totalSize;
uint_32 _nextBrowse;
uint_32 _prevBrowse;
uint_32 _topicNum;
uint_32 _startNonScroll;
uint_32 _startScroll;
uint_32 _nextTopic;
uint_32 _size;
TopicLink *_myLink;
TopicHeader( uint_32 tnum );
void dumpTo( TopicLink *dest );
friend class HFTopic;
};
#define TEXT_ARG_MAX 10
#define TEXT_ATTR_MAX 25
//
// TextHeader --Class to store text headers, one type of
// type-specific header.
//
#define TEXT_HEADER_SIZE 9
class TextHeader
{
uint_32 _size;
uint_32 _parAttrSize;
uint_16 _headerSize;
uint_16 _textSize;
uint_8 _numColumns;
uint_32 _flags;
Buffer<uint_16> _tabStops;
Buffer<uint_8> _tabFlags;
uint_16 _numStops, _maxStops;
uint_32 _border;
uint_16 _spacing[6];
static const uint_32 _parBits[];
Buffer<TextAttr> _attribs;
int _numAttribs;
int _maxAttribs;
static const uint_8 _attrBits[];
static const int _attrSizes[];
TextHeader();
~TextHeader();
// Functions to manipulate paragraph attributes (tabs, indents, ...)
void dumpTo( TopicLink *dest );
int setTab( int val, uint_8 flags );
int setPar( ParFlags type, int val );
void unsetPar( ParFlags type );
void clearPar();
int addAttr( FontFlags type, uint_32 val, char const str[], int length );
int appendAttr( int index, FontFlags type, uint_32 val,
char const str[], int length );
void chgAttr( int index, FontFlags type, uint_32 val,
char const str[], int length );
uint_32 attrData( int index );
void reset();
friend class HFTopic;
};
//
// TextHolder --Class to store raw text, for topic titles and help text.
//
#define TEXT_BLOCK_SIZE 0x200
#define TEXT_ZERO_SIZE 10
class TextHolder
{
uint_32 _size;
uint_32 _uncompSize;
uint_32 _maxSize;
Buffer<char> _text;
// Formatting changes are signalled by 0x00 bytes in the text;
// I must be able to insert those zeroes in the middle of the text.
Buffer<uint_16> _zeroes;
uint_16 _numZeroes;
uint_16 _maxZeroes;
TextHolder();
void dumpTo( TopicLink *dest );
void reset() { _size = 0; _uncompSize = 0; _numZeroes = 0; };
friend class HFTopic;
};
// TopicLink::TopicLink
TopicLink::TopicLink( uint_32 s ) : _size( s ), _myData( s ), _isFirstLink(0)
{
// empty
}
// GenericNode::GenericNode
GenericNode::GenericNode( uint_32 prev )
: _prevNode( prev ),
_topicSize( GENERIC_NODE_SIZE ),
_size( GENERIC_NODE_SIZE ),
_dataSize( 0 ),
_nextNode( ~0 )
{
// empty
}
// GenericNode::DumpTo --Convert the node to it's binary form.
void GenericNode::dumpTo( TopicLink *dest )
{
memcpy( dest->_myData, this, GENERIC_NODE_SIZE ); // EXTREME unsafeness!
dest->_size = _size;
}
// TopicHeader::TopicHeader
TopicHeader::TopicHeader( uint_32 tnum )
: _topicNum( tnum ),
_size( TOPIC_HEADER_SIZE ),
_totalSize( 0 ),
_nextTopic( ~0 ),
_nextBrowse( ~0 ),
_prevBrowse( ~0 ),
_startNonScroll( ~0 ),
_startScroll( ~0 )
{
// empty
}
// TopicHeader::DumpTo --Convert the node to it's binary form.
void TopicHeader::dumpTo( TopicLink *dest )
{
memcpy( dest->_myData, this, TOPIC_HEADER_SIZE ); // EXTREME unsafeness!
dest->_size = _size;
}
// PageHeader::PageHeader
PageHeader::PageHeader()
: _next(NULL)
{
// empty
}
// TextHeader c-tor and d-tor.
#define TSTOP_BLOCKS 10
TextHeader::TextHeader()
: _tabStops( TSTOP_BLOCKS ),
_tabFlags( TSTOP_BLOCKS ),
_attribs( TEXT_ATTR_MAX ),
_size( TEXT_HEADER_SIZE ),
_parAttrSize( 0 ),
_flags( 0 ),
_numStops( 0 ),
_maxStops( TSTOP_BLOCKS ),
_numAttribs( 0 ),
_maxAttribs( TEXT_ATTR_MAX )
{
// empty
}
TextHeader::~TextHeader()
{
reset();
}
// TextHeader::reset --Clear the text attributes.
void TextHeader::reset()
{
for( int i=0; i<_numAttribs; i++ ){
if( _attribs[i]._stringDat != NULL ){
delete[] _attribs[i]._stringDat;
}
}
_size = TEXT_HEADER_SIZE;
_numColumns = 0;
_numAttribs = 0;
}
// The bitfields corresponding to paragraph attributes.
const uint_32 TextHeader::_parBits[] = {
0x00020000,
0x00040000,
0x00080000,
0x00100000,
0x00200000,
0x00400000,
0x01000000,
0x02000000,
0x04000000,
0x08000000,
0x10000000
};
// TextHeader::setTab --Set a (possibly non-standard) tab stop.
#define INT_SMALL_LIMIT 0x80
#define INT_LARGE_LIMIT 0x4000
#define BORDER_BYTE_SIZE 3
int TextHeader::setTab( int val, uint_8 flag )
{
uint_16 trueval;
if( val < 0 ){
return 0;
} else if( val >= INT_LARGE_LIMIT ){
return 0;
}
// Convert the value into WinHelp's bizarre format for
// storing integers; see "topic.doc".
trueval = (uint_16) (val/10);
trueval <<= 1;
if( trueval < INT_SMALL_LIMIT ){
_parAttrSize += 1;
} else {
trueval |= 0x1;
_parAttrSize += 2;
}
if( flag != 0x0 ){
_parAttrSize += 1;
if( trueval < INT_SMALL_LIMIT ){
trueval |= 0x80;
} else {
trueval |= 0x8000;
}
}
if( _numStops == 0 ){
_parAttrSize += 1;
} else if( _numStops == _maxStops ){
_maxStops += TSTOP_BLOCKS;
_tabStops.resize( _maxStops );
_tabFlags.resize( _maxStops );
}
_tabStops[_numStops] = trueval;
_tabFlags[_numStops] = flag;
if( ++_numStops == 0x40 ){
_parAttrSize += 1;
}
_flags |= _parBits[TOP_TAB_STOPS];
return 1;
}
// TextHeader::setPar --Set a paragraph attribute.
int TextHeader::setPar( ParFlags type, int val )
{
int already_set = _flags & _parBits[type];
int sign;
uint_16 trueval;
if( val < 0 && type == TOP_TAB_STOPS ){
return 0;
}
if( type == TOP_BORDER ){
_border = (uint_32) val;
_parAttrSize += BORDER_BYTE_SIZE;
} else {
// Convert the value into binary form.
// This is complicated by WinHelp's bizarre format for
// storing integers; see "topic.doc".
if( type < TOP_RIGHT_JUST ){
if( val == -1 ) return 1;
sign = val < 0;
if( sign ){
val = -val;
}
if( val >= INT_LARGE_LIMIT ) {
return 0;
}
trueval = (uint_16) (val/10);
trueval <<= 1;
}
if( type == TOP_TAB_STOPS ){
if( trueval < INT_SMALL_LIMIT ){
_parAttrSize += 1;
} else {
trueval |= 0x1;
_parAttrSize += 2;
}
if( _numStops == 0 ){
_parAttrSize += 1;
} else if( _numStops == _maxStops ){
_maxStops += TSTOP_BLOCKS;
_tabStops.resize( _maxStops );
_tabFlags.resize( _maxStops );
}
_tabStops[ _numStops ] = trueval;
_tabFlags[ _numStops ] = 0x0;
if( ++_numStops == 0x40 ){
_parAttrSize += 1;
}
} else if( type < TOP_TAB_STOPS ){
if( already_set ){
if( _spacing[ type ] & 0x1 ){
_parAttrSize -= 2;
} else {
_parAttrSize -= 1;
}
}
if( trueval < INT_SMALL_LIMIT ){
trueval |= 0x80;
_parAttrSize += 1;
} else {
trueval |= 0x8001;
_parAttrSize += 2;
}
if( sign ){
if( trueval & 01 ){
trueval ^= (uint_16) ~1;
} else {
trueval ^= (uint_8) ~1;
}
trueval += 4;
}
_spacing[ type ] = trueval;
}
}
_flags |= _parBits[type];
return 1;
}
// TextHeader::unsetPar --Clear a paragraph attribute.
void TextHeader::unsetPar( ParFlags type )
{
int already_set = _flags & _parBits[type];
if( !already_set ) return;
_flags ^= _parBits[type];
if( type == TOP_TAB_STOPS ){
_parAttrSize -= _numStops;
for( int i=0; i < _numStops; ++i ){
if( _tabStops[i] & 0x1 ){
_parAttrSize -= 1;
}
if( _tabFlags[i] != 0 ){
_parAttrSize -= 1;
}
}
if( _numStops >= 0x40 ){
_parAttrSize -= 2;
} else if( _numStops > 0 ){
_parAttrSize -= 1;
}
_numStops = 0;
} else if( type == TOP_BORDER ){
_parAttrSize -= BORDER_BYTE_SIZE;
} else if( type < TOP_TAB_STOPS ){
if( _spacing[type] & 0x1 ){
_parAttrSize -= 2;
} else {
_parAttrSize -= 1;
}
}
}
// TextHeader::clearPar --Clear all paragraph attributes.
void TextHeader::clearPar()
{
_flags = 0;
_parAttrSize = 0;
_numStops = 0;
}
// The flag values corresponding to text attributes.
const uint_8 TextHeader::_attrBits[] = {
0x80, 0x81, 0x82, 0x83, 0x86, 0x87, 0x88, 0x89, 0xC8, 0xCC,
0xE2, 0xE3, 0xE6, 0xE7, 0xEA, 0xEB, 0xEE, 0xEF, 0xFF
};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?