Word wrapping
G4C WRAPPER

// ===================================================================
// A routine which, given 2 listviews will wrap and/or indent/unindent
// the text from the 1st and put it into the 2nd listview..
//
// --- CALL with :
// GuiLoad Wrapper.gc gui lv1 lv2 wrapWidth addHead remHead
//
// --- WHERE:
// gui          Is the name of the gui containing the 2 listviews
// lv1          The ID of the listview containing the unwrapped text
// lv2          The ID of the listview in which to put the wrapped text
// wrapWidth    The maximum line width wanted
// addHead      The string to add in front of each line, eg "> "
// remHead      The characters to remove from the front of each line
//
//    --- EXAMPLE:
// Guiload :Wrapper.gc MyGui LV1 LV2 50 "> " "> /\t"
// ===================================================================

// wrap lv text..
xOnLoad gui lv1 lv2 wrapWidth addHead remHead
    local c/len/buff2/lastline/lastspace
    guiquit #this // ensure we quit when we're done..
    buff = '' // init - This is a gui-wide variable.
    use lv $gui $lv1
    lv go top
    gosub #this getMoreText $remHead
    while $$return != FINISHED

        while $buff > ''

            lastline = 0 // flag - is it the last line in paragraph?..
            use lv $gui $lv1
            extract buff length len
            while $len < $wrapWidth
            and $lastline = 0
                lv go next
                gosub #this getMoreText $remHead
                if $$return = LASTLINE
                or $$return = FINISHED
                    lastline = 1
                endif
                extract buff length len
            endwhile

            use lv $gui $lv2
            if $len > $wrapWidth

                lastspace = 0 // find the last space char within the wrap width..
                for c 0 $wrapWidth
                    if $buff[$c][1] = ' '
                        lastspace = $c // last space character..
                    endif
                endfor

                if $lastspace = 0    // = 0 if there was no space char..
                    cutvar buff cut char $wrapWidth buff2 // cut abruptly..
                else
                    cutvar buff cut char $lastspace buff2
                endif

                lv add '$addHead\#$buff2'
                buff = $buff[1] // remove leading space char from remaining buff..

            else // end of buffer..
                lv add '$addHead\#$buff'
                buff = '' // finished paragraph..
                if $lastline = 1    // add empty line between paragraphs..
                    lv add ''
                endif
            endif
        endwhile

        use lv $gui $lv1
        if $$lv.valid = 1
            lv go next
        endif
        gosub #this getMoreText $remHead
    endwhile


// get next line into buff..
xRoutine getMoreText remHead
    local tb/c/bufflen/tblen

    if $$lv.valid = 0 // last line..
        return FINISHED
    endif
    c = 0
    tb = $$lv.text
    // remove all starting characters like in remHead
    gosub #this isIn $tb[0][1] $remHead
    while $$return = 1
        ++c
        gosub #this isIn $tb[$c][1] $remHead
    endwhile
    tb = $tb[$c]

    if $tb = ''    // empty line = paragraph
        return LASTLINE
    endif

    if $buff > ''    // add space between last text and this..
        appvar buff ' '
    endif
    appvar buff $tb    // - problem with lines over buffer size!


// return 1 = char is in str, 0 = its not..
xRoutine isIn char str
    local slen
    if $char = '';    or $str = ''
        return 0
    endif // null byte..

    extract str length slen
    --slen
    for c 0 $slen
        if $str[$c][1] = $char
            return 1
        endif
    endfor
    return 0