home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / INTERNET / WWW / LYNX / SOURCE / SRC0_8A.ZIP / DOSLYNX / SRC / TURLVIEW.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-17  |  22.7 KB  |  740 lines

  1. //      Copyright (c) 1994, University of Kansas, All Rights Reserved
  2. //
  3. //      Class:          TURLView
  4. //      Include File:   turlview.h
  5. //      Purpose:        Provide a view for an HTML document.
  6. //      Remarks/Portability/Dependencies/Restrictions:
  7. //              These functions in effect take the place of the original
  8. //              gridtext functions and provide a multiple document interface
  9. //              since each view will have its own rendered copy of the
  10. //              original HTML image.
  11. //              All functions are here in the same file since all will be
  12. //              called at once.  No need to split up to help overlay manager.
  13. //              The collection TNSCp_lines is used to hold the offset of
  14. //              all inserted lines in the collection.
  15. //      Revision History:
  16. //              02-15-94        created
  17. //              02-18-94        Possible cause for heap corruption adjusted,
  18. //                              incorrect pointer addition.
  19. //                              This only corrected rendered output, heap
  20. //                              corruption still occuring.
  21. //              02-18-94        Changed appendCharacter to accept a
  22. //                              character instead of an signed short int.
  23. //                              Changes split_line to reset the line
  24. //                              split value each time it is called.
  25. //                              No more corrupt heaps it seems.
  26. //              02-18-94        Experiencing crashes after a large number
  27. //                              of lines are processed, no apparent reason.
  28. //                              Optimizing the code, it is very slow....
  29. //              02-21-94        Beginning to see increase in speed due to
  30. //                              minimizing the number of function calls made.
  31. //                              Crashes resulting due to large number of
  32. //                              lines seem to be avoided by increasing the
  33. //                              delta argument in the TNSCollection
  34. //                              constructor (see TURLView constructor).
  35. //              02-22-94        Added member to class, B_avoidinfinite, to
  36. //                              avoid infinite loops in the Double font and
  37. //                              appendCharacter.
  38. //        02-25-94    Modified to work with no HText styles,
  39. //                anchors, or paragraphs in memory.
  40. //                Always assuming that a style is active for
  41. //                speed.
  42. #define Uses_TProgram
  43. #define Uses_TKeys
  44. #include"turlview.h"
  45. #include"tcapture.h"
  46. #include"trace.h"
  47. #include "tform.h"
  48. #include<string.h>
  49.  
  50. extern "C"      {
  51. #include"htfont.h"
  52. };
  53.  
  54. void TURLView::FormatHTML()     {
  55. //      Purpose:        Format the HTML image file produced in gridtext.cpp
  56. //                      into a rendered document fit for display in a view.
  57. //      Arguments:      void
  58. //      Return Value:   void
  59. //      Remarks/Portability/Dependencies/Restrictions:
  60. //              Using indexOf on the HText paragraph collection is fatal
  61. //              for some reason.  Using the member of TextAttribute to find
  62. //              the index.
  63. //      Revision History:
  64. //              02-15-94        created
  65. //        02-25-94    modified so will not read HText image file
  66. //                with anchors, sytles, paragraphs in memory.
  67. //        04-06-94    Modified to compensate for WWW not calling
  68. //                HText_endAppend.
  69. #ifndef RELEASE
  70.     trace("Entering FormatHTML.");
  71. #endif // RELEASE
  72.     //    In certain cases, the WWW library does not call
  73.     //    HText_endAppend.  Do this for them.  We can tell if the image
  74.     //    file still exists.
  75.     if(HTp_HyperDoc->fsp_image != NULL)    {
  76. #ifndef RELEASE
  77.         trace("WWW did not call HText_endAppend.  Doing so now.");
  78. #endif // RELEASE
  79.         ::HText_endAppend(HTp_HyperDoc);
  80.     }
  81.  
  82.     //      Open the HTML image file for reading.
  83.     fsp_image = new fstream(HTp_HyperDoc->TTNp_fspname->
  84.         getName(), ios::in | ios::nocreate | ios::binary);
  85.     if(fsp_image == NULL)   {
  86.         doslynxmessage("Unable to open HText image file " <<
  87.             HTp_HyperDoc->TTNp_fspname->getName());
  88.         B_valid = False;
  89.         return;
  90.     }
  91.  
  92.     //      Open the view's temporary rendered file for writing.
  93.     fsp_temp = new fstream(TTNp_temp->getName(), ios::out | ios::trunc |
  94.         ios::binary);
  95.     if(fsp_temp == NULL)    {
  96.         doslynxmessage("Unable to open HTML rendering file " <<
  97.             TTNp_temp->getName());
  98.         //      Close the HTML image file.
  99.         fsp_image->close();
  100.         delete(fsp_image);
  101.         B_valid = False;
  102.         return;
  103.     }
  104.  
  105.     //      Allocate the two lines with the appropriate screen size and
  106.     //      a safety buffer.
  107.     L_last = (Line *)new char[sizeof(Line) + size.x + 80];
  108.     L_new = (Line *)new char[sizeof(Line) + size.x + 80];
  109.  
  110.     if(L_last == NULL || L_new == NULL)     {
  111.         doslynxmessage("Unable to allocate enough memory to create.");
  112.         //      Close the files.
  113.         fsp_image->close();
  114.         fsp_temp->close();
  115.         delete(fsp_image);
  116.         delete(fsp_temp);
  117.         B_valid = False;
  118.         if(L_last != NULL)      {
  119.             delete[](L_last);
  120.         }
  121.         if(L_new != NULL)       {
  122.             delete[](L_new);
  123.         }
  124.         return;
  125.     }
  126.     L_last->ssi_indent = 0;
  127.     L_last->ssi_length = 0;
  128.  
  129.     //      We are in a new paragraph and can't split anywhere.
  130.     B_line_1 = True;
  131.     ssi_splitAt = 0;
  132.  
  133.     //      Right now, there are no limits to the view.
  134.     limit.y = limit.x = 0;
  135.  
  136.     //      Set member to avoid infinite loop in appendcharacter and
  137.     //      the double font.
  138.     B_avoidinfinite = False;
  139.  
  140.     //    There have been no spaces, but start out if so.
  141.     B_lastSpace = True;
  142.     //    Right now we will collapse spaces.
  143.     B_collapseSpaces = True;
  144.  
  145.     //    No current style
  146.     HTSp_style = NULL;
  147.  
  148.     //    If there were anchors skipped, report it.
  149.     if(usi_skipped != 0U)    {
  150.         doslynxmessage(usi_skipped << " anchors not created due to "
  151.             "memory limitations.");
  152.         usi_skipped = 0U;
  153.     }
  154.  
  155.     //      Go through the HTML image file, calling the appropriate
  156.     //      rendering functions for the temporary rendered file.
  157.     char c_append;
  158.     unsigned short int usi_checkEsc = 0;
  159.     signed long int sli_tellg = fsp_image->tellg();
  160.     while(fsp_image->eof() == 0)    {
  161.         //      Get a character and act upon it.
  162.         //      Update where we are in the file.
  163.         c_append = fsp_image->get();
  164.         sli_tellg++;
  165.         if(c_append == EOF || fsp_image->bad() != 0)    {
  166.             break;
  167.         }
  168.         //    Check for embedded characters.
  169.         else if(c_append == c_Embedded)    {
  170.             //    Is an embedded character, get the next one
  171.             //    that tells us what type of embed it is.
  172.             c_append = fsp_image->get();
  173.             sli_tellg++;
  174.             if(c_append == EOF || fsp_image->bad() != 0)    {
  175.                 break;
  176.             }
  177.             //      Check for styles.
  178.             else if(c_append == c_SetStyle)    {
  179.  
  180.                 auto HTStyle *HTSp_nextStyle;
  181.  
  182.                 //    Changing the current style.
  183.                 //    Get the style pointer from the file.
  184.                 fsp_image->read((char *)(&HTSp_nextStyle),
  185.                     sizeof(HTStyle *));
  186.                 sli_tellg += sizeof(HTStyle *);
  187.                 if(fsp_image->gcount() != sizeof(HTStyle *) ||
  188.                     fsp_image->bad() != 0)    {
  189.                     break;
  190.                 }
  191.  
  192.                 //    If there was a previous style, insert
  193.                 //    blank lines.
  194.                 if(HTSp_style != NULL)    {
  195.                     blank_lines(max(HTSp_style->
  196.                         spaceAfter,
  197.                         HTSp_nextStyle->spaceBefore));
  198.                 }
  199.  
  200.                 //    Change to the current style.
  201.                 HTSp_style = HTSp_nextStyle;
  202.  
  203.                 //    Set wether or not to collapse spaces.
  204.                 //    Will do so whenever style is not
  205.                 //    preformatted or an example.
  206.                 if(HTSp_style != NULL)    {
  207. #ifndef RELEASE
  208.                     trace("Current style is now " <<
  209.                         HTSp_style->name);
  210. #endif // RELEASE
  211.                     if(!strcmp(HTSp_style->name,
  212.                         "Preformatted") ||
  213.                         !strcmp(HTSp_style->name,
  214.                         "Example"))    {
  215.                         B_collapseSpaces = False;
  216.                     }
  217.                     else    {
  218.                         B_collapseSpaces = True;
  219.                     }
  220.                 }
  221.             }
  222.             //    Check for paragraph.
  223.             else if(c_append == c_AppendParagraph)    {
  224.  
  225.                 //    Assume we have a style regardless.
  226.                 blank_lines(max(HTSp_style->spaceAfter,
  227.                     HTSp_style->spaceBefore));
  228.             }
  229.             //    Check for beginning an anchor.
  230.             else if(c_append == c_BeginAnchor)    {
  231.                 auto HTChildAnchor *HTCAp_newAnchor;
  232.  
  233.                 //    Read the value of the pointer from
  234.                 //    file.
  235.                 fsp_image->read((char *)(&HTCAp_newAnchor),
  236.                     sizeof(HTChildAnchor *));
  237.                 sli_tellg += sizeof(HTChildAnchor *);
  238.                 if(fsp_image->gcount() != sizeof(
  239.                     HTChildAnchor *) ||
  240.                     fsp_image->bad() != 0)    {
  241.                     break;
  242.                 }
  243.  
  244.                 //    Begin the anchor in the view.
  245.                 beginAnchor(HTCAp_newAnchor);
  246.             }
  247.             //    Check for ending an anchor.
  248.             else if(c_append == c_EndAnchor)    {
  249.                 //    Simply call end anchor.
  250.                 endAnchor();
  251.             }
  252.             //    Check for the beginning of a Form.
  253.             else if(c_append == c_BeginForm)    {
  254.             }
  255.             //    Check for the ending of a Form.
  256.             else if(c_append == c_EndForm)    {
  257.             }
  258.         }
  259.         //    Otherwise, should be an appendable character.
  260.         else    {
  261.             appendCharacter(c_append);
  262.         }
  263.  
  264.         //      Every 1k of read information, check to see if
  265.         //      user is trying to interrupt.
  266.         if(usi_checkEsc++ > 1024U)     {
  267.             //      Reset usi_checkEsc
  268.             usi_checkEsc = 0U;
  269.  
  270.             //    Check if safe to coninue formatting due to
  271.             //    memory limitations.  The last ??? chunks of
  272.             //    mem will cause this to break.
  273.             if(really_safe_pool[Stop_Rendering] == NULL)    {
  274.                 doslynxmessage("Unable to display full "
  275.                     "document due to memory limitations.");
  276.                 break;
  277.             }
  278.  
  279.             auto TEvent TE;
  280.  
  281.             //      Get any events in the application.
  282.             //      Calls this to also call idle.
  283.             TProgram::application->getEvent(TE);
  284.  
  285.             //      Interrupt on ESC key.
  286.             if(TE.what & evKeyDown) {
  287.                 if(TE.keyDown.keyCode == kbEsc) {
  288.                     doslynxmessage("Interrupting the "
  289.                         "format process.");
  290.                     doslynxmessage("Display will not "
  291.                         "represent the full "
  292.                         "document.");
  293.                     //      Clear the event.
  294.                     TProgram::application->clearEvent(TE);
  295.                     break;
  296.                 }
  297.             }
  298.  
  299.             //      Print a message if other events occured.
  300.             if(TE.what != evNothing && !(TE.what & evMouseMove)
  301.                 && !(TE.what & evMouseUp))      {
  302.                 doslynxmessage("Formatting.... press ESC to "
  303.                     "interrupt.");
  304.             }
  305.  
  306.             //      Clear the event.
  307.             TProgram::application->clearEvent(TE);
  308.         }
  309.     }
  310.  
  311.     if(fsp_image->bad() != 0)    {
  312.         doslynxmessage("Error while reading HText image file.");
  313.         doslynxmessage("Displaying rendering as is.");
  314.     }
  315.  
  316.     //      Flush and release the lines.
  317.     split_line(0);
  318.     delete[]((char *)L_last);
  319.     delete[]((char *)L_new);
  320.  
  321.     //      Close the files.
  322.     fsp_image->close();
  323.     delete(fsp_image);
  324.     fsp_temp->close();
  325.     delete(fsp_temp);
  326.  
  327.     //      Adjust the selected anchor to now select the anchor in
  328.     //      the rendered file.
  329.     if(HTCAp_2BSelected != NULL)        {
  330.         adjustSelected();
  331.     }
  332.  
  333.     //      Tell the view what it's new bounds are.
  334.     //      This will set the scroll bar values.
  335.     setLimit(limit.x, limit.y);
  336.  
  337. #ifndef RELEASE
  338.     trace("FormatHTML returning.");
  339. #endif // RELEASE
  340. }
  341.  
  342. void TURLView::blank_lines(signed short int ssi_blanks) {
  343. //      Purpose:        Insert a number of blank lines into the rendered
  344. //                      image.
  345. //      Arguments:      ssi_blanks      The number of blank lines to insert.
  346. //      Return Value:   void
  347. //      Remarks/Portability/Dependencies/Restrictions:
  348. //              Will not count the number of previous blank lines before
  349. //              insertion.
  350. //      Revision History:
  351. //              02-16-94        created
  352.  
  353.     //      Insert the appropriate number of blanks.
  354.     //    Always atleast split one line.
  355.     do    {
  356.         split_line(0);
  357.     }
  358.     while(--ssi_blanks > 0);
  359.  
  360.     B_line_1 = True;
  361. }
  362.  
  363. void TURLView::appendCharacter(char c_append)   {
  364. //      Purpose:        Append a character to the output stream.
  365. //      Arguments:      c_append        The character to append.
  366. //      Return Value:   void
  367. //      Remarks/Portability/Dependencies/Restrictions:
  368. //              Assumes that any functions changing the actual last line
  369. //              in the rendered image will update the last line member.
  370. //      Revision History:
  371. //              02-16-94        created
  372. //        03-16-94    Modified to collapse spaces ' ' around all
  373. //                types of whitespace.  For prettier output.
  374. //                Care should be taken to not call this
  375. //                function using spaces to align or indent
  376. //                text, or the formatting will be collapsed.
  377.  
  378.     //    Check to see if we should ignore a space.
  379.     if(c_append == ' ')    {
  380.         //    Ignore it if need be.
  381.         if(B_lastSpace == True && B_collapseSpaces == True)    {
  382.             return;
  383.         }
  384.  
  385.         //    Set for future condensing.
  386.         B_lastSpace = True;
  387.  
  388.         //    Can split the line here.
  389.         ssi_splitAt = L_last->ssi_length;
  390.     }
  391.     else    {
  392.         //    Set so next time we know we have no spaces collapsed.
  393.         B_lastSpace = False;
  394.     }
  395.  
  396.     //      Determine the current indention of the line, if we have
  397.     //      style.
  398.     auto signed short int ssi_indent = 0;
  399.     if(B_line_1 == True)    {
  400.         ssi_indent = HTSp_style->indent1st;
  401.     }
  402.     else    {
  403.         ssi_indent = HTSp_style->leftIndent;
  404.     }
  405.  
  406.     //      Check for new lines.
  407.     //    Set whitespace here.
  408.     if(c_append == '\n')    {
  409.         //    Considered a space so that following spaces are
  410.         //    collapsed.
  411.         B_lastSpace = True;
  412.         split_line(0);
  413.         B_line_1 = True;
  414.         return;
  415.     }
  416.     //      Check for tabs.
  417.     //    If so, consider whitespace.
  418.     else if(c_append == '\t')       {
  419.         //    Considered a space so that we collapse more spaces.
  420.         B_lastSpace = True;
  421.         //      The tab table.
  422.         HTTabStop *HTTSp;
  423.         //      Where to tab to.
  424.         int i_target;
  425.         //      Where we are.
  426.         int i_here = L_last->ssi_length + L_last->ssi_indent
  427.             + ssi_indent;
  428.  
  429.         //      If we have a tab table.
  430.         if(HTSp_style->tabs != NULL) {
  431.             //      Loop through the tab table until
  432.             //      a tab will put the cursor past our
  433.             //      current postion.
  434.             for(HTTSp = HTSp_style->tabs; HTTSp->position <=
  435.                 i_here; HTTSp++)
  436.             {
  437.                 //      No tab specified.
  438.                 if(HTTSp->position == 0)        {
  439.                     split_line(0);
  440.                     return;
  441.                 }
  442.             }
  443.             i_target = HTTSp->position;
  444.         }
  445.         //      No tab table, if in line 1 of a paragraph,
  446.         //      use the leftIndent.
  447.         else if(B_line_1 == True)       {
  448.             //      If already beyond the left indent.
  449.             if(i_here >= HTSp_style->leftIndent)     {
  450.                 split_line(0);
  451.                 return;
  452.             }
  453.             else    {
  454.                 i_target = HTSp_style->leftIndent;
  455.             }
  456.         }
  457.         //      No tab table, not in line 1, use default mod 8
  458.         else    {
  459. #ifdef TABS8
  460.             i_target = (L_last->ssi_indent + L_last->ssi_length +
  461.                 8) % 8 + HTSp_style->leftIndent;
  462. #else
  463.             // Just split the line.
  464.             split_line(0);
  465. #endif // TABS8
  466.             return;
  467.         }
  468.  
  469.         //      If we are past the right margin.
  470.         if(i_target > size.x - HTSp_style->rightIndent)    {
  471.             split_line(0);
  472.             return;
  473.         }
  474.         //      Otherwise, indent the tab.
  475.         else    {
  476.             //      We can split the line here.
  477.             ssi_splitAt = L_last->ssi_length;
  478.             //      If there is nothing in the line, just
  479.             //      increase the indentation.
  480.             if(L_last->ssi_length == 0)     {
  481.                 L_last->ssi_indent += i_target - i_here;
  482.             }
  483.             //      Otherwise, space out.
  484.             else    {
  485.                 for(; i_here < i_target; i_here++)      {
  486.                     *((char *)L_last + sizeof(Line) +
  487.                         L_last->ssi_length) = ' ';
  488.                     L_last->ssi_length++;
  489.                 }
  490.             }
  491.             return;
  492.         }
  493.     }
  494.  
  495.     //      Check if beyond the screen width.
  496.     if(ssi_indent + L_last->ssi_indent + L_last->ssi_length + HTSp_style->
  497.         rightIndent >= size.x)
  498.     {
  499.         if(HTSp_style->wordWrap != 0)        {
  500.             split_line(ssi_splitAt);
  501.             //      We can ignore a space causing a split
  502.             if(c_append == ' ')     {
  503.                 return;
  504.             }
  505.         }
  506.         else    {
  507.             split_line(0);
  508.         }
  509.     }
  510.  
  511.     //      The font of the sytle.
  512.     HTFont HTF = HTSp_style->font;
  513.  
  514.     //      Convert NBS to a space.
  515.     //    Do not consider as whitespace.
  516.     if(c_append == HT_NON_BREAK_SPACE)      {
  517.         c_append = ' ';
  518.     }
  519.     //      Convert the character according to font.
  520.     else if(HTF & HT_CAPITALS)      {
  521.         c_append = toupper(c_append);
  522.     }
  523.  
  524.     //      Add the character to the line.
  525.     *((char *)L_last + sizeof(Line) + L_last->ssi_length) = c_append;
  526.     L_last->ssi_length++;
  527.  
  528.     //      On the double font, do again with a NBS
  529.     if(HTF & HT_DOUBLE)     {
  530.         //      Failsafe to not go infinitly recursive.
  531.         if(B_avoidinfinite == False)    {
  532.             B_avoidinfinite = True;
  533.         }
  534.         else    {
  535.             B_avoidinfinite = False;
  536.         }
  537.  
  538.         if(B_avoidinfinite == True)     {
  539.             appendCharacter(HT_NON_BREAK_SPACE);
  540.         }
  541.     }
  542. }
  543.  
  544. void TURLView::split_line(signed short int ssi_split)   {
  545. //      Purpose:        Split a line at the required offset.
  546. //      Arguments:      ssi_split       Where to split the line.
  547. //                                      If 0, no split, just a new line.
  548. //      Return Value:   void
  549. //      Remarks/Portability/Dependencies/Restrictions:
  550. //      Revision History:
  551. //              02-16-94        created
  552. //              02-22-98        Modified to use nothing but a TNSCollection
  553. //                              to keep track of line offsets into the
  554. //                              rendered file.  No memory other than the
  555. //                              collection is allocated.
  556.  
  557.     //      Reset where last line will be split.
  558.     ssi_splitAt = 0;
  559.  
  560.     //      Fill the members with pertinent data for the new line.
  561.     L_new->ssi_indent = L_new->ssi_length = 0;
  562.  
  563.     //      Split at required point, skip if not needed
  564.     if(ssi_split != 0 && L_last->ssi_length != 0)   {
  565.         //      End the line.
  566.         *((char *)L_last + sizeof(Line) + L_last->ssi_length) =
  567.             '\0';
  568.         //      Skip any space at the split point.
  569.         char *cp;
  570.         for(cp = (char *)L_last + sizeof(Line) + ssi_split; *cp !=
  571.             '\0'; cp++)     {
  572.             if(*cp != ' ')  {
  573.                 break;
  574.             }
  575.         }
  576.         //      Copy the remaining information into the new line and
  577.         //      set the members.
  578.         strcpy(((char *)L_new + sizeof(Line)), cp);
  579.         L_new->ssi_length = strlen(((char *)L_new + sizeof(Line)));
  580.         L_last->ssi_length = ssi_split;
  581.     }
  582.  
  583.     //    Take off any trailing spaces.
  584.     while(L_last->ssi_length != 0 && *((char *)L_last + sizeof(Line) +
  585.         L_last->ssi_length) == ' ' - 1)    {
  586.         L_last->ssi_length--;
  587.     }
  588.  
  589.     //      End the line.
  590.     if(L_last->ssi_length != 0)     {
  591.         *((char *)L_last + sizeof(Line) + L_last->ssi_length) =
  592.             '\0';
  593.     }
  594.  
  595.     //      Align the line according to style.
  596.     auto int i_indent = (B_line_1 == True) ? HTSp_style->indent1st :
  597.         HTSp_style->leftIndent;
  598.     auto int i_spare = size.x - HTSp_style->rightIndent +
  599.         HTSp_style->leftIndent - L_last->ssi_length;
  600.  
  601.     switch(HTSp_style->alignment)        {
  602.     case HT_CENTER:
  603.         L_last->ssi_indent += i_indent + i_spare / 2;
  604.         break;
  605.     case HT_RIGHT:
  606.         L_last->ssi_indent += i_indent + i_spare;
  607.         break;
  608.     default:
  609.         L_last->ssi_indent += i_indent;
  610.         break;
  611.     }
  612.  
  613.     //      We are no longer in the first line of a paragraph unless
  614.     //      the calling function sets this otherwise.
  615.     B_line_1 = False;
  616.  
  617.     //      Set the line collection to know where the offset of the
  618.     //      line to be serialized is.  Using only an offset to track.
  619.     //      Using the offset as a void * to track.
  620.     TNSCp_lines->insert((void *)(fsp_temp->tellp()));
  621.  
  622.     //      Write the line to the rendered image file.
  623.     fsp_temp->write((const char *)L_last, sizeof(Line) + L_last->
  624.         ssi_length);
  625.     //    Check for error in write, if so, must unfortunately exit.
  626.     if(fsp_temp->bad() != 0)    {
  627.         doslynxmessage("Error in creating rendered image.");
  628.  
  629.         //    Attemp closing the files.
  630.         fsp_temp->close();
  631.         fsp_image->close();
  632.  
  633.         //    Cause the application to quit.
  634.         TEvent TE_quit;
  635.         TE_quit.what = evMessage;
  636.         TE_quit.message.command = cmQuit;
  637.         TProgram::application->handleEvent(TE_quit);
  638.     }
  639.  
  640.     //      Increment the total number of lines and maximum width.
  641.     limit.y++;
  642.     limit.x = max(limit.x, L_last->ssi_length + L_last->ssi_indent);
  643.  
  644.     //      We have a new last line.
  645.     Line *L_temp = L_last;
  646.     L_last = L_new;
  647.     L_new = L_temp;
  648. }
  649.  
  650. void TURLView::beginAnchor(const HTChildAnchor *HTCAp_anchor)    {
  651. //      Purpose:        Mark the beginning of an anchor in the rendered image.
  652. //      Arguments:      HTCAp_anchor    The child anchor to begin.
  653. //      Return Value:   void
  654. //      Remarks/Portability/Dependencies/Restrictions:
  655. //              Creates a new anchor entry with offsets in the rendered file
  656. //              pointing to the corresponding current anchor.
  657. //      Revision History:
  658. //              02-17-94        created
  659.  
  660.     //      Create a new anchor.
  661.     TextAttribute *TAp_newanc = new TextAttribute(HTCAp_anchor);
  662.     if(TAp_newanc == NULL)  {
  663.         doslynxmessage("Unable to allocate space for new anchor.");
  664.         B_valid = False;
  665.         return;
  666.     }
  667.  
  668.     //      Get the offset of the last line and it's offset by length
  669.     //      and structure size.
  670.     signed long int sli_where = fsp_temp->tellp() + (signed long int)
  671.         (L_last->ssi_length + sizeof(Line));
  672.  
  673.     //      Set the beginning offset in the rendering.
  674.     TAp_newanc->Begin(sli_where);
  675.  
  676.     //      Insert the anchor into the anchor collection.
  677.     TNSCp_anchors->insert((void *)TAp_newanc);
  678. }
  679.  
  680. void TURLView::endAnchor()      {
  681. //      Purpose:        End an anchor in the rendered image.
  682. //      Arguments:      void
  683. //      Return Value:   void
  684. //      Remarks/Portability/Dependencies/Restrictions:
  685. //              Ends the last anchor in the collection at the current
  686. //              length of the last line in the offset of the rendering.
  687. //      Revision History:
  688. //              02-17-94        created
  689.  
  690.     auto signed short int ssi_goback = 1;
  691.  
  692.     //      Get the last anchor.  Assume there is always one.
  693.     //    Since we now allow nested anchors, search for the latest
  694.     //        unused anchor.
  695.     TextAttribute *TAp_anclast = (TextAttribute *)(TNSCp_anchors->at(
  696.         TNSCp_anchors->getCount() - ssi_goback));
  697.  
  698.     while(TAp_anclast->getEnd() != 0L)    {
  699.         ssi_goback++;
  700.         TAp_anclast = (TextAttribute *)(TNSCp_anchors->at(
  701.             TNSCp_anchors->getCount() - ssi_goback));
  702.     }
  703.  
  704.     //      Get the offset of the last line and it's offset by length
  705.     //      and structure size.
  706.     signed long int sli_where = fsp_temp->tellp() + (signed long int)
  707.         (L_last->ssi_length + sizeof(Line));
  708.  
  709.     //      Set the ending offset in the rendering.
  710.     TAp_anclast->End(sli_where);
  711. }
  712.  
  713. void TURLView::adjustSelected() {
  714. //      Purpose:        The selected anchor originally points to the anchor
  715. //                      owned by HText.  Convert the pointer of that anchor
  716. //                      to the corresponding anchor owned by the view.
  717. //      Arguments:      void
  718. //      Return Value:   void
  719. //      Remarks/Portability/Dependencies/Restrictions:
  720. //      Revision History:
  721. //              02-17-94        created
  722.  
  723. #ifndef RELEASE
  724.     trace("Adjusting the selected anchor.");
  725. #endif // RELEASE
  726.  
  727.     //      Find the corresponding anchor.
  728.     //      Assume that a match will always be found.
  729.     TextAttribute *TAp_same;
  730.     for(TAp_same = (TextAttribute *)(TNSCp_anchors->at(0));
  731.         TAp_same->HTCAp_anchor != HTCAp_2BSelected;
  732.         TAp_same = (TextAttribute *)(TNSCp_anchors->at(TNSCp_anchors
  733.         ->indexOf((void *)TAp_same) + 1)))      {
  734.         //      Null body
  735.     }
  736.  
  737.     //      Set the selected anchor.
  738.     TAp_selected = TAp_same;
  739. }
  740.