Code: Select all
#SOC = SizeOf(Character)
#CharactersInFrontOfText = 1
Structure LineInfoStructure
Addr.i
Length.i
EndStructure
Procedure.i GetLongestLine(*c.Character, List LineInfoList.LineInfoStructure())
Protected.i l, s
ClearList(LineInfoList())
AddElement(LineInfoList())
LineInfoList()\Addr = *c
While *c\c
If *c\c=#LF
If s>l : l=s : EndIf
LineInfoList()\Length = s
AddElement(LineInfoList())
LineInfoList()\Addr = *c + #SOC
s=0
ElseIf *c\c<>#CR
s+1
EndIf
*c+#SOC
Wend
If s ; For last line without #LF at end.
If s>l : l=s : EndIf
LineInfoList()\Length = s
Else
DeleteElement(LineInfoList())
EndIf
ProcedureReturn l
EndProcedure
Procedure.s Boxed(*text.Character)
Protected.i NumLines, MaxLineLength, i, j
Protected Result$
Protected *BoxText, *Help.Character
Protected NewList LineInfoList.LineInfoStructure()
MaxLineLength = GetLongestLine(*text, LineInfoList())
NumLines = ListSize(LineInfoList())
;Debug MaxLineLength
;Debug NumLines
; allocate the needed memory for the result text
;'+' + MaxLineLength + '+' + 'CRLF' ->
; 1 + MaxLineLength + 1 + 2
; multiplied by number of lines + 1 startline + 1 endline
; + additional character for the string termination
*BoxText = AllocateMemory((1 + MaxLineLength + 1 + 2) * (1 + NumLines + 1) * #SOC + #SOC, #PB_Memory_NoClear)
If *BoxText
; fill all with space character
FillMemory(*BoxText, MemorySize(*BoxText), ' ', #PB_Character)
; terminate the string
; write a terminating 0 at last address of the memory - 1 character
PokeC(*BoxText + MemorySize(*BoxText) - #SOC, #Null)
; write first box line
PokeC(*BoxText + Ptr , '+')
FillMemory(*BoxText + Ptr + #SOC, MaxLineLength * #SOC, '-', #PB_Character)
PokeC(*BoxText + Ptr + (1 + MaxLineLength) * #SOC, '+')
PokeC(*BoxText + Ptr + (1 + MaxLineLength + 1) * #SOC, #CR)
PokeC(*BoxText + Ptr + (1 + MaxLineLength + 2) * #SOC, #LF)
; calc the pointer for the first text line
*Help = *BoxText + (1 + MaxLineLength + 1 + 2) * #SOC
; process each line of text
ForEach LineInfoList()
*Help\c = '|' : *Help + #SOC ; write '+' and increase the pointer
; copy the original text to the place of the pointer
CopyMemory(LineInfoList()\Addr, *Help, LineInfoList()\Length * #SOC)
; add the MaxLineLength to the pointer
*Help + (MaxLineLength * #SOC)
*Help\c = '|' : *Help + #SOC ; write '+' and increase the pointer
*Help\c = #CR : *Help + #SOC ; write CR and increase the pointer
*Help\c = #LF : *Help + #SOC ; write LF and increase the pointer
Next
; calc Ptr
; size of one line multiplied with number of lines + the additional start line
Ptr = (1 + MaxLineLength + 1 + 2) * (NumLines + 1) * #SOC
; write last box line
PokeC(*BoxText + Ptr , '+')
FillMemory(*BoxText + Ptr + #SOC, MaxLineLength * #SOC, '-', #PB_Character)
PokeC(*BoxText + Ptr + (1 + MaxLineLength) * #SOC, '+')
PokeC(*BoxText + Ptr + (1 + MaxLineLength + 1) * #SOC, #CR)
PokeC(*BoxText + Ptr + (1 + MaxLineLength + 2) * #SOC, #LF)
;ShowMemoryViewer(*BoxText, MemorySize(*BoxText))
Result$ = PeekS(*BoxText)
FreeMemory(*BoxText)
EndIf
ProcedureReturn Result$
EndProcedure
Structure LineListStructure
Left$
Right$
EndStructure
Procedure.s DudeBoxed(*text.Character, List StartLineList.LineListStructure(), HorFillChar.c, TextLineDistance.i, *NormalLine.LineListStructure, List EndLineList.LineListStructure())
Protected.i NumTextLines, MaxLineLength, i, j, LeftLength, RightLength, StartLineListOk, LineInfoListOk, TotalLines, Lines1
Protected Result$
Protected *BoxText, *Help.Character
Protected NewList LineInfoList.LineInfoStructure()
MaxLineLength = GetLongestLine(*text, LineInfoList())
NumTextLines = ListSize(LineInfoList())
FirstElement(StartLineList())
LeftLength = Len(StartLineList()\Left$)
RightLength = Len(StartLineList()\Right$)
If ListSize(StartLineList()) > NumTextLines
Lines1 = ListSize(StartLineList())
Else
Lines1 = 1 + NumTextLines
EndIf
If TextLineDistance = 0
TotalLines = Lines1 + 1 + ListSize(EndLineList())
Else
If (TextLineDistance * 2) > ListSize(StartLineList())
TotalLines = (TextLineDistance * 2) + Lines1 + ListSize(EndLineList())
Else
TotalLines = Lines1 + (TextLineDistance * 2) + 1 + ListSize(EndLineList())
EndIf
EndIf
;Debug MaxLineLength
;Debug NumLines
; allocate the needed memory for the result text
;'+' + MaxLineLength + '+' + 'CRLF' ->
; 1 + MaxLineLength + 1 + 2
; multiplied by number of lines + 1 startline + 1 endline
; + additional character for the string termination
*BoxText = AllocateMemory((LeftLength + MaxLineLength + RightLength + 2) * TotalLines * #SOC + #SOC, #PB_Memory_NoClear)
If *BoxText
; fill all with space character
FillMemory(*BoxText, MemorySize(*BoxText), ' ', #PB_Character)
; terminate the string
; write a terminating 0 at last address of the memory - 1 character
PokeC(*BoxText + MemorySize(*BoxText) - #SOC, #Null)
; write first box line
PokeS(*BoxText + Ptr , StartLineList()\Left$, -1, #PB_String_NoZero)
FillMemory(*BoxText + Ptr + LeftLength * #SOC, MaxLineLength * #SOC, HorFillChar, #PB_Character)
PokeS(*BoxText + Ptr + (LeftLength + MaxLineLength) * #SOC, StartLineList()\Right$, -1, #PB_String_NoZero)
PokeC(*BoxText + Ptr + (LeftLength + MaxLineLength + RightLength + 1) * #SOC, #CR)
PokeC(*BoxText + Ptr + (LeftLength + MaxLineLength + RightLength + 2) * #SOC, #LF)
StartLineListOk = NextElement(StartLineList())
; calc the pointer for the first text line
*Help = *BoxText + (LeftLength + MaxLineLength + RightLength + 2) * #SOC
; process each line of text
LineInfoListOk = FirstElement(LineInfoList())
j = 0
Repeat
If StartLineListOk
PokeS(*Help, StartLineList()\Left$, -1, #PB_String_NoZero)
Else
PokeS(*Help, *NormalLine\Left$, -1, #PB_String_NoZero)
EndIf
If j >= TextLineDistance And LineInfoListOk
; copy the original text to the place of the pointer
CopyMemory(LineInfoList()\Addr, *Help + LeftLength * #SOC, LineInfoList()\Length * #SOC)
LineInfoListOk = NextElement(LineInfoList())
EndIf
; add the MaxLineLength to the pointer
*Help + (LeftLength + MaxLineLength) * #SOC
If StartLineListOk
PokeS(*Help, StartLineList()\Right$, -1, #PB_String_NoZero)
StartLineListOk = NextElement(StartLineList())
Else
PokeS(*Help, *NormalLine\Right$, -1, #PB_String_NoZero)
EndIf
*Help + RightLength * #SOC
*Help\c = #CR : *Help + #SOC ; write CR and increase the pointer
*Help\c = #LF : *Help + #SOC ; write LF and increase the pointer
j + 1
Until TotalLines >= j And LineInfoListOk = #False And StartLineListOk = #False
; calc Ptr
; size of one line multiplied with number of lines + the additional start line
Ptr = (LeftLength + MaxLineLength + RightLength + 2) * (j + 1) * #SOC
For i = 1 To TextLineDistance
PokeS(*BoxText + Ptr , *NormalLine\Left$, -1, #PB_String_NoZero)
PokeS(*BoxText + Ptr + (LeftLength + MaxLineLength) * #SOC, *NormalLine\Right$, -1, #PB_String_NoZero)
PokeC(*BoxText + Ptr + (LeftLength + MaxLineLength + RightLength + 1) * #SOC, #CR)
PokeC(*BoxText + Ptr + (LeftLength + MaxLineLength + RightLength + 2) * #SOC, #LF)
Ptr + (LeftLength + MaxLineLength + RightLength + 2) * #SOC
Next i
; write last box line
PokeS(*BoxText + Ptr , *NormalLine\Left$, -1, #PB_String_NoZero)
FillMemory(*BoxText + Ptr + LeftLength * #SOC, MaxLineLength * #SOC, HorFillChar, #PB_Character)
PokeS(*BoxText + Ptr + (LeftLength + MaxLineLength) * #SOC, *NormalLine\Right$, -1, #PB_String_NoZero)
PokeC(*BoxText + Ptr + (LeftLength + MaxLineLength + RightLength + 1) * #SOC, #CR)
PokeC(*BoxText + Ptr + (LeftLength + MaxLineLength + RightLength + 2) * #SOC, #LF)
Ptr + (LeftLength + MaxLineLength + RightLength + 2) * #SOC
ForEach EndLineList()
PokeS(*BoxText + Ptr , EndLineList()\Left$, -1, #PB_String_NoZero)
PokeS(*BoxText + Ptr + (LeftLength + MaxLineLength) * #SOC, EndLineList()\Right$, -1, #PB_String_NoZero)
PokeC(*BoxText + Ptr + (LeftLength + MaxLineLength + RightLength + 1) * #SOC, #CR)
PokeC(*BoxText + Ptr + (LeftLength + MaxLineLength + RightLength + 2) * #SOC, #LF)
Ptr + (LeftLength + MaxLineLength + RightLength + 2) * #SOC
Next
;ShowMemoryViewer(*BoxText, MemorySize(*BoxText))
Result$ = PeekS(*BoxText)
FreeMemory(*BoxText)
EndIf
ProcedureReturn Result$
EndProcedure
text$="One"+#CRLF$
text$+"Two"+#CRLF$
text$+"Three"+#CRLF$
; text$+"Four"+#CRLF$
; text$+"Five"+#CRLF$
; text$+"Six"+#CRLF$
; text$+"Seven"+#CRLF$
Debug Boxed(@text$)
NewList StartLineList.LineListStructure()
Define NormalLine.LineListStructure
NewList EndLineList.LineListStructure()
AddElement(StartLineList())
StartLineList()\Left$ = " .------"
StartLineList()\Right$ = "------. "
AddElement(StartLineList())
StartLineList()\Left$ = " / .-. "
StartLineList()\Right$ = " .-. \ "
AddElement(StartLineList())
StartLineList()\Left$ = "| / \ "
StartLineList()\Right$ = " / \ |"
AddElement(StartLineList())
StartLineList()\Left$ = "| |\_. |"
StartLineList()\Right$ = "| /| |"
AddElement(StartLineList())
StartLineList()\Left$ = "|\| | /|"
StartLineList()\Right$ = "|\ | |/|"
AddElement(StartLineList())
StartLineList()\Left$ = "| `---' |"
StartLineList()\Right$ = "| '---´ |"
NormalLine\Left$ = "| |"
NormalLine\Right$ = "| |"
AddElement(EndLineList())
EndLineList()\Left$ = "\ |"
EndLineList()\Right$ = "| /"
AddElement(EndLineList())
EndLineList()\Left$ = " \ / "
EndLineList()\Right$ = " \ / "
AddElement(EndLineList())
EndLineList()\Left$ = " `---' "
EndLineList()\Right$ = " '---´ "
Debug DudeBoxed(@text$, StartLineList(), '-', 0, @NormalLine, EndLineList())