1a5ae21e4Smrg#!/usr/bin/env perl 204b94745Smrg# $XTermId: wrap.pl,v 1.12 2007/07/13 00:15:28 tom Exp $ 3a5ae21e4Smrg# ----------------------------------------------------------------------------- 4a5ae21e4Smrg# Copyright 2007 by Thomas E. Dickey 5a5ae21e4Smrg# 6a5ae21e4Smrg# All Rights Reserved 7a5ae21e4Smrg# 8a5ae21e4Smrg# Permission is hereby granted, free of charge, to any person obtaining a 9a5ae21e4Smrg# copy of this software and associated documentation files (the 10a5ae21e4Smrg# "Software"), to deal in the Software without restriction, including 11a5ae21e4Smrg# without limitation the rights to use, copy, modify, merge, publish, 12a5ae21e4Smrg# distribute, sublicense, and/or sell copies of the Software, and to 13a5ae21e4Smrg# permit persons to whom the Software is furnished to do so, subject to 14a5ae21e4Smrg# the following conditions: 15a5ae21e4Smrg# 16a5ae21e4Smrg# The above copyright notice and this permission notice shall be included 17a5ae21e4Smrg# in all copies or substantial portions of the Software. 18a5ae21e4Smrg# 19a5ae21e4Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20a5ae21e4Smrg# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21a5ae21e4Smrg# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 22a5ae21e4Smrg# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 23a5ae21e4Smrg# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24a5ae21e4Smrg# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25a5ae21e4Smrg# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26a5ae21e4Smrg# 27a5ae21e4Smrg# Except as contained in this notice, the name(s) of the above copyright 28a5ae21e4Smrg# holders shall not be used in advertising or otherwise to promote the 29a5ae21e4Smrg# sale, use or other dealings in this Software without prior written 30a5ae21e4Smrg# authorization. 31a5ae21e4Smrg# ----------------------------------------------------------------------------- 32a5ae21e4Smrg# Generates a series of wrapping lines, according to the terminal width. 33a5ae21e4Smrg# The wrapping text optionally includes double-width or other characters 34a5ae21e4Smrg# encoded in UTF-8. 35a5ae21e4Smrguse strict; 36a5ae21e4Smrg 37a5ae21e4Smrguse Getopt::Std; 38a5ae21e4Smrg 39a5ae21e4Smrgour ($opt_i, $opt_n, $opt_r, $opt_w); 40a5ae21e4Smrgour ($lineno, $test_string, $term_width); 41a5ae21e4Smrg 42a5ae21e4Smrg# Return a string of two-column characters given an ASCII alpha/numeric string 43a5ae21e4Smrgsub double_cells($) { 44a5ae21e4Smrg my $value = $_[0]; 45a5ae21e4Smrg $value =~ s/ / /g; 46a5ae21e4Smrg pack("U*", 47a5ae21e4Smrg map { ($_ <= 32 || $_ > 127) # if non-ASCII character... 48a5ae21e4Smrg ? 32 # ...just show a blank 49a5ae21e4Smrg : (0xff00 + ($_ - 32)) # map to "Fullwidth Form" 50a5ae21e4Smrg } unpack("C*", $value)); # unpack unsigned-char characters 51a5ae21e4Smrg} 52a5ae21e4Smrg 53a5ae21e4Smrg# Insert a character using escape sequences to push the existing text to the 54a5ae21e4Smrg# right, write the actual character and then move left one column so succeeding 55a5ae21e4Smrg# calls will do the same. This will not cause the pushed-text to wrap, but 56a5ae21e4Smrg# will exercise the right-margin logic in other ways. 57a5ae21e4Smrg# 58a5ae21e4Smrg# Since this script does not modify the autowrap mode, you can reset that 59a5ae21e4Smrg# outside the script and compare the default (unwrapped) versus the "-i" 60a5ae21e4Smrg# option. 61a5ae21e4Smrgsub insert_char($$) { 62a5ae21e4Smrg my $value = $_[0]; 63a5ae21e4Smrg my $final = $_[1]; 64a5ae21e4Smrg my $cells = defined($opt_w) ? 2 : 1; 65a5ae21e4Smrg printf "\x1b[%d@", $cells; 66a5ae21e4Smrg printf "%s", defined($opt_w) ? double_cells($value) : $value; 67a5ae21e4Smrg if ( ! $final ) { 68a5ae21e4Smrg printf "\x1b[%dD", $cells; 69a5ae21e4Smrg } 70a5ae21e4Smrg} 71a5ae21e4Smrg 72a5ae21e4Smrg# vary the starting point of each line, to make a more interesting pattern 73a5ae21e4Smrgsub starts_of($) { 74a5ae21e4Smrg my $value = $_[0]; 75a5ae21e4Smrg if (defined($opt_w)) { 76a5ae21e4Smrg # 0,1,1,2,2,3,3,... 77a5ae21e4Smrg $value = (($value + 1) / 2) % length($test_string); 78a5ae21e4Smrg } else { 79a5ae21e4Smrg $value %= length($test_string); 80a5ae21e4Smrg } 81a5ae21e4Smrg return $value; 82a5ae21e4Smrg} 83a5ae21e4Smrg 84a5ae21e4Smrg# Vary the length of each line from $term_width - 5 to $term_width + 5, then 85a5ae21e4Smrg# double it, and then repeat. That's 22/cycle. 86a5ae21e4Smrgsub length_of($) { 87a5ae21e4Smrg my $value = $_[0]; 88a5ae21e4Smrg my $cycle = $value % 22; 89a5ae21e4Smrg if ( $cycle < 11 ) { 90a5ae21e4Smrg $value = $term_width; 91a5ae21e4Smrg } else { 92a5ae21e4Smrg $value = $term_width * 2; 93a5ae21e4Smrg $cycle /= 2; 94a5ae21e4Smrg } 95a5ae21e4Smrg return $value + $cycle - 5; 96a5ae21e4Smrg} 97a5ae21e4Smrg 98a5ae21e4Smrg# Write the text for the given line-number. 99a5ae21e4Smrgsub testit($) { 100a5ae21e4Smrg my $number = $_[0]; 101a5ae21e4Smrg my $length = length_of($number); 102a5ae21e4Smrg if ( defined($opt_n) ) { 103a5ae21e4Smrg printf "%5d ", $number % 99999; 104a5ae21e4Smrg $length -= 6; 105a5ae21e4Smrg } 106a5ae21e4Smrg # If we're printing double-column characters, we have half as much 107a5ae21e4Smrg # space effectively - but don't forget the remainder, so we can push 108a5ae21e4Smrg # the characters by single-columns. 109a5ae21e4Smrg my $starts = starts_of($number); 110a5ae21e4Smrg if ( defined($opt_w) ) { 111a5ae21e4Smrg printf " ", if ( ($number % 2 ) != 0); 112a5ae21e4Smrg $length = ($length + (($number + 1) % 2)) / 2; 113a5ae21e4Smrg } 114a5ae21e4Smrg my $string = substr($test_string, $starts); 115a5ae21e4Smrg while ( length($string) < $length ) { 116a5ae21e4Smrg $string = $string . $test_string; 117a5ae21e4Smrg } 118a5ae21e4Smrg $string = substr($string, 0, $length); 119a5ae21e4Smrg if ( defined($opt_i) ) { 120a5ae21e4Smrg my ($n, $c); 121a5ae21e4Smrg for ($n = length($string) - 1; $n >= 0; $n--) { 122a5ae21e4Smrg insert_char(substr($string, $n, 1), $n == 0); 123a5ae21e4Smrg } 124a5ae21e4Smrg printf "\n"; 125a5ae21e4Smrg } else { 126a5ae21e4Smrg if ( defined($opt_w) ) { 127a5ae21e4Smrg $string = double_cells($string); 128a5ae21e4Smrg } 129a5ae21e4Smrg printf "%s\n", $string; 130a5ae21e4Smrg } 131a5ae21e4Smrg} 132a5ae21e4Smrg 133a5ae21e4Smrgsub main::HELP_MESSAGE() { 134a5ae21e4Smrg printf STDERR <<EOF 135a5ae21e4SmrgUsage: $0 [options] 136a5ae21e4Smrg 137a5ae21e4SmrgOptions: 138a5ae21e4Smrg 139a5ae21e4Smrg-i construct lines by inserting characters on the left 140a5ae21e4Smrg-n write line-numbers 141a5ae21e4Smrg-r repeat indefinitely 142a5ae21e4Smrg-w write wide-character test-string 143a5ae21e4SmrgEOF 144a5ae21e4Smrg; 145a5ae21e4Smrg exit; 146a5ae21e4Smrg} 147a5ae21e4Smrg 148a5ae21e4Smrg&getopts('inrw') || die(); 149a5ae21e4Smrg 150a5ae21e4Smrg$term_width=`tput cols`; 151a5ae21e4Smrg 152a5ae21e4Smrg$test_string="0123456789 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 153a5ae21e4Smrg 154a5ae21e4Smrgbinmode(STDOUT, ":utf8"); 155a5ae21e4Smrgif ( defined($opt_r) ) { 156a5ae21e4Smrg for ($lineno = 0; ; ++$lineno) { 157a5ae21e4Smrg testit($lineno); 158a5ae21e4Smrg } 159a5ae21e4Smrg} else { 160a5ae21e4Smrg for ($lineno = 0; $lineno < 24; ++$lineno) { 161a5ae21e4Smrg testit($lineno); 162a5ae21e4Smrg } 163a5ae21e4Smrg} 164a5ae21e4Smrg 165a5ae21e4Smrgexit; 166