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