home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_122 / 10.ddi / TVSRC.ZIP / HELPBASE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  13.7 KB  |  653 lines

  1. /*------------------------------------------------------------*/
  2. /* filename -       HelpBase.cpp                              */
  3. /*                                                            */
  4. /* function(s)                                                */
  5. /*                  Member function(s) of following classes   */
  6. /*                      THelpTopic                            */
  7. /*                      THelpIndex                            */
  8. /*                      THelpFile                             */
  9. /*------------------------------------------------------------*/
  10.  
  11. /*------------------------------------------------------------*/
  12. /*                                                            */
  13. /*    Turbo Vision -  Version 1.0                             */
  14. /*                                                            */
  15. /*                                                            */
  16. /*    Copyright (c) 1991 by Borland International             */
  17. /*    All Rights Reserved.                                    */
  18. /*                                                            */
  19. /*------------------------------------------------------------*/
  20.  
  21. #define Uses_TStreamableClass
  22. #define Uses_TPoint
  23. #define Uses_TStreamable
  24. #define Uses_ipstream
  25. #define Uses_opstream
  26. #define Uses_fpstream
  27. #define Uses_TRect
  28. #include <tv.h>
  29.  
  30. #if !defined( __HELP_H )
  31. #include "HelpBase.h"
  32. #endif  // __HELP_H
  33.  
  34. #if !defined( __UTIL_H )
  35. #include "Util.h"
  36. #endif  // __UTIL_H
  37.  
  38. #if !defined( __STRING_H )
  39. #include <string.h>
  40. #endif  // __STRING_H
  41.  
  42. #if !defined( __LIMITS_H )
  43. #include <limits.h>
  44. #endif  // __LIMITS_H
  45.  
  46. #if !defined( __STAT_H )
  47. #include <sys\stat.h>
  48. #endif  // __STAT_H
  49.  
  50. #if !defined( __CTYPE_H )
  51. #include <ctype.h>
  52. #endif  // __CTYPE_H
  53.  
  54. #if !defined( __IO_H )
  55. #include <io.h>
  56. #endif  // __IO_H
  57.  
  58. #pragma warn -dsz
  59.  
  60. TCrossRefHandler crossRefHandler = notAssigned;
  61.  
  62. // THelpTopic
  63. const char * const near THelpTopic::name = "THelpTopic";
  64.  
  65. void THelpTopic::write( opstream& os )
  66. {
  67.     writeParagraphs( os );
  68.     writeCrossRefs( os );
  69.     
  70. }
  71.  
  72. void *THelpTopic::read( ipstream& is )
  73. {
  74.     readParagraphs( is );
  75.     readCrossRefs( is );
  76.     width = 0;
  77.     lastLine = INT_MAX; 
  78.     return this;
  79. }
  80.  
  81. TStreamable *THelpTopic::build()
  82. {
  83.     return new THelpTopic( streamableInit );
  84. }
  85.  
  86.  
  87. TStreamableClass RHelpTopic( THelpTopic::name,
  88.                                   THelpTopic::build,
  89.                                   __DELTA(THelpTopic)
  90.                                 );
  91.  
  92. THelpTopic::THelpTopic() : TObject()
  93. {
  94.     paragraphs = 0;
  95.     numRefs = 0;
  96.     crossRefs = 0;
  97.     width = 0;
  98.     lastOffset = 0;
  99.     lastLine = INT_MAX;
  100.     lastParagraph = 0;
  101. };
  102.  
  103. void THelpTopic::readParagraphs( ipstream& s )
  104. {
  105.     int  i, size;
  106.     TParagraph **pp;
  107.     int temp;
  108.  
  109.     s >> i;
  110.     pp = ¶graphs;
  111.     while ( i > 0)
  112.     {
  113.         s >> size;
  114.         *pp = new TParagraph;
  115.         (*pp)->text = new char[size];
  116.         (*pp)->size = (ushort) size;
  117.     s >> temp;
  118.         (*pp)->wrap = Boolean(temp);
  119.         s.readBytes((*pp)->text, (*pp)->size);
  120.         pp = &((*pp)->next);
  121.         --i;
  122.     }
  123.     *pp = 0;
  124. }
  125.  
  126. void THelpTopic::readCrossRefs( ipstream& s )
  127. {
  128.     int i;
  129.     TCrossRef *crossRefPtr;
  130.  
  131.     s >> numRefs;
  132.     crossRefs = new TCrossRef[numRefs];
  133.     for (i = 0; i < numRefs; ++i)
  134.         {
  135.         crossRefPtr = (TCrossRef *)crossRefs + i;
  136.         s.readBytes(crossRefPtr, sizeof(TCrossRef));
  137.         }
  138. }
  139.  
  140. void THelpTopic::disposeParagraphs()
  141. {
  142.     TParagraph *p, *t;
  143.  
  144.     p = paragraphs;
  145.     while (p != 0)
  146.         {
  147.         t = p;
  148.         p = p->next;
  149.         delete t->text; 
  150.         delete t;
  151.         }
  152. }
  153.  
  154.  
  155. THelpTopic::~THelpTopic()
  156. {
  157.     TCrossRef *crossRefPtr;
  158.  
  159.     disposeParagraphs();
  160.     if (crossRefs != 0)
  161.        {
  162.        crossRefPtr = (TCrossRef *)crossRefs;
  163.        delete [numRefs] crossRefPtr;
  164.        }
  165. }
  166.  
  167. void THelpTopic::addCrossRef( TCrossRef ref )
  168. {
  169.     TCrossRef *p;
  170.     TCrossRef *crossRefPtr;
  171.  
  172.     p =  new TCrossRef[numRefs+1];
  173.     if (numRefs > 0)
  174.         {
  175.         crossRefPtr = crossRefs;
  176.         memmove(p, crossRefPtr, numRefs * sizeof(TCrossRef));
  177.         delete [numRefs] crossRefPtr;
  178.         }
  179.     crossRefs = p;
  180.     crossRefPtr = crossRefs + numRefs;
  181.     *crossRefPtr = ref;
  182.     ++numRefs;
  183. }
  184.  
  185.  
  186. void THelpTopic::addParagraph( TParagraph *p )
  187. {
  188.     TParagraph  *pp, *back;
  189.  
  190.     if (paragraphs == 0)
  191.         paragraphs = p;
  192.     else
  193.         {
  194.         pp = paragraphs;
  195.         back = pp;
  196.         while (pp != 0)
  197.             {
  198.             back = pp;
  199.             pp = pp->next;
  200.             }
  201.         back->next = p;
  202.         }
  203.     p->next = 0;
  204. }
  205.  
  206. void THelpTopic::getCrossRef( int i, TPoint& loc, uchar& length,
  207.          int& ref )
  208. {
  209.     int oldOffset, curOffset, offset, paraOffset;
  210.     TParagraph *p;
  211.     int line;
  212.     TCrossRef *crossRefPtr;
  213.  
  214.     paraOffset = 0;
  215.     curOffset = 0;
  216.     oldOffset = 0;
  217.     line = 0;
  218.     crossRefPtr = crossRefs + i;
  219.     offset = crossRefPtr->offset;
  220.     p = paragraphs;
  221.     while (paraOffset + curOffset < offset)
  222.         {
  223.         oldOffset = paraOffset + curOffset;
  224.         wrapText(p->text, p->size, curOffset, p->wrap);
  225.         ++line;
  226.         if (curOffset >= p->size)
  227.             {
  228.             paraOffset += p->size;
  229.             p = p->next;
  230.             curOffset = 0;
  231.             }
  232.         }
  233.     loc.x = offset - oldOffset - 1;
  234.     loc.y = line;
  235.     length = crossRefPtr->length;
  236.     ref = crossRefPtr->ref;
  237. }
  238.  
  239. char *THelpTopic::getLine( int line )
  240. {
  241.     int offset, i;
  242.     TParagraph *p;
  243.     char buffer[256];
  244.  
  245.     if (lastLine < line)
  246.         {
  247.         i = line;
  248.         line -= lastLine;
  249.         lastLine = i;
  250.         offset = lastOffset;
  251.         p = lastParagraph;
  252.         }
  253.     else
  254.         {
  255.         p = paragraphs;
  256.         offset = 0;
  257.         lastLine = line;
  258.         }
  259.     buffer[0] = 0;
  260.     while (p != 0)
  261.     {
  262.         while (offset < p->size)
  263.         {
  264.             --line;
  265.             strcpy(buffer, wrapText(p->text, p->size, offset, p->wrap));
  266.             if (line == 0)
  267.                 {
  268.                 lastOffset = offset;
  269.                 lastParagraph = p;
  270.                 return buffer;
  271.                 }
  272.         }
  273.         p = p->next;
  274.         offset = 0;
  275.     }
  276.     buffer[0] = 0;
  277.     return buffer;
  278. }
  279.  
  280. int THelpTopic::getNumCrossRefs()
  281. {
  282.     return numRefs;
  283. }
  284.  
  285. int THelpTopic::numLines()
  286. {
  287.     int offset, lines;
  288.     TParagraph *p;
  289.  
  290.     offset = 0;
  291.     lines = 0;
  292.     p = paragraphs;
  293.     while (p != 0)
  294.         {
  295.         offset = 0; 
  296.         while (offset < p->size)
  297.             {
  298.             ++lines;
  299.             wrapText(p->text, p->size, offset, p->wrap);
  300.             }
  301.         p = p->next;
  302.         }
  303.     return lines;
  304. }
  305.  
  306. void THelpTopic::setCrossRef( int i, TCrossRef& ref )
  307. {
  308.     TCrossRef *crossRefPtr;
  309.  
  310.     if (i < numRefs)
  311.         {
  312.         crossRefPtr = crossRefs + i;
  313.         *crossRefPtr = ref;
  314.         }
  315. }       
  316.  
  317.  
  318. void THelpTopic::setNumCrossRefs( int i )
  319. {
  320.     TCrossRef  *p, *crossRefPtr;
  321.  
  322.     if (numRefs == i)
  323.         return;
  324.     p = new TCrossRef[i];
  325.     if (numRefs > 0)
  326.         {
  327.         crossRefPtr = crossRefs;
  328.         if (i > numRefs)
  329.             memmove(p, crossRefPtr, numRefs * sizeof(TCrossRef));
  330.         else
  331.             memmove(p, crossRefPtr, i * sizeof(TCrossRef));
  332.  
  333.         delete [numRefs] crossRefPtr; 
  334.         }
  335.     crossRefs = p;
  336.     numRefs = i;
  337. }
  338.  
  339.  
  340. void THelpTopic::setWidth( int aWidth )
  341. {
  342.     width = aWidth;
  343. }
  344.  
  345. void THelpTopic::writeParagraphs( opstream& s )
  346. {
  347.     int i;
  348.     TParagraph  *p;
  349.     int temp;
  350.  
  351.     p = paragraphs;
  352.     for (i = 0; p != 0; ++i)
  353.         p = p->next;
  354.     s << i;
  355.     for(p = paragraphs; p != 0; p = p->next)
  356.         {
  357.         s << p->size;
  358.         temp = int(p->wrap);
  359.         s << temp;
  360.         s.writeBytes(p->text, p->size);
  361.         }
  362. }
  363.  
  364.  
  365. void THelpTopic::writeCrossRefs( opstream& s )
  366. {
  367.     int i;
  368.     TCrossRef *crossRefPtr;
  369.  
  370.     s << numRefs;
  371.     if (crossRefHandler == notAssigned)
  372.         {
  373.         for(i = 0; i < numRefs; ++i)
  374.             {
  375.             crossRefPtr = crossRefs + i;
  376.             s << crossRefPtr->ref << crossRefPtr->offset << crossRefPtr->length;
  377.             }
  378.         }
  379.     else
  380.         for (i = 0; i < numRefs; ++i)
  381.             {
  382.             crossRefPtr = crossRefs + i;
  383.             crossRefHandler(s, crossRefPtr->ref);
  384.             s << crossRefPtr->offset << crossRefPtr->length;
  385.             }
  386. }
  387.  
  388. Boolean isBlank( char ch )
  389. {
  390.     if (isspace(ch))
  391.         return True;
  392.     else
  393.         return False;
  394. }
  395.  
  396. int scan( char *p, int offset, char c)
  397. {
  398.     char *temp1, *temp2;
  399.     
  400.     temp1 = p + offset;
  401.     temp2 = strchr(temp1, c);
  402.     if (temp2 == 0)
  403.        return 256;
  404.     else
  405.        {
  406.        if ((int)(temp2 - temp1) <= 256 )
  407.          return (int) (temp2 - temp1) + 1;
  408.        else
  409.          return 256;
  410.        }
  411. }
  412.  
  413. void textToLine( void *text, int offset, int length, char *line )
  414. {
  415.     strncpy(line, (char *)text+offset, length);
  416.     line[length] = 0;
  417. }
  418.  
  419. char *THelpTopic::wrapText( char *text, int size,
  420.           int& offset, Boolean wrap )
  421. {
  422.     char line[256];
  423.     int i;
  424.  
  425.     i = scan(text, offset, '\n');
  426.     if (i + offset > size )
  427.         i = size - offset;
  428.     if ((i >= width) && (wrap == True))
  429.         {
  430.         i = offset + width;
  431.         if (i > size)
  432.             i = size;
  433.         else
  434.             {
  435.             while((i > offset) && !(isBlank(text[i])))
  436.                 --i;
  437.             if (i == offset)
  438.                 i = offset + width;
  439.             else
  440.                 ++i;
  441.             }
  442.         if (i == offset)
  443.         i = offset + width;
  444.         i -= offset;
  445.         }
  446.     textToLine(text, offset, i, line);
  447.     if (line[strlen(line) - 1] == '\n')
  448.         line[strlen(line) - 1] = 0;
  449.     offset += i;
  450.     return line;
  451. }
  452.  
  453. // THelpIndex 
  454.  
  455. const char * const near THelpIndex::name = "THelpIndex";
  456.  
  457. void THelpIndex::write( opstream& os )
  458. {
  459.     long *indexArrayPtr;
  460.  
  461.     os << size;
  462.     for (int i = 0; i < size; ++i)
  463.         {
  464.         indexArrayPtr = index + i; 
  465.         os << *indexArrayPtr;
  466.         }
  467. }
  468.  
  469. void *THelpIndex::read( ipstream& is )
  470. {
  471.     long *indexArrayPtr;
  472.  
  473.     is >> size;
  474.     if (size == 0)
  475.         index = 0;
  476.     else
  477.         {
  478.         index =  new long[size];
  479.         for(int i = 0; i < size; ++i)
  480.             {
  481.             indexArrayPtr = index + i;
  482.             is >> *indexArrayPtr;
  483.             }
  484.         }
  485.     return this;
  486. }
  487.  
  488. TStreamable *THelpIndex::build()
  489. {
  490.     return new THelpIndex( streamableInit );
  491. }
  492.  
  493. TStreamableClass RHelpIndex( THelpIndex::name,
  494.                                   THelpIndex::build,
  495.                                   __DELTA(THelpIndex)
  496.                             );
  497.  
  498. THelpIndex::~THelpIndex()
  499. {
  500.     delete [size] index;
  501. }
  502.  
  503.  
  504. THelpIndex::THelpIndex(void): TObject ()
  505. {
  506.     size = 0;
  507.     index = 0;
  508. }
  509.  
  510. long THelpIndex::position(int i)
  511. {
  512.     long *indexArrayPtr;
  513.  
  514.     if (i < size)
  515.         {
  516.         indexArrayPtr = index + i;
  517.         return (*indexArrayPtr);
  518.         }
  519.     else
  520.         return -1;
  521. }
  522.  
  523. void THelpIndex::add( int i, long val )
  524. {
  525.     int delta = 10;
  526.     long *p;
  527.     int newSize;
  528.     long *indexArrayPtr;
  529.  
  530.     if (i >= size)
  531.         {
  532.         newSize = (i + delta) / delta * delta;
  533.         p = new long[newSize];
  534.         if (p != 0)
  535.             {
  536.             memmove(p, index, size * sizeof(long));
  537.             memset(p+size, 0xFF, (newSize - size) * sizeof(long));
  538.             }
  539.         if (size > 0)
  540.             {
  541.             delete [size] index;
  542.             }
  543.         index = p;
  544.         size = newSize;
  545.         }
  546.     indexArrayPtr = index + i;
  547.     *indexArrayPtr = val;
  548. }
  549.  
  550. // THelpFile
  551.  
  552. THelpFile::THelpFile( fpstream&  s )
  553. {
  554.     long magic;
  555.     int handle;
  556.     long size;
  557.  
  558.     magic = 0;
  559.     s.seekg(0);
  560.     handle = s.rdbuf()->fd();
  561.     size = filelength(handle);
  562.     if (size > sizeof(magic))
  563.         s >> magic;
  564.     if (magic != magicHeader)
  565.         {
  566.         indexPos = 12;
  567.         s.seekg(indexPos);
  568.         index =  new THelpIndex;
  569.         modified = True;
  570.         }
  571.     else
  572.         {
  573.         s.seekg(8);
  574.         s >> indexPos;
  575.         s.seekg(indexPos);
  576.         s >> index; 
  577.         modified = False;
  578.         }
  579.     stream = &s;
  580. }
  581.  
  582. THelpFile::~THelpFile(void)
  583. {
  584.     long magic, size;
  585.     int handle;
  586.  
  587.     if (modified == True)
  588.         {
  589.         stream->seekp(indexPos);
  590.         *stream << index;
  591.         stream->seekp(0);
  592.         magic = magicHeader;
  593.         handle = stream->rdbuf()->fd();
  594.         size = filelength(handle) - 8;
  595.         *stream << magic;
  596.         *stream << size;
  597.         *stream << indexPos;
  598.         }
  599.     delete stream;
  600.     delete index;
  601. }
  602.  
  603. THelpTopic *THelpFile::getTopic( int i )
  604. {
  605.     long pos;
  606.     THelpTopic *topic;
  607.  
  608.     pos = index->position(i);
  609.     if (pos > 0 )
  610.         {
  611.         stream->seekg(pos);
  612.         *stream >> topic;
  613.         return topic;
  614.         }
  615.     else return(invalidTopic());
  616. }
  617.  
  618. THelpTopic *THelpFile::invalidTopic()
  619. {
  620.     THelpTopic *topic;
  621.     TParagraph *para;
  622.     char invalidText[] = "\n No help available in this context.";
  623.  
  624.     topic =  new THelpTopic;
  625.     para =  new TParagraph;
  626.     para->text = newStr(invalidText);
  627.     para->size = strlen(invalidText);
  628.     para->wrap = False;
  629.     para->next = 0;
  630.     topic->addParagraph(para);
  631.     return topic;
  632. }
  633.  
  634. void THelpFile::recordPositionInIndex( int i )
  635. {
  636.     index->add(i, indexPos);
  637.     modified = True;
  638. }
  639.  
  640. void THelpFile::putTopic( THelpTopic *topic )
  641. {
  642.     stream->seekp(indexPos);
  643.     *stream << topic;
  644.     indexPos = stream->tellp();
  645.     modified = True;
  646. }
  647.  
  648. void notAssigned( opstream& , int )
  649. {
  650. }
  651.  
  652.  
  653.