Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
PrintW - print a long string, breaking it at the last space or hyphen before col. 79
#1
This is a function I think is useful, and I hope I won't find out that one of QB/QB64pe's more than 20,000 keywords, functions and compiler directives, does the same thing. (Yes, I know it's just under 500, but sometimes it feels like it's a lot more.)

I've created a subroutine called PrintW to take a string, breaking it at the last space or hyphen, printing up to that point, then repeating with what is left of the string. In short, it provides a print with wraparound. 

I have tested it with an appropriate passage, the three paragraph Gettysburg Address.

Code: (Select All)
L$ = "Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal."
PrintW L$
Print
PrintW "Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this."
Print
PrintW "But, in a larger sense, we can not dedicate, we can not consecrate, we can not hallow, this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us, that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion, that we here highly resolve that these dead shall not have died in vain, that this nation, under God, shall have a new birth of freedom, and that government of the people, by the people, for the people, shall not perish from the earth."
Print
Print "- Abraham Lincoln"

End

Sub PrintW (Msg$)
    Dim Temp$, Split$, breakspace%, breakdash%
    Temp$ = Msg$
    While Len(Temp$) > 79
        ''      Print Len(Temp$)
        Split$ = Left$(Temp$, 79)
        breakspace% = _InStrRev(Split$, " ")
        breakdash% = _InStrRev(Split$, "-")
        ''      Print Split$
        ''      Print breakspace%; breakdash%
        ''      Input X$
        If breakspace% > breakdash% Then
            Split$ = Left$(Split$, breakspace%)
            Temp$ = Mid$(Temp$, breakspace% + 1, Len(Temp$))
        Else
            Split$ = Left$(Split$, breakdash%)
            Temp$ = Mid$(Temp$, breakdash% + 1, Len(Temp$))
        End If
        ''    Print "*"; Len(Temp$)
        Print Split$
    Wend
    Print Temp$
End Sub


[Image: printw.png]


Attached Files
.bas   PrintW.bas (Size: 2.27 KB / Downloads: 26)
While 1
   Fix Bugs
   report all bugs fixed
   receive bug report
end while
Reply
#2
yes that could be handy but even more so if you can set the width ie just change 79 to something input from function call. then, you are a short step away from creating a word box of text at row, column and cutting up a long string into it.

this was maybe before -InStrRev/
Code: (Select All)
_Title "wrap$ test" 'b+ 2019-12-28  a simple way

'now test in graphics screen
'SCREEN _NEWIMAGE(640, 600, 32) 'now test in graphics screen

Print "Here is our test string:"
test$ = "12345678901234567890123456789012345678901234567890123456789012345678901234567890     Here is a super long string to test with the wrap$ Function that splits a string at first space found before the maxLen limit to keep the strings at or under the maxLen length."
Print test$
Print
Print "press any for printWrap demo... "
Sleep
Cls

Print "Here is printWrap at row = 12, col = 1, wrap length is 80:"
printWrap test$, 80, 12, 1
Locate 25, 20: Print "press any for another demo... ";
Sleep
Cls

Print "Here is printWrap at row = 9, col = 20, wrap length is 40:"
printWrap test$, 40, 9, 20
Locate 25, 20: Print "press any for another demo... ";
Sleep
Cls

Print "Here is printWrap at row = 5, col = 30, wrap length is 20:"
printWrap test$, 20, 5, 30
Locate 24, 20: Print "end of demos... ";


'This function returns the first segment of string less than or equal to maxLen AND
'the remainder of the string (if any) is returned in tail$ to be used by wrap$ again
Function wrap$ (s$, maxLen, tail$)
    If Len(s$) > maxLen Then
        p = maxLen + 1
        While Mid$(s$, p, 1) <> " " And p > 1
            p = p - 1
        Wend
        If p = 1 Then
            wrap$ = Mid$(s$, 1, maxLen): tail$ = Mid$(s$, maxLen + 1)
        Else
            wrap$ = Mid$(s$, 1, p - 1): tail$ = Mid$(s$, p + 1)
        End If
    Else
        wrap$ = s$: tail$ = ""
    End If
End Function

'this sub uses the wrap$ function to print out a string with row and column offsets
Sub printWrap (s$, maxLen, rowOffset, colOffset)
    ss$ = s$ 'work with copy
    Do
        Locate rowOffset + i, colOffset: Print wrap$(ss$, maxLen, st$)
        ss$ = st$
        i = i + 1
    Loop Until Len(ss$) = 0
End Sub
b = b + ...
Reply
#3
One of my may Wrap routines, which is actually also a RAP routine!

 - Use arrows right and left to narrow and widen right screen margin.

Code: (Select All)
WIDTH 160, 42
_FONT 16
_SCREENMOVE 10, 10
w = _WIDTH
DO
    _LIMIT 30
    REM x$ = "In West    Los Angeles born and raised, at    the    yacht club is where I spent most of my      days, 'til a couple of coders      who were up to no good, started making trouble in my neighborhood. I got booted off Discord and my vids wouldn't play, so I moved to the hills in the State of VA. I pulled up to the forum 'bout a week into April and I yelled to the browser save password log in later. Now I'm able to post and my speech is still free as I sit on my throne as the Prince of P.E."
    x$ = "In West Los Angeles born and raised, at the yacht club is where I spent most of my days, 'til a couple of coders who were up to no good, started making trouble in my neighborhood. I got booted off Discord and my vids won't play, so I moved to the hills in the State of VA. I pulled up to the forum 'bout a week into April and I yelled to the browser, 'save password log in later!' Now I'm able to post and my speech is still free as I sit on my throne as the Prince of P.E."
    CLS
    IF w < _WIDTH - 1 THEN
        FOR i = 1 TO _HEIGHT: LOCATE i, w + 1: PRINT CHR$(179);: NEXT
    END IF
    LOCATE 1, 1
    DO
        WHILE -1
            t$ = MID$(x$, 1, w)
            chop = 1
            IF w <> 1 THEN
                DO
                    IF LEFT$(t$, 1) = " " THEN
                        ' Only happens with more than 1 space between characters.
                        IF LTRIM$(t$) = "" THEN EXIT DO ELSE x$ = LTRIM$(x$): EXIT WHILE
                    END IF

                    IF MID$(x$, w + 1, 1) <> " " AND LTRIM$(t$) <> "" THEN ' Now we have to chop it.
                        IF INSTR(x$, " ") > 1 AND INSTR(t$, " ") <> 0 AND LEN(x$) > w THEN
                            t$ = MID$(t$, 1, _INSTRREV(t$, " ") - 1)
                            chop = 2
                        END IF
                    ELSE
                        chop = 2
                    END IF
                    EXIT DO
                LOOP
                x$ = MID$(x$, LEN(t$) + chop)
            ELSE
                x$ = MID$(x$, LEN(t$) + 1)
            END IF
            IF LEN(t$) AND CSRLIN < _HEIGHT - 1 THEN LOCATE , ml + 1: PRINT LTRIM$(t$)
            EXIT WHILE
        WEND
    LOOP UNTIL LEN(t$) AND LEN(LTRIM$(x$)) = 0
    DO
        b$ = INKEY$
        IF LEN(b$) THEN
            IF b$ = CHR$(27) THEN SYSTEM
            SELECT CASE MID$(b$, 2, 1)
                CASE "K"
                    IF w > 1 THEN w = w - 1
                    EXIT DO
                CASE "M"
                    IF w < _WIDTH - 1 THEN w = w + 1
                    EXIT DO
            END SELECT
        END IF
    LOOP
LOOP


Pete

- I love to WRAP!
Reply
#4
mine is easy to adapt to other people's code (and works) ;-))

Code: (Select All)
_Title "wrap$ test" 'b+ 2019-12-28  a simple way

'now test in graphics screen
'SCREEN _NEWIMAGE(640, 600, 32) 'now test in graphics screen

test$ = "Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal."


Print "Here is printWrap at row = 9, col = 10, wrap length is 60:"
printWrap test$, 60, 9, 10
Locate 25, 20: Print "press any for another demo... ";
Sleep
Cls
test$ = "Now we are engaged in a great civil war, testing whether that nation, or any nation so conceived and so dedicated, can long endure. We are met on a great battle-field of that war. We have come to dedicate a portion of that field, as a final resting place for those who here gave their lives that that nation might live. It is altogether fitting and proper that we should do this."
Print "Here is printWrap at row = 5, col = 40, wrap length is 20:"
printWrap test$, 40, 5, 20
Locate 25, 20: Print "press any for another demo... ";
Sleep
Cls

test$ = "But, in a larger sense, we can not dedicate, we can not consecrate, we can not hallow, this ground. The brave men, living and dead, who struggled here, have consecrated it, far above our poor power to add or detract. The world will little note, nor long remember what we say here, but it can never forget what they did here. It is for us the living, rather, to be dedicated here to the unfinished work which they who fought here have thus far so nobly advanced. It is rather for us to be here dedicated to the great task remaining before us, that from these honored dead we take increased devotion to that cause for which they gave the last full measure of devotion, that we here highly resolve that these dead shall not have died in vain, that this nation, under God, shall have a new birth of freedom, and that government of the people, by the people, for the people, shall not perish from the earth."
Print "Here is printWrap at row = 5, col = 10, wrap length is 60:"
printWrap test$, 60, 5, 10
Locate 25, 20: Print "press any for another demo... ";
Sleep
End


'This function returns the first segment of string less than or equal to maxLen AND
'the remainder of the string (if any) is returned in tail$ to be used by wrap$ again
Function wrap$ (s$, maxLen, tail$)
    If Len(s$) > maxLen Then
        p = maxLen + 1
        While Mid$(s$, p, 1) <> " " And p > 1
            p = p - 1
        Wend
        If p = 1 Then
            wrap$ = Mid$(s$, 1, maxLen): tail$ = Mid$(s$, maxLen + 1)
        Else
            wrap$ = Mid$(s$, 1, p - 1): tail$ = Mid$(s$, p + 1)
        End If
    Else
        wrap$ = s$: tail$ = ""
    End If
End Function

'this sub uses the wrap$ function to print out a string with row and column offsets
Sub printWrap (s$, maxLen, rowOffset, colOffset)
    ss$ = s$ 'work with copy
    Do
        Locate rowOffset + i, colOffset: Print wrap$(ss$, maxLen, st$)
        ss$ = st$
        i = i + 1
    Loop Until Len(ss$) = 0
End Sub
b = b + ...
Reply
#5
Mine was made for and works in SCREEN 0. Eventually, I will need to make one for graphics screens that includes different text character widths, as my hypertext project.

Pete Wink
Shoot first and shoot people who ask questions, later.
Reply
#6
Even this one!
Code: (Select All)
_Title "wrap$ test, press w for widen, d for decrease." 'b+ 2019-12-28  a simple way


test$ = "In West Los Angeles born and raised, at the yacht club is where I spent most of my days, 'til a couple of coders who were up to no good, started making trouble in my neighborhood. I got booted off Discord and my vids won't play, so I moved to the hills in the State of VA. I pulled up to the forum 'bout a week into April and I yelled to the browser, 'save password log in later!' Now I'm able to post and my speech is still free as I sit on my throne as the Prince of P.E."
w = 60: m = 20
Do
    k$ = InKey$
    If k$ = "d" Then w = w - 1
    If k$ = "w" Then w = w + 1
    If w > 70 Then w = 70
    If w < 30 Then w = 30
    m = Int((78 - w) / 2)
    Cls
    printWrap test$, w, 5, m
    _Limit 10
Loop Until _KeyDown(27)

'This function returns the first segment of string less than or equal to maxLen AND
'the remainder of the string (if any) is returned in tail$ to be used by wrap$ again
Function wrap$ (s$, maxLen, tail$)
    If Len(s$) > maxLen Then
        p = maxLen + 1
        While Mid$(s$, p, 1) <> " " And p > 1
            p = p - 1
        Wend
        If p = 1 Then
            wrap$ = Mid$(s$, 1, maxLen): tail$ = Mid$(s$, maxLen + 1)
        Else
            wrap$ = Mid$(s$, 1, p - 1): tail$ = Mid$(s$, p + 1)
        End If
    Else
        wrap$ = s$: tail$ = ""
    End If
End Function

'this sub uses the wrap$ function to print out a string with row and column offsets
Sub printWrap (s$, maxLen, rowOffset, colOffset)
    ss$ = s$ 'work with copy
    Do
        Locate rowOffset + i, colOffset: Print wrap$(ss$, maxLen, st$)
        ss$ = st$
        i = i + 1
    Loop Until Len(ss$) = 0
End Sub

(04-14-2024, 10:07 PM)Pete Wrote: Mine was made for and works in SCREEN 0. Eventually, I will need to make one for graphics screens that includes different text character widths, as my hypertext project.

Pete Wink

man what graphic screen?
b = b + ...
Reply
#7
Mark, yours can be modified to print the text as a single vertical line, by taking out the width restriction; however, it won't preserve the space between words like mine does when displayed as a vertical line of text. Note to test this just REM out the IF w < 30 THEN w = 30 line and make the text string a lot shorter, so it won't go vertically off the page. Oh mine compensates for that, too! Smile

Pete
Shoot first and shoot people who ask questions, later.
Reply
#8
Not very 'fisticated, but this works:

Code: (Select All)
text$ = "Four score and seven years ago our fathers brought forth on this continent, a new nation, conceived in Liberty, and dedicated to the proposition that all men are created equal."
text$ = text$ + " " '                                                                              add space at end to catch remnant of text

LineStart = 1 '                                                                                    set linelength to be 40
Print String$(40, "-") '                                                                           reference 40 char string
LineEnd = LineStart + 39 '                                                                         LineEnd is 40
FindSpace:
Ch$ = Mid$(text$, LineEnd + 1, 1)
If Ch$ <> " " Then '                                                                               Ch$ is character after LineEnd
    LineEnd = LineEnd - 1 '                                                                        if it's NOT a space, move LineEnd left until it IS
    GoTo FindSpace
End If
Print Mid$(text$, LineStart, LineEnd - LineStart + 1) '                                                print line from linestart to lineend
LineStart = LineEnd + 2
If Mid$(text$, LineStart + 1, 1) = " " Then '                                                       if char after end is a space (it's not)
    LineStart = LineStart + 1 '                                                                     step past it for new LineStart position
End If
LineEnd = LineEnd + 40
If LineStart >= Len(text$) Then Sleep
GoTo FindSpace '                                                                                    go again if not at end of text
Of all the places on Earth, and all the planets in the Universe, I'd rather live here (Perth, W.A.) Big Grin
Please visit my Website at: http://oldendayskids.blogspot.com/
Reply
#9
I used to write these little type programs all the time -- but then I saw the light and got enlightened!!

https://qb64phoenix.com/forum/showthread.php?tid=2480

My thinking now is that PRINT usally isn't a process that most folks really consider to be a bottleneck in a program.  Sure, it's one of the slowest commands we make use of, but one doesn't really make use of it when SPEED might be a factor, such as in a racing game or first person shooter.  Instead of starting at the final column of a screen, and then backing up one character a time, my new concept for word wrap is simply to start from the left, separate words one at a time from our extended text, using a list of valid separater characters (.,;- !? and such), and then if there's room on the line, print them.

This "print word by word as we go" approach offers complete flexibility to how expansive one wants to make their word-wrap and text handling.

<color=red>Hello </color><color=blue>World</color><br>

Now, folks might know the above as simple html formatting, but if you think about what I've written above, you'll see that's how it's processed...

left to right.  
look for valid word separators (only the space after hello here).  
Strip out the text to the left:  <color=red>Hello(space)
You can now parse the command from the actual text, and remove the <color=red> from that text, and use it to change the color on the screen.
With the Hello(space) that's left, you then see if it'll print on the existing line, and if not, then you move it down to the start of the next line.
And that now leaves you with </color><br> to continue to process on the next pass.

Word-by-word, with flexibility to add control features of any type that you might want into your text!!   Sure, it's a little slower than starting at column 79 and breaking the print, counting backwards, but it's oh so worth it, IMHO, just for the variety of things that you can end up doing with it!!
Reply
#10
I first thought this was some unicode/wide string thing since it has the "W" suffix.
Tread on those who tread on you

Reply




Users browsing this thread: 3 Guest(s)