home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
drdobbs
/
1990
/
06
/
king.lst
< prev
next >
Wrap
File List
|
1990-05-02
|
12KB
|
495 lines
_A SELF-REFERENTIAL HYPERTEXT ENGINE_
by Todd King
[LISTING ONE]
/*-----------------------------------------
Demonstrates basic principles of hypertext
document construction and management.
(c) Copyright 1989 Todd King
All Rights Reserved
Written: Todd King
-------------------------------------------*/
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <ctype.h>
#include "hyper_d.h"
main()
{
int n;
clrscr();
printf("(c) Copyright 1989 Todd King. All Rights Reserved\n");
sleep(2);
if((Hyper_fptr = fopen("HYPER.TXT", "r")) == NULL)
{
perror("fopen");
exit(1);
}
build_hyperbase();
n = 0;
while((n = enter_text(Hyperbase[n].tag)) != -1) ;
clrscr();
fclose(Hyper_fptr);
}
/*-----------------------------------------
Builds the global index data base for the
hypertext document.
Written: Todd King
-------------------------------------------*/
build_hyperbase()
{
char buffer[MAX_HYPER_LINE];
HYPERITEM *hitem;
int n;
for(;;)
{
if(fgets(buffer, sizeof(buffer), Hyper_fptr) == NULL)
{
break;
}
switch(buffer[0])
{
case '\f':
if((hitem = make_item()) == NULL)
{
fprintf(stderr, "No more room in the Hyperbase\n");
exit(0);
}
fgets(buffer, sizeof(buffer), Hyper_fptr);
n = strlen(buffer);
if(buffer[n - 1] == '\n') buffer[n - 1] = '\0';
set_tag(hitem, buffer);
set_position(hitem, ftell(Hyper_fptr));
break;
}
}
return(Hyper_cnt);
}
/*-----------------------------------------
Enters the hypertext document at a specific
tag location. It then allows navigation within
the document.
Written: Todd King
-------------------------------------------*/
enter_text(tag)
char tag[];
{
int c, n;
HYPERITEM *hitem;
char *bptr;
char *pptr;
char *tptr;
int i;
char buffer[MAX_HYPER_LINE];
int line_put;
int line_cnt = 3;
int col_cnt = 0;
int ref_cnt = 0;
int hidx;
HYPER_REF hyper_ref[MAX_HYPER];
hitem = find_item(tag);
if(hitem == NULL)
{
fprintf(stderr,
"No hypertext subject by the name of '%s' exists\n", tag);
return(-1);
}
hidx = hyper_idx(tag);
clrscr();
fseek(Hyper_fptr, hitem->position, SEEK_SET);
bptr = fgets(buffer, sizeof(buffer), Hyper_fptr);
textcolor(LIGHTGRAY);
gotoxy(1,24);
cputs("ESCAPE: to exit; UP ARROW, DOWN ARROW: to navigate");
gotoxy(1,1);
cputs(tag); cputs("\r\n"); cputs("\r\n");
while(bptr != NULL) /* For all lines in the current hypercard */
{
col_cnt = 1;
for(i = 0; i < Hyper_cnt; i++)
{
if((pptr = strstr(bptr, Hyperbase[i].tag)) != NULL)
{
if( i == hidx) continue; /* no self-referencing */
if(pptr != bptr)
{
if(!ispunct(*(pptr - 1)) && !isspace(*(pptr - 1))) continue;
}
tptr = pptr + strlen(Hyperbase[i].tag);
if(ispunct(*tptr) || isspace(*tptr) || *tptr == '\0')
{
/* Deliniator */
} else { /* No good */
continue;
}
/* If we reach here we've found a genuine tag */
pptr[0] ='\0';
col_cnt += strlen(bptr);
hyper_ref[ref_cnt].line = line_cnt;
hyper_ref[ref_cnt].column = col_cnt;
hyper_ref[ref_cnt].tag = Hyperbase[i].tag;
cputs(bptr);
textcolor(YELLOW);
cputs(Hyperbase[i].tag);
textcolor(LIGHTGRAY);
bptr = pptr + strlen(Hyperbase[i].tag);
col_cnt += strlen(Hyperbase[i].tag);
ref_cnt++;
}
}
cputs(bptr);
cprintf("\r");
if(line_cnt >= 23) { /* What to do at the end of a screen */
break;
}
bptr = fgets(buffer, sizeof(buffer), Hyper_fptr);
if(buffer[0] == '\f') bptr = NULL;
line_cnt++;
col_cnt = 0;
}
if((n = nav_ref(hyper_ref, ref_cnt)) >= 0) return(n);
}
/*-----------------------------------------
The function which performs the actual
navigation within a hypertext document.
Written: Todd King
-------------------------------------------*/
nav_ref(hyper_ptr, max_ref)
HYPER_REF hyper_ptr[];
int max_ref;
{
int advance = 0;
int selected = -1;
int cur_ref = 0;
for(;;)
{
cur_ref += advance;
if(cur_ref < 0) cur_ref = max_ref - 1;
if(cur_ref >= max_ref) cur_ref = 0;
advance = 0;
gotoxy(hyper_ptr[cur_ref].column, hyper_ptr[cur_ref].line);
textbackground(LIGHTGRAY);
textcolor(BLACK);
cputs(hyper_ptr[cur_ref].tag);
switch(getch())
{
case 0:
switch(getch())
{
case DOWN_ARROW:
advance = 1;
break;
case UP_ARROW:
advance = -1;
break;
}
break;
case '\r':
case '\n':
selected = cur_ref;
break;
case ESC:
textbackground(BLACK);
textcolor(LIGHTGRAY);
return(-1);
}
gotoxy(hyper_ptr[cur_ref].column, hyper_ptr[cur_ref].line);
textcolor(YELLOW);
textbackground(BLACK);
cputs(hyper_ptr[cur_ref].tag);
if(selected != -1) return(hyper_idx(hyper_ptr[selected].tag));
}
}
/*-----------------------------------------
Determines the index of a hypertext tag
within the global database.
Written: Todd King
-------------------------------------------*/
hyper_idx(tag_str)
char tag_str[];
{
int i;
for(i = 0; i < Hyper_cnt; i++) {
if(strcmp(tag_str, Hyperbase[i].tag) == 0) return(i);
}
return(-1);
}
/*-----------------------------------------
Locates an item in the global database
with the tag as a key. Returns a pointer
to the entry or NULL if one does not exist.
Written: Todd King
-------------------------------------------*/
HYPERITEM *find_item(tag)
char tag[];
{
HYPERITEM *hitem;
int i;
for(i = 0; i < Hyper_cnt; i++)
{
hitem = &Hyperbase[i];
if(strcmp(tag, hitem->tag) == 0) return(hitem);
}
return(NULL);
}
/*-----------------------------------------
Sets the tag portion of a database entry to
the contents in a passed string
Written: Todd King
-------------------------------------------*/
set_tag(hitem, buffer)
HYPERITEM *hitem;
char buffer[];
{
char *malloc();
hitem->tag = malloc(strlen(buffer) + 1);
if(hitem->tag == NULL)
{
perror("malloc");
exit(2);
}
strcpy(hitem->tag, buffer);
}
/*-----------------------------------------
Makes (extracts) a new database entry item
from the item pool.
Written: Todd King
-------------------------------------------*/
HYPERITEM *make_item()
{
if(Hyper_cnt >= MAX_HYPER) return(NULL);
return(&Hyperbase[Hyper_cnt++]);
}
[LISTING TWO]
#define UP_ARROW 72
#define DOWN_ARROW 80
#define ESC 27
typedef struct {
char *tag;
int position;
} HYPERITEM;
typedef struct {
int line;
int column;
char *tag;
} HYPER_REF;
#define MAX_HYPER 1024
HYPERITEM Hyperbase[MAX_HYPER];
int Hyper_cnt = 0;
FILE *Hyper_fptr;
HYPERITEM *make_item();
HYPERITEM *find_item();
#define set_position(h, p) h->position = p
#define TRUE 1
#define FALSE 0
#define MAX_HYPER_LINE 80
[LISTING THREE]
.................................................................
Function Flow Diagram
main() build_hyperbase() make_item()
set_tag()
set_position()
enter_text() find_item()
hyper_idx()
nav_ref()
.................................................................
main()
This is an application which displays a hypertext document.
It automatically creates a list of hyper-items (or cards)
which are in the hypertext document. Then it creates the
appropriate links so that you can navigate to any item
which is referenced by any other item. It uses the contents
of the file "HYPER.TXT" as the hypertext document and begins
at the first item in the document.
Function Flow Diagram
.................................................................
build_hyperbase()
build_hyperbase()
This function builds the global database for the hypertext
document. It scans the entire document an assembles a list
of all cards in the document and stores their location
within the file and the tag which the card is to be known
by. This database is stored in the global variable
"Hyperbase".
Function Flow Diagram
.................................................................
enter_text()
enter_text(tag)
char tag[];
Enters the hypertext document at a specific
tag location. The tag (a string) is passed in the variable
first variable called "tag". It then allows navigation
within the document.
Function Flow Diagram
.................................................................
nav_ref()
nav_ref(cur_ref, hyper_ptr, max_ref)
int cur_ref;
HYPER_REF hyper_ptr[];
int max_ref;
This function performs the actual navigation within a
single card. It returns the index of the hyper-item within
the card which was selected. A special code (-1) is returned
if a request to exit is entered. "cur_ref" is the index of
the current card, "hyper_ptr" is a pointer to a structure
containing the list of references in the card and "max_ref
is the number of references in "hyper_ptr".
Function Flow Diagram
.................................................................
hyper_idx()
hyper_idx(tag_str)
char tag_str();
Returns the index of the tag "tag_str". The global
database ("Hyperbase") is searched for the existence of
the tag.
Function Flow Diagram
.................................................................
find_item()
HYPERITEM *find_item(tag)
char tag[];
Locates an item in the global database ("Hyperbase")
with the tag as a key. Returns a pointer
to the entry or NULL if one does not exist.
Function Flow Diagram
.................................................................
set_tag()
set_tag(hitem, buffer)
HYPERITEM *hitem;
char buffer[];
Sets the tag portion of the database entry pointed
to by "hitem" to the contents in the string "buffer".
Function Flow Diagram
.................................................................
make_item()
HYPERITEM *make_item()
Makes a new database entry. Actually it extracts
the next available entry for a pool and returns a pointer
to the entry.
Function Flow Diagram
.................................................................
set_position()
set_position(h, p)
HYPERITEM *h;
int p;
Actually a psuedo-function (created with a define) which
assigns an location of an item in a file to the item
definition.
Function Flow Diagram
.................................................................
HYPERITEM
A structure which contains a complete description a single
item (or card) with the hypertext document. It is of the
form:
typedef struct {
char *tag;
int position;
} HYPERITEM;
Function Flow Diagram
.................................................................
HYPER_REF
A structure of the form:
typedef struct {
int line;
int column;
char *tag;
} HYPER_REF;
Function Flow Diagram
.................................................................
HYPER.TXT
The text file which contains the hypertext document. The
beginning of an item is marked by a special line. This line
is a formfeed followed by a newline. The next line after
this is considerd to be the name of the item (the item tag).
If this name appears in any other tag then navigation to
the item is allowed by selecting the tag in the item.
Function Flow Diagram