home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1990 / 06 / king.lst < prev    next >
File List  |  1990-05-02  |  12KB  |  495 lines

  1. _A SELF-REFERENTIAL HYPERTEXT ENGINE_
  2. by Todd King
  3.  
  4. [LISTING ONE]
  5.  
  6. /*-----------------------------------------
  7.   Demonstrates basic principles of hypertext
  8.   document construction and management.
  9.   (c) Copyright 1989 Todd King
  10.      All Rights Reserved
  11.   Written: Todd King
  12. -------------------------------------------*/
  13.  
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <conio.h>
  17. #include <ctype.h>
  18. #include "hyper_d.h"
  19.  
  20. main()
  21. {
  22.   int n;
  23.  
  24.   clrscr();
  25.   printf("(c) Copyright 1989 Todd King. All Rights Reserved\n");
  26.   sleep(2);
  27.  
  28.   if((Hyper_fptr = fopen("HYPER.TXT", "r")) == NULL)
  29.   {
  30.     perror("fopen");
  31.     exit(1);
  32.   }
  33.  
  34.   build_hyperbase();
  35.  
  36.   n = 0;
  37.   while((n = enter_text(Hyperbase[n].tag)) != -1) ;
  38.  
  39.   clrscr();
  40.   fclose(Hyper_fptr);
  41. }
  42.  
  43. /*-----------------------------------------
  44.   Builds the global index data base for the
  45.   hypertext document.
  46.   Written: Todd King
  47. -------------------------------------------*/
  48. build_hyperbase()
  49. {
  50.   char buffer[MAX_HYPER_LINE];
  51.   HYPERITEM *hitem;
  52.    int n;
  53.  
  54.   for(;;)
  55.   {
  56.     if(fgets(buffer, sizeof(buffer), Hyper_fptr) == NULL)
  57.     {
  58.       break;
  59.     }
  60.     switch(buffer[0])
  61.     {
  62.       case '\f':
  63.     if((hitem = make_item()) == NULL)
  64.     {
  65.       fprintf(stderr, "No more room in the Hyperbase\n");
  66.       exit(0);
  67.     }
  68.     fgets(buffer, sizeof(buffer), Hyper_fptr);
  69.     n = strlen(buffer);
  70.     if(buffer[n - 1] == '\n') buffer[n - 1] = '\0';
  71.     set_tag(hitem, buffer);
  72.     set_position(hitem, ftell(Hyper_fptr));
  73.     break;
  74.     }
  75.   }
  76.   return(Hyper_cnt);
  77. }
  78.  
  79. /*-----------------------------------------
  80.   Enters the hypertext document at a specific
  81.   tag location. It then allows navigation within
  82.   the document.
  83.   Written: Todd King
  84. -------------------------------------------*/
  85. enter_text(tag)
  86. char tag[];
  87. {
  88.   int c, n;
  89.   HYPERITEM *hitem;
  90.   char *bptr;
  91.   char *pptr;
  92.   char *tptr;
  93.   int i;
  94.   char buffer[MAX_HYPER_LINE];
  95.   int line_put;
  96.   int line_cnt = 3;
  97.   int col_cnt = 0;
  98.   int ref_cnt = 0;
  99.   int hidx;
  100.   HYPER_REF hyper_ref[MAX_HYPER];
  101.  
  102.   hitem = find_item(tag);
  103.   if(hitem == NULL)
  104.   {
  105.      fprintf(stderr,
  106.       "No hypertext subject by the name of '%s' exists\n", tag);
  107.     return(-1);
  108.   }
  109.   hidx = hyper_idx(tag);
  110.   clrscr();
  111.   fseek(Hyper_fptr, hitem->position, SEEK_SET);
  112.   bptr = fgets(buffer, sizeof(buffer), Hyper_fptr);
  113.   textcolor(LIGHTGRAY);
  114.   gotoxy(1,24);
  115.   cputs("ESCAPE: to exit; UP ARROW, DOWN ARROW: to navigate");
  116.   gotoxy(1,1);
  117.   cputs(tag); cputs("\r\n"); cputs("\r\n");
  118.   while(bptr != NULL)    /* For all lines in the current hypercard */
  119.   {
  120.     col_cnt = 1;
  121.     for(i = 0; i < Hyper_cnt; i++)
  122.     {
  123.      if((pptr = strstr(bptr, Hyperbase[i].tag)) != NULL)
  124.      {
  125.        if( i == hidx) continue;    /* no self-referencing */
  126.        if(pptr != bptr)
  127.        {
  128.      if(!ispunct(*(pptr - 1)) && !isspace(*(pptr - 1))) continue;
  129.        }
  130.        tptr = pptr + strlen(Hyperbase[i].tag);
  131.        if(ispunct(*tptr) || isspace(*tptr) || *tptr == '\0')
  132.        {
  133.      /* Deliniator */
  134.        } else {        /* No good */
  135.      continue;
  136.        }
  137.  /* If we reach here we've found a genuine tag */
  138.     pptr[0] ='\0';
  139.     col_cnt += strlen(bptr);
  140.     hyper_ref[ref_cnt].line = line_cnt;
  141.     hyper_ref[ref_cnt].column = col_cnt;
  142.     hyper_ref[ref_cnt].tag = Hyperbase[i].tag;
  143.     cputs(bptr);
  144.     textcolor(YELLOW);
  145.     cputs(Hyperbase[i].tag);
  146.     textcolor(LIGHTGRAY);
  147.     bptr = pptr + strlen(Hyperbase[i].tag);
  148.     col_cnt += strlen(Hyperbase[i].tag);
  149.     ref_cnt++;
  150.       }
  151.     }
  152.     cputs(bptr);
  153.     cprintf("\r");
  154.     if(line_cnt >= 23) {  /* What to do at the end of a screen */
  155.        break;
  156.     }
  157.     bptr = fgets(buffer, sizeof(buffer), Hyper_fptr);
  158.     if(buffer[0] == '\f') bptr = NULL;
  159.     line_cnt++;
  160.     col_cnt = 0;
  161.   }
  162.   if((n = nav_ref(hyper_ref, ref_cnt)) >= 0) return(n);
  163.  
  164. }
  165.  
  166. /*-----------------------------------------
  167.   The function which performs the actual
  168.   navigation within a hypertext document.
  169.   Written: Todd King
  170. -------------------------------------------*/
  171. nav_ref(hyper_ptr, max_ref)
  172. HYPER_REF hyper_ptr[];
  173. int max_ref;
  174. {
  175.   int advance = 0;
  176.   int selected = -1;
  177.   int cur_ref = 0;
  178.  
  179.   for(;;)
  180.   {
  181.     cur_ref += advance;
  182.     if(cur_ref < 0) cur_ref = max_ref - 1;
  183.     if(cur_ref >= max_ref) cur_ref = 0;
  184.     advance = 0;
  185.     gotoxy(hyper_ptr[cur_ref].column, hyper_ptr[cur_ref].line);
  186.     textbackground(LIGHTGRAY);
  187.     textcolor(BLACK);
  188.     cputs(hyper_ptr[cur_ref].tag);
  189.     switch(getch())
  190.     {
  191.       case 0:
  192.     switch(getch())
  193.     {
  194.       case DOWN_ARROW:
  195.         advance = 1;
  196.         break;
  197.       case UP_ARROW:
  198.         advance = -1;
  199.         break;
  200.     }
  201.     break;
  202.       case '\r':
  203.       case '\n':
  204.     selected = cur_ref;
  205.     break;
  206.        case ESC:
  207.     textbackground(BLACK);
  208.     textcolor(LIGHTGRAY);
  209.     return(-1);
  210.     }
  211.     gotoxy(hyper_ptr[cur_ref].column, hyper_ptr[cur_ref].line);
  212.     textcolor(YELLOW);
  213.     textbackground(BLACK);
  214.     cputs(hyper_ptr[cur_ref].tag);
  215.     if(selected != -1) return(hyper_idx(hyper_ptr[selected].tag));
  216.   }
  217. }
  218.  
  219. /*-----------------------------------------
  220.   Determines the index of a hypertext tag
  221.   within the global database.
  222.   Written: Todd King
  223. -------------------------------------------*/
  224. hyper_idx(tag_str)
  225. char tag_str[];
  226. {
  227.   int i;
  228.   for(i = 0; i < Hyper_cnt; i++) {
  229.     if(strcmp(tag_str, Hyperbase[i].tag) == 0) return(i);
  230.   }
  231.   return(-1);
  232. }
  233.  
  234. /*-----------------------------------------
  235.   Locates an item in the global database
  236.   with the tag as a key. Returns a pointer
  237.   to the entry or NULL if one does not exist.
  238.   Written: Todd King
  239. -------------------------------------------*/
  240. HYPERITEM *find_item(tag)
  241. char tag[];
  242. {
  243.   HYPERITEM *hitem;
  244.   int i;
  245.  
  246.   for(i = 0; i < Hyper_cnt; i++)
  247.   {
  248.     hitem = &Hyperbase[i];
  249.     if(strcmp(tag, hitem->tag) == 0) return(hitem);
  250.   }
  251.   return(NULL);
  252. }
  253.  
  254. /*-----------------------------------------
  255.   Sets the tag portion of a database entry to
  256.   the contents in a passed string
  257.   Written: Todd King
  258. -------------------------------------------*/
  259. set_tag(hitem, buffer)
  260. HYPERITEM *hitem;
  261. char buffer[];
  262. {
  263.   char *malloc();
  264.  
  265.   hitem->tag = malloc(strlen(buffer) + 1);
  266.   if(hitem->tag == NULL)
  267.   {
  268.     perror("malloc");
  269.     exit(2);
  270.   }
  271.   strcpy(hitem->tag, buffer);
  272. }
  273.  
  274. /*-----------------------------------------
  275.   Makes (extracts) a new database entry item
  276.   from the item pool.
  277.   Written: Todd King
  278. -------------------------------------------*/
  279. HYPERITEM *make_item()
  280. {
  281.   if(Hyper_cnt >= MAX_HYPER) return(NULL);
  282.   return(&Hyperbase[Hyper_cnt++]);
  283. }
  284.  
  285.  
  286. [LISTING TWO]
  287.  
  288. #define UP_ARROW    72
  289. #define DOWN_ARROW    80
  290. #define ESC        27
  291.  
  292. typedef struct {
  293.   char *tag;
  294.   int position;
  295. } HYPERITEM;
  296.  
  297. typedef struct {
  298.     int line;
  299.     int column;
  300.     char *tag;
  301.   } HYPER_REF;
  302.  
  303. #define MAX_HYPER    1024
  304. HYPERITEM Hyperbase[MAX_HYPER];
  305. int Hyper_cnt = 0;
  306.  
  307. FILE *Hyper_fptr;
  308.  
  309. HYPERITEM *make_item();
  310. HYPERITEM *find_item();
  311. #define set_position(h, p)  h->position = p
  312.  
  313. #define TRUE    1
  314. #define FALSE    0
  315.  
  316. #define MAX_HYPER_LINE    80
  317.  
  318.  
  319.  
  320.  
  321. [LISTING THREE]
  322.  
  323. ................................................................. 
  324. Function Flow Diagram
  325.  
  326.  main()       build_hyperbase()             make_item() 
  327.  
  328.                                              set_tag() 
  329.  
  330.                                           set_position() 
  331.  
  332.                  enter_text()              find_item() 
  333.  
  334.                                           hyper_idx() 
  335.  
  336.                                             nav_ref() 
  337. ................................................................. 
  338. main()
  339.  
  340. This is an application which displays a hypertext document.
  341. It automatically creates a list of hyper-items (or cards)
  342. which are in the hypertext document. Then it creates the
  343. appropriate links so that you can navigate to any item
  344. which is referenced by any other item. It uses the contents
  345. of the file "HYPER.TXT" as the hypertext document and begins
  346. at the first item in the document.
  347.  
  348.  
  349. Function Flow Diagram
  350. .................................................................
  351. build_hyperbase()
  352.  
  353. build_hyperbase()
  354.  
  355. This function builds the global database for the hypertext
  356. document. It scans the entire document an assembles a list
  357. of all cards in the document and stores their location
  358. within the file and the tag which the card is to be known
  359. by. This database is stored in the global variable
  360. "Hyperbase".
  361.  
  362.  
  363. Function Flow Diagram
  364. .................................................................
  365. enter_text()
  366.  
  367. enter_text(tag)
  368. char tag[];
  369.  
  370. Enters the hypertext document at a specific
  371. tag location. The tag (a string) is passed in the variable
  372. first variable called "tag". It then allows navigation
  373. within the document.
  374.  
  375.  
  376. Function Flow Diagram
  377. .................................................................
  378. nav_ref()
  379.  
  380. nav_ref(cur_ref, hyper_ptr, max_ref)
  381. int cur_ref;
  382. HYPER_REF hyper_ptr[];
  383. int max_ref;
  384.  
  385. This function performs the actual navigation within a
  386. single card. It returns the index of the hyper-item within
  387. the card which was selected. A special code (-1) is returned
  388. if a request to exit is entered. "cur_ref" is the index of
  389. the current card, "hyper_ptr" is a pointer to a structure
  390. containing the list of references in the card and "max_ref
  391. is the number of references in "hyper_ptr".
  392.  
  393.  
  394. Function Flow Diagram
  395. .................................................................
  396. hyper_idx()
  397.  
  398. hyper_idx(tag_str)
  399. char tag_str();
  400.  
  401. Returns the index of the tag "tag_str". The global
  402. database ("Hyperbase") is searched for the existence of
  403. the tag.
  404.  
  405.  
  406. Function Flow Diagram
  407. .................................................................
  408. find_item()
  409.  
  410. HYPERITEM *find_item(tag)
  411. char tag[];
  412.  
  413. Locates an item in the global database ("Hyperbase")
  414. with the tag as a key. Returns a pointer
  415. to the entry or NULL if one does not exist.
  416.  
  417.  
  418. Function Flow Diagram
  419. .................................................................
  420. set_tag()
  421.  
  422. set_tag(hitem, buffer)
  423. HYPERITEM *hitem;
  424. char buffer[];
  425.  
  426. Sets the tag portion of the database entry pointed
  427. to by "hitem" to the contents in the string "buffer".
  428.  
  429.  
  430. Function Flow Diagram
  431. .................................................................
  432. make_item()
  433.  
  434. HYPERITEM *make_item()
  435.  
  436. Makes a new database entry. Actually it extracts
  437. the next available entry for a pool and returns a pointer
  438. to the entry.
  439.  
  440.  
  441. Function Flow Diagram
  442. .................................................................
  443. set_position()
  444.  
  445. set_position(h, p)
  446. HYPERITEM *h;
  447. int p;
  448.  
  449. Actually a psuedo-function (created with a define) which
  450. assigns an location of an item in a file to the item
  451. definition.
  452.  
  453.  
  454. Function Flow Diagram
  455. .................................................................
  456. HYPERITEM
  457.  
  458. A structure which contains a complete description a single
  459. item (or card) with the hypertext document. It is of the
  460. form:
  461.  
  462. typedef struct {
  463.   char *tag;
  464.   int position;
  465. } HYPERITEM;
  466.  
  467.  
  468. Function Flow Diagram
  469. .................................................................
  470. HYPER_REF
  471.  
  472. A structure of the form:
  473.  
  474. typedef struct {
  475.     int line;
  476.     int column;
  477.     char *tag;
  478.   } HYPER_REF;
  479.  
  480.  
  481. Function Flow Diagram
  482. .................................................................
  483. HYPER.TXT
  484.  
  485. The text file which contains the hypertext document. The
  486. beginning of an item is marked by a special line. This line
  487. is a formfeed followed by a newline. The next line after
  488. this is considerd to be the name of the item (the item tag).
  489. If this name appears in any other tag then navigation to
  490. the item is allowed by selecting the tag in the item.
  491.  
  492.  
  493. Function Flow Diagram
  494.  
  495.