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 >
Wrap
C/C++ Source or Header
|
1992-12-08
|
15KB
|
636 lines
/*
* Copyright (c) 1992 U.S. Geological Survey (USGS)
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of USGS not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. USGS makes no representations about the
* suitability of this software for any purpose. It is provided "as is"
* without express or implied warranty.
*
* USGS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL USGS
* BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
*/
#include "Command.h"
#include "HyperView.h"
#include "TextView.h"
#include "PageBorder.h"
#include "PageButton.h"
#include <IV-look/button.h>
#include <IV-look/kit.h>
#include <InterViews/background.h>
#include <InterViews/bitmap.h>
#include <InterViews/border.h>
#include <InterViews/box.h>
#include <InterViews/center.h>
#include <InterViews/font.h>
#include <InterViews/glue.h>
#include <InterViews/hit.h>
#include <InterViews/label.h>
#include <InterViews/listener.h>
#include <InterViews/margin.h>
#include <InterViews/patch.h>
#include <InterViews/stencil.h>
#include <InterViews/world.h>
#include <InterViews/session.h>
#include <list.h>
#include <string.h>
#include <stdlib.h>
/*-------------------------------------------------------------------------
Class HyperView
The HyperView class provides a window for viewing TextView instances
and a set of buttons for paging or printing the current TextView.
TextViews are loaded on an AS NEEDED basis.
Members:
command - processes a button press
event - required to receive events
hypertext - skip to page containing hypertext section
jump_to - jump to page containing a given character item
nextview - view the next TextView item
prevview - view the previous TextView item
page_to - changes the current page
pop - pop last hypertext source
readTOC - reads the Table of Contents
_toc - list of Table of Contents items
updateTOC - update the TOC offset variable
TOC - finds TOC index for a given tag
*-------------------------------------------------------------------------*/
//
// *** create TOC structure (see list.h)
//
declareList(TextItem_List, TextItem)
implementList(TextItem_List, TextItem)
//
// *** create TOC structure (see list.h)
//
declareList(TOC_List, TOCItem)
implementList(TOC_List, TOCItem)
//
// *** create Hypertext source stack
//
declareList(Hypertext_Stack, HyperSource)
implementList(Hypertext_Stack, HyperSource)
const int MAXSTACKDEPTH = 5;
//
// *** read of line of text from an MML file
//
int getline(FILE* fd, char* line)
{
int i = 0;
int c;
//
// *** skip leading blanks
//
while (((c = fgetc(fd)) != EOF) && ((c == ' ') || (c == '\n')));
line[i++] = c;
if ((c == EOF) || (c == '\n'))
return(c);
while (((c = fgetc(fd)) != EOF) && (c != '\n'))
line[i++] = (char)c;
line[i] = '\0';
return((char)c);
}
HyperViewer::HyperViewer (const char* htag=NULL)
: ApplicationWindow(_top = new Patch(nil)), Handler()
{
FILE *fd;
int i;
char fullname[256];
void init_fonts();
_home = getenv("HYPERDOC");
//
// *** get default colors and font
//
World* world = World::current();
const Color* fg = world->foreground();
const Color* bg = world->background();
const Font* font = world->font();
//
// *** initialize fonts needed by textview
//
init_fonts();
_textlist = new TextItem_List(20);
_hyperstack = new Hypertext_Stack(MAXSTACKDEPTH);
//
// *** initialize Table of contents
//
_toc = new TOC_List(10);
if (_home != NULL)
{
strcpy(fullname, _home);
strcat(fullname, "/TOC");
}
else
strcpy(fullname, "TOC");
if ((fd = fopen(fullname, "r")) == (FILE*)NULL)
{
printf("Cannot open Table of Contents\n");
exit(0);
}
readTOC(fd);
fclose(fd);
//
// *** create textview of given hyper tag
//
if (htag == NULL)
htag = _toc->item(0)._tag;
i = 0;
while ((i < _toc->count()) &&
(strcasecmp(_toc->item(i)._tag, htag) != 0))
i++;
if (i < _toc->count())
{
TextItem t;
t._view = new TextView(this, _toc->item(i)._filename, i);
_textlist->append(t);
_item = 0;
}
else
{
printf("Unknown HyperText: %s\n", htag);
exit(0);
}
//
// *** using Kit class, define footer buttons
//
Kit* kit = Kit::instance();
// _prev_page = new PageButton(
// new HCenter(new Label("-", font, fg)), fg);
//
_prev_page = kit->simple_push_button("Prev",
Session::instance()->style(),
new Command(this, "page backward"));
_prev_page->ref();
_next_page = kit->simple_push_button("Next",
Session::instance()->style(),
new Command(this, "page forward"));
_next_page->ref();
_pop = kit->simple_push_button("Pop",
Session::instance()->style(),
new Command(this, "pop"));
_pop->ref();
_print = kit->simple_push_button("Print",
Session::instance()->style(),
new Command(this, "print"));
_print->ref();
_quit = kit->simple_push_button("Quit",
Session::instance()->style(),
new Command(this, "quit"));
_quit->ref();
//
// *** align buttons left to right
//
LRBox* buttons = new LRBox();
buttons->append(nil);
buttons->append(_prev_page);
buttons->append(_next_page);
buttons->append(_pop);
buttons->append(_print);
buttons->append(_quit);
_footer_patch = new Patch(buttons);
_page_patch = new Patch(nil);
_body_patch = new Patch(
new TBBox(
new Margin(
new PageBorder(new Margin(_page_patch, 1, 5, 5, 1), fg),
0, 0, 0, 0, fil, 0, 5, fil, 0, 0, 0, 0
),
_footer_patch
)
);
Listener* listener = new Listener(
new Background(
new TBBox(
new Margin(_body_patch, 5)
), bg
), this
);
listener->button(true);
_top->body(listener);
_page_patch->body(
new Margin(_textlist->item(_item)._view, 10.0, 10.0, 10.0, 10.0)
);
//
// *** skip to requested hypertext
//
jump_to(_toc->item(i)._offset);
}
HyperViewer::~HyperViewer()
{
_top->body(nil);
_prev_page->unref();
_next_page->unref();
_pop->unref();
_print->unref();
_quit->unref();
_textlist->item(_item)._view->unref();
}
//
// *** command is invoked by the HyperView buttons
//
void HyperViewer::command(const char* command)
{
if (strcmp(command, "page forward") == 0)
{
if (_current_page < _textlist->item(_item)._view->Count())
_textlist->item(_item)._view->view_page(++_current_page);
else
nextview();
}
else if (strcmp(command, "page backward") == 0)
{
if (_current_page > 1)
_textlist->item(_item)._view->view_page(--_current_page);
else
prevview();
}
else if (strcmp(command, "pop") == 0)
pop();
else if (strcmp(command, "print") == 0)
_textlist->item(_item)._view->printout();
else if (strcmp(command, "quit") == 0)
{
delete this;
exit(0);
}
}
void HyperViewer::event (Event& e)
{
}
//
// *** page within the current textview
//
void HyperViewer::page_to(int p)
{
_current_page = p;
_textlist->item(_item)._view->view_page(_current_page);
}
//
// *** jump to given character offset
//
void HyperViewer::jump_to(int offset)
{
_textlist->item(_item)._view->jump_to(offset);
}
void HyperViewer::readTOC(FILE* fd)
{
TOCItem tocitem;
char filename[80];
char tag[80];
char line[100];
char c;
while (getline(fd, line) != EOF)
{
switch (line[0])
{
case ' ':
case '\n':
break;
//
// *** assume comment
//
case '<':
if (strchr(line, '>') == NULL)
{
while ((c = getc(fd)) != '>');
while ((c = getc(fd)) != '\n');
}
break;
default:
sscanf(line, "%f %s %s", &tocitem._section, filename, tag);
tocitem._filename = strcpy(new char[strlen(filename)+1], filename);
tocitem._tag = strcpy(new char[strlen(tag)+1], tag);
tocitem._offset = -1;
_toc->append(tocitem);
break;
}
}
}
void HyperViewer::updateTOC(FILE* fd, int tcount)
{
long offset;
float sect;
char line[100];
int i;
offset = ftell(fd);
if (getline(fd, line) != EOF)
{
sscanf(line, "%f", §);
/*
* *** find TOC entry for this section and update offset
*/
for (i = 0; i < _toc->count(); i++)
{
if (_toc->item(i)._section == sect)
{
_toc->item(i)._offset = tcount;
break;
}
}
}
//
// *** reset file to original position
//
fseek(fd, offset, 0);
}
int HyperViewer::TOC(char* tag)
{
int i;
for (i = 0; i < _toc->count(); i++)
{
if (strcmp(tag, _toc->item(i)._tag) == 0)
return((int)i);
}
return(255);
}
void HyperViewer::hypertext(int index)
{
TextItem titem;
HyperSource hypsrc;
int newitem;
int i;
//
// *** add current location to hypertext stack
//
hypsrc._item = _item;
hypsrc._page = _current_page;
//
// *** append to list, if at maximum stack depth, remove first item
//
if (_hyperstack->count() < MAXSTACKDEPTH)
_hyperstack->append(hypsrc);
else
{
_hyperstack->remove(0);
_hyperstack->append(hypsrc);
}
//
// *** if hypertext in current textview
//
if (strcmp(_toc->item(index)._filename,
_textlist->item(_item)._view->MMLFile()) == 0)
{
jump_to(_toc->item(index)._offset);
return;
}
//
// *** check loaded file for hypertext
//
for (i = 0; i < _textlist->count(); i++)
{
if (strcmp(_textlist->item(i)._view->MMLFile(),
_toc->item(index)._filename) == 0)
break;
}
//
// *** if view with hypertext is not loaded, load new MML file
//
if (i < _textlist->count())
newitem = i;
else
{
titem._view = new TextView(this, _toc->item(index)._filename, index);
newitem = (int)_textlist->count();
_textlist->append(titem);
}
//
// *** jump to hypertext page
//
_item = newitem;
_page_patch->body(
new Margin(_textlist->item(newitem)._view, 10.0, 10.0, 10.0, 10.0)
);
_page_patch->reallocate();
_page_patch->redraw();
jump_to(_toc->item(index)._offset);
}
void HyperViewer::nextview()
{
TextItem titem;
int i, j;
int newitem;
char *current;
current = (char*)_textlist->item(_item)._view->MMLFile();
//
// *** find next MML file name
//
i = 0;
while (strcmp(_toc->item(i)._filename, current) != 0)
i++;
while ((i < _toc->count()) &&
(strcmp(_toc->item(i)._filename, current) == 0))
i++;
//
// *** if at end, return
//
if (i ==_toc->count())
return;
j = 0;
for (j = 0; j < _textlist->count(); j++)
{
if (strcmp(_textlist->item(j)._view->MMLFile(),
_toc->item(i)._filename) == 0)
{
newitem = j;
break;
}
}
//
// *** if next section is not loaded, create new TextView
//
if (j == _textlist->count())
{
titem._view = new TextView(this, _toc->item(i)._filename, i);
newitem = (int)_textlist->count();
_textlist->append(titem);
}
//
// *** change text view and view first page
//
if (newitem != _item)
{
_item = newitem;
_page_patch->body(
new Margin(_textlist->item(newitem)._view, 10.0, 10.0, 10.0, 10.0)
);
_page_patch->reallocate();
_page_patch->redraw();
page_to(1);
}
}
void HyperViewer::prevview()
{
TextItem titem;
int i, j;
int newitem;
char *current;
current = (char*)_textlist->item(_item)._view->MMLFile();
//
// *** find previous MML file name
//
i = 0;
while (strcmp(_toc->item(i)._filename, current) != 0)
i++;
while ((i > 0) && (strcmp(_toc->item(i)._filename, current) == 0))
i--;
if (i < 0)
return;
j = 0;
for (j = 0; j < _textlist->count(); j++)
{
if (strcmp(_textlist->item(j)._view->MMLFile(),
_toc->item(i)._filename) == 0)
{
newitem = j;
break;
}
}
//
// *** if not loaded, create new TextView
//
if (j == _textlist->count())
{
titem._view = new TextView(this, (char*)_toc->item(i)._filename, i);
newitem = (int)_textlist->count();
_textlist->append(titem);
}
//
// *** view last page of previous file
//
if (newitem != _item)
{
_item = newitem;
_page_patch->body(
new Margin(_textlist->item(newitem)._view, 10.0, 10.0, 10.0, 10.0)
);
_page_patch->reallocate();
_page_patch->redraw();
_current_page = _textlist->item(newitem)._view->last_page();
}
}
void HyperViewer::pop()
{
long top;
HyperSource hypersrc;
//
// *** if nothing in stack, return
//
if ((top = _hyperstack->count()) == 0)
return;
//
// *** pop stack
//
hypersrc = _hyperstack->item(top - 1);
_hyperstack->remove(top-1);
//
// *** jump back to the hypertext source
//
if (_item != hypersrc._item)
{
_item = hypersrc._item;
_page_patch->body(
new Margin(_textlist->item(_item)._view, 10.0, 10.0, 10.0, 10.0)
);
_page_patch->reallocate();
_page_patch->redraw();
if (hypersrc._page != 0)
page_to(hypersrc._page);
}
else
page_to(hypersrc._page);
}