www.pudn.com > SmartFDISK.zip > helpbase.cc


#define HELPEXTENSIONS 
/*------------------------------------------------------------*/ 
/* filename -       HelpBase.cpp                              */ 
/*                                                            */ 
/* function(s)                                                */ 
/*                  Member function(s) of following classes   */ 
/*                      THelpTopic                            */ 
/*                      THelpIndex                            */ 
/*                      THelpFile                             */ 
/*------------------------------------------------------------*/ 
 
/*------------------------------------------------------------*/ 
/*                                                            */ 
/*    Turbo Vision -  Version 1.0                             */ 
/*                                                            */ 
/*                                                            */ 
/*    Copyright (c) 1991 by Borland International             */ 
/*    All Rights Reserved.                                    */ 
/*                                                            */ 
/*------------------------------------------------------------*/ 
 
#define Uses_TStreamableClass 
#define Uses_TPoint 
#define Uses_TStreamable 
#define Uses_ipstream 
#define Uses_opstream 
#define Uses_fpstream 
#define Uses_TRect 
#define Uses_TObject 
#include  
 
#if !defined( __HELP_H ) 
#include "HelpBase.h" 
#endif  // __HELP_H 
 
#if !defined( __UTIL_H ) 
#include "Util.h" 
#endif  // __UTIL_H 
 
#if !defined( __STRING_H ) 
#include  
#endif  // __STRING_H 
 
#if !defined( __LIMITS_H ) 
#include  
#endif  // __LIMITS_H 
 
#if !defined( __STAT_H ) 
#include  
#endif  // __STAT_H 
 
#if !defined( __CTYPE_H ) 
#include  
#endif  // __CTYPE_H 
 
#if !defined( __IO_H ) 
#include  
#endif  // __IO_H 
 
#ifdef HELPEXTENSIONS 
    int THelpFile::oldFront; 
    int THelpFile::oldCount; 
    unsigned int THelpFile::oldTopics[THelpFile::maxOldTopics]; 
#endif 
 
 
TCrossRefHandler crossRefHandler = notAssigned; 
 
// THelpTopic 
const char * const near THelpTopic::name = "THelpTopic"; 
 
void THelpTopic::write( opstream& os ) 
{ 
    writeParagraphs( os ); 
    writeCrossRefs( os ); 
     
} 
 
void *THelpTopic::read( ipstream& is ) 
{ 
    readParagraphs( is ); 
    readCrossRefs( is ); 
    width = 0; 
    lastLine = INT_MAX;  
    return this; 
} 
 
TStreamable *THelpTopic::build() 
{ 
    return new THelpTopic( streamableInit ); 
} 
 
 
TStreamableClass RHelpTopic( THelpTopic::name, 
                                  THelpTopic::build, 
                                  __DELTA(THelpTopic) 
                                ); 
 
THelpTopic::THelpTopic() : TObject() 
{ 
    paragraphs = 0; 
    numRefs = 0; 
    crossRefs = 0; 
    width = 0; 
    lastOffset = 0; 
    lastLine = INT_MAX; 
    lastParagraph = 0; 
}; 
 
void THelpTopic::readParagraphs( ipstream& s ) 
{ 
    int  i; 
    unsigned int size; 
    TParagraph **pp; 
    int temp; 
 
    s >> i; 
    pp = ¶graphs; 
    while ( i > 0) 
    { 
        s >> size; 
        *pp = new TParagraph; 
        (*pp)->text = new char[size]; 
        (*pp)->size = size; 
    s >> temp; 
        (*pp)->wrap = Boolean(temp); 
        s.readBytes((*pp)->text, (*pp)->size); 
        pp = &((*pp)->next); 
        --i; 
    } 
    *pp = 0; 
} 
 
void THelpTopic::readCrossRefs( ipstream& s ) 
{ 
    int i; 
    TCrossRef *crossRefPtr; 
 
    s >> numRefs; 
    crossRefs = new TCrossRef[numRefs]; 
    for (i = 0; i < numRefs; ++i) 
        { 
        crossRefPtr = (TCrossRef *)crossRefs + i; 
        s >> crossRefPtr->ref >> crossRefPtr->offset >> crossRefPtr->length; 
//        s.readBytes(crossRefPtr, sizeof(TCrossRef)); 
        } 
} 
 
void THelpTopic::disposeParagraphs() 
{ 
    TParagraph *p, *t; 
 
    p = paragraphs; 
    while (p != 0) 
        { 
        t = p; 
        p = p->next; 
        delete t->text;  
        delete t; 
        } 
} 
 
 
THelpTopic::~THelpTopic() 
{ 
    TCrossRef *crossRefPtr; 
 
    disposeParagraphs(); 
    if (crossRefs != 0) 
       { 
       crossRefPtr = (TCrossRef *)crossRefs; 
       delete crossRefPtr; 
       } 
} 
 
void THelpTopic::addCrossRef( TCrossRef ref ) 
{ 
    TCrossRef *p; 
    TCrossRef *crossRefPtr; 
 
    p =  new TCrossRef[numRefs+1]; 
    if (numRefs > 0) 
        { 
        crossRefPtr = crossRefs; 
        memmove(p, crossRefPtr, numRefs * sizeof(TCrossRef)); 
        delete crossRefPtr; 
        } 
    crossRefs = p; 
    crossRefPtr = crossRefs + numRefs; 
    *crossRefPtr = ref; 
    ++numRefs; 
} 
 
 
void THelpTopic::addParagraph( TParagraph *p ) 
{ 
    TParagraph  *pp, *back; 
 
    if (paragraphs == 0) 
        paragraphs = p; 
    else 
        { 
        pp = paragraphs; 
        back = pp; 
        while (pp != 0) 
            { 
            back = pp; 
            pp = pp->next; 
            } 
        back->next = p; 
        } 
    p->next = 0; 
} 
 
void THelpTopic::getCrossRef( int i, TPoint& loc, uchar& length, 
         int& ref ) 
{ 
    int oldOffset, curOffset, offset, paraOffset; 
    TParagraph *p; 
    int line; 
    TCrossRef *crossRefPtr; 
 
    paraOffset = 0; 
    curOffset = 0; 
    oldOffset = 0; 
    line = 0; 
    crossRefPtr = crossRefs + i; 
    offset = crossRefPtr->offset; 
    p = paragraphs; 
    while (paraOffset + curOffset < offset) 
        { 
        oldOffset = paraOffset + curOffset; 
        wrapText(p->text, p->size, curOffset, p->wrap); 
        ++line; 
        if ((uint32)curOffset >= p->size) 
            { 
            paraOffset += p->size; 
            p = p->next; 
            curOffset = 0; 
            } 
        } 
    loc.x = offset - oldOffset - 1; 
    loc.y = line; 
    length = crossRefPtr->length; 
    ref = crossRefPtr->ref; 
} 
 
char *THelpTopic::getLine( int line ) 
{ 
    int offset, i; 
    TParagraph *p; 
    static char buffer[256]; 
 
    if (lastLine < line) 
        { 
        i = line; 
        line -= lastLine; 
        lastLine = i; 
        offset = lastOffset; 
        p = lastParagraph; 
        } 
    else 
        { 
        p = paragraphs; 
        offset = 0; 
        lastLine = line; 
        } 
    buffer[0] = 0; 
    while (p != 0) 
    { 
        while ((uint32)offset < p->size) 
        { 
            --line; 
            strcpy(buffer, wrapText(p->text, p->size, offset, p->wrap)); 
            if (line == 0) 
                { 
                lastOffset = offset; 
                lastParagraph = p; 
                return buffer; 
                } 
        } 
        p = p->next; 
        offset = 0; 
    } 
    buffer[0] = 0; 
    return buffer; 
} 
 
int THelpTopic::getNumCrossRefs() 
{ 
    return numRefs; 
} 
 
int THelpTopic::numLines() 
{ 
    int offset, lines; 
    TParagraph *p; 
 
    offset = 0; 
    lines = 0; 
    p = paragraphs; 
    while (p != 0) 
        { 
        offset = 0;  
        while ((uint32)offset < p->size) 
            { 
            ++lines; 
            wrapText(p->text, p->size, offset, p->wrap); 
            } 
        p = p->next; 
        } 
    return lines; 
} 
 
void THelpTopic::setCrossRef( int i, TCrossRef& ref ) 
{ 
    TCrossRef *crossRefPtr; 
 
    if (i < numRefs) 
        { 
        crossRefPtr = crossRefs + i; 
        *crossRefPtr = ref; 
        } 
}        
 
 
void THelpTopic::setNumCrossRefs( int i ) 
{ 
    TCrossRef  *p, *crossRefPtr; 
 
    if (numRefs == i) 
        return; 
    p = new TCrossRef[i]; 
    if (numRefs > 0) 
        { 
        crossRefPtr = crossRefs; 
        if (i > numRefs) 
            memmove(p, crossRefPtr, numRefs * sizeof(TCrossRef)); 
        else 
            memmove(p, crossRefPtr, i * sizeof(TCrossRef)); 
 
        delete crossRefPtr; 
        } 
    crossRefs = p; 
    numRefs = i; 
} 
 
 
void THelpTopic::setWidth( int aWidth ) 
{ 
    width = aWidth; 
} 
 
void THelpTopic::writeParagraphs( opstream& s ) 
{ 
    int i; 
    TParagraph  *p; 
    int temp; 
 
    p = paragraphs; 
    for (i = 0; p != 0; ++i) 
        p = p->next; 
    s << i; 
    for(p = paragraphs; p != 0; p = p->next) 
        { 
        s << p->size; 
        temp = int(p->wrap); 
        s << temp; 
        s.writeBytes(p->text, p->size); 
        } 
} 
 
 
void THelpTopic::writeCrossRefs( opstream& s ) 
{ 
    int i; 
    TCrossRef *crossRefPtr; 
 
    s << numRefs; 
    if (crossRefHandler == notAssigned) 
        { 
        for(i = 0; i < numRefs; ++i) 
            { 
            crossRefPtr = crossRefs + i; 
            s << crossRefPtr->ref << crossRefPtr->offset << crossRefPtr->length; 
            } 
        } 
    else 
        for (i = 0; i < numRefs; ++i) 
            { 
            crossRefPtr = crossRefs + i; 
            crossRefHandler(s, crossRefPtr->ref); 
            s << crossRefPtr->offset << crossRefPtr->length; 
            } 
} 
 
Boolean isBlank( uchar ch )      // fix Help-4 
{ 
    if (isspace(ch)) 
        return True; 
    else 
        return False; 
} 
 
int scan( char *p, int offset, char c) 
{ 
    char *temp1, *temp2; 
     
    temp1 = p + offset; 
    temp2 = strchr(temp1, c); 
    if (temp2 == 0) 
       return 256; 
    else 
       { 
       if ((int)(temp2 - temp1) <= 256 ) 
         return (int) (temp2 - temp1) + 1; 
       else 
         return 256; 
       } 
} 
 
void textToLine( void *text, int offset, int length, char *line ) 
{ 
    strncpy(line, (char *)text+offset, length); 
    line[length] = 0; 
} 
 
char *THelpTopic::wrapText( char *text, int size, 
          int& offset, Boolean wrap ) 
{ 
    static char line[256]; 
    int i; 
 
    i = scan(text, offset, '\n'); 
    if (i + offset > size ) 
        i = size - offset; 
    if ((i >= width) && (wrap == True)) 
        { 
        i = offset + width; 
        if (i > size) 
            i = size; 
        else 
            { 
            while((i > offset) && !(isBlank(text[i]))) 
                --i; 
/************************************************************************ 
            if (i == offset) 
                i = offset + width; 
            else 
                ++i; 
*************************************************************************/ 
            if (i == offset) 
               { 
                i = offset + width; 
                while ( (i < size) && !isBlank(text[i]) ) 
                  ++i; 
                if ( i < size ) 
                  ++i;                    // Skip blank 
                } 
            else 
                ++i; 
            } 
        if (i == offset) 
        i = offset + width; 
        i -= offset; 
        } 
    textToLine(text, offset, i, line); 
    if (line[strlen(line) - 1] == '\n') 
        line[strlen(line) - 1] = 0; 
    offset += i; 
    return line; 
} 
 
// THelpIndex  
 
const char * const near THelpIndex::name = "THelpIndex"; 
 
void THelpIndex::write( opstream& os ) 
{ 
    long *indexArrayPtr; 
 
    os << size; 
    for (int i = 0; i < (int)size; ++i) 
        { 
        indexArrayPtr = index + i;  
        os << *indexArrayPtr; 
        } 
} 
 
void *THelpIndex::read( ipstream& is ) 
{ 
    long *indexArrayPtr; 
 
    is >> size; 
    if (size == 0) 
        index = 0; 
    else 
        { 
        index =  new long[size]; 
        for(int i = 0; i < (int)size; ++i) 
            { 
            indexArrayPtr = index + i; 
            is >> *indexArrayPtr; 
            } 
        } 
    return this; 
} 
 
TStreamable *THelpIndex::build() 
{ 
    return new THelpIndex( streamableInit ); 
} 
 
TStreamableClass RHelpIndex( THelpIndex::name, 
                                  THelpIndex::build, 
                                  __DELTA(THelpIndex) 
                            ); 
 
THelpIndex::~THelpIndex() 
{ 
    delete index; 
} 
 
 
THelpIndex::THelpIndex(void): TObject () 
{ 
    size = 0; 
    index = 0; 
} 
 
long THelpIndex::position(int i) 
{ 
    long *indexArrayPtr; 
 
    if (i < (int)size) 
        { 
        indexArrayPtr = index + i; 
        return (*indexArrayPtr); 
        } 
    else 
        return -1; 
} 
 
void THelpIndex::add( int i, long val ) 
{ 
    int delta = 10; 
    long *p; 
    int newSize; 
    long *indexArrayPtr; 
 
    if (i >= (int)size) 
        { 
        newSize = (i + delta) / delta * delta; 
        p = new long[newSize]; 
        if (p != 0) 
            { 
            memmove(p, index, size * sizeof(long)); 
            memset(p+size, 0xFF, (newSize - size) * sizeof(long)); 
            } 
        if (size > 0) 
            { 
            delete index; 
            } 
        index = p; 
        size = newSize; 
        } 
    indexArrayPtr = index + i; 
    *indexArrayPtr = val; 
} 
 
// THelpFile 
 
THelpFile::THelpFile( fpstream&  s ) 
{ 
    long magic; 
    int handle; 
    long size; 
 
#ifdef HELPEXTENSIONS 
    helpAlreadyPopped = False; 
#endif 
    magic = 0; 
    s.seekg(0); 
    handle = s.rdbuf()->fd(); 
    size = filelength(handle); 
    if (size > (long)sizeof(magic)) 
        s >> magic; 
    if (magic != magicHeader) 
        { 
	indexPos = 12; 
        s.seekg(indexPos); 
        index =  new THelpIndex; 
        modified = True; 
        } 
    else 
        { 
        s.seekg(8); 
        s >> indexPos; 
        s.seekg(indexPos); 
        s >> index;  
        modified = False; 
        } 
    stream = &s; 
} 
 
THelpFile::~THelpFile(void) 
{ 
    long magic, size; 
    int handle; 
 
    if (modified == True) 
        { 
        stream->seekp(indexPos); 
        *stream << index; 
        stream->seekp(0); 
        magic = magicHeader; 
        handle = stream->rdbuf()->fd(); 
        size = filelength(handle) - 8; 
        *stream << magic; 
        *stream << size; 
        *stream << indexPos; 
        } 
    delete stream; 
    delete index; 
} 
 
THelpTopic *THelpFile::getTopic( int i ) 
{ 
    long pos; 
    THelpTopic *topic; 
 
#ifdef HELPEXTENSIONS 
    if (i == previousTopic)                         // Show previous help 
	if (oldCount == 0) 
	    i = 0;                                  // No previous topics 
	else 
     	    { 
	    if (helpAlreadyPopped) 
	        { 
	        // Skip current (saved) topic 
	        oldFront--; 
	        if (oldFront < 0) 
		    oldFront=maxOldTopics; 
	        oldCount--; 
                } 
 
	    if (helpAlreadyPopped && oldCount == 0) 
	        i = 0;                              // No previous topics 
	    else 
	        i = oldTopics[oldFront];            // Get previous topic 
	    } 
    else 
	// Don't save duplicate entries 
	if (oldCount == 0 || i != (int)oldTopics[oldFront]) 
	{ 
	    // Save new topic in oldTopics stack 
	    oldFront++; 
	    if (oldFront > maxOldTopics) 
	      oldFront = 0; 
	    oldTopics[oldFront] = i; 
	    if (oldCount < maxOldTopics) 
	      oldCount++; 
	} 
 
    helpAlreadyPopped = True; 
#endif 
 
    pos = index->position(i); 
    if (pos > 0 ) 
	{ 
	stream->seekg(pos); 
	*stream >> topic; 
        return topic; 
        } 
    else return(invalidTopic()); 
} 
 
THelpTopic *THelpFile::invalidTopic() 
{ 
    THelpTopic *topic; 
    TParagraph *para; 
    char invalidText[] = "\n No help available in this context."; 
 
    topic =  new THelpTopic; 
    para =  new TParagraph; 
    para->text = newStr(invalidText); 
    para->size = strlen(invalidText); 
    para->wrap = False; 
    para->next = 0; 
    topic->addParagraph(para); 
    return topic; 
} 
 
void THelpFile::recordPositionInIndex( int i ) 
{ 
    index->add(i, indexPos); 
    modified = True; 
} 
 
void THelpFile::putTopic( THelpTopic *topic ) 
{ 
    stream->seekp(indexPos); 
    *stream << topic; 
    indexPos = stream->tellp(); 
    modified = True; 
} 
 
void notAssigned( opstream& , int ) 
{ 
}