VBspeed / String / WordWrap
VBspeed © 2000-10, updated: 18-mar-2005
WordWrap


Function WordWrap
Wraps a string to a given number of characters using a line break character.
Note, that our function is a wrapper based on character counting; we are not measuring the rendered text width within a given device context. By the way, "LineWrap" is another, slightly better, term for what the function does: wrapping lines at word boundaries; nevertheless, "WordWrap" is more common.

   Function WordWrap( _
      ByRef Text As String, _
      ByVal Width As Long, _
      Optional ByRef CountLines As Long) As String
  
Note the following points:
  1. Text can be wrapped at space (ASCII 32) and hyphen (ASCII 45) characters.
  2. Words that are longer than Width are cut.
  3. We wrap lossless: no string characters of the original string are replaced, so that the output is fully revertible to the input by simply removing the line break characters. To achieve this, lines wrapped at a space character will end in that space character (see examples below). In other words, the space behaves exactly as a wrapping hyphen.
  4. The line break character is fixed to 2-byte vbCrLf (ASCII 13 & ASCII 10).
  5. No line breaks are added to the very end of the output (see last example below).
  6. Any line break characters in the original string are ignored. It's the responsability of the caller to take care of removing them.
  7. If Width is 0 the function returns an empty string.
  8. CountLines is an optional return argument that's handy when you need to know the height of the wrapped string returned or whether anything has been wrapped (CountLines > 1).
Examples (the comma stands for vbCrLf):
  
  WordWrap("ab cdef ghi", 2)       --> "ab ,cd,ef ,gh,i"
  WordWrap("ab cdef ghi", 3)       --> "ab ,cde,f ,ghi"
  WordWrap("ab cdef ghi", 4)       --> "ab ,cdef ,ghi"
  WordWrap("ab-cdef-ghi", 4)       --> "ab-,cdef-,ghi"
  WordWrap("abcedef", 0)           --> ""
  WordWrap("abcedef", 1)           --> "a,b,c,d,e,f,g"
  WordWrap("abcedef", 2)           --> "ab,cd,ef,g"
  WordWrap("abcedef", 3)           --> "abc,def,g"
  WordWrap("a ", 1)                --> "a " (not "a ,")

Use this function (VB5/6-compatible) to verify the correctness of your code.
Code
WordWrap01
Public Function WordWrap01( _
    ByRef Text As String, _
    ByVal Width As Long, _
    Optional ByRef CountLines As Long) As String
' by Donald, donald@xbeat.net, 20040913
  Dim i As Long
  Dim lenLine As Long
  Dim posBreak As Long
  Dim cntBreakChars As Long
  Dim abText() As Byte
  Dim abTextOut() As Byte
  Dim ubText As Long

  ' no fooling around
  If Width <= 0 Then
    CountLines = 0
    Exit Function
  End If
  If Len(Text) <= Width Then  ' no need to wrap
    CountLines = 1
    WordWrap01 = Text
    Exit Function
  End If
  
  abText = StrConv(Text, vbFromUnicode)
  ubText = UBound(abText)
  ReDim abTextOut(ubText * 3) 'dim to potential max
  
  For i = 0 To ubText
    Select Case abText(i)
    Case 32, 45 'space, hyphen
      posBreak = i
    Case Else
    End Select
    
    abTextOut(i + cntBreakChars) = abText(i)
    lenLine = lenLine + 1
    
    If lenLine > Width Then
      If posBreak > 0 Then
        ' don't break at the very end
        If posBreak = ubText Then Exit For
        ' wrap after space, hyphen
        abTextOut(posBreak + cntBreakChars + 1) = 13  'CR
        abTextOut(posBreak + cntBreakChars + 2) = 10  'LF
        i = posBreak
        posBreak = 0
      Else
        ' cut word
        abTextOut(i + cntBreakChars) = 13     'CR
        abTextOut(i + cntBreakChars + 1) = 10 'LF
        i = i - 1
      End If
      cntBreakChars = cntBreakChars + 2
      lenLine = 0
    End If
  Next
  
  CountLines = cntBreakChars \ 2 + 1
  
  ReDim Preserve abTextOut(ubText + cntBreakChars)
  WordWrap01 = StrConv(abTextOut, vbUnicode)
  
End Function
WordWrap02
Author: by Marzo Junior, marzojr_NO~SPAM_@taskmail.com.br, 20041027
Doping: FastString TLB (cf. Dope'n'Declarations)
Code: Class-wrapped. The class is waiting for you here.
Calls
1Text = Replicate(5, "Many a mickle makes a muckle. ")
Width = 5
2Text = Replicate(5, "Many a mickle makes a muckle. ")
Width = 72
3Text = Replicate(50, "Many a mickle makes a muckle. ")
Width = 5
4Text = Replicate(50, "Many a mickle makes a muckle. ")
Width = 72
Charts
 VB5 Charts
CodeAuthorDopingNotes
WordWrap01 Donald  
WordWrap02 MarzoAPI,TLB 
Call 1
22.088.872µs
11.004.262µs
Call 2
22.776.974µs
11.002.516µs
Call 3
21.3655.037µs
11.0040.347µs
Call 4
21.5735.895µs
11.0022.845µs
 VB6 Charts
CodeAuthorDopingNotes
WordWrap01 Donald  
WordWrap02 MarzoAPI,TLB 
Call 1
22.249.408µs
11.004.205µs
Call 2
23.117.732µs
11.002.485µs
Call 3
21.3554.021µs
11.0039.904µs
Call 4
21.6737.177µs
11.0022.219µs
Notes & Conclusions
...
Got comments? How to read all those numbers

top




VBspeed © 2000-10 by Donald Lessau