DECLARE SUB LoadLinks (LinkArray() AS ANY)
DECLARE SUB Main (LinkArray() AS ANY)
DECLARE SUB Parse (link%, LinkArray() AS ANY)
DECLARE FUNCTION OnLink% (Row AS INTEGER, Col AS INTEGER, LinkArray() AS ANY)
DECLARE FUNCTION TabLink% (Row AS INTEGER, Col AS INTEGER, LinkArray() AS ANY)
DEFINT A-Z

'$INCLUDE: 'dialog.bi'
'$DYNAMIC

TYPE LinkStringType
   text AS STRING * 200
   Row AS INTEGER
   Col AS INTEGER
   WordLen AS INTEGER
   Pointer AS INTEGER
END TYPE

CONST DEFAULT = 1, MAXLINKS = 50, TABSPACE = 4

DIM SHARED LinkCount AS INTEGER
DIM LinkArray(0) AS LinkStringType

CALL Parse(DEFAULT, LinkArray())
CALL Main(LinkArray())

END

LinkData:

DATA "<name='default'><span>QBLinks<hr>"
DATA "<tab>QBLinks is a utility designed for QB programmers to implement an on screen"
DATA "link system. It uses tags similar to those found in HTML to interpret where"
DATA "links are and where they point to."
DATA "<tab>Use the arrow keys to move the cursor around the screen, or press the TAB"
DATA "key to goto the next link. Then select a link by pressing ENTER or SPACEBAR.<br>"
DATA "<link ref='tags'>QBLink Tags</link>"
DATA "<link ref='whitesp'>White Space</link>"
DATA "<link ref='data'>DATA Statements</link>"
DATA "<link ref='limits'>Limitations</link></span>"

DATA "<name='tags'><span>QBLink Tags<col 40><link ref='default'>Main Page</link><hr>"
DATA "<tab>When QBLinks is used without any tags, it will just print the text on the"
DATA "screen. The following table is a list of tags available to both format your"
DATA "text and insert links.<br>"
DATA "<link ref='hr'> <hr> </link><col 15>Horizonal Rules (lines)"
DATA "<link ref='tab'> <tab> </link><col 15>Tabs"
DATA "<link ref='link'> <link> </link><col 15>Links"
DATA "<link ref='char'> <char> </link><col 15>Screen Characters"
DATA "<link ref='name'> <name> </link><col 15>Naming the Links"
DATA "<link ref='col'> <col> </link><col 15>Column Alignment"
DATA "<link ref='span'> <span> </link><col 15>Multiple DATA line pages"
DATA "<link ref='br'> <br> </link><col 15>New Lines"
DATA "<link ref='src'> <src> </link><col 15>Using an external data file"
DATA "</span>"

DATA "<name='whitesp'><span>White Space<col 40><link ref='default'>Main Page</link><hr>"
DATA "<tab>White Space is generally the term used when writing text for an application"
DATA "that interprets tags in the text for special purposes. As in HTML, the author"
DATA "of the page can write the page in notepad, inserting tags as required, and use"
DATA "spacing to easily see the code. Web browsers will ignore this extra whitespace"
DATA "when they interpret the page and it's tags. So how the text spacing looks in"
DATA "the text editor will not be how it looks in the browser.<br>"
DATA "<tab>QBLinks does not do this. All the whitespace the author puts in the page"
DATA "will be displayed on the screen.</span>

DATA "<name='data'><span>DATA Statements<col 40><link ref='default'>Main Page</link><hr>"
DATA "<tab>QBLinks initially reads it's data from the QB DATA statement."
DATA "The first line of data it reads MUST come from a data statement, while"
DATA "subsequent pages and even the default page may come from a data file."
DATA "<tab>The first page displayed is, naturally, the default page. This page"
DATA "may come from either a DATA statement, or an external file using the <link ref='src'>Source</link>"
DATA "tag.</span>"

DATA "<name='limits'><span>Limits to QBLinks<col 40><link ref='default'>Main Page</link><hr>"
DATA "<tab>The limits of QBLinks is the same as that of the QB enviornment as well"
DATA "as a the few listed below.<br>"
DATA "<char 7> Page Size. The page size is limited to 32767 characters long, or 32k."
DATA "<tab>On a 25x80 resolution text screen (the default for QB and QBLinks, this is"
DATA "<tab>about 30 'screens' long. It would be best to keep your entire page within"
DATA "<tab>one (1) screen. The limit on the number of pages is restricted to the"
DATA "<tab>amount of memory QB provides.<br>"
DATA "<char 7> Number of Links. The number of links allowed on a page defaults to 50."
DATA "<tab>This can be easily increased or decreased by changing the constant"
DATA "<tab>MAXLINKS, found at the beginning of the program.</span>"

DATA "<name='hr'><span>The Horizonal Rule<col 40><link ref='default'>Main Page</link> <link ref='tags'>Tags</link><hr>
DATA "<char 7> Syntax: \<hr [len] [/]><br>"
DATA "<tab>The Horizontal Rule is nothing more than a line going across the screen."
DATA "It defaults to going all the way from the left side to the right, 80 characters"
DATA "long, and it prints a <link ref='br'>NewLine character</link>. These defaults can be overridden"
DATA "to force the line to a specific length at the end of the current line, or to"
DATA "prevent the newline.<br>"
DATA "<tab>Default horizonal rule: \<hr><hr>"
DATA "<tab>Horizonal rule with no newline:\<hr/><hr/>"
DATA "<br><tab>Specify a line five (5) characters long: \<hr 5><hr 5>"
DATA "<tab>Horizontal rule five (5) characters long and no newline: \<hr 5/><hr 5/>Text"
DATA "<br><tab>To fully understand how this works, you will have to actually use it in"
DATA "your own variations.</span>"

DATA "<name='tab'><span>Tab<col 40><link ref='default'>Main Page</link> <link ref='tags'>Tags</link><hr>"
DATA "<char 7> Syntax: \<tab><br>"
DATA "<tab>The Tab tag will automatically move your cursor a set number of spaces to"
DATA "the right from the current cursor position. The number of spaces a single"
DATA "\<tab> will move the cursor depends on the value of the global constant,"
DATA "TABSPACES, found in the beginning of the program.</span>"

DATA "<name='link'><span>Links<col 40><link ref='default'>Main Page</link> <link ref='tags'>Tags</link><hr>"
DATA "<char 7> Syntax: \<link { ref | number } [nosides]> text \</link><br>"
DATA "<tab>The \<link> tag is the most important tag in QBLinks. It is the tag that"
DATA "the user will interact with to navigate around your help system.<br>"
DATA "<tab>It is important that the link know which page to load once the user has"
DATA "selected it. This can be done by either specifying the <link ref='name'>name</link> of the page"
DATA "using 'ref', or by specifying the link 'number' relative to the beginning"
DATA "of your DATA statements.<br>"
DATA "<char 7> Using 'ref': \<link ref='howto'>See how to do it\</link>"
DATA "<char 7> Using 'number': \<link 2>Go to the page in the second DATA statement.\</link>"
DATA "<br><tab>By default, all links have the arrows on the sides. This is so users"
DATA "can easily see where a link is. But sometimes, borders are unnecessary;"
DATA "so borders can be turned off for a single link by using the 'nosides' attribute.</span>"

DATA "<name='char'><span>Extra Characters<col 40><link ref='default'>Main Page</link> <link ref='tags'>Tags</link><hr>"
DATA "<char 7> Syntax: \<char { ascii code }><br>"
DATA "<tab>The \<char> tag is used to display ASCII characters on the screen that would"
DATA "normally have an OS related function associated with them, such as characters"
DATA "1-31. These characters also have a printable 'character' as well. But the QB"
DATA "enviornment will always intercept these codes before they can be printed to"
DATA "the screen. That is where \<char> comes in to play. Use this tag to specify"
DATA "the ASCII code of any one (1) character to print. The most common use will"
DATA "probably be bullets: <char 7></span>"

DATA "<name='name'><span>Naming the pages<col 40><link ref='default'>Main Page</link> <link ref='tags'>Tags</link><hr>"
DATA "<char 7> Syntax: \<name='{ name }'><br>
DATA "<tab>Use the \<name> tag to specify the name for a page. Using a name is much"
DATA "more simple than having to keep track of how many DATA statements you have, or"
DATA "how long your data file is if you read all your pages in using the <link ref='src'>Source</link>"
DATA "tag. This tag is must be used before attempting to reference a page with the
DATA "<link ref='link'>Link</link> tag and using the 'ref={ name }' attribute.</span>"

DATA "<name='col'><span>Column Alignment<col 40><link ref='default'>Main Page</link> <link ref='tags'>Tags</link><hr>"
DATA "<char 7> Syntax: \<col { column number }><br>"
DATA "<tab>Use the \<col> tag to move the cursor to the specified column on the current"
DATA "row. This tag is usefull to help keep text aligned vertically when working"
DATA "with multiple columns. If the column specified is out of range (less than 1"
DATA "or greater than 80), this tag will have no effect.</span>"

DATA "<name='span'><span>Multiple DATA line pages<col 40><link ref='default'>Main Page</link> <link ref='tags'>Tags</link><hr>"
DATA "<char 7> Syntax: \<span>page text<br>"
DATA "<tab>This tag is very important. It allows the page author to use multiple DATA"
DATA "statements to write a help page. Without using this tag, the author is"
DATA "restricted to a 256 character help page (the max length allowed in the QB"
DATA "enviornment).<br>"
DATA "<tab>Be sure to always have the closing tag \</span> when using this tag to"
DATA "prevent QBLinks from reading all the way through your DATA statements."
DATA "<br><tab><char 7> View the source code to see exactly how this tag works.</span>"

DATA "<name='br'><span>NewLine<col 40><link ref='default'>Main Page</link> <link ref='tags'>Tags</link><hr>"
DATA "<char 7> Syntax: \<br><br>"
DATA "<tab>The newline tag is one of the more simple tags, yet very usefull."
DATA "It allows you to separate the lines in the help page so the user can see"
DATA "your page more clearly.</span>"

DATA "<name='src'><span>Using an external data file<col 40><link ref='default'>Main Page</link> <link ref='tags'>Tags</link><hr>"
DATA "<char 7> Syntax: \<src='{ filename }'><br>"
DATA "<tab>You can specify an external data file as a source for your help page,"
DATA "rather than relying on multiple QB DATA statements. This external file must be"
DATA "written using all the same tags as in the QB DATA statements except for the"
DATA "\<span> tag, which is used only for DATA statements.<br>"
DATA "<tab>Users of QB4.5 can take great advantage of this feature because of the QB"
DATA "enviornment's ability to load and modify text documents with the QBLinks"
DATA "program loaded. This allows users to build their text file then test it"
DATA "immediately to ensure it looks right. Users of older versions will have"
DATA "to write the file in an external editor, then run QB to test it."
DATA "</span>"

DATA "EOF"

REM $STATIC
SUB Main (LinkArray() AS LinkStringType)

DIM Row AS INTEGER, Col AS INTEGER
DIM kb AS STRING
DIM LinkX AS INTEGER

Row = 1
Col = 1
LinkX = TabLink(Row, Col, LinkArray())
IF LinkX THEN
   Row = LinkArray(LinkX).Row
   Col = LinkArray(LinkX).Col + 1
END IF
DO
   LOCATE Row, Col, 1
   DO
      kb$ = INKEY$
   LOOP WHILE kb$ = ""
   IF LEFT$(kb$, 1) = CHR$(0) THEN
      SELECT CASE RIGHT$(kb$, 1)
         CASE CHR$(cstUP)
            IF Row > 1 THEN Row = Row - 1
         CASE CHR$(cstDOWN)
            IF Row < 25 THEN Row = Row + 1
         CASE CHR$(cstLEFT)
            IF Col > 1 THEN Col = Col - 1
         CASE CHR$(cstRIGHT)
            IF Col < 80 THEN Col = Col + 1
      END SELECT

   ELSEIF kb$ = CHR$(cstENTER) OR kb$ = CHR$(cstSPACE) THEN
      LinkX = OnLink(Row, Col, LinkArray())
      IF LinkX THEN CALL Parse(LinkX, LinkArray())
      Row = 1: Col = 1
      LinkX = TabLink(Row, Col, LinkArray())
      IF LinkX THEN
         Row = LinkArray(LinkX).Row
         Col = LinkArray(LinkX).Col + 1
      END IF

   ELSEIF kb$ = CHR$(cstTAB) THEN
      LinkX = TabLink(Row, Col, LinkArray())
      IF LinkX THEN
         Row = LinkArray(LinkX).Row
         Col = LinkArray(LinkX).Col + 1
      END IF

   END IF
LOOP UNTIL kb$ = CHR$(cstESC)

END SUB

FUNCTION OnLink (Row AS INTEGER, Col AS INTEGER, LinkArray() AS LinkStringType)

OnLink = 0
FOR x = 1 TO LinkCount
   IF Row = LinkArray(x).Row THEN
      IF Col >= LinkArray(x).Col AND Col <= LinkArray(x).Col + LinkArray(x).WordLen + 1 THEN
         OnLink = LinkArray(x).Pointer
         EXIT FOR
      END IF
   END IF
NEXT x

END FUNCTION

SUB Parse (Parent, LinkArray() AS LinkStringType)

DIM file AS STRING
DIM tag AS STRING
DIM Letter AS STRING * 1
DIM link AS STRING
DIM x AS INTEGER, Row AS INTEGER, Col AS INTEGER

x = 1
Row = 1
Col = 1

RESTORE LinkData
FOR x = 1 TO Parent - 1
   READ link
   LinkLine = LinkLine + 1
NEXT x

DIM TempLinks(1 TO MAXLINKS) AS LinkStringType
LinkCount = 0

CLS
DataSpan = 0
DO
   LinkLine = LinkLine + 1
   READ link
   IF link = "EOF" THEN EXIT DO
   IF INSTR(link, "<name=") THEN
      x = INSTR(5, link, ">") + 1
      link = MID$(link, x)
   END IF
   x = 1
   DO UNTIL x > LEN(link)

      Letter = MID$(link, x, 1)
      IF Letter = "<" AND Literal = FALSE THEN

         tag = ""
         DO UNTIL Letter = ">"
            Letter = MID$(link, x, 1)
            tag = tag + Letter
            x = x + 1
         LOOP

         IF tag = "<br>" THEN
            Col = 1: Row = Row + 1

         ELSEIF tag = "<tab>" THEN
            Col = Col + TABSPACE
            IF Col > 80 THEN Col = 1: Row = Row + 1

         ELSEIF LEFT$(tag, 4) = "<col" THEN
            tag = LEFT$(tag, LEN(tag) - 1)
            tag = MID$(tag, 6)
            xCol = VAL(tag)
            IF xCol > 0 AND xCol < 81 THEN Col = xCol

         ELSEIF LEFT$(tag, 5) = "<char" THEN
            ch = VAL(MID$(tag, 6))
            LOCATE Row, Col
            CALL scrPrint(ch, 7, 0)
            Col = Col + 1

         ELSEIF LEFT$(tag, 3) = "<hr" THEN
            newline = TRUE
            IF MID$(tag, 4, 1) = "/" THEN
               newline = FALSE
               tag = LEFT$(tag, 3) + MID$(tag, 5)
            END IF
            IF LEN(tag) > 4 THEN
               tag = LEFT$(tag, LEN(tag) - 1)
               tag = MID$(tag, 4)
               ruler = VAL(tag)
            ELSE
               'Col = 0
               'Row = Row + 1
               ruler = 80
            END IF
            LOCATE Row, Col + 1
            PRINT STRING$(ruler, CHR$(196));
            Col = Col + 1
            IF newline THEN Row = Row + 1

         ELSEIF LEFT$(tag, 4) = "<src" THEN
            FileNum = FREEFILE
            ftstart = INSTR(tag, "='") + 2
            ftend = INSTR(tag, "'>")
            FileName$ = MID$(tag, ftstart, ftend - ftstart)
            OPEN FileName$ FOR INPUT AS #FileNum
            DIM Lk AS STRING
            link = ""
            DO UNTIL EOF(FileNum)
               LINE INPUT #FileNum, Lk
               link = link + Lk + " "
            LOOP
            CLOSE #FileNum
            LinkCount = 0
            CLS : x = 1: Col = 1: Row = 1

         ELSEIF LEFT$(tag, 5) = "<span" THEN
            DataSpan = 0

            tag$ = LEFT$(tag, LEN(tag$) - 1)
            tag$ = MID$(tag, 6)
            IF tag$ = "" THEN
               DataSpan = TRUE
            ELSE
               DataSpan = VAL(tag$)
            END IF

         ELSEIF tag = "</span>" THEN
            DataSpan = 0

         ELSEIF LEFT$(tag, 5) = "<link" THEN

            LinkCount = LinkCount + 1

            InTag$ = ""
            nosides = FALSE
            InX = 6
            num = 0
            InXStr$ = ""
            opt$ = ""
            DO UNTIL InXStr$ = ">"
               InXStr$ = MID$(tag, InX, 1)
               IF InXStr$ = " " OR InXStr$ = ">" THEN
                  IF opt$ = "nosides" THEN
                     nosides = TRUE
                  ELSEIF LEFT$(opt$, 4) = "ref=" THEN
                     RefX = 0
                     RefXLink$ = ""
                     RESTORE LinkData
                     Search$ = "<name=" + MID$(opt$, 5)
                     DO UNTIL INSTR(RefXLink$, Search$) OR RefXLink$ = "EOF"
                        READ RefXLink$
                        RefX = RefX + 1
                     LOOP
                     num = RefX
                     RESTORE LinkData
                     FOR px = 1 TO LinkLine
                        READ pd$
                     NEXT px
                  ELSE
                     num = VAL(opt$)
                  END IF
                  opt$ = ""
               ELSE
                  opt$ = opt$ + InXStr$
               END IF
               InX = InX + 1
            LOOP

            Col = Col + nosides
            TempLinks(LinkCount).Pointer = num
            TempLinks(LinkCount).Row = Row
            TempLinks(LinkCount).Col = Col

            endword = INSTR(x, link, "</link>")
            Word$ = MID$(link, x, endword - x)
            MID$(Word$, 1, 1) = UCASE$(LEFT$(Word$, 1))
            TempLinks(LinkCount).WordLen = LEN(Word$) + nosides

            x = endword
            LOCATE Row, Col
            IF NOT nosides THEN CALL scrPrint(17, 2, 0)
            LOCATE , Col + 1 + noside: PRINT Word$;
            IF NOT nosides THEN CALL scrPrint(16, 2, 0)
            Col = Col + LEN(Word$) + 2 + nosides

         END IF
      ELSE
         IF Letter = "\" AND Literal = FALSE THEN
            Literal = TRUE
            x = x + 1
         ELSE
            LOCATE Row, Col
            PRINT Letter;
            x = x + 1
            Col = Col + 1
            IF Col = 81 THEN Col = 1: Row = Row + 1
            Literal = FALSE
         END IF
      END IF
   LOOP
   IF DataSpan > 0 THEN DataSpan = DataSpan - 1
   Row = Row + 1: Col = 1
LOOP WHILE DataSpan <> 0

IF LinkCount > 0 THEN
REDIM LinkArray(1 TO LinkCount) AS LinkStringType
FOR x = 1 TO LinkCount
LinkArray(x) = TempLinks(x)
NEXT x
END IF

END SUB

FUNCTION TabLink (Row AS INTEGER, Col AS INTEGER, LinkArray() AS LinkStringType)

TabLink = 0

pRow = Row
pCol = Col
LinkFound = FALSE
IF LinkCount > 0 THEN
DO UNTIL LinkFound
   FOR pRow = Row TO 25
      FOR xCol = pCol TO 80
         FOR hp = 1 TO LinkCount
            IF pRow = LinkArray(hp).Row AND xCol <= LinkArray(hp).Col THEN
               TabLink = hp
               LinkFound = TRUE
               EXIT FUNCTION
            END IF
         NEXT hp
      NEXT xCol
      pCol = 1
   NEXT pRow
   Row = 1
LOOP
END IF

END FUNCTION
1
Hosted by www.Geocities.ws