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