Method code for $string.ansi_wrap_line()

[Turn off line numbering]
  1: arg str, len, @stuff;
  2: var output, cutoff, firstline, prefix, plen, x, ansilist, lengthvals, counter, elem, wordlist, wordsum, flag;
  3: 
  4: // Thanks Scott for letting me port this back from TEC.
  5: //   - Bruce
  6: // takes string and wraps it by words, compared to length, returns a list. 
  7: [(prefix ?= ""), (firstline ?= 0)] = stuff;
  8: output = "";
  9: if (firstline)
 10:     str = prefix + str;
 11: plen = strlen(prefix);
 12: while (strlen(str) > len) {
 13:     refresh();
 14:     flag = "
";
 15:     counter = 0;
 16: 
 17:     // Check for ansi codes first
 18:     ansilist = .weed_ansi(str);
 19: 
 20:     // If there are ansi codes, do the spiel, otherwise do a regular
 21:     // line wrap (this can happen on a segment by segment basis)
 22:     if (listlen(ansilist) > 1) {
 23:         // create a word-only list w/o the ansi codes, and a letter-count
 24:         // list both for the entire list and for the word-only list
 25:         lengthvals = map x in (ansilist) to (strlen(x));
 26:         wordlist = ansilist.odds();
 27:         wordsum = map x in (wordlist) to (strlen(x)).sum();
 28: 
 29:         // wordsum = lengthvals.odds().sum();
 30:         // if the letter-count for the word-only list is greater than the 
 31:         // line length, then we'll need to hack it up, otherwise, we'll
 32:         // just use the length of the entire line, codes and all
 33:         if (wordsum > len) {
 34:             // We've got too many letters. Have to find out where in
 35:             // the word (non-ansi-code) part of the string the len is.
 36:             // we mark its spot in the master list, but only count its
 37:             // letter value if it's really a word. We also need to
 38:             // remember how many letters we've gone through before
 39:             // possibly hitting a big chunk of string (counter).
 40:             elem = find x in (ansilist) where (x in wordlist && (counter += strlen(x)) > len);
 41:             if (elem)
 42:                 counter -= strlen(x);
 43: 
 44:             // Going to establish where to cut the string. Take the
 45:             // sum of the letter-count list up to the marker we just found
 46:             cutoff = lengthvals.subrange(1, elem - 1).sum();
 47: 
 48:             // We already know the string is too long for a line, or we
 49:             // wouldn't be here. If the counter is less than our line length
 50:             // it probably means the next element was too long to add, 
 51:             // (a big chunk of string with no codes) so we'll tack on the
 52:             // len - our counter value.
 53:             if (counter < len)
 54:                 cutoff += len - counter;
 55:             cutoff = stridx(substr(str, 1, cutoff), " ", -1);
 56:         } else {
 57:             cutoff = lengthvals.sum();
 58:             flag = "";
 59:         }
 60:     } else {
 61:         cutoff = stridx(substr(str, 1, len), " ", -1);
 62:     }
 63: 
 64:     // The rest of this has been tweaked slightly. The main goal was to
 65:     // get cutoff vals that this section of the code will be happy with.
 66:     if (cutoff <= plen) {
 67:         output += "
" + substr(str, 1, len);
 68:         str = prefix + substr(str, len + 1);
 69:     } else {
 70:         output += "
" + substr(str, 1, cutoff);
 71:         str = prefix + substr(str, cutoff + 1);
 72:     }
 73: }
 74: 
 75: // Here's the tweak and the pain in the ass I'd like solved. When the
 76: // length of the word value of the string matches the line length, the
 77: // extra "
" at the end causes extra spacing for .atelln()
 78: return (output ? output.subrange(3) + flag : "") + str;

// Created 27-Mar-1995 as a part of ColdCore, see: @help Credit

Tlon