home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xhyper10.zip / XHyper_v1.0 / src / HyperView.c < prev    next >
C/C++ Source or Header  |  1992-12-08  |  15KB  |  636 lines

  1. /*
  2.  * Copyright (c) 1992 U.S. Geological Survey (USGS)
  3.  *
  4.  * Permission to use, copy, modify, distribute, and sell this software and its
  5.  * documentation for any purpose is hereby granted without fee, provided that
  6.  * the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of USGS not be used in advertising or
  9.  * publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  USGS makes no representations about the
  11.  * suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * USGS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  15.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL USGS
  16.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  17.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  18.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  19.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  20.  *
  21.  */
  22.  
  23. #include "Command.h"
  24. #include "HyperView.h"
  25. #include "TextView.h"
  26. #include "PageBorder.h"
  27. #include "PageButton.h"
  28.  
  29. #include <IV-look/button.h>
  30. #include <IV-look/kit.h>
  31. #include <InterViews/background.h>
  32. #include <InterViews/bitmap.h>
  33. #include <InterViews/border.h>
  34. #include <InterViews/box.h>
  35. #include <InterViews/center.h>
  36. #include <InterViews/font.h>
  37. #include <InterViews/glue.h>
  38. #include <InterViews/hit.h>
  39. #include <InterViews/label.h>
  40. #include <InterViews/listener.h>
  41. #include <InterViews/margin.h>
  42. #include <InterViews/patch.h>
  43. #include <InterViews/stencil.h>
  44. #include <InterViews/world.h>
  45. #include <InterViews/session.h>
  46. #include <list.h>
  47. #include <string.h>
  48. #include <stdlib.h>
  49.  
  50. /*-------------------------------------------------------------------------
  51.    Class HyperView
  52.  
  53.    The HyperView class provides a window for viewing TextView instances
  54.    and a set of buttons for paging or printing the current TextView.
  55.    TextViews are loaded on an AS NEEDED basis.
  56.  
  57.    Members:
  58.       command    - processes a button press
  59.       event    - required to receive events
  60.       hypertext - skip to page containing hypertext section
  61.       jump_to    - jump to page containing a given character item
  62.       nextview  - view the next TextView item
  63.       prevview  - view the previous TextView item
  64.       page_to    - changes the current page
  65.       pop    - pop last hypertext source
  66.       readTOC    - reads the Table of Contents
  67.       _toc    - list of Table of Contents items
  68.       updateTOC - update the TOC offset variable
  69.       TOC       - finds TOC index for a given tag
  70.  
  71.  *-------------------------------------------------------------------------*/
  72.  
  73. //
  74. // *** create TOC structure (see list.h)
  75. //
  76. declareList(TextItem_List, TextItem)
  77. implementList(TextItem_List, TextItem)
  78.  
  79. //
  80. // *** create TOC structure (see list.h)
  81. //
  82. declareList(TOC_List, TOCItem)
  83. implementList(TOC_List, TOCItem)
  84.  
  85. //
  86. // *** create Hypertext source stack
  87. //
  88. declareList(Hypertext_Stack, HyperSource)
  89. implementList(Hypertext_Stack, HyperSource)
  90.  
  91. const int MAXSTACKDEPTH = 5;
  92.  
  93. //
  94. //  *** read of line of text from an MML file
  95. //
  96. int getline(FILE* fd, char* line)
  97.    {
  98.    int   i = 0;
  99.    int   c;
  100.  
  101.    //
  102.    //   *** skip leading blanks
  103.    //
  104.    while (((c = fgetc(fd)) != EOF) && ((c == ' ') || (c == '\n')));
  105.  
  106.    line[i++] = c;
  107.  
  108.    if ((c == EOF) || (c == '\n'))
  109.       return(c);
  110.  
  111.    while (((c = fgetc(fd)) != EOF) && (c != '\n'))
  112.          line[i++] = (char)c;
  113.  
  114.    line[i] = '\0';
  115.    return((char)c);
  116.    }
  117.  
  118. HyperViewer::HyperViewer (const char* htag=NULL)
  119.           : ApplicationWindow(_top = new Patch(nil)), Handler() 
  120.     {
  121.     FILE   *fd;
  122.     int    i;
  123.     char   fullname[256];
  124.     void   init_fonts();
  125.  
  126.     _home = getenv("HYPERDOC");
  127.  
  128.     //
  129.     //  *** get default colors and font
  130.     //
  131.     World* world = World::current();
  132.     const Color* fg = world->foreground();
  133.     const Color* bg = world->background();
  134.     const Font* font = world->font();
  135.  
  136.     //
  137.     //  *** initialize fonts needed by textview 
  138.     //
  139.     init_fonts();
  140.  
  141.     _textlist   = new TextItem_List(20);
  142.     _hyperstack = new Hypertext_Stack(MAXSTACKDEPTH);
  143.  
  144.     //
  145.     //   *** initialize Table of contents
  146.     //
  147.     _toc  = new TOC_List(10);
  148.  
  149.     if (_home != NULL)
  150.        {
  151.        strcpy(fullname, _home);
  152.        strcat(fullname, "/TOC");
  153.        }
  154.     else
  155.        strcpy(fullname, "TOC");
  156.  
  157.     if ((fd = fopen(fullname, "r")) == (FILE*)NULL)
  158.        {
  159.        printf("Cannot open Table of Contents\n");
  160.        exit(0);
  161.        }
  162.  
  163.     readTOC(fd);
  164.     fclose(fd);
  165.  
  166.     //
  167.     //  *** create textview of given hyper tag
  168.     //
  169.     if (htag == NULL)
  170.        htag = _toc->item(0)._tag;
  171.  
  172.     i = 0;
  173.     while ((i < _toc->count()) &&
  174.            (strcasecmp(_toc->item(i)._tag, htag) != 0))
  175.        i++;
  176.  
  177.     if (i < _toc->count())
  178.        {
  179.        TextItem  t;
  180.  
  181.        t._view = new TextView(this, _toc->item(i)._filename, i);
  182.        _textlist->append(t);
  183.        _item = 0;
  184.        }
  185.     else
  186.        {
  187.        printf("Unknown HyperText:  %s\n", htag);
  188.        exit(0);
  189.        }
  190.  
  191.     //
  192.     //  *** using Kit class, define footer buttons
  193.     //
  194.     Kit*  kit = Kit::instance();
  195.  
  196.     // _prev_page = new PageButton(
  197.     //     new HCenter(new Label("-", font, fg)), fg);
  198.     //
  199.     _prev_page = kit->simple_push_button("Prev",  
  200.                            Session::instance()->style(),
  201.                            new Command(this, "page backward"));
  202.     _prev_page->ref();
  203.  
  204.     _next_page = kit->simple_push_button("Next",  
  205.                           Session::instance()->style(),
  206.                           new Command(this, "page forward"));
  207.     _next_page->ref();
  208.  
  209.     _pop = kit->simple_push_button("Pop",  
  210.                           Session::instance()->style(),
  211.                           new Command(this, "pop"));
  212.     _pop->ref();
  213.  
  214.     _print = kit->simple_push_button("Print",  
  215.                           Session::instance()->style(),
  216.                           new Command(this, "print"));
  217.     _print->ref();
  218.  
  219.     _quit = kit->simple_push_button("Quit",
  220.                           Session::instance()->style(),
  221.                           new Command(this, "quit"));
  222.     _quit->ref();
  223.  
  224.     //
  225.     //  *** align buttons left to right
  226.     //
  227.     LRBox* buttons = new LRBox();
  228.     buttons->append(nil);
  229.     buttons->append(_prev_page);
  230.     buttons->append(_next_page);
  231.     buttons->append(_pop);
  232.     buttons->append(_print);
  233.     buttons->append(_quit);
  234.     _footer_patch = new Patch(buttons);
  235.  
  236.     _page_patch = new Patch(nil);
  237.     _body_patch = new Patch(
  238.         new TBBox(
  239.             new Margin(
  240.                 new PageBorder(new Margin(_page_patch, 1, 5, 5, 1), fg),
  241.                 0, 0, 0, 0, fil, 0, 5, fil, 0, 0, 0, 0
  242.             ),
  243.             _footer_patch
  244.         )
  245.     );
  246.  
  247.     Listener* listener = new Listener(
  248.         new Background(
  249.             new TBBox(
  250.                 new Margin(_body_patch, 5)
  251.             ), bg
  252.         ), this
  253.     );
  254.     listener->button(true);
  255.     _top->body(listener);
  256.  
  257.     _page_patch->body(
  258.         new Margin(_textlist->item(_item)._view, 10.0, 10.0, 10.0, 10.0)
  259.         );
  260.  
  261.    //
  262.    //  *** skip to requested hypertext
  263.    //
  264.    jump_to(_toc->item(i)._offset);
  265.    }
  266.  
  267. HyperViewer::~HyperViewer()
  268.    {
  269.    _top->body(nil);
  270.    _prev_page->unref();
  271.    _next_page->unref();
  272.    _pop->unref();
  273.    _print->unref();
  274.    _quit->unref();
  275.    _textlist->item(_item)._view->unref();
  276.    }
  277.  
  278. //
  279. //  *** command is invoked by the HyperView buttons
  280. //
  281. void HyperViewer::command(const char* command)
  282.    {
  283.    if (strcmp(command, "page forward") == 0)
  284.       {
  285.       if (_current_page < _textlist->item(_item)._view->Count())
  286.          _textlist->item(_item)._view->view_page(++_current_page);
  287.       else
  288.          nextview();
  289.       }
  290.    else if (strcmp(command, "page backward") == 0)
  291.       {
  292.       if (_current_page > 1)
  293.          _textlist->item(_item)._view->view_page(--_current_page);
  294.       else
  295.          prevview();
  296.       }
  297.    else if (strcmp(command, "pop") == 0)
  298.       pop();
  299.    else if (strcmp(command, "print") == 0)
  300.       _textlist->item(_item)._view->printout();
  301.    else if (strcmp(command, "quit") == 0)
  302.       {
  303.       delete this;
  304.       exit(0);
  305.       }
  306.    }
  307.  
  308.  
  309. void HyperViewer::event (Event& e) 
  310.    {
  311.    }
  312.  
  313. //
  314. //  *** page within the current textview
  315. //
  316. void HyperViewer::page_to(int p)
  317.    {
  318.    _current_page = p;
  319.    _textlist->item(_item)._view->view_page(_current_page);
  320.    }
  321.  
  322. //
  323. //  *** jump to given character offset
  324. //
  325. void HyperViewer::jump_to(int offset)
  326.    {
  327.    _textlist->item(_item)._view->jump_to(offset);
  328.    }
  329.  
  330. void HyperViewer::readTOC(FILE* fd)
  331.    {
  332.    TOCItem tocitem;
  333.    char    filename[80];
  334.    char    tag[80];
  335.    char    line[100];
  336.    char    c;
  337.  
  338.    while (getline(fd, line) != EOF)
  339.       {
  340.       switch (line[0])
  341.          {
  342.          case ' ':
  343.          case '\n':
  344.             break;
  345.  
  346.          //
  347.          // *** assume comment
  348.          //
  349.          case '<':
  350.             if (strchr(line, '>') == NULL)
  351.                {
  352.                while ((c = getc(fd)) != '>');
  353.                while ((c = getc(fd)) != '\n');
  354.                }
  355.             break;
  356.  
  357.          default:
  358.             sscanf(line, "%f %s %s", &tocitem._section, filename, tag);
  359.             tocitem._filename = strcpy(new char[strlen(filename)+1], filename);
  360.             tocitem._tag      = strcpy(new char[strlen(tag)+1], tag);
  361.             tocitem._offset   = -1;
  362.             _toc->append(tocitem);
  363.             break;
  364.          }
  365.       }
  366.    }
  367.  
  368. void HyperViewer::updateTOC(FILE* fd, int tcount)
  369.    {
  370.    long  offset;
  371.    float sect;
  372.    char  line[100];
  373.    int   i;
  374.  
  375.    offset = ftell(fd);
  376.  
  377.    if (getline(fd, line) != EOF)
  378.       {
  379.       sscanf(line, "%f", §);
  380.  
  381.      /*
  382.       *  *** find TOC entry for this section and update offset
  383.       */
  384.       for (i = 0; i < _toc->count(); i++)
  385.          {
  386.          if (_toc->item(i)._section == sect)
  387.             {
  388.             _toc->item(i)._offset = tcount;
  389.             break;
  390.             }
  391.          }
  392.       }
  393.  
  394.    //
  395.    //  *** reset file to original position
  396.    //
  397.    fseek(fd, offset, 0);
  398.    }
  399.  
  400. int HyperViewer::TOC(char* tag)
  401.    {
  402.    int   i;
  403.  
  404.    for (i = 0; i < _toc->count(); i++)
  405.       {
  406.       if (strcmp(tag, _toc->item(i)._tag) == 0)
  407.          return((int)i);
  408.       }
  409.  
  410.    return(255);
  411.    }
  412.  
  413. void HyperViewer::hypertext(int index)
  414.    {
  415.    TextItem    titem;
  416.    HyperSource hypsrc;
  417.    int         newitem;
  418.    int         i;
  419.  
  420.    //
  421.    //  *** add current location to hypertext stack
  422.    //
  423.    hypsrc._item  = _item;
  424.    hypsrc._page = _current_page;
  425.  
  426.    //
  427.    //  *** append to list, if at maximum stack depth, remove first item
  428.    //
  429.    if (_hyperstack->count() < MAXSTACKDEPTH)
  430.       _hyperstack->append(hypsrc);
  431.    else
  432.       {
  433.       _hyperstack->remove(0);
  434.       _hyperstack->append(hypsrc);
  435.       }
  436.    
  437.    //
  438.    // *** if hypertext in current textview
  439.    //
  440.    if (strcmp(_toc->item(index)._filename, 
  441.               _textlist->item(_item)._view->MMLFile()) == 0)
  442.       {
  443.       jump_to(_toc->item(index)._offset);
  444.       return;
  445.       }
  446.  
  447.    //
  448.    //  *** check loaded file for hypertext
  449.    //
  450.    for (i = 0; i < _textlist->count(); i++)
  451.       {
  452.       if (strcmp(_textlist->item(i)._view->MMLFile(), 
  453.                  _toc->item(index)._filename) == 0)
  454.          break;
  455.       }
  456.  
  457.    //
  458.    //  *** if view with hypertext is not loaded, load new MML file
  459.    //
  460.    if (i < _textlist->count())
  461.       newitem = i;
  462.    else
  463.       {
  464.       titem._view = new TextView(this,  _toc->item(index)._filename, index);
  465.       newitem = (int)_textlist->count();
  466.       _textlist->append(titem);
  467.       }
  468.  
  469.    //
  470.    //  *** jump to hypertext page
  471.    //
  472.    _item = newitem;
  473.    _page_patch->body( 
  474.            new Margin(_textlist->item(newitem)._view, 10.0, 10.0, 10.0, 10.0)
  475.            );
  476.    _page_patch->reallocate();
  477.    _page_patch->redraw();
  478.    jump_to(_toc->item(index)._offset);
  479.    }
  480.  
  481. void HyperViewer::nextview()
  482.    {
  483.    TextItem titem;
  484.    int      i, j;
  485.    int      newitem;
  486.    char     *current;
  487.  
  488.    current = (char*)_textlist->item(_item)._view->MMLFile();
  489.  
  490.    //
  491.    //  *** find  next MML file name
  492.    //
  493.    i = 0;
  494.    while (strcmp(_toc->item(i)._filename, current) != 0)
  495.       i++;
  496.  
  497.    while ((i < _toc->count()) &&
  498.           (strcmp(_toc->item(i)._filename, current) == 0)) 
  499.       i++;
  500.  
  501.    //
  502.    //  *** if at end, return
  503.    //
  504.    if (i ==_toc->count())
  505.       return;
  506.  
  507.    j = 0;
  508.    for (j = 0; j < _textlist->count(); j++)
  509.        {
  510.        if (strcmp(_textlist->item(j)._view->MMLFile(), 
  511.                   _toc->item(i)._filename) == 0)
  512.           {
  513.           newitem = j;
  514.           break;
  515.           }
  516.        }
  517.  
  518.    //
  519.    //  *** if next section is not loaded, create new TextView
  520.    //
  521.    if (j == _textlist->count())
  522.       {
  523.       titem._view = new TextView(this,  _toc->item(i)._filename, i);
  524.       newitem = (int)_textlist->count();
  525.       _textlist->append(titem);
  526.       }
  527.  
  528.    //
  529.    //  *** change text view and view first page
  530.    //
  531.    if (newitem != _item)
  532.       {
  533.       _item = newitem;
  534.       _page_patch->body( 
  535.            new Margin(_textlist->item(newitem)._view, 10.0, 10.0, 10.0, 10.0)
  536.       );
  537.       _page_patch->reallocate();
  538.       _page_patch->redraw();
  539.       page_to(1);
  540.       }
  541.    }
  542.  
  543. void HyperViewer::prevview()
  544.    {
  545.    TextItem titem;
  546.    int      i, j;
  547.    int      newitem;
  548.    char     *current;
  549.  
  550.    current = (char*)_textlist->item(_item)._view->MMLFile();
  551.  
  552.    //
  553.    //  *** find previous MML file name
  554.    //
  555.    i = 0;
  556.    while (strcmp(_toc->item(i)._filename, current) != 0)
  557.       i++;
  558.  
  559.    while ((i > 0) && (strcmp(_toc->item(i)._filename, current) == 0)) 
  560.       i--;
  561.  
  562.    if (i < 0)
  563.       return;
  564.  
  565.    j = 0;
  566.    for (j = 0; j < _textlist->count(); j++)
  567.        {
  568.        if (strcmp(_textlist->item(j)._view->MMLFile(), 
  569.                   _toc->item(i)._filename) == 0)
  570.           {
  571.           newitem = j;
  572.           break;
  573.           }
  574.        }
  575.  
  576.    //
  577.    //  *** if not loaded, create new TextView
  578.    //
  579.    if (j == _textlist->count())
  580.       {
  581.       titem._view = new TextView(this, (char*)_toc->item(i)._filename, i);
  582.       newitem = (int)_textlist->count();
  583.       _textlist->append(titem);
  584.       }
  585.  
  586.    //
  587.    //  *** view last page of previous file
  588.    //
  589.    if (newitem != _item)
  590.       {
  591.       _item = newitem;
  592.       _page_patch->body( 
  593.            new Margin(_textlist->item(newitem)._view, 10.0, 10.0, 10.0, 10.0)
  594.       );
  595.       _page_patch->reallocate();
  596.       _page_patch->redraw();
  597.       _current_page = _textlist->item(newitem)._view->last_page();
  598.       }
  599.    }
  600.  
  601. void HyperViewer::pop()
  602.    {
  603.    long         top;
  604.    HyperSource  hypersrc;
  605.    
  606.    //
  607.    //  *** if nothing in stack, return
  608.    //
  609.    if ((top = _hyperstack->count()) == 0)
  610.       return;
  611.  
  612.    //
  613.    //  *** pop stack
  614.    //
  615.    hypersrc = _hyperstack->item(top - 1);
  616.    _hyperstack->remove(top-1);
  617.  
  618.    //
  619.    //  *** jump back to the hypertext source
  620.    //
  621.    if (_item != hypersrc._item)
  622.       {
  623.       _item = hypersrc._item;
  624.       _page_patch->body(
  625.            new Margin(_textlist->item(_item)._view, 10.0, 10.0, 10.0, 10.0)
  626.            );
  627.       _page_patch->reallocate();
  628.       _page_patch->redraw();
  629.       if (hypersrc._page != 0)
  630.          page_to(hypersrc._page);
  631.       }
  632.    else
  633.       page_to(hypersrc._page);
  634.    }
  635.  
  636.