After some reading and testing it seems that handling RTFData can be too slow for a user interface. In a large (300K) text document getting RTFData to Styled Text took about 1 minute. (using macOS15.1, M1, Xojo 4.1)
DTTextArea1.StyledText.Text = DTTextArea2.StyledText.RTFData ’ takes about 60 seconds
I copied the code example in the Xojo docs to explore MEMORYBOLCK for gaining some speed and found no advantage at first. Some documents were taking up to 3 minutes.
Var mb As MemoryBlock
MB = glbl.TextAreaToMemB(DTTextArea2.StyledText) ' takes about 2 seconds
DTTextArea1.StyledText = glbl.TextAreaFromMemB(MB) ' still took about 60 seconds
(code for these is shown below)
However, changing
sr.FontName = mb.CString(pos)
sr.Text = mb.CString(pos+stFontLen)
to
sr.FontName = mb.CString(pos).DefineEncoding(Encodings.ASCII)
sr.Text = mb.CString(pos+stFontLen).DefineEncoding(Encodings.ASCII)
in TextAreaFromMemB made the speed very acceptable.
Using UTF8 made the tabs and carriage returns appear as odd characters.
Using UTF16 was slow.
Using ASCII was fast and the resulting text looked like it was supposed to.
This leads to some questions.
Is there a better approach in general to saving and retrieving user styled docs?
Could Xojo’s built in method benefit from using ASCII encoding? Not sure if that can be set.
Thanks - KC
' TextAreaToMemB
' Input: sta As StyledText
Var sr As StyleRun
Var i, Count As Integer
Var textLen, fontLen As Integer
Var staticInfo, curLength,startLength As Integer
Var mb As MemoryBlock
mb=New MemoryBlock(0)
' We already know that a style run takes up a certain amount of space
' 3 bytes for the booleans, 4 for size and 4 for color (when size is integer32)
' bold italic underline textcolor fontsize fontnamelength textlength - fontName and text appear next
staticInfo = 1 + 1 + 1 + 4 + 4 + 4 + 4
Count = sta.StyleRunCount ' Get the number of styles
curLength=0 ' of mb
For i = 0 To Count - 1 ' get the MemoryBox size so it can be set once
startLength=curLength
sr = sta.StyleRun(i)
textLen = sr.Text.Length + 1 ' +1 sets the null byte
fontLen = sr.FontName.Length + 1
curLength=curLength+staticInfo + fontLen + textLen+1
Next
mb.size=curLength
curLength=0 ' start over so the values can be set
For i = 0 To Count - 1 ' get the StyleRuns
startLength=curLength
sr = sta.StyleRun(i)
textLen = sr.Text.Length + 1 ' +1 sets the null byte
fontLen = sr.FontName.Length + 1
curLength=curLength+staticInfo + fontLen + textLen+1
' Stuff the style run content and style info into a memory block
mb.BooleanValue(startLength+0) = sr.Bold
mb.BooleanValue(startLength+1) = sr.Italic
mb.BooleanValue(startLength+2) = sr.Underline
mb.ColorValue(startLength+3, 32) = sr.TextColor
mb.Int32Value(startLength+7) = sr.FontSize
mb.Int32Value(startLength+11) = fontLen
mb.Int32Value(startLength+15) = textLen
mb.CString(startLength+19) = sr.FontName
mb.CString(startLength+19+fontLen) = sr.Text
Next
Return mb
' TextAreaFromMemB
' Input: mb As MemoryBlock created by TextAreaToMemB
Var sta As StyledText
Var pos, staticInfo As Integer
Var sr As StyleRun
Var stFontLen, stTextLen As Integer
staticInfo = 1 + 1 + 1 + 4 + 4 + 4 + 4' bold italic underline textcolor fontsize fontnamelength textlength - fontName and text appear next
pos = 0
sta = New StyledText
While pos < mb.Size
sr = New StyleRun
sr.Bold = mb.BooleanValue(pos+0)
sr.Italic = mb.BooleanValue(pos+1)
sr.Underline = mb.BooleanValue(pos+2)
sr.TextColor = mb.ColorValue(pos+3, 32)
sr.FontSize = mb.Long(pos+7)
stFontLen = mb.Long(pos+11)
stTextLen = mb.Long(pos+15)
pos = pos + 19 ' fontName starts here
sr.FontName = mb.CString(pos).DefineEncoding(Encodings.ASCII)
sr.Text = mb.CString(pos+stFontLen).DefineEncoding(Encodings.ASCII)
sta.AddStyleRun(sr)
pos = pos+stFontLen+stTextLen+1
Wend
Return sta