1a5ae21e4Smrg#!/usr/bin/env perl 204b94745Smrg# $XTermId: xtra-scroll.pl,v 1.12 2021/09/03 18:34:50 tom Exp $ 3a5ae21e4Smrg# ----------------------------------------------------------------------------- 4a5ae21e4Smrg# this file is part of xterm 5a5ae21e4Smrg# 6a5ae21e4Smrg# Copyright 2021 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# Interactively test screen-updates which can exercise the cdXtraScroll and 35a5ae21e4Smrg# tiXtraScroll features. 36a5ae21e4Smrg 37a5ae21e4Smrguse strict; 38a5ae21e4Smrguse warnings; 39a5ae21e4Smrg 40a5ae21e4Smrguse Getopt::Std; 41a5ae21e4Smrguse Term::ReadKey; 42a5ae21e4Smrguse I18N::Langinfo qw(langinfo CODESET); 43a5ae21e4Smrg 44a5ae21e4Smrg$! = 1; 45a5ae21e4Smrg 46a5ae21e4Smrgour $target = ""; 47a5ae21e4Smrg 48a5ae21e4Smrgour $encoding = lc( langinfo( CODESET() ) ); 49a5ae21e4Smrgour ($opt_8); 50a5ae21e4Smrg 51a5ae21e4Smrgour $dirty = 1; # nonzero if the screen should be painted 52a5ae21e4Smrgour $mode_margin = 0; # nonzero if left/right margin mode enabled 53a5ae21e4Smrgour $mode_origin = 0; # nonzero if origin-mode in effect 54a5ae21e4Smrgour $mode_screen = 0; # nonzero if using alternate screen 55a5ae21e4Smrgour $pos_x = 0; # current cursor-Y, absolute 56a5ae21e4Smrgour $pos_y = 0; # current cursor-X, absolute 57a5ae21e4Smrgour $term_high; # terminal's height 58a5ae21e4Smrgour $term_wide; # terminal's width 59a5ae21e4Smrgour $CSI = "\x1b["; 60a5ae21e4Smrgour $crlf = "\r\n"; 61a5ae21e4Smrgour $text_sample = "THE QUICK BROWN FOX JUMPED OVER THE LAZY DOG "; 62a5ae21e4Smrgour $text_filler = ""; 63a5ae21e4Smrgour %margins; 64a5ae21e4Smrg 65a5ae21e4Smrgsub raw() { 66a5ae21e4Smrg ReadMode 'ultra-raw', 'STDIN'; # allow single-character inputs 67a5ae21e4Smrg} 68a5ae21e4Smrg 69a5ae21e4Smrgsub cooked() { 70a5ae21e4Smrg ReadMode 'normal'; 71a5ae21e4Smrg} 72a5ae21e4Smrg 73a5ae21e4Smrgsub utf8_sample() { 74a5ae21e4Smrg my $text = ""; 75a5ae21e4Smrg for my $n ( 0 .. length($text_sample) ) { 76a5ae21e4Smrg my $chr = substr( $text_sample, $n, 1 ); 77a5ae21e4Smrg if ( $chr eq " " ) { 78a5ae21e4Smrg $chr = " "; 79a5ae21e4Smrg } 80a5ae21e4Smrg elsif ( ord($chr) < 32 ) { 81a5ae21e4Smrg 82a5ae21e4Smrg # leave control characters as-is 83a5ae21e4Smrg } 84a5ae21e4Smrg else { 85a5ae21e4Smrg $chr = chr( 0xff00 + ord($chr) - 32 ); 86a5ae21e4Smrg } 87a5ae21e4Smrg $text .= $chr; 88a5ae21e4Smrg } 89a5ae21e4Smrg return $text; 90a5ae21e4Smrg} 91a5ae21e4Smrg 92a5ae21e4Smrgsub next_x($) { 93a5ae21e4Smrg my $value = shift; 94a5ae21e4Smrg if ($mode_margin) { 95a5ae21e4Smrg $value = $margins{R} if ( $value < $margins{R} ); 96a5ae21e4Smrg $value = $margins{L} if ( $value > $margins{L} ); 97a5ae21e4Smrg } 98a5ae21e4Smrg else { 99a5ae21e4Smrg $value = $value % $term_wide; 100a5ae21e4Smrg } 101a5ae21e4Smrg return $value; 102a5ae21e4Smrg} 103a5ae21e4Smrg 104a5ae21e4Smrgsub next_y($) { 105a5ae21e4Smrg my $value = shift; 106a5ae21e4Smrg if ($mode_origin) { 107a5ae21e4Smrg $value = $margins{B} if ( $value < $margins{T} ); 108a5ae21e4Smrg $value = $margins{T} if ( $value > $margins{B} ); 109a5ae21e4Smrg } 110a5ae21e4Smrg else { 111a5ae21e4Smrg $value = $value % $term_high; 112a5ae21e4Smrg } 113a5ae21e4Smrg return $value; 114a5ae21e4Smrg} 115a5ae21e4Smrg 116a5ae21e4Smrgsub move() { 117a5ae21e4Smrg my $y = $pos_y; 118a5ae21e4Smrg if ($mode_origin) { 119a5ae21e4Smrg my $min_y = ( $margins{T} >= 0 ) ? $margins{T} : 0; 120a5ae21e4Smrg my $two_y = $min_y + 1; # scrolling region is at least 2 lines 121a5ae21e4Smrg my $max_y = ( $margins{B} >= $two_y ) ? $margins{B} : $two_y; 122a5ae21e4Smrg $y = $max_y if ( $y > $max_y ); 123a5ae21e4Smrg $y -= $min_y; # convert to relative ordinate 124a5ae21e4Smrg } 125a5ae21e4Smrg $y = 0 if ( $y < 0 ); 126a5ae21e4Smrg printf STDERR "%s%d;%dH", $CSI, 1 + $y, 1 + $pos_x; 127a5ae21e4Smrg} 128a5ae21e4Smrg 129a5ae21e4Smrgsub home() { 130a5ae21e4Smrg printf STDERR "%sH", $CSI; 131a5ae21e4Smrg $pos_x = 0; 132a5ae21e4Smrg $pos_y = 0; 133a5ae21e4Smrg &move; 134a5ae21e4Smrg} 135a5ae21e4Smrg 136a5ae21e4Smrgsub erase_display($) { 137a5ae21e4Smrg my $mode = shift; 138a5ae21e4Smrg printf STDERR "%s%sJ", $CSI, $mode; 139a5ae21e4Smrg} 140a5ae21e4Smrg 141a5ae21e4Smrgsub erase_line($) { 142a5ae21e4Smrg my $mode = shift; 143a5ae21e4Smrg printf STDERR "%s%sK", $CSI, $mode; 144a5ae21e4Smrg} 145a5ae21e4Smrg 146a5ae21e4Smrgsub toggle($) { 147a5ae21e4Smrg my $value = shift; 148a5ae21e4Smrg return ( $value == 0 ) ? 1 : 0; 149a5ae21e4Smrg} 150a5ae21e4Smrg 151a5ae21e4Smrg################################################################################ 152a5ae21e4Smrg 153a5ae21e4Smrgsub set_margin_mode($) { 154a5ae21e4Smrg my $mode = shift; 155a5ae21e4Smrg printf STDERR "%s?69%s", $CSI, ( $mode == 0 ) ? "l" : "h"; 156a5ae21e4Smrg $mode_margin = $mode; 157a5ae21e4Smrg} 158a5ae21e4Smrg 159a5ae21e4Smrg################################################################################ 160a5ae21e4Smrg 161a5ae21e4Smrgsub set_origin_mode($) { 162a5ae21e4Smrg my $mode = shift; 163a5ae21e4Smrg printf STDERR "%s?6%s", $CSI, ( $mode == 0 ) ? "l" : "h"; 164a5ae21e4Smrg $mode_origin = $mode; 165a5ae21e4Smrg} 166a5ae21e4Smrg 167a5ae21e4Smrg################################################################################ 168a5ae21e4Smrg 169a5ae21e4Smrgsub set_screen_mode($) { 170a5ae21e4Smrg my $mode = shift; 171a5ae21e4Smrg printf STDERR "%s?1049%s", $CSI, ( $mode == 0 ) ? "l" : "h"; 172a5ae21e4Smrg $mode_screen = $mode; 173a5ae21e4Smrg} 174a5ae21e4Smrg 175a5ae21e4Smrg################################################################################ 176a5ae21e4Smrg 177a5ae21e4Smrgsub do_tb_margins($$) { 178a5ae21e4Smrg my $param_T = ""; 179a5ae21e4Smrg my $param_B = ""; 180a5ae21e4Smrg $param_T = sprintf( "%d", 1 + $margins{T} ) if ( $margins{T} >= 0 ); 181a5ae21e4Smrg $param_B = sprintf( "%d", 1 + $margins{B} ) 182a5ae21e4Smrg if ( $margins{B} > $margins{T} ); 183a5ae21e4Smrg printf STDERR "%s%s;%sr", $CSI, $param_T, $param_B; 184a5ae21e4Smrg &move; 185a5ae21e4Smrg} 186a5ae21e4Smrg 187a5ae21e4Smrgsub undo_tb_margins() { 188a5ae21e4Smrg &do_tb_margins( -1, -1 ); 189a5ae21e4Smrg} 190a5ae21e4Smrg 191a5ae21e4Smrgsub redo_tb_margins() { 192a5ae21e4Smrg &do_tb_margins( $margins{T}, $margins{B} ); 193a5ae21e4Smrg} 194a5ae21e4Smrg 195a5ae21e4Smrgsub set_tb_margins($$) { 196a5ae21e4Smrg my $reset = ( not defined $margins{T} or not defined $margins{B} ) ? 1 : 0; 197a5ae21e4Smrg my $old_T = 1; 198a5ae21e4Smrg my $old_B = $term_high; 199a5ae21e4Smrg $old_T = $margins{T} if ( defined $margins{T} ); 200a5ae21e4Smrg $old_B = $margins{B} if ( defined $margins{B} ); 201a5ae21e4Smrg $margins{T} = shift; 202a5ae21e4Smrg $margins{B} = shift; 203a5ae21e4Smrg if ( $reset == 0 ) { 204a5ae21e4Smrg $reset = 1 if ( $old_T != $margins{T} ); 205a5ae21e4Smrg $reset = 1 if ( $old_B != $margins{B} ); 206a5ae21e4Smrg } 207a5ae21e4Smrg &redo_tb_margins if ( $reset == 1 ); 208a5ae21e4Smrg} 209a5ae21e4Smrg 210a5ae21e4Smrg################################################################################ 211a5ae21e4Smrg 212a5ae21e4Smrgsub do_lr_margins($$) { 213a5ae21e4Smrg my $param_L = ""; 214a5ae21e4Smrg my $param_R = ""; 215a5ae21e4Smrg $param_L = sprintf( "%d", 1 + $margins{L} ) if ( $margins{L} >= 0 ); 216a5ae21e4Smrg $param_R = sprintf( "%d", 1 + $margins{R} ) 217a5ae21e4Smrg if ( $margins{R} > $margins{T} ); 218a5ae21e4Smrg printf STDERR "%s%s;%ss", $CSI, $param_L, $param_R; 219a5ae21e4Smrg &move; 220a5ae21e4Smrg} 221a5ae21e4Smrg 222a5ae21e4Smrgsub undo_lr_margins() { 223a5ae21e4Smrg &do_lr_margins( -1, -1 ); 224a5ae21e4Smrg} 225a5ae21e4Smrg 226a5ae21e4Smrgsub redo_lr_margins() { 227a5ae21e4Smrg &do_lr_margins( $margins{L}, $margins{R} ); 228a5ae21e4Smrg} 229a5ae21e4Smrg 230a5ae21e4Smrgsub set_lr_margins($$) { 231a5ae21e4Smrg my $reset = ( not defined $margins{L} or not defined $margins{R} ) ? 1 : 0; 232a5ae21e4Smrg my $old_L = 1; 233a5ae21e4Smrg my $old_R = $term_high; 234a5ae21e4Smrg $old_L = $margins{L} if ( defined $margins{L} ); 235a5ae21e4Smrg $old_R = $margins{R} if ( defined $margins{R} ); 236a5ae21e4Smrg $margins{L} = shift; 237a5ae21e4Smrg $margins{R} = shift; 238a5ae21e4Smrg if ( $reset == 0 ) { 239a5ae21e4Smrg $reset = 1 if ( $old_L != $margins{L} ); 240a5ae21e4Smrg $reset = 1 if ( $old_R != $margins{R} ); 241a5ae21e4Smrg } 242a5ae21e4Smrg &redo_lr_margins if ( $reset == 1 ); 243a5ae21e4Smrg} 244a5ae21e4Smrg 245a5ae21e4Smrg################################################################################ 246a5ae21e4Smrg 247a5ae21e4Smrgsub has_tb_margins() { 248a5ae21e4Smrg my $result = 0; 249a5ae21e4Smrg $result = 1 if ( $margins{T} != 1 ); 250a5ae21e4Smrg $result = 1 if ( $margins{B} != $term_high ); 251a5ae21e4Smrg return $result; 252a5ae21e4Smrg} 253a5ae21e4Smrg 254a5ae21e4Smrgsub repaint($) { 255a5ae21e4Smrg my $erase = shift; 256a5ae21e4Smrg my $save_x = $pos_x; 257a5ae21e4Smrg my $save_y = $pos_y; 258a5ae21e4Smrg $dirty = 0; 259a5ae21e4Smrg if ($erase) { 260a5ae21e4Smrg &home; 261a5ae21e4Smrg &erase_display(2); 262a5ae21e4Smrg } 263a5ae21e4Smrg if ( $text_filler ne "" ) { 264a5ae21e4Smrg if ( $mode_origin and &has_tb_margins ) { 265a5ae21e4Smrg my @rows = split /$crlf/, $text_filler; 266a5ae21e4Smrg for my $row ( 0 .. $#rows ) { 267a5ae21e4Smrg next unless ( $row >= $margins{T} ); 268a5ae21e4Smrg next unless ( $row <= $margins{B} ); 269a5ae21e4Smrg printf STDERR "%s$crlf", $rows[$row]; 270a5ae21e4Smrg } 271a5ae21e4Smrg } 272a5ae21e4Smrg else { 273a5ae21e4Smrg printf STDERR "%s$crlf", $text_filler; 274a5ae21e4Smrg } 275a5ae21e4Smrg } 276a5ae21e4Smrg else { 277a5ae21e4Smrg my $cells = 0; 278a5ae21e4Smrg my $limit = $term_high * $term_wide; 279a5ae21e4Smrg while ( $cells < $limit ) { 280a5ae21e4Smrg my $sample = ( $encoding eq "utf-8" ) ? &utf8_sample : $text_sample; 281a5ae21e4Smrg printf STDERR "%s", $sample; 282a5ae21e4Smrg $cells += length($sample); 283a5ae21e4Smrg } 284a5ae21e4Smrg } 285a5ae21e4Smrg $pos_x = $save_x; 286a5ae21e4Smrg $pos_y = $save_y; 287a5ae21e4Smrg &move; 288a5ae21e4Smrg} 289a5ae21e4Smrg 290a5ae21e4Smrgsub initialize() { 291a5ae21e4Smrg if ( $encoding eq "utf-8" ) { 292a5ae21e4Smrg binmode( STDOUT, ":utf8" ); 293a5ae21e4Smrg binmode( STDERR, ":utf8" ); 294a5ae21e4Smrg } 295a5ae21e4Smrg if ($opt_8) { 296a5ae21e4Smrg if ( $encoding eq "utf-8" ) { 297a5ae21e4Smrg undef $opt_8; 298a5ae21e4Smrg printf "...ignoring -8 option since locale uses %s\n", $encoding; 299a5ae21e4Smrg } 300a5ae21e4Smrg else { 301a5ae21e4Smrg printf STDERR "\x1b G"; 302a5ae21e4Smrg $CSI = "\x9b"; 303a5ae21e4Smrg } 304a5ae21e4Smrg } 305a5ae21e4Smrg 306a5ae21e4Smrg &raw; 307a5ae21e4Smrg 308a5ae21e4Smrg my @term_size = GetTerminalSize( \*STDERR ); 309a5ae21e4Smrg $term_wide = 80; 310a5ae21e4Smrg $term_wide = $term_size[0] if ( $#term_size >= 0 ); 311a5ae21e4Smrg $term_wide = 80 if ( $term_wide <= 0 ); 312a5ae21e4Smrg $term_high = 24; 313a5ae21e4Smrg $term_high = $term_size[1] if ( $#term_size >= 1 ); 314a5ae21e4Smrg $term_high = 24 if ( $term_high <= 0 ); 315a5ae21e4Smrg 316a5ae21e4Smrg &set_margin_mode(0); 317a5ae21e4Smrg &set_origin_mode(0); 318a5ae21e4Smrg &set_screen_mode(0); 319a5ae21e4Smrg 320a5ae21e4Smrg &set_tb_margins( -1, -1 ); 321a5ae21e4Smrg &set_lr_margins( 1, $term_wide ); 322a5ae21e4Smrg 323a5ae21e4Smrg &home; 324a5ae21e4Smrg &erase_display("2"); 325a5ae21e4Smrg} 326a5ae21e4Smrg 327a5ae21e4Smrgsub cleanup() { 328a5ae21e4Smrg &cooked; 329a5ae21e4Smrg 330a5ae21e4Smrg printf STDERR "\x1b F" if ($opt_8); 331a5ae21e4Smrg 332a5ae21e4Smrg &set_margin_mode(0); 333a5ae21e4Smrg &set_origin_mode(0); 334a5ae21e4Smrg &set_screen_mode(0); 335a5ae21e4Smrg 336a5ae21e4Smrg &undo_tb_margins; 337a5ae21e4Smrg 338a5ae21e4Smrg $pos_x = 1; 339a5ae21e4Smrg $pos_y = $term_high - 2; 340a5ae21e4Smrg &move; 341a5ae21e4Smrg &erase_display(""); 342a5ae21e4Smrg} 343a5ae21e4Smrg 344a5ae21e4Smrgsub beep() { 345a5ae21e4Smrg printf STDERR "\a"; 346a5ae21e4Smrg} 347a5ae21e4Smrg 348a5ae21e4Smrgsub main::HELP_MESSAGE() { 349a5ae21e4Smrg printf STDERR <<EOF 350a5ae21e4SmrgUsage: $0 [options] [datafile] 351a5ae21e4SmrgOptions: 352a5ae21e4Smrg -8 use 8-bit controls 353a5ae21e4SmrgEOF 354a5ae21e4Smrg ; 355a5ae21e4Smrg exit 1; 356a5ae21e4Smrg} 357a5ae21e4Smrg 358a5ae21e4Smrg$Getopt::Std::STANDARD_HELP_VERSION = 1; 359a5ae21e4Smrg&getopts('8') || &main::HELP_MESSAGE; 360a5ae21e4Smrg$#ARGV <= 0 || &main::HELP_MESSAGE; 361a5ae21e4Smrg 362a5ae21e4Smrg# provide for reading file containing text to repaint 363a5ae21e4Smrgif ( $#ARGV == 0 ) { 364a5ae21e4Smrg if ( open( FP, $ARGV[0] ) ) { 365a5ae21e4Smrg my @lines = <FP>; 366a5ae21e4Smrg chomp @lines; 367a5ae21e4Smrg close FP; 368a5ae21e4Smrg $text_filler = join( $crlf, @lines ); 369a5ae21e4Smrg } 370a5ae21e4Smrg} 371a5ae21e4Smrg 372a5ae21e4Smrgprintf "encoding $encoding\n"; 373a5ae21e4Smrg 374a5ae21e4Smrg&initialize(); 375a5ae21e4Smrg 376a5ae21e4Smrgwhile (1) { 377a5ae21e4Smrg my $cmd; 378a5ae21e4Smrg 379a5ae21e4Smrg printf "\r\nCommand (? for help):" if ( $dirty != 0 ); 380a5ae21e4Smrg $cmd = ReadKey 0; 381a5ae21e4Smrg if ( not $cmd ) { 382a5ae21e4Smrg sleep 1; 383a5ae21e4Smrg } 384a5ae21e4Smrg elsif ( $cmd eq "?" ) { 385a5ae21e4Smrg $dirty = 1; 386a5ae21e4Smrg &home; 387a5ae21e4Smrg &erase_display(2); 388a5ae21e4Smrg printf $crlf 389a5ae21e4Smrg . "General:" 390a5ae21e4Smrg . $crlf 391a5ae21e4Smrg . " ? (help)," 392a5ae21e4Smrg . " q (quit)" 393a5ae21e4Smrg . $crlf 394a5ae21e4Smrg . "Clear:" 395a5ae21e4Smrg . $crlf 396a5ae21e4Smrg . " C (entire screen)," 397a5ae21e4Smrg . " c (screen-below)," 398a5ae21e4Smrg . " E (entire line)," 399a5ae21e4Smrg . " e (line-right)" 400a5ae21e4Smrg . $crlf . "Fill:" 401a5ae21e4Smrg . $crlf 402a5ae21e4Smrg . " @ (margin-box)," 403a5ae21e4Smrg . " # (prompt-char)" 404a5ae21e4Smrg . $crlf 405a5ae21e4Smrg . "Move cursor:\r\n" 406a5ae21e4Smrg . " h,j,k,l (vi-like)," 407a5ae21e4Smrg . " H (to home)." 408a5ae21e4Smrg . $crlf 409a5ae21e4Smrg . "Set margin using current position:" 410a5ae21e4Smrg . $crlf 411a5ae21e4Smrg . " T (top)," 412a5ae21e4Smrg . " B (bottom)," 413a5ae21e4Smrg . " L (left)," 414a5ae21e4Smrg . " R (right)" 415a5ae21e4Smrg . $crlf 416a5ae21e4Smrg . "Reset modes" 417a5ae21e4Smrg . $crlf 418a5ae21e4Smrg . " M (margins)" 419a5ae21e4Smrg . $crlf 420a5ae21e4Smrg . "Toggle modes" 421a5ae21e4Smrg . $crlf 422a5ae21e4Smrg . " A (alternate-screen)," 423a5ae21e4Smrg . " O (origin-mode)" 424a5ae21e4Smrg . " | (left/right-mode)" 425a5ae21e4Smrg . $crlf 426a5ae21e4Smrg . "Print sample:" 427a5ae21e4Smrg . " form-feed (repaint)"; 428a5ae21e4Smrg } 429a5ae21e4Smrg elsif ( $cmd eq "\033" ) { 430a5ae21e4Smrg 431a5ae21e4Smrg # try to ignore special-keys 432a5ae21e4Smrg my $count = 0; 433a5ae21e4Smrg while (1) { 434a5ae21e4Smrg $cmd = ReadKey 0; 435a5ae21e4Smrg $count++; 436a5ae21e4Smrg next if ( $count == 1 and $cmd eq "O" ); 437a5ae21e4Smrg next unless ( $cmd =~ /^[A-~]$/ ); 438a5ae21e4Smrg $cmd = ReadKey 0; 439a5ae21e4Smrg last; 440a5ae21e4Smrg } 441a5ae21e4Smrg } 442a5ae21e4Smrg elsif ( $cmd eq "q" ) { 443a5ae21e4Smrg last; 444a5ae21e4Smrg } 445a5ae21e4Smrg elsif ( index( "CcEe@#hjklHMTBLRAO|\f", $cmd ) >= 0 ) { 446a5ae21e4Smrg my $was_dirty = $dirty; 447a5ae21e4Smrg &repaint(1) if ( $dirty != 0 ); 448a5ae21e4Smrg if ( $cmd eq "C" ) { 449a5ae21e4Smrg &home; 450a5ae21e4Smrg &erase_display("2"); 451a5ae21e4Smrg } 452a5ae21e4Smrg elsif ( $cmd eq "c" ) { 453a5ae21e4Smrg &erase_display(""); 454a5ae21e4Smrg } 455a5ae21e4Smrg elsif ( $cmd eq "E" ) { 456a5ae21e4Smrg &erase_line("2"); 457a5ae21e4Smrg } 458a5ae21e4Smrg elsif ( $cmd eq "e" ) { 459a5ae21e4Smrg &erase_line(""); 460a5ae21e4Smrg } 461a5ae21e4Smrg elsif ( $cmd eq "@" ) { 462a5ae21e4Smrg 463a5ae21e4Smrg # FIXME 464a5ae21e4Smrg } 465a5ae21e4Smrg elsif ( $cmd eq "#" ) { 466a5ae21e4Smrg $text_sample = ReadKey 0; 467a5ae21e4Smrg if ( $text_filler ne "" ) { 468a5ae21e4Smrg my $save_filler = $text_filler; 469a5ae21e4Smrg $text_filler =~ s/[^\d\s]/$text_sample/g; 470a5ae21e4Smrg &repaint(0); 471a5ae21e4Smrg $text_filler = $save_filler; 472a5ae21e4Smrg } 473a5ae21e4Smrg else { 474a5ae21e4Smrg &repaint(0); 475a5ae21e4Smrg } 476a5ae21e4Smrg } 477a5ae21e4Smrg elsif ( $cmd eq "h" ) { 478a5ae21e4Smrg $pos_x = &next_x( $pos_x - 1 ); 479a5ae21e4Smrg &move; 480a5ae21e4Smrg } 481a5ae21e4Smrg elsif ( $cmd eq "j" ) { 482a5ae21e4Smrg $pos_y = &next_y( $pos_y + 1 ); 483a5ae21e4Smrg &move; 484a5ae21e4Smrg } 485a5ae21e4Smrg elsif ( $cmd eq "k" ) { 486a5ae21e4Smrg $pos_y = &next_y( $pos_y - 1 ); 487a5ae21e4Smrg &move; 488a5ae21e4Smrg } 489a5ae21e4Smrg elsif ( $cmd eq "l" ) { 490a5ae21e4Smrg $pos_x = &next_x( $pos_x + 1 ); 491a5ae21e4Smrg &move; 492a5ae21e4Smrg } 493a5ae21e4Smrg elsif ( $cmd eq "H" ) { 494a5ae21e4Smrg &home; 495a5ae21e4Smrg } 496a5ae21e4Smrg elsif ( $cmd eq "M" ) { 497a5ae21e4Smrg &set_tb_margins( -1, -1 ); 498a5ae21e4Smrg &set_lr_margins( -1, -1 ); 499a5ae21e4Smrg &repaint(0); 500a5ae21e4Smrg } 501a5ae21e4Smrg elsif ( $cmd eq "T" ) { 502a5ae21e4Smrg &set_tb_margins( $pos_y, $margins{B} ); 503a5ae21e4Smrg } 504a5ae21e4Smrg elsif ( $cmd eq "B" ) { 505a5ae21e4Smrg &set_tb_margins( $margins{T}, $pos_y ); 506a5ae21e4Smrg } 507a5ae21e4Smrg elsif ( $cmd eq "L" ) { 508a5ae21e4Smrg &set_lr_margins( $pos_x, $margins{R} ); 509a5ae21e4Smrg } 510a5ae21e4Smrg elsif ( $cmd eq "R" ) { 511a5ae21e4Smrg &set_lr_margins( $margins{L}, $pos_x ); 512a5ae21e4Smrg } 513a5ae21e4Smrg elsif ( $cmd eq "A" ) { 514a5ae21e4Smrg &set_screen_mode( &toggle($mode_screen) ); 515a5ae21e4Smrg &repaint(1); 516a5ae21e4Smrg } 517a5ae21e4Smrg elsif ( $cmd eq "O" ) { 518a5ae21e4Smrg &set_origin_mode( &toggle($mode_origin) ); 519a5ae21e4Smrg } 520a5ae21e4Smrg elsif ( $cmd eq "|" ) { 521a5ae21e4Smrg &set_margin_mode( &toggle($mode_margin) ); 522a5ae21e4Smrg } 523a5ae21e4Smrg elsif ( $cmd eq "\f" ) { 524a5ae21e4Smrg &repaint(1) unless ($was_dirty); 525a5ae21e4Smrg } 526a5ae21e4Smrg else { 527a5ae21e4Smrg &beep; 528a5ae21e4Smrg $dirty = 2; 529a5ae21e4Smrg } 530a5ae21e4Smrg } 531a5ae21e4Smrg else { 532a5ae21e4Smrg &beep; 533a5ae21e4Smrg } 534a5ae21e4Smrg} 535a5ae21e4Smrg 536a5ae21e4Smrg&cleanup; 537a5ae21e4Smrgprintf " ...quit\r\n"; 538a5ae21e4Smrg 539a5ae21e4Smrg1; 540