[Turn on line numbering]arg str, len, @stuff; var output, cutoff, firstline, prefix, plen, x, ansilist, lengthvals, counter, elem, wordlist, wordsum, flag; // Thanks Scott for letting me port this back from TEC. // - Bruce // takes string and wraps it by words, compared to length, returns a list. [(prefix ?= ""), (firstline ?= 0)] = stuff; output = ""; if (firstline) str = prefix + str; plen = strlen(prefix); while (strlen(str) > len) { refresh(); flag = " "; counter = 0; // Check for ansi codes first ansilist = .weed_ansi(str); // If there are ansi codes, do the spiel, otherwise do a regular // line wrap (this can happen on a segment by segment basis) if (listlen(ansilist) > 1) { // create a word-only list w/o the ansi codes, and a letter-count // list both for the entire list and for the word-only list lengthvals = map x in (ansilist) to (strlen(x)); wordlist = ansilist.odds(); wordsum = map x in (wordlist) to (strlen(x)).sum(); // wordsum = lengthvals.odds().sum(); // if the letter-count for the word-only list is greater than the // line length, then we'll need to hack it up, otherwise, we'll // just use the length of the entire line, codes and all if (wordsum > len) { // We've got too many letters. Have to find out where in // the word (non-ansi-code) part of the string the len is. // we mark its spot in the master list, but only count its // letter value if it's really a word. We also need to // remember how many letters we've gone through before // possibly hitting a big chunk of string (counter). elem = find x in (ansilist) where (x in wordlist && (counter += strlen(x)) > len); if (elem) counter -= strlen(x); // Going to establish where to cut the string. Take the // sum of the letter-count list up to the marker we just found cutoff = lengthvals.subrange(1, elem - 1).sum(); // We already know the string is too long for a line, or we // wouldn't be here. If the counter is less than our line length // it probably means the next element was too long to add, // (a big chunk of string with no codes) so we'll tack on the // len - our counter value. if (counter < len) cutoff += len - counter; cutoff = stridx(substr(str, 1, cutoff), " ", -1); } else { cutoff = lengthvals.sum(); flag = ""; } } else { cutoff = stridx(substr(str, 1, len), " ", -1); } // The rest of this has been tweaked slightly. The main goal was to // get cutoff vals that this section of the code will be happy with. if (cutoff <= plen) { output += " " + substr(str, 1, len); str = prefix + substr(str, len + 1); } else { output += " " + substr(str, 1, cutoff); str = prefix + substr(str, cutoff + 1); } } // Here's the tweak and the pain in the ass I'd like solved. When the // length of the word value of the string matches the line length, the // extra " " at the end causes extra spacing for .atelln() return (output ? output.subrange(3) + flag : "") + str;
// Created 27-Mar-1995 as a part of ColdCore, see: @help Credit