Processing Hypertext

The front-end application requires that each hypertext link have an integer associated with that identifies a record in the Hypertext table. In addition, the front-end application requires a specific formatting code sequence to identify a segment of text as hypertext (which it will then turn green and underlined). Rather than having the author try to specify hyperlinks the way front end expects them, we developed an alternative format that the compiler can translate into the appropriate format. The author specifies a hypertext link as follows:


^.^Text to be made hot@Id of screen&

This text consists of the phrase the author wants to be hot, the id of the screen to be displayed when the hot text is clicked, and three delimiters: ^.^ marks the beginning of the hot text; @ marks the end of the hot text and the beginning of the screen id; & marks the end of the screen id.

When the compiler finds this type of text string it translates it into the appropriate front-end formatting and creates a record in the Hypertext table. For example, the text above might look like this when the compiler has transformed it


\ATXht123 \uldb \ATXul1282 Text to be made hot\ATXht0 \ulnone \ATXul0

The hot text is bracketed by various formatting and hypertext identifiers. The screen id has been transformed into an integer code (in this case 123).

The transformation is accomplished in the following routine. It searches for the delimiters in the string it is passed (sText), transforms the string, and creates a record in the Hypertext table (if the appropriate one does not already exist.


Function bProcessHotText (sText As String) As Integer
    'kill variations on the starting tag
    sText = sReplaceString(sText, "^" & Chr$(13) & Chr$(10) & ".^", "^.^")
    sText = sReplaceString(sText, "^." & Chr$(13) & Chr$(10) & "^", "^.^")
    
    ' find hypertext hot text and screen id
    nOffset1 = InStr(sText, "^.^")
    nMax = Len(sText)
    Do While nOffset1
        nOffset2 = nOffset1
        Do While Mid$(sText, nOffset2, 1) <> "@"
            If nOffset2 > nMax Then
                <error trap: missing @>
                Exit Function
            End If
            nOffset2 = nOffset2 + 1
        Loop
        nOffset3 = nOffset2
        Do While Mid$(sText, nOffset3, 1) <> "&"
            If nOffset3 > nMax Then
              <error trap: missing &>
              Exit Function
            End If
            nOffset3 = nOffset3 + 1
        Loop

        'figure id
        sId = Mid$(sText, nOffset2 + 1, nOffset3 - nOffset2 - 1)
        'Kill any CRs or line feeds stuck in there
        sId = sReplaceString(sId, Chr$(13), "")
        sId = sReplaceString(sId, Chr$(10), "")
        sId = UCase$(sId)

        'get or create integer key
        sKey = Format$(nLogHtLink(sId))
        
        'Reformat text with hotlink formatting
        sMidStr = Mid$(sText, nOffset1 + 3, nOffset2 - nOffset1 - 3)
        sMidStr = sReplaceString(sMidStr, "}{", "")
        sText = Left$(sText, nOffset1 - 1)
        sText = sText & "\ATXht" & sKey & " \uldb \ATXul1282 " 
        sText = sText & sMidStr & "\ATXht0 \ulnone \ATXul0 " 
        sText = sText & Mid$(sText, nOffset3 + 1)
        
        'get next hyperlink
        nOffset1 = InStr(sText, "^.^")
        nMax = Len(sText)
    Loop
    bProcessHotText = True
End Function

The routine above uses string manipulations to extract the hot text and screen id that the author entered. Much of the code is there to avoid problems in the RTF stream. For example, suppose the author types ^.^ in the source document. In a valid RTF representation of these characters there could be a carriage return/line feed between any two of these characters. Thus, the routine cannot simply search for these three contiguous characters. It must first reduce the various representations of this delimiter to a single version before searching the input string for it.

Character formatting in the RTF text may introduce any of a large variety of character combinations between any two characters in a given text segment. To avoid the potential problems of character formatting, we make sure that there is no character formatting applied to our hypertext delimiters.

To transform the screen id that the author types into the integer key that the front-end expects, the compiler uses the following routine.


Function nLogHtLink (sId As String) As Integer
    If Len(sId) > 15 Then
        errorflag "Invalid Hypertext id: " & sId
    Else
        mtbHyper.Index = "id"
        mtbHyper.Seek "=", sId
        If mtbHyper.NoMatch Then
          mtbHyper.AddNew
          mtbHyper("id") = sId
          mtbHyper.Update
          mtbHyper.Seek "=", sId
        End If
        mtbHyper.Seek "=", sId
        nLogHtLink = mtbHyper("key")
    End If

The routine searches the Hypertext table for the screen id it is passed. If the screen id is there, the routine returns the integer key associated with this screen id. If the screen id is not already in the Hypertext table, the routine creates a new record with the screen id it is passed. Because the integer key is an Access counter field, it is automatically set to the next available integer. To figure out what this next integer is, the routine seeks to the newly created record after creating it and returns its integer key.