[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