1a5ae21e4Smrg#!/usr/bin/env perl 204b94745Smrg# $XTermId: halves.pl,v 1.11 2022/11/17 00:45:00 tom Exp $ 3a5ae21e4Smrg# ----------------------------------------------------------------------------- 4a5ae21e4Smrg# this file is part of xterm 5a5ae21e4Smrg# 65307cd1aSmrg# Copyright 2007,2022 by Thomas E. Dickey 7a5ae21e4Smrg# 8a5ae21e4Smrg# All Rights Reserved 9a5ae21e4Smrg# 10a5ae21e4Smrg# Permission is hereby granted, free of charge, to any person obtaining a 11a5ae21e4Smrg# copy of this software and associated documentation files (the 12a5ae21e4Smrg# "Software"), to deal in the Software without restriction, including 13a5ae21e4Smrg# without limitation the rights to use, copy, modify, merge, publish, 14a5ae21e4Smrg# distribute, sublicense, and/or sell copies of the Software, and to 15a5ae21e4Smrg# permit persons to whom the Software is furnished to do so, subject to 16a5ae21e4Smrg# the following conditions: 17a5ae21e4Smrg# 18a5ae21e4Smrg# The above copyright notice and this permission notice shall be included 19a5ae21e4Smrg# in all copies or substantial portions of the Software. 20a5ae21e4Smrg# 21a5ae21e4Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 22a5ae21e4Smrg# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 23a5ae21e4Smrg# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 24a5ae21e4Smrg# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY 25a5ae21e4Smrg# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 26a5ae21e4Smrg# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 27a5ae21e4Smrg# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 28a5ae21e4Smrg# 29a5ae21e4Smrg# Except as contained in this notice, the name(s) of the above copyright 30a5ae21e4Smrg# holders shall not be used in advertising or otherwise to promote the 31a5ae21e4Smrg# sale, use or other dealings in this Software without prior written 32a5ae21e4Smrg# authorization. 33a5ae21e4Smrg# ----------------------------------------------------------------------------- 34a5ae21e4Smrg# Draw a grid of characters (optionally double-width) and modify it using 35a5ae21e4Smrg# overstrike, insert- and delete-characters to see if the double-width 36a5ae21e4Smrg# characters are completely cleared when "partly" modified. 37a5ae21e4Smrguse strict; 385307cd1aSmrguse warnings; 39a5ae21e4Smrg 40a5ae21e4Smrguse Getopt::Std; 41a5ae21e4Smrg 425307cd1aSmrgour ( $opt_c, $opt_n, $opt_r, $opt_w ); 435307cd1aSmrgour ( $lineno, $test_string, $term_width ); 44a5ae21e4Smrg 45a5ae21e4Smrg# returns the number of columns in the screen 46a5ae21e4Smrgsub screen_width() { 475307cd1aSmrg open( FP, "resize -u |" ) or exit $!; 485307cd1aSmrg my (@input) = <FP>; 495307cd1aSmrg chomp @input; 505307cd1aSmrg close(FP); 515307cd1aSmrg my $result = 80; 525307cd1aSmrg for my $n ( 0 .. $#input ) { 535307cd1aSmrg if ( $input[$n] =~ /^COLUMNS=/ ) { 545307cd1aSmrg $result = $input[$n]; 555307cd1aSmrg $result =~ s/^[^=]*=//; 565307cd1aSmrg $result =~ s/;.*//; 575307cd1aSmrg last; 585307cd1aSmrg } 595307cd1aSmrg } 605307cd1aSmrg return $result; 61a5ae21e4Smrg} 62a5ae21e4Smrg 63a5ae21e4Smrgsub set_color($) { 645307cd1aSmrg my $code = $_[0]; 655307cd1aSmrg if ( defined($opt_c) ) { 665307cd1aSmrg if ( $code == 3 ) { 675307cd1aSmrg printf "\x1b[1;33;42m"; # yellow-on-green 685307cd1aSmrg } 695307cd1aSmrg elsif ( $code == 2 ) { 705307cd1aSmrg printf "\x1b[0;31;45m"; # red-on-magenta 715307cd1aSmrg } 725307cd1aSmrg elsif ( $code == 1 ) { 735307cd1aSmrg printf "\x1b[0;36;44m"; # cyan-on-blue 745307cd1aSmrg } 755307cd1aSmrg else { 765307cd1aSmrg printf "\x1b[0;39;49m"; 775307cd1aSmrg } 785307cd1aSmrg } 79a5ae21e4Smrg} 80a5ae21e4Smrg 81a5ae21e4Smrg# returns a string of two-column characters given an ASCII alpha/numeric string 82a5ae21e4Smrgsub double_cells($) { 835307cd1aSmrg my $value = $_[0]; 845307cd1aSmrg $value =~ s/ / /g; 855307cd1aSmrg pack( 865307cd1aSmrg "U*", 875307cd1aSmrg map { 885307cd1aSmrg ( $_ <= 32 || $_ > 127 ) # if non-ASCII character... 895307cd1aSmrg ? 32 # ...just show a blank 905307cd1aSmrg : ( 0xff00 + ( $_ - 32 ) ) # map to "Fullwidth Form" 915307cd1aSmrg } unpack( "C*", $value ) 925307cd1aSmrg ); # unpack unsigned-char characters 93a5ae21e4Smrg} 94a5ae21e4Smrg 95a5ae21e4Smrgsub move_to($) { 965307cd1aSmrg printf "\x1b[%dG", $_[0] + 1; 97a5ae21e4Smrg} 98a5ae21e4Smrg 99a5ae21e4Smrgsub delete_char() { 1005307cd1aSmrg set_color(2); 1015307cd1aSmrg printf "\x1b[%dP", 1; 1025307cd1aSmrg set_color(1); 103a5ae21e4Smrg} 104a5ae21e4Smrg 105a5ae21e4Smrgsub insert_once($) { 1065307cd1aSmrg set_color(2); 1075307cd1aSmrg printf "\x1b[%d@", length( $_[0] ); 1085307cd1aSmrg write_chars( $_[0] ); 109a5ae21e4Smrg} 110a5ae21e4Smrg 111a5ae21e4Smrgsub insert_mode($) { 1125307cd1aSmrg set_color(2); 1135307cd1aSmrg printf "\x1b[%dP", length( $_[0] ); 1145307cd1aSmrg printf "\x1b[4h"; 1155307cd1aSmrg write_chars( $_[0] ); 1165307cd1aSmrg printf "\x1b[4l"; 117a5ae21e4Smrg} 118a5ae21e4Smrg 119a5ae21e4Smrgsub write_chars($) { 1205307cd1aSmrg set_color(3); 1215307cd1aSmrg printf "%s", $_[0]; 1225307cd1aSmrg set_color(1); 123a5ae21e4Smrg} 124a5ae21e4Smrg 125a5ae21e4Smrg# vary the starting point of each line, to make a more interesting pattern 126a5ae21e4Smrgsub starts_of($) { 1275307cd1aSmrg my $value = $_[0]; 1285307cd1aSmrg if ( defined($opt_w) ) { 1295307cd1aSmrg 1305307cd1aSmrg # 0,1,1,2,2,3,3,... 1315307cd1aSmrg $value = ( ( $value + 1 ) / 2 ) % length($test_string); 1325307cd1aSmrg } 1335307cd1aSmrg else { 1345307cd1aSmrg $value %= length($test_string); 1355307cd1aSmrg } 1365307cd1aSmrg return $value; 137a5ae21e4Smrg} 138a5ae21e4Smrg 139a5ae21e4Smrg# write the text for the given line-number 140a5ae21e4Smrgsub testit($) { 1415307cd1aSmrg my $number = $_[0]; 1425307cd1aSmrg my $length = $term_width; 1435307cd1aSmrg if ( defined($opt_n) ) { 1445307cd1aSmrg printf "%5d ", $number % 99999; 1455307cd1aSmrg $length -= 6; 1465307cd1aSmrg } 1475307cd1aSmrg 1485307cd1aSmrg # if we're printing double-column characters, we have half as much 1495307cd1aSmrg # space effectively - but don't forget the remainder, so we can push 1505307cd1aSmrg # the characters by single-columns. 1515307cd1aSmrg if ( defined($opt_c) ) { 1525307cd1aSmrg set_color(1); 1535307cd1aSmrg printf "\x1b[K"; 1545307cd1aSmrg } 1555307cd1aSmrg my $starts = starts_of($number); 1565307cd1aSmrg if ( defined($opt_w) ) { 1575307cd1aSmrg printf " ", if ( ( $number % 2 ) != 0 ); 1585307cd1aSmrg $length = ( $length - ( ($number) % 2 ) ) / 2; 1595307cd1aSmrg } 1605307cd1aSmrg my $string = substr( $test_string, $starts ); 1615307cd1aSmrg while ( length($string) < $length ) { 1625307cd1aSmrg $string = $string . $test_string; 1635307cd1aSmrg } 1645307cd1aSmrg $string = substr( $string, 0, $length ); 1655307cd1aSmrg if ( defined($opt_w) ) { 1665307cd1aSmrg $string = double_cells($string); 1675307cd1aSmrg } 1685307cd1aSmrg printf "%s", $string; 1695307cd1aSmrg 1705307cd1aSmrg # now - within the line - modify it 1715307cd1aSmrg move_to( ( 4 * $term_width ) / 5 ); 1725307cd1aSmrg insert_mode("XX"); 1735307cd1aSmrg move_to( ( 3 * $term_width ) / 5 ); 1745307cd1aSmrg delete_char(); 1755307cd1aSmrg move_to( ( 2 * $term_width ) / 5 ); 1765307cd1aSmrg insert_once('~'); 1775307cd1aSmrg move_to( ( 1 * $term_width ) / 5 ); 1785307cd1aSmrg write_chars('~'); 1795307cd1aSmrg move_to(0); 1805307cd1aSmrg set_color(0); 1815307cd1aSmrg printf "\n"; 182a5ae21e4Smrg} 183a5ae21e4Smrg 184a5ae21e4Smrgsub main::HELP_MESSAGE() { 1855307cd1aSmrg printf STDERR <<EOF 186a5ae21e4SmrgUsage: $0 [options] 187a5ae21e4Smrg 188a5ae21e4SmrgOptions: 189a5ae21e4Smrg 190a5ae21e4Smrg-c use color 191a5ae21e4Smrg-n write line-numbers 192a5ae21e4Smrg-r repeat indefinitely 193a5ae21e4Smrg-w write wide-characters 194a5ae21e4SmrgEOF 1955307cd1aSmrg ; 1965307cd1aSmrg exit; 197a5ae21e4Smrg} 198a5ae21e4Smrg 199a5ae21e4Smrg&getopts('cnrw') || die(); 200a5ae21e4Smrg 201a5ae21e4Smrg$term_width = screen_width(); 202a5ae21e4Smrg 2035307cd1aSmrg$test_string = 2045307cd1aSmrg "0123456789 abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 205a5ae21e4Smrg 2065307cd1aSmrgbinmode( STDOUT, ":utf8" ); 207a5ae21e4Smrgif ( defined($opt_r) ) { 2085307cd1aSmrg for ( $lineno = 0 ; ; ++$lineno ) { 2095307cd1aSmrg testit($lineno); 2105307cd1aSmrg } 2115307cd1aSmrg} 2125307cd1aSmrgelse { 2135307cd1aSmrg for ( $lineno = 0 ; $lineno < 24 ; ++$lineno ) { 2145307cd1aSmrg testit($lineno); 2155307cd1aSmrg } 216a5ae21e4Smrg} 217a5ae21e4Smrg 218a5ae21e4Smrgexit; 219