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.