xterm-353/0000755000175100001440000000000013615425516011254 5ustar tomusersxterm-353/testxmc.c0000644000175100001440000001550213506202762013105 0ustar tomusers/* $XTermId: testxmc.c,v 1.53 2019/06/30 18:56:50 tom Exp $ */ /* * Copyright 1997-2014,2019 by Thomas E. Dickey * * All Rights Reserved * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name(s) of the above copyright * holders shall not be used in advertising or otherwise to promote the * sale, use or other dealings in this Software without prior written * authorization. */ /* * This module provides test support for curses applications that must work * with terminals that have the xmc (magic cookie) glitch. The xmc_glitch * resource denotes the number of spaces that are emitted when switching to or * from standout (reverse) mode. Some terminals implement this by storing the * attribute controls in the character cell that is skipped. So if the cell is * overwritten by text, then the attribute change in the cell is cancelled, * causing attributes to the left of the change to propagate. * * We implement the glitch by writing a character that won't be mistaken for * other normal characters (and mapping normal writes to that character to a * different one). * * Since xmc isn't normally part of xterm, we document it here rather than in * the man-page. This module is driven by resources rather than by the * termcap/terminfo description to make it a little more flexible for testing * purposes. * * Resources: * * xmcGlitch (class XmcGlitch) * When true, enables this extension. The default is `0', which disables * the module. (termcap sg, terminfo xmc). * * xmcAttributes (class XmcAttributes) * The attributes for which we'll generate a glitch, as a bitmask. * * INVERSE 1 * UNDERLINE 2 * BOLD 4 * BLINK 8 * * The default is `1' (INVERSE). Some terminals emit glitches for * underline. Just for completeness, we recognize all of the video * attributes. * * xmcInline (class XmcInline) * When true, limits the extent of an SGR change to the current line. * The default is `false'. (No termcap or terminfo equivalent, though * there are comments in some entries relating to this issue). * * xmcMoveSGR (class XmcMoveSGR) * When false, a cursor movement will leave a glitch when SGR's are * active. The default is `true'. (termcap ms, terminfo msgr). * * TODO: * When xmc is active, the terminfo max_attributes (ma) capability is * assumed to be 1. * * The xmcAttributes resource should also apply to alternate character * sets and to color. */ #include #include #define MARK_ON(a) (Bool) ((my_attrs & a) != 0 && (xw->flags & (whichone = CharOf(a))) == 0) #define MARK_OFF(a) (Bool) ((my_attrs & a) != 0 && (xw->flags & (whichone = CharOf(a))) != 0) void Mark_XMC(XtermWidget xw, int param) { static IChar *glitch; TScreen *screen = TScreenOf(xw); Bool found = False; unsigned my_attrs = CharOf(screen->xmc_attributes & XMC_FLAGS); unsigned whichone = 0; if (glitch == 0) { unsigned len = screen->xmc_glitch; glitch = TypeMallocN(IChar, len); if (glitch == NULL) { xtermWarning("Not enough core for xmc glitch mode\n"); return; } else { while (len--) glitch[len] = XMC_GLITCH; } } switch (param) { case -1: /* DEFAULT */ case 0: /* FALLTHRU */ found = MARK_OFF((xw->flags & XMC_FLAGS)); break; case 1: found = MARK_ON(BOLD); break; case 4: found = MARK_ON(UNDERLINE); break; case 5: found = MARK_ON(BLINK); break; case 7: found = MARK_ON(INVERSE); break; case 22: found = MARK_OFF(BOLD); break; case 24: found = MARK_OFF(UNDERLINE); break; case 25: found = MARK_OFF(BLINK); break; case 27: found = MARK_OFF(INVERSE); break; } /* * Write a glitch with the attributes temporarily set to the new(er) * ones. */ if (found) { unsigned save = xw->flags; xw->flags ^= whichone; TRACE(("XMC Writing glitch (%d/%d) after SGR %d\n", my_attrs, whichone, param)); dotext(xw, '?', glitch, screen->xmc_glitch); xw->flags = save; } } /* * Force a glitch on cursor movement when we're in standout mode and not at the * end of a line. */ void Jump_XMC(XtermWidget xw) { TScreen *screen = TScreenOf(xw); if (!screen->move_sgr_ok && screen->cur_col <= LineMaxCol(screen, getLineData(screen, screen->cur_row))) { Mark_XMC(xw, -1); } } /* * After writing text to the screen, resolve mismatch between the current * location and any attributes that would have been set by preceding locations. */ void Resolve_XMC(XtermWidget xw) { TScreen *screen = TScreenOf(xw); LineData *ld; Bool changed = False; IAttr start; IAttr my_attrs = CharOf(screen->xmc_attributes & XMC_FLAGS); int row = screen->cur_row; int col = screen->cur_col; /* Find the preceding cell. */ ld = getLineData(screen, row); if (ld->charData[col] != XMC_GLITCH) { if (col != 0) { col--; } else if (!screen->xmc_inline && row != 0) { ld = getLineData(screen, --row); col = LineMaxCol(screen, ld); } } start = (ld->attribs[col] & my_attrs); /* Now propagate the starting state until we reach a cell which holds * a glitch. */ for (;;) { if (col < LineMaxCol(screen, ld)) { col++; } else if (!screen->xmc_inline && row < screen->max_row) { col = 0; ld = getLineData(screen, ++row); } else break; if (ld->charData[col] == XMC_GLITCH) break; if ((ld->attribs[col] & my_attrs) != start) { ld->attribs[col] = (IAttr) (start | (ld->attribs[col] & ~my_attrs)); changed = True; } } TRACE(("XMC %s (%s:%d/%d) from %d,%d to %d,%d\n", changed ? "Ripple" : "Nochange", BtoS(xw->flags & my_attrs), my_attrs, start, screen->cur_row, screen->cur_col, row, col)); if (changed) { ScrnUpdate(xw, screen->cur_row, 0, row + 1 - screen->cur_row, MaxCols(screen), True); } } xterm-353/vttests/0000755000175100001440000000000013610650270012760 5ustar tomusersxterm-353/vttests/mouse-codes0000755000175100001440000001223413413526645015144 0ustar tomusers#!/usr/bin/env perl # $XTermId: mouse-codes,v 1.6 2019/01/04 00:49:41 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2018,2019 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Imitate xterm's BtnCode() function, to enumerate the possible inputs (button, # event state) versus output (xterm mouse-code). use strict; use warnings; use diagnostics; use Getopt::Std; our ( $opt_b, $opt_i, $opt_x ); # Typically, # - Buttons 1, 2, and 3 are left-to-right assignments on a 3-button mouse. # - Buttons 4 and 5 are (by convention) assigned to a wheel mouse's # up/down events. # - Buttons 6 and 7 may happen to work, e.g., as left/right events from a # tiltable wheel mouse. There is no explicit support for these (there # are no related symbols in Xt), so it is not possible to use them in the # translations resource. our $maxbutton = 7; # xterm uses code 3 internally for release-events. sub ButtonName($) { my $code = shift; my $result = ""; if ( $code < 0 ) { $result = "release"; } else { $result = sprintf "Button%d", ( $code > 3 ) ? $code : ( $code + 1 ); } return $result; } # Combine the modifier state as bits: # shift key -> 1 # meta key -> 2 (Mod1 came from X11R1, but was adapted from X10) # control key -> 4 our $maxstates = 7; sub KeyState($) { my $mask = shift; my $result = ""; $result .= " + shift" if ( ( $mask & 1 ) != 0 ); $result .= " + meta" if ( ( $mask & 2 ) != 0 ); $result .= " + control" if ( ( $mask & 4 ) != 0 ); return $result; } sub Motion($) { my $code = shift; my $result = ""; $result = " + motion" if ( $code != 0 ); return $result; } sub report() { my $button; my $states; my $motion; my %encoded; my %reports; for $states ( 0 .. $maxstates ) { for $motion ( 0 .. 1 ) { for $button ( -1 .. $maxbutton ) { next if ( $button == 3 ); my $result = ( 32 + ( $states << 2 ) ); $result += 32 if ( $motion != 0 ); if ( $button < 0 ) { $result += 3; } else { $result += $button & 3; if ( $button & 4 ) { $result += 64; } if ( $button & 8 ) { $result += 128; } } my $code = sprintf "%3d", $result; my $report = sprintf "%s%s%s", &ButtonName($button), &KeyState($states), &Motion($motion); if ( defined $encoded{$code} ) { printf "OOPS %s ->%s versus %s\n", $code, $report, $encoded{$code}; } elsif ( $result > 255 and not defined $opt_x ) { printf "OOPS %s ->%s\n", $code, $report; } $encoded{$code} = $report; $reports{$report} = $result; } } } if ($opt_i) { foreach my $report ( sort keys %reports ) { printf "%s = %s\n", $report, $reports{$report}; } } else { foreach my $code ( sort keys %encoded ) { printf "%s = %s\n", $code, $encoded{$code}; } } } sub main::HELP_MESSAGE() { printf STDERR <; close TTY; system "stty $old"; if ( defined $reply ) { die("^C received\n") if ( "$reply" eq "\003" ); } return $reply; } sub hexified($) { my $value = $_[0]; my $result = ""; my $n; for ( $n = 0 ; $n < length($value) ; ++$n ) { $result .= sprintf( "%02X", ord substr( $value, $n, 1 ) ); } return $result; } sub modify_tcap($) { my $name = $_[0]; my $param = &hexified($name); &no_reply( "\x1bP+p" . $param . "\x1b\\" ); } sub begin_query() { @query_params = (); } sub add_param($) { $query_params[ $#query_params + 1 ] = &hexified( $_[0] ); } sub finish_query() { my $reply = &get_reply( "\x1bP+q" . join( ';', @query_params ) . "\x1b\\" ); return unless defined $reply; if ( $reply =~ /\x1bP1\+r[[:xdigit:]]+=[[:xdigit:]]*.*/ ) { my $n; $reply =~ s/^\x1bP1\+r//; $reply =~ s/\x1b\\//; my $result = ""; my $count = 0; my $state = 0; my $error = "?"; for ( $n = 0 ; $n < length($reply) ; ) { my $c = substr( $reply, $n, 1 ); if ( $c eq ';' ) { $n += 1; printf "%d%s\t%s\n", $count, $error, $result if ( $result ne "" ); $result = ""; $state = 0; $error = "?"; $count++; } elsif ( $c eq '=' ) { $error = "" if ( $count <= $#query_params and &hexified($result) eq $query_params[$count] ); $n += 1; $result .= $c; $state = 1; } elsif ( $c =~ /[[:punct:]]/ ) { $n += 1; $result .= $c; } else { my $k = hex substr( $reply, $n, 2 ); if ( $k == 0x1b ) { $result .= "\\E"; } elsif ( $k == 0x7f ) { $result .= "^?"; } elsif ( $k == 32 ) { $result .= "\\s"; } elsif ( $k < 32 ) { $result .= sprintf( "^%c", $k + 64 ); } elsif ( $k > 128 ) { $result .= sprintf( "\\%03o", $k ); } else { $result .= chr($k); } $n += 2; } } printf "%d%s\t%s\n", $count, $error, $result if ( $result ne "" ); } } sub query_tcap($$) { my $tcap = shift; my $tinfo = shift; &begin_query unless ($opt_q); &add_param($tcap) if ( $opt_b or not $opt_i ); &add_param($tinfo) if ( $opt_b or $opt_i ); &finish_query unless ($opt_q); } # extended-keys are a feature of ncurses 5.0 and later sub query_extended($) { my $name = $_[0]; my $n; $name = "k" . $name if ( $name !~ /^k/ ); for ( $n = 2 ; $n <= 7 ; ++$n ) { my $test = $name; $test = $test . $n if ( $n > 2 ); &query_tcap( $name, $test ); } } &begin_query if ($opt_q); &query_tcap( "TN", "name" ); if ( defined($opt_t) ) { printf "Setting TERM=%s\n", $opt_t; &modify_tcap($opt_t); } # See xtermcapKeycode() if ( defined($opt_a) || defined($opt_c) ) { &query_tcap( "ku", "kcuu1" ); &query_tcap( "kd", "kcud1" ); &query_tcap( "kr", "kcuf1" ); &query_tcap( "kl", "kcub1" ); &query_tcap( "kF", "kind" ); &query_tcap( "kR", "kri" ); &query_tcap( "%i", "kRIT" ); &query_tcap( "#4", "kLFT" ); } if ( defined($opt_a) || defined($opt_e) ) { &query_tcap( "kD", "kdch1" ); &query_tcap( "kI", "kich1" ); &query_tcap( "kh", "khome" ); &query_tcap( "\@7", "kend" ); &query_tcap( "#2", "kHOM" ); &query_tcap( "*7", "kEND" ); &query_tcap( "*6", "kslt" ); &query_tcap( "#6", "kSLT" ); &query_tcap( "\@0", "kfnd" ); &query_tcap( "*0", "kFND" ); &query_tcap( "kN", "knp" ); &query_tcap( "kP", "kpp" ); &query_tcap( "%c", "kNXT" ); &query_tcap( "%e", "kPRV" ); } if ( defined($opt_a) || defined($opt_f) ) { &query_tcap( "k1", "kf1" ); &query_tcap( "k2", "kf2" ); &query_tcap( "k3", "kf3" ); &query_tcap( "k4", "kf4" ); &query_tcap( "k5", "kf5" ); &query_tcap( "k6", "kf6" ); &query_tcap( "k7", "kf7" ); &query_tcap( "k8", "kf8" ); &query_tcap( "k9", "kf9" ); &query_tcap( "k;", "kf10" ); &query_tcap( "F1", "kf11" ); &query_tcap( "F2", "kf12" ); &query_tcap( "F3", "kf13" ); &query_tcap( "F4", "kf14" ); &query_tcap( "F5", "kf15" ); &query_tcap( "F6", "kf16" ); &query_tcap( "F7", "kf17" ); &query_tcap( "F8", "kf18" ); &query_tcap( "F9", "kf19" ); &query_tcap( "FA", "kf20" ); &query_tcap( "FB", "kf21" ); &query_tcap( "FC", "kf22" ); &query_tcap( "FD", "kf23" ); &query_tcap( "FE", "kf24" ); &query_tcap( "FF", "kf25" ); &query_tcap( "FG", "kf26" ); &query_tcap( "FH", "kf27" ); &query_tcap( "FI", "kf28" ); &query_tcap( "FJ", "kf29" ); &query_tcap( "FK", "kf30" ); &query_tcap( "FL", "kf31" ); &query_tcap( "FM", "kf32" ); &query_tcap( "FN", "kf33" ); &query_tcap( "FO", "kf34" ); &query_tcap( "FP", "kf35" ); &query_tcap( "FQ", "kf36" ); &query_tcap( "FR", "kf37" ); &query_tcap( "FS", "kf38" ); &query_tcap( "FT", "kf39" ); &query_tcap( "FU", "kf40" ); &query_tcap( "FV", "kf41" ); &query_tcap( "FW", "kf42" ); &query_tcap( "FX", "kf43" ); &query_tcap( "FY", "kf44" ); &query_tcap( "FZ", "kf45" ); &query_tcap( "Fa", "kf46" ); &query_tcap( "Fb", "kf47" ); &query_tcap( "Fc", "kf48" ); &query_tcap( "Fd", "kf49" ); &query_tcap( "Fe", "kf50" ); &query_tcap( "Ff", "kf51" ); &query_tcap( "Fg", "kf52" ); &query_tcap( "Fh", "kf53" ); &query_tcap( "Fi", "kf54" ); &query_tcap( "Fj", "kf55" ); &query_tcap( "Fk", "kf56" ); &query_tcap( "Fl", "kf57" ); &query_tcap( "Fm", "kf58" ); &query_tcap( "Fn", "kf59" ); &query_tcap( "Fo", "kf60" ); &query_tcap( "Fp", "kf61" ); &query_tcap( "Fq", "kf62" ); &query_tcap( "Fr", "kf63" ); } if ( defined($opt_a) || defined($opt_k) ) { &query_tcap( "K1", "ka1" ); &query_tcap( "K3", "ka3" ); &query_tcap( "K4", "kc1" ); &query_tcap( "K5", "kc3" ); } if ( defined($opt_a) || defined($opt_m) ) { &query_tcap( "kB", "kcbt" ); &query_tcap( "kC", "kclr" ); &query_tcap( "&8", "kund" ); &query_tcap( "kb", "kbs" ); &query_tcap( "%1", "khlp" ); &query_tcap( "#1", "kHLP" ); &query_tcap( "Co", "colors" ); &query_tcap( "Co", "RGB" ) if ($opt_i); } if ( defined($opt_x) ) { &query_extended($opt_x); } if ( defined($opt_X) ) { if ( defined($opt_c) ) { &query_extended("DN"); &query_extended("UP"); &query_extended("LFT"); &query_extended("RIT"); } if ( defined($opt_e) ) { &query_extended("DC"); &query_extended("END"); &query_extended("HOM"); &query_extended("IC"); &query_extended("NXT"); &query_extended("PRV"); } } &finish_query if ($opt_q); 1; xterm-353/vttests/sgrPushPop.pl0000755000175100001440000000665613330671432015451 0ustar tomusers#!/usr/bin/env perl # $XTermId: sgrPushPop.pl,v 1.10 2018/08/02 21:09:46 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm, contributed by Dan Thompson # # Copyright 2018 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- use strict; use warnings; # This script demonstrates the utility of the [non-standard] SGR push/pop # control sequences. The ability to save (on a stack) the current SGR # attributes (fg/bg color, bold, etc.) and then later restore them allows # [SGR-containing] text from independent sources to be easily composed # together, without requiring any sort of global coordination. our ( $pushSgr, $popSgr, $lib1Fmt, $lib2Fmt, $redOnBlack, $blackOnYellow, $blueOnGreen, $bg, $fg ); $pushSgr = "\x1b[#{"; $popSgr = "\x1b[#}"; # lib1Fmt represents a "top-level" program, and controls the current "ambient" # fg/bg colors. $lib1Fmt = "\x1b[48;5;%sm\x1b[38;5;%sm%03.3d/%03.3d "; # lib2Fmt represents some intermediate library. Note that it contains no SGR # control sequences at all. $lib2Fmt = "Test stack: %s, %s, %s"; # The following represent individual bits of colorized data that come from # other, "leaf-level" libraries. $redOnBlack = $pushSgr . "\x1b[1;31m\x1b[40m" . "redOnBlack" . $popSgr; $blackOnYellow = $pushSgr . "\x1b[30m\x1b[4;43m" . "blackOnYellow" . $popSgr; $blueOnGreen = $pushSgr . "\x1b[34m\x1b[42m" . "blueOnGreen" . $popSgr; printf $pushSgr; printf "\x1b[40;37mSetting ambient colors to white-on-black\n"; printf $pushSgr; for ( $bg = 0 ; $bg < 16 ; $bg++ ) { for ( $fg = 0 ; $fg < 16 ; $fg++ ) { printf $pushSgr; printf $lib1Fmt, $fg, $bg, $fg, $bg; printf $lib2Fmt, $redOnBlack, $blackOnYellow, $blueOnGreen; print " something else"; printf $popSgr; # keep the newline from bleeding color print "\n"; } print "\n"; } printf $popSgr; printf "The ambient colors should still be white-on-black.\n"; printf $popSgr; printf "Now we should be back to whatever it was before we got here.\n"; 1; xterm-353/vttests/16colors.sh0000755000175100001440000000655211671154202014776 0ustar tomusers#!/bin/sh # $XTermId: 16colors.sh,v 1.14 2011/12/11 16:21:22 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 1999-2003,2011 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Show a simple 16-color test pattern. It is a little more confusing than # 8colors.sh, since everything is abbreviated to fit on an 80-column line. # The high (8-15) combinations for foreground or background are marked with # a '+' sign. ESC="" CMD='/bin/echo' OPT='-n' SUF='' TMP=/tmp/xterm$$ eval '$CMD $OPT >$TMP || echo fail >$TMP' 2>/dev/null ( test ! -f $TMP || test -s $TMP ) && for verb in printf print ; do rm -f $TMP eval '$verb "\c" >$TMP || echo fail >$TMP' 2>/dev/null if test -f $TMP ; then if test ! -s $TMP ; then CMD="$verb" OPT= SUF='\c' break fi fi done rm -f $TMP if ( trap "echo exit" EXIT 2>/dev/null ) >/dev/null then trap '$CMD ""; exit' EXIT HUP INT TRAP TERM else trap '$CMD ""; exit' 0 1 2 5 15 fi echo "" while true do for AT in 0 1 4 7 do case $AT in 0) attr=" ";; 1) attr="BO ";; 4) attr="UN ";; 7) attr="RV ";; esac for FG in 0 1 2 3 4 5 6 7 do case $FG in 0) fcolor="BLK ";; 1) fcolor="RED ";; 2) fcolor="GRN ";; 3) fcolor="YEL ";; 4) fcolor="BLU ";; 5) fcolor="MAG ";; 6) fcolor="CYN ";; 7) fcolor="WHT ";; esac for HI in 3 9 do if test $HI = 3 ; then color=" $fcolor" else color="+$fcolor" fi $CMD $OPT "[0;${AT}m$attr$SUF" $CMD $OPT "[${HI}${FG}m$color$SUF" for BG in 1 2 3 4 5 6 7 do case $BG in 0) bcolor="BLK ";; 1) bcolor="RED ";; 2) bcolor="GRN ";; 3) bcolor="YEL ";; 4) bcolor="BLU ";; 5) bcolor="MAG ";; 6) bcolor="CYN ";; 7) bcolor="WHT ";; esac $CMD $OPT "[4${BG}m$bcolor$SUF" $CMD $OPT "[10${BG}m+$bcolor$SUF" done echo "" done done sleep 1 done done xterm-353/vttests/modify-keys.pl0000755000175100001440000013454613610650264015600 0ustar tomusers#!/usr/bin/env perl # $XTermId: modify-keys.pl,v 1.90 2020/01/18 18:38:44 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2019,2020 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Print a table to illustrate the modifyOtherKeys resource choices. # # Some of the key combinations are unavailable unless certain translations # resource settings are suppressed. This command helped to verify those: # xterm -xrm '*omitTranslation:fullscreen,scroll-lock,shift-fonts' # # Additionally, a test-script was written to exercise xterm when the # "Allow SendEvents" feature is enabled, in combination with keys sent by # commands like this: # xdotool key --window XXX shift 2>/dev/null # # A curses application running in the target xterm showed the received data # in the terminfo-style format used in this script. # TODO factor in the backspace/delete meta/alt/escape resource-settings # TODO show keycodes via "xmodmap -pk" as alternative to xkbcomp # TODO show different sort-order (code, sym, xkb) # TODO use U+xxxx codepoints in keysymdef.h for rendering plain text # TODO optionally show 2**N, e.g., 4 (shift+control), 8 (shift+alt+control) or 16 (+meta) modifiers # TODO optionally show -c (cursor) -e (edit) -f (function-keys) with modifiers use strict; use warnings; use Getopt::Std; $| = 1; our ( $opt_d, $opt_h, $opt_k, $opt_K, $opt_l, $opt_m, $opt_o, $opt_u, $opt_v ); our $REPORT; our @headers; our @nolinks = (); our ( $xkb_layout, $xkb_model ); our $keyfile = "/usr/include/X11/keysymdef.h"; our @keyNames; # xkb's notion of key-names (undocumented) our %keySyms; # all keysyms, hashed by name our %keyCodes; # all keysyms, hashed by keycode our %uniCodes; # keysym Unicode values, hashed by keycode our %uniNames; # keysym Unicode descriptions, hashed by keycode our @keyTypes; # XkbKeyTypeRec our @symCache; # keysyms defined in keysymdef.h which might be used our @symMap; # index into symCache from keyNames our %keysUsed; # report derived from @symMap, etc. our %linkUsed; # check for uniqueness of html anchor-names our $MAXMODS = 8; # maximum for modifier-param our %Shifted; # map keycode to shifted-keycode seen by xterm # imitate /usr/include/X11/X.h our $ShiftMask = 1; our $LockMask = 2; our $ControlMask = 4; our $AltMask = 8; # assume mod1=alt our $MetaMask = 16; # assume mod2=meta our %editKeys = qw( XK_Delete 1 XK_Prior 1 XK_Next 1 XK_Insert 1 XK_Find 1 XK_Select 1 XK_KP_Delete 1 XK_KP_Insert 1 XK_ISO_Left_Tab 1 ); sub failed($) { printf STDERR "%s\n", $_[0]; exit 1; } # prefer hex with 4 digit for hash keys sub toCode($) { my $value = shift; $value = sprintf( "0x%04x", $value ) if ( $value =~ /^\d+$/ ); return $value; } sub codeOf($) { my $value = shift; my $result = 0; &failed("missing keysym") unless ( defined $value ); if ( $value =~ /^\d+$/ ) { $result = $value; } elsif ( $value =~ /^0x[[:xdigit:]]+$/i ) { $result = hex $value; } elsif ( $value =~ /^XK_/ ) { $result = hex $keySyms{$value}; } else { &failed("not a keysym: $value"); } return $result; } # macros from sub IsKeypadKey($) { my $code = &codeOf( $_[0] ); my $result = ( ( $code >= &codeOf("XK_KP_Space") ) and ( $code <= &codeOf("XK_KP_Equal") ) ) ? 1 : 0; return $result; } sub IsPrivateKeypadKey($) { my $code = &codeOf( $_[0] ); my $result = ( ( $code >= 0x11000000 ) and ( $code <= 0x1100FFFF ) ) ? 1 : 0; return $result; } sub IsCursorKey($) { my $code = &codeOf( $_[0] ); my $result = ( ( $code >= &codeOf("XK_Home") ) and ( $code < &codeOf("XK_Select") ) ) ? 1 : 0; return $result; } sub IsPFKey($) { my $code = &codeOf( $_[0] ); my $result = ( ( $code >= &codeOf("XK_KP_F1") ) and ( $code <= &codeOf("XK_KP_F4") ) ) ? 1 : 0; return $result; } sub IsFunctionKey($) { my $code = &codeOf( $_[0] ); my $result = ( ( $code >= &codeOf("XK_F1") ) and ( $code <= &codeOf("XK_F35") ) ) ? 1 : 0; return $result; } sub IsMiscFunctionKey($) { my $code = &codeOf( $_[0] ); my $result = ( ( $code >= &codeOf("XK_Select") ) and ( $code <= &codeOf("XK_Break") ) ) ? 1 : 0; return $result; } sub IsModifierKey($) { my $code = &codeOf( $_[0] ); my $result = ( ( ( $code >= &codeOf("XK_Shift_L") ) and ( $code <= &codeOf("XK_Hyper_R") ) ) or ( ( $code >= &codeOf("XK_ISO_Lock") ) and ( $code <= &codeOf("XK_ISO_Level5_Lock") ) ) or ( $code == &codeOf("XK_Mode_switch") ) or ( $code == &codeOf("XK_Num_Lock") ) ) ? 1 : 0; return $result; } # debugging/reporting # Xutil.h's macros do not cover the whole range of special keys, which are not # actually printable. sub IsSpecialKey($) { my $code = &codeOf( $_[0] ); my $result = ( ( $code >= 0xff00 ) and ( $code <= 0xffff ) ) ? 1 : 0; return $result; } sub VisibleChar($) { my $ch = shift; my $ord = ord $ch; my $result = $ch; if ( $ord < 32 ) { if ( $ord == 8 ) { $result = '\b'; } elsif ( $ord == 9 ) { $result = '\t'; } elsif ( $ord == 10 ) { $result = '\n'; } elsif ( $ord == 12 ) { $result = '\f'; } elsif ( $ord == 13 ) { $result = '\r'; } elsif ( $ord == 27 ) { $result = '\E'; } else { $result = sprintf( "^%c", $ord + 64 ); } } elsif ( $ord == 32 ) { $result = '\s'; } elsif ( $ord == 94 ) { $result = '\^'; } elsif ( $ord == 92 ) { $result = '\\\\'; } elsif ( $ord == 127 ) { $result = '^?'; } return $result; } sub IsShift($$) { my $code = shift; my $state = shift; # 0/1=normal, 2=shift my $result = 0; if ( ( ( $state - 1 ) & 1 ) != 0 ) { if ( $Shifted{$code} ) { return 1 if ( $Shifted{$code} ne $code ); } } return 0; } sub TypeOf($) { my $code = &toCode( $_[0] ); my $result = "other"; $result = "special" if ( &IsSpecialKey($code) ); $result = "keypad" if ( &IsKeypadKey($code) ); $result = "*keypad" if ( &IsPrivateKeypadKey($code) ); $result = "cursor" if ( &IsCursorKey($code) ); $result = "pf-key" if ( &IsPFKey($code) ); $result = "func-key" if ( &IsFunctionKey($code) ); $result = "misc-key" if ( &IsMiscFunctionKey($code) ); $result = "edit-key" if ( &IsEditFunctionKey($code) ); $result = "modifier" if ( &IsModifierKey($code) ); return $result; } sub KeyToS($$) { my $code = &codeOf( $_[0] ); my $state = $_[1]; my $result = ""; $code = &codeOf( $Shifted{ $_[0] } ) if ( &IsShift( $_[0], $state ) ); my $type = &TypeOf( &toCode($code) ); if ( $type ne "other" ) { $result = ( $type eq "special" ) ? "-ignore-" : "?"; } elsif ($opt_u) { $result = sprintf( "\\E[%d;%du", $code, $state ); } else { $result = sprintf( "\\E[27;%d;%d~", $state, $code ); } return $result; } sub ParamToQ($) { my $param = shift; my $result = shift; $param--; $result .= ( $param & 1 ) ? 's' : '-'; $result .= ( $param & 2 ) ? 'a' : '-'; $result .= ( $param & 4 ) ? 'c' : '-'; $result .= ( $param & 8 ) ? 'm' : '-'; return $result; } sub ParamToS($) { my $param = shift; my $result = ""; if ( $param-- > 1 ) { $result .= "+Shift" if ( $param & 1 ); $result .= "+Alt" if ( $param & 2 ); $result .= "+Ctrl" if ( $param & 4 ); $result .= "+Meta" if ( $param & 8 ); $result =~ s/^\+//; } return $result; } sub StateToS($) { my $state = shift; my $result = ""; $result .= "+Shift" if ( $state & $ShiftMask ); $result .= "+Lock" if ( $state & $LockMask ); $result .= "+Ctrl" if ( $state & $ControlMask ); $result .= "+Alt" if ( $state & $AltMask ); $result .= "+Meta" if ( $state & $MetaMask ); $result =~ s/^\+//; return $result; } # macros/functions in xterm's input.c sub Masked($$) { my $value = shift; my $mask = shift; my $result = ( ($value) & ( ~($mask) ) ); return $result; } sub IsPredefinedKey($) { my $code = &codeOf( $_[0] ); my $result = 0; if ( $keySyms{"XK_ISO_Lock"} ) { $result = ( $code >= &codeOf("XK_ISO_Lock") and $code <= &codeOf("XK_Delete") ) ? 1 : 0; } else { $result = ( $code >= &codeOf("XK_BackSpace") and $code <= &codeOf("XK_Delete") ) ? 1 : 0; } return $result; } sub IsTabKey($) { my $code = &codeOf( $_[0] ); my $result = 0; if ( $keySyms{"XK_ISO_Left_Tab"} ) { $result = ( $code == &codeOf("XK_Tab") || $code == &codeOf("XK_ISO_Left_Tab") ); } else { $result = ( $code == &codeOf("XK_Tab") ) ? 1 : 0; } return $result; } sub IsEditFunctionKey($) { my $code = shift; my $result = 0; if ( $keyCodes{$code} ) { my $name = $keyCodes{$code}; $result = 1 if ( $editKeys{$name} ); } return $result; } sub IS_CTRL($) { my $code = &codeOf( $_[0] ); my $result = ( $code < 32 || ( $code >= 0x7f && $code <= 0x9f ) ); return $result; } sub IsControlInput($) { my $code = &codeOf( $_[0] ); my $result = 0; $result = 1 if ( $code >= 0x40 && $code <= 0x7f ); return $result; } sub IsControlOutput($) { my $code = shift; my $result = 0; $result = 1 if &IS_CTRL($code); return $result; } sub IsControlAlias($$) { my $code = shift; my $state = shift; my $result = 0; $code = &toCode($code); $code = &toCode( &AliasedKey($code) ); if ( hex $code < 256 ) { $result = &IS_CTRL($code); # In xterm, this function does not directly test evt_state, but relies # upon kd.strbuf converted by Xutf8LookupString or XmbLookupString # (ultimately in _XTranslateKeysym). # # See https://www.mail-archive.com/xorg@lists.x.org/msg04434.html # # xterm does its own special cases for XK_BackSpace if ( $state & $ControlMask ) { my $ch = chr &codeOf($code); $result = 1 if ( &IsTabKey($code) ); $result = 1 if ( &IsControlInput($code) ); $result = 1 if ( $ch =~ /^[\/ 2-8]$/ ); } } return $result; } sub computeMaskedModifier($$) { my $state = shift; my $mask = shift; my $result = &xtermStateToParam( &Masked( $state, $mask ) ); return $result; } sub xtermStateToParam($) { my $state = shift; my $modify_parm = 1; $modify_parm += 1 if ( $state & $ShiftMask ); $modify_parm += 2 if ( $state & $AltMask ); $modify_parm += 4 if ( $state & $ControlMask ); $modify_parm += 8 if ( $state & $MetaMask ); $modify_parm = 0 if ( $modify_parm == 1 ); return $modify_parm; } sub ParamToState($) { my $modify_parm = shift; my $state = 0; $modify_parm-- if ( $modify_parm > 0 ); $state |= $ShiftMask if ( $modify_parm & 1 ); $state |= $AltMask if ( $modify_parm & 2 ); $state |= $ControlMask if ( $modify_parm & 4 ); $state |= $MetaMask if ( $modify_parm & 8 ); return $state; } sub allowedCharModifiers($$) { my $other_key = shift; my $state = shift; my $code = shift; my $result = $state & ( $ShiftMask | $AltMask | $ControlMask | $MetaMask ); # If modifyOtherKeys is off or medium (0 or 1), moderate its effects by # excluding the common cases for modifiers. if ( $other_key <= 1 ) { my $sym = $keyCodes{$code}; if ( &IsControlInput($code) and &Masked( $result, $ControlMask ) == 0 ) { # These keys are already associated with the control-key if ( $other_key == 0 ) { $result &= ~$ControlMask; } } elsif ( $sym eq "XK_Tab" || $sym eq "XK_Return" ) { # } elsif ( &IsControlAlias( $code, $state ) ) { # Things like "^_" work here... if ( &Masked( $result, ( $ControlMask | $ShiftMask ) ) == 0 ) { if ( $sym =~ /^XK_[34578]$/ or $sym eq "XK_slash" ) { $result = 0 if ( $state == $ControlMask ); } else { $result = 0; } } } elsif ( !&IsControlOutput($code) && !&IsPredefinedKey($code) ) { # Printable keys are already associated with the shift-key if ( !( $result & $ControlMask ) ) { $result &= ~$ShiftMask; } } # TODO: # result = filterAltMeta(result, # xw->work.meta_mods, # TScreenOf(xw)->meta_sends_esc, kd); # if (TScreenOf(xw)->alt_is_not_meta) { # result = filterAltMeta(result, # xw->work.alt_mods, # TScreenOf(xw)->alt_sends_esc, kd); # } } return $result; } # Some details are omitted (e.g., the backspace/delete toggle), but this gives # the general sense of the corresponding function in xterm's input.c sub ModifyOtherKeys($$$$) { my $code = shift; # the keycode to test my $other_key = shift; # "modifyOtherKeys" resource my $modify_parm = shift; # 0=unmodified, 2=shift, etc my $state = shift; # mask of modifiers, e.g., ControlMask my $result = 0; $modify_parm = 0 if ( $modify_parm == 1 ); if ( &IsModifierKey($code) ) { # xterm filters out bare modifiers (ignore) } elsif (&IsFunctionKey($code) or &IsEditFunctionKey($code) or &IsKeypadKey($code) or &IsCursorKey($code) or &IsPFKey($code) or &IsMiscFunctionKey($code) or &IsPrivateKeypadKey($code) ) { # Exclude the keys already covered by a modifier. } elsif ( $state > 0 ) { my $sym = ""; $sym = $keyCodes{$code} if ( $keyCodes{$code} ); # TODO: #if (IsBackarrowToggle(keyboard, kd->keysym, state)) { # kd->keysym = XK_Delete; # UIntClr(state, ControlMask); #} if ( !&IsPredefinedKey($code) ) { $state = &allowedCharModifiers( $other_key, $state, $code ); } if ( $state != 0 ) { if ( $other_key == 1 ) { if ( $sym eq "XK_BackSpace" or $sym eq "XK_Delete" ) { } elsif ( $sym eq "XK_ISO_Left_Tab" ) { $result = 1 if ( &computeMaskedModifier( $state, $ShiftMask ) ); } elsif ($sym eq "XK_Return" or $sym eq "XK_Tab" ) { $result = ( $modify_parm != 0 ); } else { if ( &IsControlInput($code) ) { if ( $state == $ControlMask or $state == $ShiftMask ) { $result = 0; } else { $result = ( $modify_parm != 0 ); } } elsif ( &IsControlAlias( $code, $state ) ) { if ( $state == $ShiftMask ) { $result = 0; } elsif ( &computeMaskedModifier( $state, $ControlMask ) ) { $result = 1; } } else { $result = 1; } } if ($result) { # second case in xterm's Input() $result = 0 if ( &allowedCharModifiers( $other_key, $state, $code ) == 0 ); } } elsif ( $other_key == 2 ) { if ( $sym eq "XK_BackSpace" ) { # strip ControlMask as per IsBackarrowToggle() $result = 1 if ( &computeMaskedModifier( $state, $ControlMask ) ); } elsif ( $sym eq "XK_Delete" ) { $result = ( &xtermStateToParam($state) != 0 ); } elsif ( $sym eq "XK_ISO_Left_Tab" ) { $result = 1 if ( &computeMaskedModifier( $state, $ShiftMask ) ); } elsif ( $sym eq "XK_Return" or $sym eq "XK_Tab" ) { $result = ( $modify_parm != 0 ); } else { if ( &IsControlInput($code) ) { $result = 1; } elsif ( $state == $ShiftMask ) { $result = ( $sym eq "XK_space" or $sym eq "XK_Return" ); } elsif ( &computeMaskedModifier( $state, $ShiftMask ) ) { $result = 1; } } } } } return $result; } # See IsControlAlias. This handles some of the special cases where the keycode # seen or used by xterm is not the same as the actual keycode. sub AliasedKey($) { my $code = &toCode( $_[0] ); my $result = &codeOf($code); my $sym = $keyCodes{$code}; if ($sym) { $result = 8 if ( $sym eq "XK_BackSpace" ); $result = 9 if ( $sym eq "XK_Tab" ); $result = 13 if ( $sym eq "XK_Return" ); $result = 27 if ( $sym eq "XK_Escape" ); } return $result; } # Returns a short display for shift/control/alt modifiers applied to the # keycode to show which are affected by "modifyOtherKeys" at the given level in # $other_key sub CheckOtherKey($$) { my $code = shift; my $other_key = shift; my $modified = 0; my $result = ""; for my $modify_parm ( 1 .. $MAXMODS ) { my $state = &ParamToState($modify_parm); if ( &ModifyOtherKeys( $code, $other_key, $modify_parm, $state ) ) { $modified++; $result .= "*"; } else { $result .= "-"; } } return $modified ? $result : "-(skip)-"; } # Use the return-string from CheckOtherKeys as a template for deciding which # keys to render as escape-sequences. sub ShowOtherKeys($$$) { my $code = &AliasedKey( $_[0] ); my $mode = $_[1]; # modifyOtherKeys: 0, 1 or 2 my $show = $_[2]; my $type = &TypeOf( $_[0] ); my @result; # index for $show[] can be tested with a bit-mask: # 1 = shift # 2 = alt # 4 = ctrl # 8 = meta for my $c ( 0 .. length($show) - 1 ) { my $rc = substr( $show, $c, 1 ); if ( $rc eq "*" ) { $result[$c] = &KeyToS( &toCode($code), $c + 1 ); } elsif ( $type eq "other" or ( $type eq "special" and $code < 256 ) ) { my $map = $code; my $tmp = &toCode($code); my $chr = chr hex $tmp; my $shift = ( $c & 1 ); my $cntrl = ( $c & 4 ); # TODO - can this be simplified using xkb groups? if ( $chr =~ /^[`345678]$/ and ( $c & 4 ) != 0 ) { if ($shift) { $map = 30 if ( $chr eq "`" ); $map = ord "#" if ( $chr eq "3" ); $map = ord '$' if ( $chr eq "4" ); $map = ord "%" if ( $chr eq "5" ); $map = 30 if ( $chr eq "6" ); $map = ord "&" if ( $chr eq "7" ); $map = ord "*" if ( $chr eq "8" ); } else { $map = 0 if ( $chr eq "`" ); $map = 27 if ( $chr eq "3" ); $map = 28 if ( $chr eq "4" ); $map = 29 if ( $chr eq "5" ); $map = 30 if ( $chr eq "6" ); $map = 31 if ( $chr eq "7" ); $map = 127 if ( $chr eq "8" ); } } else { $map = &codeOf( $Shifted{$tmp} ) if ( defined( $Shifted{$tmp} ) and $shift ); if ($cntrl) { if ( $chr =~ /^[190:<=>.,+*()'&%\$#"!]$/ ) { # ignore } elsif ( $chr =~ /^[2]$/ ) { $map = 0; } elsif ( $chr =~ /^[:;]$/ ) { $map = 27 if ( $mode > 0 ); } elsif ( $chr eq '-' ) { $map = 31 if ($shift); } elsif ( $chr eq '/' ) { $map = $shift ? 127 : 31 if ( $mode == 0 ); $map = 31 if ( not $shift and $mode == 1 ); } elsif ( $chr eq '?' ) { $map = 127; } else { $map = ( $code & 0x1f ) if ( $code < 128 ); } } } $result[$c] = &VisibleChar( chr $map ); } elsif ( $type eq "special" ) { $result[$c] = "-ignore-"; } else { $result[$c] = sprintf( "%d:%s", $c + 1, $type ); } } return @result; } sub readfile($) { my $data = shift; my @data; if ( open my $fp, $data ) { @data = <$fp>; close $fp; chomp @data; } return @data; } sub readpipe($) { my $cmd = shift; return &readfile("$cmd 2>/dev/null |"); } sub trim($) { my $text = shift; $text =~ s/^\s+//; $text =~ s/\s+$//; $text =~ s/\s+/ /g; return $text; } sub html_ref($) { my $header = shift; my $anchor = lc &trim($header); $anchor =~ s/\s/_/g; return $anchor; } sub rightarrow() { return $opt_h ? "→" : "->"; } sub safe_html($) { my $text = shift; if ($opt_h) { $text =~ s/\&/\&/g; $text =~ s/\= 128 ); $s .= $ch if ( $ord < 128 ); } $text = $s; } } return $text; } sub begin_report() { if ($opt_o) { open( $REPORT, '>', $opt_o ) or &failed("cannot open $opt_o"); select $REPORT; } if ($opt_h) { printf < XTERM - Modified "Other" Keys ($xkb_layout-$xkb_model) EOF ; } } sub end_report() { if ($opt_h) { my $output = "output.html"; $output = $opt_o if ($opt_o); printf <
    EOF ; for my $h ( 0 .. $#headers ) { printf "
  • %s
  • \n", &html_ref( $headers[$h] ), $headers[$h]; } printf < EOF ; } if ($opt_o) { select STDOUT; close $REPORT; } } sub begin_section($) { my $header = shift; $headers[ $#headers + 1 ] = $header; if ($opt_h) { printf "

    %s

    \n", &html_ref($header), $header; } else { printf "\n"; printf "%s:\n", $header; } printf STDERR "** %s\n", $header if ($opt_o); } sub begin_table() { my $title = shift; &begin_section($title); if ($opt_h) { printf "\n"; } } sub end_table() { if ($opt_h) { printf "
    \n"; } } sub tt_cell($) { my $text = shift; return sprintf "%s", $text; } sub td_any($) { my $text = shift; return sprintf "%s", &tt_cell($text); } sub td_left($) { my $text = shift; return sprintf "%s", &tt_cell($text); } sub td_right($) { my $text = shift; return sprintf "%s", &tt_cell($text); } sub padded($$) { my $size = shift; my $text = shift; $text = sprintf( "%*s", $size, $text ) if ( $size > 0 ); $text = sprintf( "%-*s", $size, $text ) if ( $size < 0 ); $text =~ s/ / /g if ($opt_h); return $text; } sub print_head() { my $argc = $#_; if ($opt_h) { printf ""; for ( my $n = 0 ; $n <= $argc ; $n += 2 ) { my $size = $_[$n]; my $text = &padded( $size, $_[ $n + 1 ] ); printf "%s", $text; } printf "\n"; } else { for ( my $n = 0 ; $n <= $argc ; $n += 2 ) { my $size = $_[$n]; my $text = &padded( $size, $_[ $n + 1 ] ); printf "%s", $text; printf " " if ( $n < $argc ); } printf "\n"; } } sub link_data($$) { my $thisis = shift; my $thatis = shift; my $column = shift; my $symbol = shift; my %result; $result{THISIS} = $thisis; # current table name $result{THATIS} = $thatis; # name of target table for link $result{COLUMN} = $column; # column counting from 0 $result{SYMBOL} = $symbol; return \%result; } sub unique_link($$) { my $thisis = shift; my $symbol = shift; my $unique = 0; for my $n ( 0 .. length($symbol) - 1 ) { $unique += ord substr( $symbol, $n, 1 ); } return sprintf( "%s:%s.%x", $thisis, $symbol, $unique ); } # print a row in the table, using pairs of lengths and strings: # + Right-align lengths greater than zero and pad; # + Left-align lengths less than zero, pad. # + For the special case of zero, just left align without padding. sub print_data() { my $argc = $#_; if ($opt_h) { my @links = @{ $_[0] }; printf ""; my $col = 0; for ( my $n = 1 ; $n <= $argc ; $n += 2 ) { my $size = $_[$n]; my $text = &padded( $size, $_[ $n + 1 ] ); if ( $#links >= 0 ) { for my $l ( 0 .. $#links ) { my %obj = %{ $links[$l] }; # link_data if ( $obj{COLUMN} == $col ) { my $props = ""; my $value = &unique_link( $obj{THISIS}, $obj{SYMBOL} ); # The symbol-map from xkbcomp has duplicates because # different modifier combinations can produce the same # keysym. Since it appears that the slots that the # user would expect are filled in first, just ignoring # the duplicate works well enough. if ( not $linkUsed{$value} ) { $props .= " name=\"$value\""; $linkUsed{$value} = 1; } $value = &unique_link( $obj{THATIS}, $obj{SYMBOL} ); $props .= " href=\"#$value\""; my $tail = $text; $text =~ s/(\ )+$//; $tail = substr( $tail, length($text) ); $text = sprintf( "%s%s", $props, $text, $tail ); last; } } } printf "%s", ( $size > 0 ) ? &td_right($text) : ( $size == 0 ) ? &td_any($text) : &td_left($text); ++$col; } printf "\n"; } else { for ( my $n = 1 ; $n <= $argc ; $n += 2 ) { my $size = $_[$n]; my $text = &padded( $size, $_[ $n + 1 ] ); printf "%s", $text; printf " " if ( $n < $argc ); } printf "\n"; } } sub begin_preformatted($) { my $title = shift; &begin_section($title); printf "
    \n" if ($opt_h);
    }
    
    sub end_preformatted() {
        printf "
    \n" if ($opt_h); } sub do_localectl($) { my $report = shift; my $cmd = "localectl status"; my @data = &readpipe($cmd); &begin_table("Output of $cmd") if ($report); for my $n ( 0 .. $#data ) { # let command-line parameters override localectl output, for reports $data[$n] =~ s/^(\s+X11 Layout:\s+).*$/$1$opt_l/ if ($opt_l); $data[$n] =~ s/^(\s+X11 Model:\s+).*$/$1$opt_m/ if ($opt_m); my @fields = split /:\s*/, $data[$n]; next unless ( $#fields == 1 ); if ($report) { if ($opt_h) { printf "%s%s\n", &td_right( $fields[0] ), &td_left( $fields[1] ); } else { printf "%s\n", $data[$n]; } } $xkb_layout = $fields[1] if ( $fields[0] =~ /x11 layout/i ); $xkb_model = $fields[1] if ( $fields[0] =~ /x11 model/i ); } if ($report) { &end_table; } } sub do_keysymdef() { my @data = &readfile($keyfile); my $lenSyms = 0; for my $n ( 0 .. $#data ) { my $value = &trim( $data[$n] ); next unless ( $value =~ /^#define\s+XK_/ ); my $name = $value; $name =~ s/^#define\s+//; $value = $name; $name =~ s/\s.*//; $value =~ s/^[^\s]+\s+//; my $note = $value; $value =~ s/\s.*//; $note =~ s/^[^\s]+\s*//; if ( $note !~ /\b(alias|deprecated)\b/ ) { if ( $note =~ /\/*.*\bU\+[[:xdigit:]]{4,8}.*\*\// ) { next if ( $note =~ /\(U\+/ ); my $code = $note; $code =~ s/^.*\bU\+([[:xdigit:]]+).*/$1/; $note =~ s/^\/\*[([:space:]]*//; $note =~ s/[)[:space:]]*\*\/$//; $uniNames{$value} = $note; $uniCodes{$value} = hex $code; } } $lenSyms = length($name) if ( length($name) > $lenSyms ); $value = lc $value; $keySyms{$name} = $value; $keyCodes{$value} = $name unless ( $keyCodes{$value} ); printf "keySyms{$name} = '$value', keyCodes{$value} = $name\n" if ($opt_d); } my $tmpfile = $keyfile; $tmpfile =~ s/^.*\///; &begin_table("Symbols from $tmpfile"); my @keys = keys %keySyms; &print_data( \@nolinks, 5, sprintf( "%d", $#keys ), 0, sprintf( "keysyms are defined (longest %d)", $lenSyms ) ); @keys = keys %keyCodes; &print_data( \@nolinks, 5, sprintf( "%d", $#keys ), 0, "keycodes are defined" ); @keys = keys %uniCodes; &print_data( \@nolinks, 5, sprintf( "%d", $#keys ), 0, "keycodes are equated to Unicode" ); &end_table; } # For what it's worth, there is a C library (xkbfile) which could be used, # but there is no documentation and would not actually solve the problem at # hand. # # setxkbmap -model pc105 -layout us -print | xkbcomp - -C -o - sub do_xkbcomp() { my @data = &readpipe( "setxkbmap " . "-model $xkb_model " . "-layout $xkb_layout -print " . "| xkbcomp - -C -o -" ); my $state = -1; my $type = {}; for my $n ( 0 .. $#data ) { if ( $data[$n] =~ /static.*\bkeyNames\[.*{/ ) { $state = 0; next; } if ( $data[$n] =~ /static.*\bsymCache\[.*{/ ) { $state = 1; next; } if ( $data[$n] =~ /static.*\bsymMap\[.*{/ ) { $state = 2; next; } if ( $data[$n] =~ /static.*\bdflt_types\[.*{/ ) { $state = 3; next; } if ( $state >= 0 ) { if ( $data[$n] =~ /^\s*};/ ) { printf "# %s\n", $data[$n] if ($opt_d); $state = -1; next; } printf "* %s\n", $data[$n] if ($opt_d); } # parse data in "keyNames[NUM_KEYS]" if ( $state == 0 ) { my $text = $data[$n]; my $name; while ( $text =~ /^.*".*".*$/ ) { $text =~ s/^[^"]*//; $name = $text; $name =~ s/"\s+}.*//; $name =~ s/"//g; $keyNames[ $#keyNames + 1 ] = $name; printf "keyNames[%d] = '%s'\n", $#keyNames, $keyNames[$#keyNames] if ($opt_v); $text =~ s/^"[^"]*"//; } } # parse data in "symCache[NUM_SYMBOLS]" elsif ( $state == 1 ) { my $text = $data[$n]; my $name; while ( $text =~ /[[:alnum:]_]/ ) { $text =~ s/^[^[[:alnum:]_]*//; $name = $text; $name =~ s/[^[[:alnum:]_].*//; $symCache[ $#symCache + 1 ] = $name; printf "symCache[%d] = %s\n", $#symCache, $symCache[$#symCache] if ($opt_v); $text =~ s/^[[:alnum:]_]+//; } } # parse data in "symMap[NUM_KEYS]" elsif ( $state == 2 ) { my $text = $data[$n]; my $code; while ( $text =~ /[{].*[}]/ ) { my %obj; $text =~ s/^[^{]*[{]\s*//; $code = $text; $code =~ s/[^[[:alnum:]].*//; $text =~ s/[[:alnum:]]+\s*,\s*//; $obj{TYPE} = $code; # KeyType my %tmp = %{ $keyTypes[$code] }; $tmp{USED} += 1; $keyTypes[$code] = \%tmp; $code = $text; $code =~ s/[^[[:alnum:]].*//; $text =~ s/[[:alnum:]]+\s*,\s*//; $obj{USED} = hex $code; # 0/1 for used/unused $code = $text; $code =~ s/[^[[:alnum:]].*//; $obj{CODE} = $code; # index in symCache[] $text =~ s/[[:alnum:]]+\s*//; $symMap[ $#symMap + 1 ] = \%obj; printf "symMap[%d] = {%d,%d,%d}\n", $#symMap, $obj{TYPE}, $obj{USED}, $obj{CODE} if ($opt_v); } } # parse data in "dflt_types[]" elsif ( $state == 3 ) { my $text = &trim( $data[$n] ); if ( $text =~ /^\s*[}](,)?$/ ) { $type->{USED} = 0; $keyTypes[ $#keyTypes + 1 ] = $type; $type = {}; } elsif ( $text =~ /^\d+,$/ ) { $text =~ s/,//; $type->{SIZE} = $text; } elsif ( $text =~ /^None,\s+lnames_[[:alnum:]_]+$/ ) { $text =~ s/^None,\s+lnames_//; $type->{NAME} = $text; } elsif ( $text =~ /^\s*[{].*[}],\s*$/ ) { $text =~ s/^\s*[{]\s*([^,]+),.*/$1/; $type->{MODS} = $text; } } } &begin_table("Summary from xkbcomp"); &print_data( \@nolinks, 5, sprintf( "%d", $#keyNames + 1 ), 0, "keyNames" ); &print_data( \@nolinks, 5, sprintf( "%d", $#keyTypes + 1 ), 0, "keyTypes" ); &print_data( \@nolinks, 5, sprintf( "%d", $#symCache + 1 ), 0, "symCache" ); &print_data( \@nolinks, 5, sprintf( "%d", $#symMap + 1 ), 0, "symMap" ); &end_table; } # Report keysymdef.h without the deprecated stuff, and sorted by keycode. sub report_keysymdef() { &begin_table("Key symbols"); &print_head( 0, "Code", 0, "Category", 0, "Symbol" ); # sort by numeric keycode rather than string my @keyCodes = keys %keyCodes; my @sortCodes; for my $c ( 0 .. $#keyCodes ) { $sortCodes[$c] = sprintf "%08X", hex $keyCodes[$c]; } @sortCodes = sort @sortCodes; for my $c ( 0 .. $#sortCodes ) { my $code = sprintf( "0x%04x", hex $sortCodes[$c] ); my $sym = $keyCodes{$code}; &print_data( \@nolinks, 9, $code, -8, &TypeOf($code), 0, $sym ); } &end_table; } sub report_key_types() { &begin_table("Key types"); &print_head( 5, "Type", 5, "Used", 5, "Levels", 0, "Name" ); for my $t ( 0 .. $#keyTypes ) { my %type = %{ $keyTypes[$t] }; next if ( $type{USED} == 0 and not $opt_v ); &print_data( \@nolinks, 5, sprintf( "%d", $t ), 5, sprintf( "%d", $type{USED} ), 5, sprintf( "%d", $type{SIZE} ), 0, $type{NAME} ); } &end_table; } sub report_modified_keys() { my @codes = sort keys %keysUsed; my $width = 14; &begin_table("Other modifiable keycodes"); &print_head( 0, "Code", 0, "Symbol", 0, "Actual", -$width, "Mode 0", -$width, "Mode 1", -$width, "Mode 2" ); $width = 0 if ($opt_h); for my $c ( 0 .. $#codes ) { next unless ( $codes[$c] ne "" ); my @links; my $sym = $keysUsed{ $codes[$c] }; $links[0] = &link_data( "summary", "detailed", 1, $sym ); &print_data( \@links, 6, $codes[$c], # -20, $keysUsed{ $codes[$c] }, # -6, sprintf( "%d", hex $codes[$c] ), # -$width, &CheckOtherKey( $codes[$c], 0 ), # -$width, &CheckOtherKey( $codes[$c], 1 ), # -$width, &CheckOtherKey( $codes[$c], 2 ) ); } &end_table; &begin_preformatted("Modify-param to/from state"); for my $param ( 0 .. $MAXMODS ) { my $state = &ParamToState($param); my $check = &xtermStateToParam($state); printf " PARAM %d %s %d %s %d (%s)\n", $param, &rightarrow, # $state, &rightarrow, # $check, &ParamToS($param); } &end_preformatted; &begin_preformatted("State to/from modify-param"); for my $state ( 0 .. 15 ) { my $param = &xtermStateToParam($state); my $check = &ParamToState($param); printf " STATE %d %s %d %s %d (%s)\n", # $state, &rightarrow, # $param, &rightarrow, # $check, &StateToS($state); } &end_preformatted; } # Make a report showing user- and program-modes. sub report_otherkey_escapes() { my @codes = sort keys %keysUsed; my $width = 14; &begin_table("Other modified-key escapes"); &print_head( 0, "Code", 0, "Symbol", 0, "Actual", -$width, "Mode 0", -$width, "Mode 1", -$width, "Mode 2" ); $width = 0 if ($opt_h); for my $c ( 0 .. $#codes ) { next unless ( $codes[$c] ne "" ); my $level0 = &CheckOtherKey( $codes[$c], 0 ); my $level1 = &CheckOtherKey( $codes[$c], 1 ); my $level2 = &CheckOtherKey( $codes[$c], 2 ); my @level0 = &ShowOtherKeys( $codes[$c], 0, $level0 ); my @level1 = &ShowOtherKeys( $codes[$c], 1, $level1 ); my @level2 = &ShowOtherKeys( $codes[$c], 2, $level2 ); my @links; my $sym = $keysUsed{ $codes[$c] }; $links[0] = &link_data( "detailed", "symmap", 1, $sym ); &print_data( \@links, # -6, $codes[$c], # -20, $keysUsed{ $codes[$c] }, # -6, sprintf( "%d", hex $codes[$c] ), # -$width, $level0, # -$width, $level1, # -$width, $level2 ); for my $r ( 0 .. $#level0 ) { &print_data( \@nolinks, # -6, &ParamToQ( $r + 1 ), # -20, "", # -6, "", # -$width, &safe_html( $level0[$r] ), # -$width, &safe_html( $level1[$r] ), # -$width, &safe_html( $level2[$r] ) ); } } &end_table; } sub report_keys_used() { &begin_table("Key map"); &print_head( 5, "Type", # 0, "Level", # 0, "Name", # 6, "Code", # 0, "Symbol" ); for my $m ( 0 .. $#symMap ) { my %obj = %{ $symMap[$m] }; next unless ( $obj{USED} ); my $sym = $symCache[ $obj{CODE} ]; next if ( $sym eq "NoSymbol" ); my $code = ""; $code = $keySyms{$sym} if ( $keySyms{$sym} ); next if ( $code eq "" ); $keysUsed{$code} = $sym; my %type = %{ $keyTypes[ $obj{TYPE} ] }; my @links; $links[0] = &link_data( "symmap", "summary", 4, $sym ); &print_data( \@links, 5, sprintf( "%d", $obj{TYPE} ), # 5, sprintf( "1/%d", $type{SIZE} ), # -4, $keyNames[$m], # 6, $code, # 0, $sym ); my $base = $code; $Shifted{$code} = $code unless ( $Shifted{$code} ); for my $t ( 1 .. $type{SIZE} - 1 ) { $sym = $symCache[ $obj{CODE} + $t ]; $code = ""; $code = $keySyms{$sym} if ( $keySyms{$sym} ); $keysUsed{$code} = $sym; $links[0] = &link_data( "symmap", "summary", 4, $sym ); &print_data( \@links, 5, "", # 5, sprintf( "%d/%d", $t + 1, $type{SIZE} ), # -4, "", # 6, $code, # 0, $sym ); @links = (); # The shift-modifier could be used in custom groups, but the only # built-in ones that appear relevant are TWO_LEVEL and ALPHABETIC, # which have two levels. This records the shifted code for a given # base. if ( $type{SIZE} == 2 and $type{MODS} and index( $type{MODS}, "ShiftMask" ) >= 0 ) { if ( $t == 1 ) { $Shifted{$base} = $code; } elsif ( not $Shifted{$code} ) { $Shifted{$code} = $code; } } } } &end_table; } sub KeyClasses($) { my $hex = shift; my $alias = &IsControlAlias( $hex, $ControlMask ) ? "alias" : ""; my $cntrl = &IS_CTRL($hex) ? "cntrl" : ""; my $ctl_i = &IsControlInput($hex) ? "ctl_i" : ""; my $ctl_o = &IsControlOutput($hex) ? "ctl_o" : ""; my $this = sprintf( "%-5s %-5s %-5s %-5s %-8s", $alias, $cntrl, $ctl_i, $ctl_o, &TypeOf($hex) ); } sub report_key_classes() { &begin_table("Keycode-classes"); my $base = -1; my $last = ""; my $next = 65535; my $form = " [%8s .. %-8s] %s\n"; &print_head( 0, "First", 0, "Last", 0, "Classes" ) if ($opt_h); for my $code ( 0 .. $next ) { my $hex = &toCode($code); my $this = &KeyClasses($hex); if ( $base < 0 ) { $base = 0; $last = $this; } elsif ( $this ne $last ) { printf $form, &toCode($base), &toCode( $code - 1 ), $last unless ($opt_h); &print_data( \@nolinks, 0, &toCode($base), 0, &toCode( $code - 1 ), 0, $last ) if ($opt_h); $base = $code; $last = $this; } } printf $form, &toCode($base), &toCode($next), $last unless ($opt_h); &print_data( \@nolinks, 0, &toCode($base), 0, &toCode($next), 0, $last ) if ($opt_h); &end_table; } sub main::HELP_MESSAGE() { printf STDERR <$TMP || echo fail >$TMP' 2>/dev/null ( test ! -f $TMP || test -s $TMP ) && for verb in printf print ; do rm -f $TMP eval '$verb "\c" >$TMP || echo fail >$TMP' 2>/dev/null if test -f $TMP ; then if test ! -s $TMP ; then CMD="$verb" OPT= SUF='\c' break fi fi done rm -f $TMP exec /dev/tty IFS=';' read junk high wide $CMD $OPT "${ESC}[19t${SUF}" > /dev/tty IFS=';' read junk maxhigh maxwide stty $old wide=`echo $wide|sed -e 's/t.*//'` maxwide=`echo $maxwide|sed -e 's/t.*//'` original=${ESC}[8\;${high}\;${wide}t${SUF} test $maxwide = 0 && maxwide=`expr $wide \* 2` test $maxhigh = 0 && maxhigh=`expr $high \* 2` if ( trap "echo exit" EXIT 2>/dev/null ) >/dev/null then trap '$CMD $OPT "$original" >/dev/tty; exit' EXIT HUP INT TRAP TERM else trap '$CMD $OPT "$original" >/dev/tty; exit' 0 1 2 5 15 fi w=$wide h=$high a=1 while true do # sleep 1 echo resizing to $h by $w $CMD $OPT "${ESC}[8;${h};${w}t" >/dev/tty if test $a = 1 ; then if test $w = $maxwide ; then h=`expr $h + $a` if test $h = $maxhigh ; then a=-1 fi else w=`expr $w + $a` fi else if test $w = $wide ; then h=`expr $h + $a` if test $h = $high ; then a=1 fi else w=`expr $w + $a` fi fi done xterm-353/vttests/dynamic.sh0000755000175100001440000000522711671154202014750 0ustar tomusers#!/bin/sh # $XTermId: dynamic.sh,v 1.17 2011/12/11 16:21:22 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 1999-2003,2011 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Demonstrate the use of dynamic colors by setting the background successively # to different values. ESC="" CMD='/bin/echo' OPT='-n' SUF='' TMP=/tmp/xterm$$ eval '$CMD $OPT >$TMP || echo fail >$TMP' 2>/dev/null ( test ! -f $TMP || test -s $TMP ) && for verb in printf print ; do rm -f $TMP eval '$verb "\c" >$TMP || echo fail >$TMP' 2>/dev/null if test -f $TMP ; then if test ! -s $TMP ; then CMD="$verb" OPT= SUF='\c' break fi fi done rm -f $TMP LIST="00 30 80 d0 ff" exec /dev/tty read original stty $old original=${original}${SUF} if ( trap "echo exit" EXIT 2>/dev/null ) >/dev/null then trap '$CMD $OPT "$original" >/dev/tty; exit' EXIT HUP INT TRAP TERM else trap '$CMD $OPT "$original" >/dev/tty; exit' 0 1 2 5 15 fi while true do for R in $LIST do for G in $LIST do for B in $LIST do $CMD $OPT "${ESC}]11;rgb:$R/$G/$B${SUF}" >/dev/tty sleep 1 done done done done xterm-353/vttests/query-dynamic.pl0000755000175100001440000001421713470215053016114 0ustar tomusers#!/usr/bin/env perl # $XTermId: query-dynamic.pl,v 1.6 2019/05/19 08:56:11 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2019 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Test the color-query features of xterm for dynamic-colors use strict; use warnings; use Getopt::Std; use IO::Handle; our ( $opt_q, $opt_s, $opt_8 ); our @query_params; our @color_names = ( "VT100 text foreground color", "VT100 text background color", "text cursor color", "mouse foreground color", "mouse background color", "Tektronix foreground color", "Tektronix background color", "highlight background color", "Tektronix cursor color", "highlight foreground color" ); $Getopt::Std::STANDARD_HELP_VERSION = 1; &getopts('qs8') || die( "Usage: $0 [options]\n Options:\n -q quicker results by merging queries -s use ^G rather than ST -8 use 8-bit controls " ); our $OSC = "\x1b\]"; $OSC = "\x9d" if ($opt_8); our $ST = $opt_8 ? "\x9c" : ( $opt_s ? "\007" : "\x1b\\" ); sub get_reply($) { open TTY, "+; close TTY; system "stty $old"; if ( defined $reply ) { die("^C received\n") if ( "$reply" eq "\003" ); } return $reply; } sub visible($) { my $reply = $_[0]; my $n; my $result = ""; for ( $n = 0 ; $n < length($reply) ; ) { my $c = substr( $reply, $n, 1 ); if ( $c =~ /[[:print:]]/ ) { $result .= $c; } else { my $k = ord substr( $reply, $n, 1 ); if ( ord $k == 0x1b ) { $result .= "\\E"; } elsif ( $k == 0x7f ) { $result .= "^?"; } elsif ( $k == 32 ) { $result .= "\\s"; } elsif ( $k < 32 ) { $result .= sprintf( "^%c", $k + 64 ); } elsif ( $k > 128 ) { $result .= sprintf( "\\%03o", $k ); } else { $result .= chr($k); } } $n += 1; } return $result; } sub begin_query() { @query_params = (); } sub add_param($) { $query_params[ $#query_params + 1 ] = $_[0]; } sub show_reply($) { my $reply = shift; printf "data={%s}", &visible($reply); } sub finish_query($) { return unless (@query_params); my $reply; my $n; my $st = $opt_8 ? qr/\x9c/ : ( $opt_s ? qr/\007/ : qr/\x1b\\/ ); my $osc = $opt_8 ? qr/\x9d/ : qr/\x1b]/; my $match = qr/${osc}.*${st}/; my $params = join( ";", @query_params ); $params =~ s/\d+/?/g; $params = sprintf( "%d;%s", $query_params[0], $params ); $reply = &get_reply( $OSC . $params . $ST ); printf "query{%s}", &visible($params); if ( defined $reply ) { printf " len=%2d ", length($reply); if ( $reply =~ /${match}/ ) { my @chunks = split /${st}${osc}/, $reply; printf "\n" if ( $#chunks > 0 ); for my $c ( 0 .. $#chunks ) { $chunks[$c] =~ s/^${osc}// if ( $c == 0 ); $chunks[$c] =~ s/${st}$// if ( $c == $#chunks ); my $param = $chunks[$c]; $param =~ s/^(\d+);.*/$1/; $param = -1 unless ( $param =~ /^\d+$/ ); $chunks[$c] =~ s/^\d+;//; printf "\t%d: ", $param if ( $#chunks > 0 ); &show_reply( $chunks[$c] ); printf " %s", $color_names[ $param - 10 ] if ( ( $param >= 10 ) and ( ( $param - 10 ) <= $#color_names ) ); printf "\n" if ( $c < $#chunks ); } } else { printf "? "; &show_reply($reply); } } printf "\n"; } sub query_color($) { my $param = shift; &begin_query unless $opt_q; if ( $#query_params >= 0 and ( $param != $query_params[$#query_params] + 1 ) ) { &finish_query; &begin_query; } &add_param($param); &finish_query unless $opt_q; } sub query_colors($$) { my $lo = shift; my $hi = shift; my $n; for ( $n = $lo ; $n <= $hi ; ++$n ) { &query_color($n); } } printf "\x1b G" if ($opt_8); &begin_query if ($opt_q); if ( $#ARGV >= 0 ) { while ( $#ARGV >= 0 ) { if ( $ARGV[0] =~ /-/ ) { my @args = split /-/, $ARGV[0]; &query_colors( $args[0], $args[1] ); } else { &query_colors( $ARGV[0], $ARGV[0] ); } shift @ARGV; } } else { &query_colors( 10, 19 ); } &finish_query if ($opt_q); printf "\x1b F" if ($opt_8); 1; xterm-353/vttests/title.sh0000755000175100001440000000544211671154202014444 0ustar tomusers#!/bin/sh # $XTermId: title.sh,v 1.18 2011/12/11 16:21:22 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 1999-2003,2011 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Obtain the current title of the window, set up a simple clock which runs # until this script is interrupted, then restore the title. ESC="" CMD='/bin/echo' OPT='-n' SUF='' TMP=/tmp/xterm$$ eval '$CMD $OPT >$TMP || echo fail >$TMP' 2>/dev/null ( test ! -f $TMP || test -s $TMP ) && for verb in printf print ; do rm -f $TMP eval '$verb "\c" >$TMP || echo fail >$TMP' 2>/dev/null if test -f $TMP ; then if test ! -s $TMP ; then CMD="$verb" OPT= SUF='\c' break fi fi done rm -f $TMP exec /dev/tty read original stty $old # We actually get this terminated by an backslash, but the backslash # is lost. We may lose doublequote characters when restoring the title, # depending on the shell. original=`echo "$original" |sed -e 's/^...//' -e 's/.$//'` original=${ESC}]2\;"${original}"${SUF} if ( trap "echo exit" EXIT 2>/dev/null ) >/dev/null then trap '$CMD $OPT "$original" >/dev/tty; exit' EXIT HUP INT TRAP TERM else trap '$CMD $OPT "$original" >/dev/tty; exit' 0 1 2 5 15 fi while true do sleep 1 $CMD $OPT "${ESC}]2;`date`" >/dev/tty done xterm-353/vttests/closest-rgb.pl0000755000175100001440000001532613333351517015557 0ustar tomusers#!/usr/bin/env perl # $XTermId: closest-rgb.pl,v 1.11 2018/08/10 18:02:55 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2017,2018 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # For a given RGB value, show its distance from xterm's 88/256-color # models or alternatively against rgb.txt use strict; use warnings; use diagnostics; use Getopt::Std; our $namedRGB = "/etc/X11/rgb.txt"; our @namedRGB; our @xtermRGB; our ( $opt_f, $opt_i, $opt_n ); sub main::HELP_MESSAGE() { printf STDERR <; close $fp; my @result; my $o = 0; for my $i ( 0 .. $#data ) { next if ( $data[$i] =~ /^\s*[[:punct:]]/ ); $result[ $o++ ] = &lookup( $data[$i] ); } return @result; } sub distance($$) { my %a = %{ $_[0] }; my %b = %{ $_[1] }; my $R = $a{R} - $b{R}; my $G = $a{G} - $b{G}; my $B = $a{B} - $b{B}; my $result = sqrt( $R * $R + $G * $G + $B * $B ); } sub show_distances($$) { my @ref = @{ $_[0] }; my @cmp = @{ $_[1] }; for my $c ( 0 .. $#cmp ) { my %cmp = %{ $cmp[$c] }; my $best = -1; my %best; for my $r ( 0 .. $#ref ) { my %ref = %{ $ref[$r] }; my $test = &distance( \%ref, \%cmp ); if ( $best < 0 ) { $best = $test; %best = %ref; } elsif ( $best > $test ) { $best = $test; %best = %ref; } } printf "%3d %-25s %5.1f %s\n", $c, $cmp{NAME}, $best, $best{NAME}; } } @namedRGB = &load_namedRGB($opt_f); printf "%d names from $opt_f\n", $#namedRGB + 1; if ( $opt_n <= 16 ) { @xtermRGB = &xterm16; } elsif ( $opt_n <= 88 ) { @xtermRGB = &xterm88; } else { @xtermRGB = &xterm256; } printf "%d names from xterm palette\n", $#xtermRGB + 1; &show_distances( \@xtermRGB, \@namedRGB ) if ($opt_i); &show_distances( \@namedRGB, \@xtermRGB ) unless ($opt_i); 1; xterm-353/vttests/paste64.pl0000755000175100001440000001136013374656763014633 0ustar tomusers#!/usr/bin/env perl # $XTermId: paste64.pl,v 1.14 2018/11/20 01:05:55 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2006-2014,2018 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Test the paste64 option of xterm. use strict; use warnings; use Term::ReadKey; use IO::Handle; use MIME::Base64; our $target = ""; sub to_hex($) { my $value = $_[0]; my $result = ""; my $n; for ( $n = 0 ; $n < length($value) ; ++$n ) { $result .= sprintf( "%02X", ord substr( $value, $n, 1 ) ); } return $result; } sub show_string($) { my $value = $_[0]; my $n; my $result = ""; for ( $n = 0 ; $n < length($value) ; $n += 1 ) { my $c = ord substr( $value, $n, 1 ); if ( $c == ord '\\' ) { $result .= "\\\\"; } elsif ( $c == 0x1b ) { $result .= "\\E"; } elsif ( $c == 0x7f ) { $result .= "^?"; } elsif ( $c == 32 ) { $result .= "\\s"; } elsif ( $c < 32 ) { $result .= sprintf( "^%c", $c + 64 ); } elsif ( $c > 128 ) { $result .= sprintf( "\\%03o", $c ); } else { $result .= chr($c); } } printf "%s\r\n", $result; } sub get_reply($) { my $command = $_[0]; my $reply = ""; printf "send: "; show_string($command); print STDOUT $command; autoflush STDOUT 1; while (1) { my $test = ReadKey 1; last if not defined $test; #printf "%d:%s\r\n", length($reply), to_hex($test); $reply .= $test; } return $reply; } sub get_paste() { my $reply = get_reply( "\x1b]52;" . $target . ";?\x1b\\" ); printf "read: "; show_string($reply); my $data = $reply; $data =~ s/^\x1b]52;[[:alnum:]]*;//; $data =~ s/\x1b\\$//; printf "chop: "; show_string($data); $data = decode_base64($data); printf "data: "; show_string($data); } sub put_paste() { ReadMode 1; printf "data: "; my $data = ReadLine 0; chomp $data; ReadMode 5; $data = encode_base64($data); chomp $data; printf "data: "; show_string($data); my $send = "\x1b]52;" . $target . ";" . $data . "\x1b\\"; printf "send: "; show_string($send); print STDOUT $send; autoflush STDOUT 1; } sub set_target() { ReadMode 1; printf "target: "; $target = ReadLine 0; $target =~ s/[^cps01234567]//g; ReadMode 5; printf "result: %s\r\n", $target; } ReadMode 5, 'STDIN'; # allow single-character inputs while (1) { my $cmd; printf "\r\nCommand (? for help):"; $cmd = ReadKey 0; if ( $cmd eq "?" ) { printf "\r\np=put selection," . " g=get selection," . " q=quit," . " r=reset target," . " s=set target\r\n"; } elsif ( $cmd eq "p" ) { printf " ...put selection\r\n"; put_paste(); } elsif ( $cmd eq "g" ) { printf " ...get selection\r\n"; get_paste(); } elsif ( $cmd eq "q" ) { printf " ...quit\r\n"; last; } elsif ( $cmd eq "r" ) { printf " ...reset\r\n"; $target = ""; } elsif ( $cmd eq "s" ) { printf " ...set target\r\n"; set_target(); } } ReadMode 0, 'STDIN'; # Reset tty mode before exiting xterm-353/vttests/sgrPushPop2.pl0000755000175100001440000001520613463152736015532 0ustar tomusers#!/usr/bin/env perl # $XTermId: sgrPushPop2.pl,v 1.2 2019/05/03 23:59:26 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2019 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- use strict; use warnings; use diagnostics; use Getopt::Std; $| = 1; our ( $opt_b, $opt_n, $opt_r ); $Getopt::Std::STANDARD_HELP_VERSION = 1; &getopts('bn:r:') || die( "Usage: $0 [options]\n Options:\n -b color backgrounds instead of foregrounds -n NUM limit test to NUM rows (default: 9) -r NUM rotate example-columns (e.g, -r1 puts direct-color in middle) " ); $opt_n = 9 unless ( defined $opt_n ); $opt_r = 0 unless ( defined $opt_r ); our @xterm_ansi = ( 0x000000, #black 0xcd0000, #red3 0x00cd00, #green3 0xcdcd00, #yellow3 0x0000ee, #blue2 0xcd00cd, #magenta3 0x00cdcd, #cyan3 0xe5e5e5 #gray90 ); # The lengths in @example_title differ to ensure that the trailing "END!" # should be the same color as the middle column, regardless of "-r" rotation. our $example_title = "COLOR-"; our @example_title = ( "Indexed", "ANSI8", "Direct" ); # demonstrate selective SGR pop by a two-level test where the top-level has # ANSI colors, while the lower-level iterates over a color test-pattern, # alternating between direct-color and indexed-colors. sub choose_fgbg($$) { my $fg = shift; my $bg = shift; my $result = $opt_b ? $bg : $fg; return $result; } sub choose_column($) { my $code = shift; return ( $code + $opt_r ) % 3; } sub pushSGR($) { my $params = shift; printf "\x1b[%s#{", $params; } sub popSGR() { printf "\x1b[#}"; } sub mark_l() { printf " {"; } sub mark_r() { printf "} "; } sub standard_example() { &mark_l; my $text = $example_title . $example_title[1]; for my $n ( 0 .. length($text) - 1 ) { printf "\x1b[%dm", ( $n % 7 ) + 1 + &choose_fgbg( 30, 40 ); printf "%s", substr( $text, $n, 1 ); } &mark_r; } # The first 16 colors of xterm-256's palette match the ANSI+aixterm range. # Do not imitate the bold-colors. sub indexed_example() { &mark_l; my $text = $example_title . $example_title[0]; for my $n ( 0 .. length($text) - 1 ) { my $c = ( $n % 7 ) + 1; printf "\x1b[%d;5:%dm", &choose_fgbg( 38, 48 ), $c; printf "%s", substr( $text, $n, 1 ); } &mark_r; } # Imitate the "ANSI" colors from xterm's palette. # (Again bold colors are not imitated here). sub direct_example() { &mark_l; my $text = $example_title . $example_title[2]; for my $n ( 0 .. length($text) - 1 ) { my $c = ( $n % 7 ) + 1; my $r = ( $xterm_ansi[$c] / ( 256 * 256 ) ) % 256; my $g = ( $xterm_ansi[$c] / (256) ) % 256; my $b = ( $xterm_ansi[$c] ) % 256; printf "\x1b[%d;2:1:%d:%d:%dm", &choose_fgbg( 38, 48 ), $r, $g, $b; printf "%s", substr( $text, $n, 1 ); } &mark_r; } sub run_example($) { my $column = shift; &indexed_example if ( &choose_column($column) == 0 ); &standard_example if ( &choose_column($column) == 1 ); &direct_example if ( &choose_column($column) == 2 ); } sub video_name($) { my $code = shift; my $result = "?"; $result = "normal" if ( $code == 0 ); $result = "bold" if ( $code == 1 ); $result = "faint" if ( $code == 2 ); $result = "italicized" if ( $code == 3 ); $result = "underlined" if ( $code == 4 ); $result = "blink" if ( $code == 5 ); $result = "inverse" if ( $code == 7 ); $result = "crossed-out" if ( $code == 9 ); $result = "double-underlined" if ( $code == 21 ); return $result; } sub reset_video() { printf "\x1b[m"; } sub set_video($) { my $row = shift; my $param = ""; my $cycle = 9; $param = 0 if ( ( $row % $cycle ) == 0 ); $param = 1 if ( ( $row % $cycle ) == 1 ); $param = 2 if ( ( $row % $cycle ) == 2 ); $param = 3 if ( ( $row % $cycle ) == 3 ); $param = 4 if ( ( $row % $cycle ) == 4 ); $param = 5 if ( ( $row % $cycle ) == 5 ); $param = 7 if ( ( $row % $cycle ) == 6 ); $param = 9 if ( ( $row % $cycle ) == 7 ); $param = 21 if ( ( $row % $cycle ) == 8 ); printf "%-20s", &video_name($param); printf "\x1b[%dm", $param; } printf "\x1b[H\x1b[J"; &pushSGR(""); printf "\x1b[40;37mSetting ambient colors to white-on-black\n"; # The three columns (indexed, ANSI, direct) will look similar. &pushSGR(""); printf "Testing white-on-black with columns %s,%s,%s\n", $example_title[ &choose_column(0) ], $example_title[ &choose_column(1) ], $example_title[ &choose_column(2) ]; for my $row ( 0 .. $opt_n ) { &pushSGR("10;11"); # save/restore only foreground/background color &set_video($row); # this attribute is set for the whole row &run_example(0); &popSGR; &run_example(1); &pushSGR("10;11"); # save/restore only foreground/background color &run_example(2); &popSGR; printf "END!"; # this is in the last color used in the middle column &reset_video(); printf "\n"; } &popSGR; printf "The ambient colors should still be white-on-black.\n"; &popSGR; printf "Now we should be back to whatever it was before we got here.\n"; 1; xterm-353/vttests/acolors.sh0000755000175100001440000000557611671154202014775 0ustar tomusers#!/bin/sh # $XTermId: acolors.sh,v 1.7 2011/12/11 16:21:22 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2002-2003,2011 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Demonstrate the use of the control sequence for changing ANSI colors. ESC="" CMD='/bin/echo' OPT='-n' SUF='' TMP=/tmp/xterm$$ eval '$CMD $OPT >$TMP || echo fail >$TMP' 2>/dev/null ( test ! -f $TMP || test -s $TMP ) && for verb in printf print ; do rm -f $TMP eval '$verb "\c" >$TMP || echo fail >$TMP' 2>/dev/null if test -f $TMP ; then if test ! -s $TMP ; then CMD="$verb" OPT= SUF='\c' break fi fi done rm -f $TMP LIST="00 30 80 d0 ff" exec /dev/tty read original stty $old original=${original}${SUF} if ( trap "echo exit" EXIT 2>/dev/null ) >/dev/null then trap '$CMD $OPT "$original" >/dev/tty; exit' EXIT HUP INT TRAP TERM else trap '$CMD $OPT "$original" >/dev/tty; exit' 0 1 2 5 15 fi $CMD "${ESC}[0;1;34mThis message is BLUE" $CMD "${ESC}[0;1;31mThis message is RED ${ESC}[0;31m(sometimes)" $CMD "${ESC}[0;1;32mThis message is GREEN${ESC}[0m" while true do for R in $LIST do for G in $LIST do for B in $LIST do # color "9" is bold-red test $R != 00 && test $G = 00 && test $B = 00 && $CMD $OPT "" >/dev/tty $CMD $OPT "${ESC}]4;9;rgb:$R/$G/$B${SUF}" >/dev/tty sleep 1 done done done done xterm-353/vttests/256colors.pl0000755000175100001440000000406713041175436015071 0ustar tomusers#!/usr/bin/env perl # $XTermId: 256colors.pl,v 1.6 2017/01/22 18:34:06 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 1999-2014,2017 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- use strict; use warnings; # This uses 33 print-lines on an 80-column display. Printing the numbers in # hexadecimal would make it compact enough for 24x80, but less readable. our ( $bg, $fg ); for ( $bg = 0 ; $bg < 256 ; $bg++ ) { # print "\x1b[9;1H\x1b[2J"; for ( $fg = 0 ; $fg < 256 ; $fg++ ) { print "\x1b[48;5;${bg}m\x1b[38;5;${fg}m"; printf "%03.3d/%03.3d ", $fg, $bg; } print "\n"; sleep 1; } xterm-353/vttests/88colors.pl0000755000175100001440000000366313041175436015015 0ustar tomusers#!/usr/bin/env perl # $XTermId: 88colors.pl,v 1.5 2017/01/22 18:34:06 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 1999-2014,2017 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Made from 256colors.pl use strict; use warnings; our ( $bg, $fg ); for ( $bg = 0 ; $bg < 88 ; $bg++ ) { print "\x1b[9;1H\x1b[48;5;${bg}m\x1b[2J"; for ( $fg = 0 ; $fg < 88 ; $fg++ ) { print "\x1b[38;5;${fg}m"; printf "%03.3d/%03.3d ", $fg, $bg; } sleep 1; print "\n"; } xterm-353/vttests/dynamic2.sh0000755000175100001440000000643711671154202015036 0ustar tomusers#!/bin/sh # $XTermId: dynamic2.sh,v 1.3 2011/12/11 16:21:22 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2006,2011 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Demonstrate the use of dynamic colors by setting each dynamic color # successively to different values. ESC="" CMD='/bin/echo' OPT='-n' SUF='' TMP=/tmp/xterm$$ eval '$CMD $OPT >$TMP || echo fail >$TMP' 2>/dev/null ( test ! -f $TMP || test -s $TMP ) && for verb in printf print ; do rm -f $TMP eval '$verb "\c" >$TMP || echo fail >$TMP' 2>/dev/null if test -f $TMP ; then if test ! -s $TMP ; then CMD="$verb" OPT= SUF='\c' break fi fi done rm -f $TMP LIST="00 30 80 d0 ff" FULL="10 11 12 13 14 15 16 17 18" echo "reading current color settings" exec /dev/tty read reply eval original$N='${reply}${SUF}' original=${original}${reply}${SUF} done stty $old if ( trap "echo exit" EXIT 2>/dev/null ) >/dev/null then trap '$CMD $OPT "$original" >/dev/tty; exit' EXIT HUP INT TRAP TERM else trap '$CMD $OPT "$original" >/dev/tty; exit' 0 1 2 5 15 fi while true do for N in $FULL do case $N in 10) echo "coloring text foreground";; 11) echo "coloring text background";; 12) echo "coloring text cursor";; 13) echo "coloring mouse foreground";; 14) echo "coloring mouse background";; 15) echo "coloring tektronix foreground";; 16) echo "coloring tektronix background";; 17) echo "coloring highlight background";; 18) echo "coloring tektronix cursor";; esac for R in $LIST do for G in $LIST do for B in $LIST do $CMD $OPT "${ESC}]$N;rgb:$R/$G/$B${SUF}" >/dev/tty sleep 1 done done done eval 'restore=$'original$N $CMD $OPT "$restore" >/dev/tty sleep 1 done done xterm-353/vttests/88colors2.pl0000755000175100001440000001451413333324506015072 0ustar tomusers#!/usr/bin/env perl # $XTermId: 88colors2.pl,v 1.18 2018/08/10 15:03:34 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 1999-2016,2018 by Thomas E. Dickey # Copyright 1999 by Steve Wall # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # # Adapted from 256colors2.pl # If -s is not given, use the resources for colors 0-15 - usually more-or-less # a reproduction of the standard ANSI colors, but possibly more pleasing # shades. use strict; use warnings; use Getopt::Std; use Encode 'encode_utf8'; our ( $opt_8, $opt_c, $opt_d, $opt_h, $opt_q, $opt_r, $opt_s, $opt_u ); $Getopt::Std::STANDARD_HELP_VERSION = 1; &getopts('8cdhqrsu') || die("Usage: $0 [options]"); die( "Usage: $0 [options]\n Options: -8 use 8-bit controls -c use colons for separating parameter values in SGR 38/48 -d use rgb values rather than palette index -h display this message -q quieter output by merging all palette initialization -r display the reverse of the usual palette -s modify system colors, i.e., 0..15 -u use UTF-8 when emitting 8-bit controls " ) if ($opt_h); our $cube = 4; our (@steps); our ( $red, $green, $blue ); our ( $gray, $level, $color ); our ( $csi, $osc, $sep, $st ); our @rgb; sub map_cube($) { my $value = $_[0]; $value = ( 3 - $value ) if defined($opt_r); return $value; } sub map_gray($) { my $value = $_[0]; $value = ( 7 - $value ) if defined($opt_r); return $value; } sub define_color($$$$) { my $index = $_[0]; my $r = $_[1]; my $g = $_[2]; my $b = $_[3]; printf( "%s4", $osc ) unless ($opt_q); printf( ";%d;rgb:%2.2x/%2.2x/%2.2x", $index, $r, $g, $b ); printf( "%s", $st ) unless ($opt_q); $rgb[$index] = sprintf "%d%s%d%s%d", $r, $sep, $g, $sep, $b; } sub select_color($) { my $index = $_[0]; if ( $opt_d and defined( $rgb[$index] ) ) { printf "%s48;2%s%sm ", $csi, $sep, $rgb[$index]; } else { printf "%s48;5%s%sm ", $csi, $sep, $index; } } sub system_color($$$$) { my $color = shift; my $red = shift; my $green = shift; my $blue = shift; &define_color( 15 - $color, $red, $green, $blue ) if ($opt_r); &define_color( $color, $red, $green, $blue ) unless ($opt_r); } if ($opt_8) { $csi = "\x9b"; $osc = "\x9d"; $st = "\x9c"; } else { $csi = "\x1b["; $osc = "\x1b]"; $st = "\x1b\\"; } if ($opt_c) { $sep = ":"; } else { $sep = ";"; } if ( $opt_8 and $opt_u ) { my $lc_ctype = `locale 2>/dev/null | fgrep LC_CTYPE | sed -e 's/^.*=//'`; if ( $lc_ctype =~ /utf.?8/i ) { binmode( STDOUT, ":utf8" ); } } printf( "%s4", $osc ) if ($opt_q); if ($opt_s) { &system_color( 0, 0, 0, 0 ); &system_color( 1, 205, 0, 0 ); &system_color( 2, 0, 205, 0 ); &system_color( 3, 205, 205, 0 ); &system_color( 4, 0, 0, 238 ); &system_color( 5, 205, 0, 205 ); &system_color( 6, 0, 205, 205 ); &system_color( 7, 229, 229, 229 ); &system_color( 8, 127, 127, 127 ); &system_color( 9, 255, 0, 0 ); &system_color( 10, 0, 255, 0 ); &system_color( 11, 255, 255, 0 ); &system_color( 12, 92, 92, 255 ); &system_color( 13, 255, 0, 255 ); &system_color( 14, 0, 255, 255 ); &system_color( 15, 255, 255, 255 ); } # colors 16-79 are a 4x4x4 color cube @steps = ( 0, 139, 205, 255 ); for ( $red = 0 ; $red < $cube ; $red++ ) { for ( $green = 0 ; $green < $cube ; $green++ ) { for ( $blue = 0 ; $blue < $cube ; $blue++ ) { &define_color( 16 + ( map_cube($red) * $cube * $cube ) + ( map_cube($green) * $cube ) + map_cube($blue), int( $steps[$red] ), int( $steps[$green] ), int( $steps[$blue] ) ); } } } # colors 80-87 are a grayscale ramp, intentionally leaving out # black and white for ( $gray = 0 ; $gray < 8 ; $gray++ ) { $level = ( map_gray($gray) * 23.18181818 ) + 46.36363636; if ( $gray > 0 ) { $level += 23.18181818; } &define_color( 80 + $gray, int($level), int($level), int($level) ); } printf( "%s", $st ) if ($opt_q); # display the colors # first the system ones: print "System colors:\n"; for ( $color = 0 ; $color < 8 ; $color++ ) { &select_color($color); } printf "%s0m\n", $csi; for ( $color = 8 ; $color < 16 ; $color++ ) { &select_color($color); } printf "%s0m\n\n", $csi; # now the color cube print "Color cube, ${cube}x${cube}x${cube}:\n"; for ( $green = 0 ; $green < $cube ; $green++ ) { for ( $red = 0 ; $red < $cube ; $red++ ) { for ( $blue = 0 ; $blue < $cube ; $blue++ ) { $color = 16 + ( $red * $cube * $cube ) + ( $green * $cube ) + $blue; &select_color($color); } printf "%s0m ", $csi; } print "\n"; } # now the grayscale ramp print "Grayscale ramp:\n"; for ( $color = 80 ; $color < 88 ; $color++ ) { &select_color($color); } printf "%s0m\n", $csi; xterm-353/vttests/report-sgr.pl0000755000175100001440000004036513515157545015447 0ustar tomusers#!/usr/bin/env perl # $XTermId: report-sgr.pl,v 1.35 2019/07/21 21:55:49 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2018,2019 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Test the report-sgr option of xterm. # TODO: add "-8" option, for 8-bit controls use strict; use warnings; use Getopt::Long qw(:config auto_help no_ignore_case); use Pod::Usage; use Term::ReadKey; our ( $opt_colors, $opt_direct, $opt_help, $opt_man ); our $csi = "\033["; our $osc = "\033]"; our $st = "\033\\"; our @sgr_names = qw( Normal Bold Faint Italicized Underlined Blink Fast-Blink Inverse Invisible Crossed-Out ); our ( $row_max, $col_max ); our ( $mark, $top_row ); our $cur_sgr = 0; # indexed colors, e.g., "ANSI" our %indexed_f = qw ( default 1 c 7 ); our %indexed_b = qw ( default 1 c 0 ); # direct colors our %direct_f = qw ( default 0 r 255 g 0 b 0 ); our %direct_b = qw ( default 0 r 0 g 0 b 255 ); our $which_value = "video-attributes"; our $which_color = "red"; our ( $row_1st, $col_1st, $row_now, $col_now ); sub beep() { printf "\a"; } sub cup($$) { my $r = shift; my $c = shift; printf "%s%d;%dH", $csi, $r, $c; } sub el($) { printf "%s%sK", $csi, $_[0]; } sub ed($) { printf "%s%sJ", $csi, $_[0]; } sub sgr($) { printf "%s%sm", $csi, $_[0]; } sub same_rgb($$) { my %c1 = %{ $_[0] }; my %c2 = %{ $_[1] }; my $result = 1; $result = 0 if ( $c1{r} ne $c2{r} ); $result = 0 if ( $c1{g} ne $c2{g} ); $result = 0 if ( $c1{b} ne $c2{b} ); return $result; } sub color_name($) { my $code = shift; my $result; if ($opt_direct) { $result = $code; } else { if ( $code < 0 ) { $result = "default"; } else { $result = $code; } } return $result; } sub color_code($$) { my $isfg = shift; my $result = ""; my $base = $isfg ? 30 : 40; if ($opt_direct) { $result = sprintf "%d:2", $base + 8; if ($isfg) { $result .= sprintf ":%d:%d:%d", # $direct_f{r}, # $direct_f{g}, # $direct_f{b}; } else { $result .= sprintf ":%d:%d:%d", # $direct_b{r}, # $direct_b{g}, # $direct_b{b}; } } else { my %data = $isfg ? %indexed_f : %indexed_b; if ( &is_default( \%data ) ) { $result = $base + 9; } else { if ( $opt_colors <= 16 ) { $base += 60 if ( $data{c} >= 8 ); $result = $base + $data{c}; } else { $result = sprintf "%d:5:%d", $base + 8, $data{c}; } } } return $result; } sub show_string($) { my $value = $_[0]; my $n; $value = "" unless $value; my $result = ""; for ( $n = 0 ; $n < length($value) ; $n += 1 ) { my $c = ord substr( $value, $n, 1 ); if ( $c == ord '\\' ) { $result .= "\\\\"; } elsif ( $c == 0x1b ) { $result .= "\\E"; } elsif ( $c == 0x7f ) { $result .= "^?"; } elsif ( $c == 32 ) { $result .= "\\s"; } elsif ( $c < 32 ) { $result .= sprintf( "^%c", $c + 64 ); } elsif ( $c > 128 ) { $result .= sprintf( "\\%03o", $c ); } else { $result .= chr($c); } } return $result; } sub get_reply($) { my $command = $_[0]; my $reply = ""; print STDOUT $command; autoflush STDOUT 1; while (1) { my $test = ReadKey 0.02; last if not defined $test; $reply .= $test; } return $reply; } sub show_status() { &cup( 1, 1 ); &el(2); my $show = ""; my $parm = ""; if ($mark) { my $r1 = ( $row_now > $row_1st ) ? $row_1st : $row_now; my $r2 = ( $row_now < $row_1st ) ? $row_1st : $row_now; my $c1 = ( $col_now > $col_1st ) ? $col_1st : $col_now; my $c2 = ( $col_now < $col_1st ) ? $col_1st : $col_now; $show = sprintf "[%d,%d] [%d,%d] ", $r1, $c1, $r2, $c2; $parm = sprintf "%d;%d;%d;%d", $r1, $c1, $r2, $c2; } else { $show = sprintf "[%d,%d] ", $row_now, $col_now; $parm = sprintf "%d;%d;%d;%d", # $row_now, $col_now, # $row_now, $col_now; } my $send = sprintf "%s%s#|", $csi, $parm; printf "%s %s ", $show, &show_string($send); &cup( $row_now, $col_now ); my $reply = &get_reply($send); &cup( 2, 1 ); &el(2); printf "read %s", &show_string($reply); &cup( $row_now, $col_now ); } sub toggle_default() { if ($opt_direct) { if ( $which_value =~ /^f/ ) { $direct_f{default} = !$direct_f{default}; } elsif ( $which_value =~ /^b/ ) { $direct_b{default} = !$direct_b{default}; } else { &beep; } } else { if ( $which_value =~ /^f/ ) { $indexed_f{default} = !$indexed_f{default}; } elsif ( $which_value =~ /^b/ ) { $indexed_b{default} = !$indexed_b{default}; } else { &beep; } } &show_example; } sub is_default($) { my $result = 0; my %data = %{ $_[0] }; $result = ( $data{default} != 0 ); return $result; } sub change_color($$) { my $inc = $_[0]; my %data = %{ $_[1] }; my $name = $_[2]; $data{$name} = ( $data{$name} + $opt_colors + $inc ) % $opt_colors; return %data; } sub set_which_value($) { $which_value = shift; &show_example; } sub set_which_color($) { $which_color = shift; &show_example; } sub change_value($) { my $inc = shift; if ( $which_value =~ /^v/ ) { $cur_sgr = ( $cur_sgr + 10 + $inc ) % 10; } elsif ( $which_value =~ /^f/ ) { if ($opt_direct) { %direct_f = &change_color( $inc, \%direct_f, "r" ) if ( $which_color =~ /^r/ ); %direct_f = &change_color( $inc, \%direct_f, "g" ) if ( $which_color =~ /^g/ ); %direct_f = &change_color( $inc, \%direct_f, "b" ) if ( $which_color =~ /^b/ ); } else { %indexed_f = &change_color( $inc, \%indexed_f, "c" ); } } elsif ( $which_value =~ /^b/ ) { if ($opt_direct) { %direct_b = &change_color( $inc, \%direct_b, "r" ) if ( $which_color =~ /^r/ ); %direct_b = &change_color( $inc, \%direct_b, "g" ) if ( $which_color =~ /^g/ ); %direct_b = &change_color( $inc, \%direct_b, "b" ) if ( $which_color =~ /^b/ ); } else { %indexed_b = &change_color( $inc, \%indexed_b, "c" ); } } &show_example; } sub show_example() { &cup( $top_row, 1 ); my $init = "0"; if ($opt_direct) { $init .= sprintf ";%s", &color_code(1); $init .= sprintf ";%s", &color_code(0); } else { $init .= sprintf ";%s", &color_code(1) unless ( &is_default( \%indexed_f ) ); $init .= sprintf ";%s", &color_code(0) unless ( &is_default( \%indexed_b ) ); } &ed(0); for my $n ( 0 .. 9 ) { my $mode = $n; $mode = $init if ( $n == 0 ); &cup( $n + $top_row, 1 ); if ($opt_direct) { &sgr($init); &sgr( &same_rgb( \%direct_f, \%direct_b ) ? "0" : $init ); } else { &sgr( $indexed_f{c} eq $indexed_b{c} ? "0" : $init ); } printf "%s SGR %d: %-12s", # ( $cur_sgr == $n ) ? "-->" : " ", # $n, $sgr_names[$n]; $mode .= ";$cur_sgr" unless ( $cur_sgr eq "0" ); &sgr($mode); printf "%.55s", # "abcdefghijklmnopqrstuvwxyz" . # "ABCDEFGHIJKLMNOPQRSTUVWXYZ" . # "0123456789"; } &sgr(0); my $end = $top_row + 11; &cup( $end++, 1 ); printf 'Change %s with "<" or ">".', ( $opt_direct and ( $which_value !~ /^v/ ) ) ? ( sprintf "%s(%s)", $which_value, $which_color ) : $which_value; &cup( $end++, 1 ); printf "Current SGR %d (%s)", $cur_sgr, $sgr_names[$cur_sgr]; if ($opt_direct) { &cup( $end++, 1 ); printf "Colors: direct"; &cup( $end++, 1 ); if ( &is_default( \%direct_f ) ) { printf " fg( default )"; } else { printf " fg( r=%s, g=%s, b=%s )", # &color_name( $direct_f{r} ), # &color_name( $direct_f{g} ), # &color_name( $direct_f{b} ); } &cup( $end++, 1 ); if ( &is_default( \%direct_b ) ) { printf " bg( default )"; } else { printf " bg( r=%s, g=%s, b=%s )", # &color_name( $direct_b{r} ), # &color_name( $direct_b{g} ), # &color_name( $direct_b{b} ); } } else { &cup( $end++, 1 ); printf "Colors: indexed"; if ( &is_default( \%indexed_f ) ) { printf ", fg=default"; } else { printf ", fg=%s", &color_name( $indexed_f{c} ); } if ( &is_default( \%indexed_b ) ) { printf ", bg=default"; } else { printf ", bg=%s", &color_name( $indexed_b{c} ); } } &cup( $end++, 1 ); printf ' ("q" to quit, "?" for help)'; } sub init_screensize() { $row_max = 24; $col_max = 80; &cup( 9999, 9999 ); my $result = &get_reply( $csi . "6n" ); if ( $result =~ /^$csi[[:digit:];]+R$/ ) { $result =~ s/^$csi[;]*//; $result =~ s/[;]*R$//; my @params = split /;/, $result; if ( $#params == 1 ) { $row_max = $params[0]; $col_max = $params[1]; } } &cup( 1, 1 ); } sub startup_screen() { ReadMode 'ultra-raw', 'STDIN'; } sub restore_screen() { &sgr(0); printf "%s102%s", $osc, $st if ($opt_direct); &cup( $row_max, 1 ); ReadMode 'restore', 'STDIN'; } GetOptions( 'colors=i', # 'help|?', # 'direct', # 'man' ) || pod2usage(2); pod2usage(1) if $opt_help; pod2usage( -verbose => 2 ) if $opt_man; $opt_colors = ( $opt_direct ? 256 : 8 ) unless ($opt_colors); $opt_colors = 8 if ( $opt_colors < 8 ); &startup_screen; &init_screensize; $mark = 0; $top_row = 4; $row_now = $row_1st = $top_row; $col_now = $col_1st = 1; &ed(2); &show_example; while (1) { my $cmd; &show_status; &cup( $row_now, $col_now ); $cmd = ReadKey 0; if ( $cmd eq "?" ) { &restore_screen; system( $0 . " -man" ); &startup_screen; &show_example; $cmd = ReadKey 0; } elsif ( $cmd eq " " ) { $mark = ( $mark != 0 ) ? 0 : 1; $row_1st = $row_now; $col_1st = $col_now; } elsif ( $cmd eq chr(12) ) { &show_example; } elsif ( $cmd eq "h" ) { $col_now-- if ( $col_now > 1 ); } elsif ( $cmd eq "j" ) { $row_now++ if ( $row_now < $row_max ); } elsif ( $cmd eq "k" ) { $row_now-- if ( $row_now > 1 ); } elsif ( $cmd eq "l" ) { $col_now++ if ( $col_now < $col_max ); } elsif ( $cmd eq "q" ) { &restore_screen; printf "\r\n...quit\r\n"; last; } elsif ( $cmd eq "=" ) { &cup( $row_now = $row_1st + $cur_sgr, $col_now = 24 ); } elsif ( $cmd eq "v" ) { &set_which_value("video-attributes (SGR)"); } elsif ( $cmd eq "f" ) { &set_which_value("foreground"); } elsif ( $cmd eq "b" ) { &set_which_value("background"); } elsif ( $cmd eq "d" ) { &toggle_default; } elsif ( $cmd eq "<" ) { &change_value(-1); } elsif ( $cmd eq ">" ) { &change_value(1); } elsif ( $opt_direct and ( $cmd eq "R" ) ) { &set_which_color("red"); } elsif ( $opt_direct and ( $cmd eq "G" ) ) { &set_which_color("green"); } elsif ( $opt_direct and ( $cmd eq "B" ) ) { &set_which_color("blue"); } else { &beep; } } 1; __END__ =head1 NAME report-sgr.pl - demonstrate xterm's report-SGR control sequence =head1 SYNOPSIS report-sgr.pl [options] Options: -help brief help message -8 use 8-bit controls -colors=NUM specify number of indexed colors -direct use direct-colors, rather than indexed =head1 OPTIONS =over 8 =item B<-help> Print a brief help message and exit. =item B<-man> Print the extended help message and exit. =item B<-colors> Specify the number of indexed colors. =item B<-direct> Use direct-colors (e.g., an RGB value), rather than indexed (e.g., ANSI colors). =back =head1 DESCRIPTION B displays a normal line, as well as one for each SGR code 1-9, with a test-string showing the effect of the SGR. Two SGR codes can be combined, as well as foreground and background colors. =head1 Commands =over 8 =item B Quit the program with B. It will ignore B<^C> and other control characters. =item B, B, B, B As you move the cursor around the screen (with vi-style h,j,k,l characters), the script sends an XTREPORTSGR control to the terminal, asking what the video attributes are for the currently selected cell. The script displays the result on the second line of the screen. =item B XTREPORTSGR returns an SGR control sequence which could be used to set the terminal's current video attributes to match the attributes found in all cells of the rectangle specified by this script. Use the spacebar to toggle the mark which denotes one corner of the rectangle. The current cursor position is the other corner. =item B<=> Move the cursor to the first cell of the test-data for the currently selected SGR code (the one with B<-->>). =item B Select the video-attribute mode. =item B Select the foreground-color mode. =item B Select the background-color mode. =item B When direct-colors are chosen, select the red-component of the currently selected foreground or background mode. =item B When direct-colors are chosen, select the green-component of the currently selected foreground or background mode. =item B When direct-colors are chosen, select the blue-component of the currently selected foreground or background mode. =item B Toggle between the selected colors and the terminal's default colors. =item B<<> Decrease the index of video-attribute to combine, or the color value depending on the selected mode. =item B<>> Increase the index of video-attribute to combine, or the color value depending on the selected mode. =item B<^L> Repaint the screen. =back =cut xterm-353/vttests/query-color.pl0000755000175100001440000001572413470215066015616 0ustar tomusers#!/usr/bin/env perl # $XTermId: query-color.pl,v 1.20 2019/05/19 08:56:22 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2012-2018,2019 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Test the color-query features of xterm using OSC 4 or OSC 5. # TODO: optionally show result in #rrggbb format. use strict; use warnings; use diagnostics; use Getopt::Std; use IO::Handle; our ( $opt_4, $opt_a, $opt_n, $opt_q, $opt_s ); $Getopt::Std::STANDARD_HELP_VERSION = 1; &getopts('4an:qs') || die( "Usage: $0 [options] [color1[-color2]]\n Options:\n -4 use OSC 4 for special colors rather than OSC 5 -a query all \"ANSI\" colors -n NUM assume terminal supports NUM \"ANSI\" colors rather than 256 -q quicker results by merging queries -s use ^G rather than ST " ); our $ST = $opt_s ? "\007" : "\x1b\\"; our $num_ansi_colors = $opt_n ? $opt_n : 256; our $last_op = -1; our $this_op = -1; our @query_params; sub get_reply($) { open TTY, "+; close TTY; system "stty $old"; if ( defined $reply ) { die("^C received\n") if ( "$reply" eq "\003" ); } return $reply; } sub visible($) { my $reply = $_[0]; my $n; my $result = ""; for ( $n = 0 ; $n < length($reply) ; ) { my $c = substr( $reply, $n, 1 ); if ( $c =~ /[[:print:]]/ ) { $result .= $c; } else { my $k = ord substr( $reply, $n, 1 ); if ( ord $k == 0x1b ) { $result .= "\\E"; } elsif ( $k == 0x7f ) { $result .= "^?"; } elsif ( $k == 32 ) { $result .= "\\s"; } elsif ( $k < 32 ) { $result .= sprintf( "^%c", $k + 64 ); } elsif ( $k > 128 ) { $result .= sprintf( "\\%03o", $k ); } else { $result .= chr($k); } } $n += 1; } return $result; } sub special2code($) { my $param = shift; $param = 0 if ( $param =~ /^bold$/i ); $param = 1 if ( $param =~ /^underline$/i ); $param = 2 if ( $param =~ /^blink$/i ); $param = 3 if ( $param =~ /^reverse$/i ); $param = 4 if ( $param =~ /^italic$/i ); return $param; } sub code2special($) { my $param = shift; my $result; $result = "bold" if ( $param == 0 ); $result = "underline" if ( $param == 1 ); $result = "blink" if ( $param == 2 ); $result = "reverse" if ( $param == 3 ); $result = "italic" if ( $param == 4 ); return $result; } sub begin_query() { @query_params = (); } sub add_param($) { $query_params[ $#query_params + 1 ] = $_[0]; } sub show_reply($) { my $reply = shift; printf "data={%s}", &visible($reply); if ( $reply =~ /^\d+;rgb:.*/ and ( $opt_4 or ( $this_op == 5 ) ) ) { my $num = $reply; my $max = $opt_4 ? $num_ansi_colors : 0; $num =~ s/;.*//; if ( $num >= $max ) { my $name = &code2special( $num - $max ); printf " %s", $name if ($name); } } } sub finish_query() { my $reply; my $n; my $st = $opt_s ? qr/\007/ : qr/\x1b\\/; my $osc = qr/\x1b]$this_op/; my $match = qr/^(${osc}.*${st})+$/; my $params = sprintf "%s;?;", ( join( ";?;", @query_params ) ); $reply = &get_reply( "\x1b]$this_op;" . $params . $ST ); printf "query%s{%s}%*s", $this_op, &visible($params), 3 - length($params), " "; if ( defined $reply ) { printf "len=%2d ", length($reply); if ( $reply =~ /${match}/ ) { my @chunks = split /${st}${osc}/, $reply; printf "\n" if ( $#chunks > 0 ); for my $c ( 0 .. $#chunks ) { $chunks[$c] =~ s/^${osc}// if ( $c == 0 ); $chunks[$c] =~ s/${st}$// if ( $c == $#chunks ); $chunks[$c] =~ s/^;//; printf "\t%d: ", $c if ( $#chunks > 0 ); &show_reply( $chunks[$c] ); printf "\n" if ( $c < $#chunks ); } } else { printf "? "; &show_reply($reply); } } printf "\n"; } sub query_color($) { my $param = shift; my $op = 4; if ( $param !~ /^\d+$/ ) { $param = &special2code($param); if ( $param !~ /^\d+$/ ) { printf STDERR "? not a color name or code: $param\n"; return; } if ($opt_4) { $param += $num_ansi_colors; } else { $op = 5; } } $this_op = $op; # FIXME handle mixed OSC 4/5 &begin_query unless $opt_q; &add_param($param); &finish_query unless $opt_q; } sub query_colors($$) { my $lo = shift; my $hi = shift; if ( $lo =~ /^\d+$/ ) { my $n; for ( $n = $lo ; $n <= $hi ; ++$n ) { &query_color($n); } } else { &query_color($lo); &query_color($hi) unless ( $hi eq $lo ); } } &begin_query if ($opt_q); if ( $#ARGV >= 0 ) { while ( $#ARGV >= 0 ) { if ( $ARGV[0] =~ /-/ ) { my @args = split /-/, $ARGV[0]; &query_colors( $args[0], $args[1] ); } else { &query_colors( $ARGV[0], $ARGV[0] ); } shift @ARGV; } } else { &query_colors( 0, $opt_a ? $num_ansi_colors : 7 ); } &finish_query if ($opt_q); 1; xterm-353/vttests/8colors.sh0000755000175100001440000000605611671154202014716 0ustar tomusers#!/bin/sh # $XTermId: 8colors.sh,v 1.14 2011/12/11 16:21:22 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 1999-2003,2011 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Show a simple 8-color test pattern ESC="" CMD='/bin/echo' OPT='-n' SUF='' TMP=/tmp/xterm$$ eval '$CMD $OPT >$TMP || echo fail >$TMP' 2>/dev/null ( test ! -f $TMP || test -s $TMP ) && for verb in printf print ; do rm -f $TMP eval '$verb "\c" >$TMP || echo fail >$TMP' 2>/dev/null if test -f $TMP ; then if test ! -s $TMP ; then CMD="$verb" OPT= SUF='\c' break fi fi done rm -f $TMP if ( trap "echo exit" EXIT 2>/dev/null ) >/dev/null then trap '$CMD $OPT ""; exit' EXIT HUP INT TRAP TERM else trap '$CMD $OPT ""; exit' 0 1 2 5 15 fi echo "" while true do for AT in 0 1 4 7 do case $AT in 0) attr="normal ";; 1) attr="bold ";; 4) attr="under ";; 7) attr="reverse ";; esac for FG in 0 1 2 3 4 5 6 7 do case $FG in 0) fcolor="black ";; 1) fcolor="red ";; 2) fcolor="green ";; 3) fcolor="yellow ";; 4) fcolor="blue ";; 5) fcolor="magenta ";; 6) fcolor="cyan ";; 7) fcolor="white ";; esac $CMD $OPT "[0;${AT}m$attr" $CMD $OPT "[3${FG}m$fcolor" for BG in 1 2 3 4 5 6 7 do case $BG in 0) bcolor="black ";; 1) bcolor="red ";; 2) bcolor="green ";; 3) bcolor="yellow ";; 4) bcolor="blue ";; 5) bcolor="magenta ";; 6) bcolor="cyan ";; 7) bcolor="white ";; esac $CMD $OPT "[4${BG}m$bcolor" done echo "" done sleep 1 done done xterm-353/vttests/query-xres.pl0000755000175100001440000001427013546477442015470 0ustar tomusers#!/usr/bin/env perl # $XTermId: query-xres.pl,v 1.6 2019/10/06 23:56:18 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2019 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Report features enabled/disabled via resource-settings # TODO: handle 8-bit controls use strict; use warnings; use Getopt::Std; use IO::Handle; our ( $opt_a, $opt_d, $opt_e, $opt_m, $opt_q ); our @query_params; our @query_result; $Getopt::Std::STANDARD_HELP_VERSION = 1; &getopts('acdemq') || die( "Usage: $0 [options]\n Options:\n -a (same as -d -e -m) -d query disabled/disallowed features -e query enabled/allowed features -m query modified keys -q quicker results by merging queries " ); if ( $#ARGV < 0 and not( defined($opt_d) or defined($opt_e) or defined($opt_m) ) ) { $opt_a = 1; } sub get_reply($) { open TTY, "+; close TTY; system "stty $old"; if ( defined $reply ) { die("^C received\n") if ( "$reply" eq "\003" ); } return $reply; } sub hexified($) { my $value = $_[0]; my $result = ""; my $n; for ( $n = 0 ; $n < length($value) ; ++$n ) { $result .= sprintf( "%02X", ord substr( $value, $n, 1 ) ); } return $result; } sub begin_query() { @query_params = (); } sub add_param($) { $query_params[ $#query_params + 1 ] = &hexified( $_[0] ); } sub finish_query() { my $reply = &get_reply( "\x1bP+Q" . join( ';', @query_params ) . "\x1b\\" ); return unless defined $reply; while ( $reply =~ /\x1bP1\+R[[:xdigit:]]+[=;][[:xdigit:]]*.*\x1b\\/ ) { my $n; my $parse; $reply =~ s/^\x1bP1\+R//; $parse = $reply; $reply =~ s/\x1b\\.*$//; $parse = substr( $parse, length($reply) ); $parse =~ s/^\x1b\\//; my $result = ""; my $count = 0; my $state = 0; my $error = "?"; for ( $n = 0 ; $n < length($reply) ; ) { my $c = substr( $reply, $n, 1 ); if ( $c eq ';' ) { $n += 1; printf "%d%s\t%s\n", $count, $error, $result if ( $result ne "" ); $result = ""; $state = 0; $error = "?"; $count++; } elsif ( $c eq '=' ) { $error = "" if ( $count <= $#query_params and &hexified($result) eq $query_params[$count] ); $n += 1; $result .= $c; $state = 1; } elsif ( $c =~ /[[:punct:]]/ ) { $n += 1; $result .= $c; } else { my $k = hex substr( $reply, $n, 2 ); if ( $k == 0x1b ) { $result .= "\\E"; } elsif ( $k == 0x7f ) { $result .= "^?"; } elsif ( $k == 32 ) { $result .= "\\s"; } elsif ( $k < 32 ) { $result .= sprintf( "^%c", $k + 64 ); } elsif ( $k > 128 ) { $result .= sprintf( "\\%03o", $k ); } else { $result .= chr($k); } $n += 2; } } printf "%d%s\t%s\n", $count, $error, $result if ( $result ne "" ); $reply = $parse; } } sub do_query($) { my $name = shift; &begin_query unless ($opt_q); &add_param($name); &finish_query unless ($opt_q); } &begin_query if ($opt_q); while ( $#ARGV >= 0 ) { &do_query( shift @ARGV ); } if ( defined($opt_a) || defined($opt_d) ) { &do_query("disallowedColorOps"); &do_query("disallowedFontOps"); &do_query("disallowedMouseOps"); &do_query("disallowedPasteControls"); &do_query("disallowedTcapOps"); &do_query("disallowedWindowOps"); } if ( defined($opt_a) ) { &do_query("allowSendEvents"); &do_query("allowPasteControls"); &do_query("allowC1Printable"); &do_query("saveLines"); } if ( defined($opt_a) || defined($opt_e) ) { &do_query("allowColorOps"); &do_query("allowFontOps"); &do_query("allowMouseOps"); &do_query("allowPasteControls"); &do_query("allowTcapOps"); &do_query("allowTitleOps"); &do_query("allowWindowOps"); } if ( defined($opt_a) || defined($opt_m) ) { &do_query("formatOtherKeys"); &do_query("modifyCursorKeys"); &do_query("modifyFunctionKeys"); &do_query("modifyKeyboard"); &do_query("modifyOtherKeys"); } &finish_query if ($opt_q); 1; xterm-353/vttests/doublechars.sh0000755000175100001440000000654511671154202015623 0ustar tomusers#!/bin/sh # $XTermId: doublechars.sh,v 1.17 2011/12/11 16:21:22 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 1999-2003,2011 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Illustrate the use of double-size characters by drawing successive lines in # the commonly used video attributes. # # Use the -w option to force the output to wrap. It will look ugly, because # the double-high lines will be split. ESC="" CMD='/bin/echo' OPT='-n' SUF='' TMP=/tmp/xterm$$ eval '$CMD $OPT >$TMP || echo fail >$TMP' 2>/dev/null ( test ! -f $TMP || test -s $TMP ) && for verb in printf print ; do rm -f $TMP eval '$verb "\c" >$TMP || echo fail >$TMP' 2>/dev/null if test -f $TMP ; then if test ! -s $TMP ; then CMD="$verb" OPT= SUF='\c' break fi fi done rm -f $TMP SAVE=yes WRAP=no if test $# != 0 ; then while test $# != 0 do case $1 in -n) SAVE=no ;; -w) WRAP=yes ;; esac shift done fi if test $SAVE = yes ; then exec /dev/tty IFS=';' read junk high wide stty $old wide=`echo $wide|sed -e 's/t.*//'` original=${ESC}[8\;${high}\;${wide}t${SUF} if ( trap "echo exit" EXIT 2>/dev/null ) >/dev/null then trap '$CMD $OPT "$original" >/dev/tty; exit' EXIT HUP INT TRAP TERM else trap '$CMD $OPT "$original" >/dev/tty; exit' 0 1 2 5 15 fi fi if test $WRAP = yes ; then # turn on wrapping and force the screen to 80 columns $CMD $OPT "${ESC}[?7h" >/dev/tty $CMD $OPT "${ESC}[?40l" >/dev/tty else # force the screen to 132 columns $CMD $OPT "${ESC}[?40h" >/dev/tty $CMD $OPT "${ESC}[?3h" >/dev/tty fi for SGR in 0 1 4 5 7 do $CMD $OPT "${ESC}[0;${SGR}m" >/dev/tty for DBL in 5 3 4 6 5 do $CMD $OPT "${ESC}#${DBL}" >/dev/tty echo "The quick brown fox jumps over the lazy dog" >/dev/tty done echo done $CMD $OPT "${ESC}[0m" >/dev/tty xterm-353/vttests/resize.pl0000755000175100001440000000764513041175436014641 0ustar tomusers#!/usr/bin/env perl # $XTermId: resize.pl,v 1.6 2017/01/22 18:34:06 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2004-2014,2017 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # resize.sh rewritten into Perl for comparison. # See also Term::ReadKey. use strict; use warnings; use IO::Handle; sub write_tty { open TTY, "+; close TTY; system "stty $old"; return $reply; } sub csi_field { my $first = $_[0]; my $second = $_[1]; $first =~ s/^[^0-9]+//; while ( --$second > 0 ) { $first =~ s/^[\d]+//; $first =~ s/^[^\d]+//; } $first =~ s/[^\d]+.*$//; return $first; } our $original = get_reply("\x1b[18t"); our $high; our $wide; if ( defined($original) and ( $original =~ /\x1b\[8;\d+;\d+t/ ) ) { $high = csi_field( $original, 2 ); $wide = csi_field( $original, 3 ); printf "parsed terminal size $high,$wide\n"; } else { die "Cannot get current terminal size via escape sequence\n"; } # our $maximize = get_reply("\x1b[19t"); our $maxhigh; our $maxwide; if ( defined($maximize) and ( $maximize =~ /^\x1b\[9;\d+;\d+t/ ) ) { $maxhigh = csi_field( $maximize, 2 ); $maxwide = csi_field( $maximize, 3 ); $maxhigh != 0 or $maxhigh = $high * 2; $maxwide != 0 or $maxwide = $wide * 2; printf "parsed terminal maxsize $maxhigh,$maxwide\n"; } else { die "Cannot get maximum terminal size via escape sequence\n"; } our $zapped; our ( $w, $h, $a ); sub catch_zap { $zapped++; } $SIG{INT} = \&catch_zap; $SIG{QUIT} = \&catch_zap; $SIG{KILL} = \&catch_zap; $SIG{HUP} = \&catch_zap; $SIG{TERM} = \&catch_zap; $w = $wide; $h = $high; $a = 1; $zapped = 0; while ( $zapped == 0 ) { # sleep 1 printf "resizing to $h by $w\n"; write_tty( "\x1b[8;$h;$w" . "t" ); if ( $a == 1 ) { if ( $w == $maxwide ) { $h += $a; if ( $h = $maxhigh ) { $a = -1; } } else { $w += $a; } } else { if ( $w == $wide ) { $h += $a; if ( $h = $high ) { $a = 1; } } else { $w += $a; } } } write_tty($original); xterm-353/vttests/256colors2.pl0000755000175100001440000001441613333324506015150 0ustar tomusers#!/usr/bin/env perl # $XTermId: 256colors2.pl,v 1.24 2018/08/10 15:03:34 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 1999-2016,2018 by Thomas E. Dickey # Copyright 2002 by Steve Wall # Copyright 1999 by Todd Larason # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # # If -s is not given, use the resources for colors 0-15 - usually more-or-less # a reproduction of the standard ANSI colors, but possibly more pleasing # shades. use strict; use warnings; use Getopt::Std; use Encode 'encode_utf8'; our ( $opt_8, $opt_c, $opt_d, $opt_h, $opt_q, $opt_r, $opt_s, $opt_u ); $Getopt::Std::STANDARD_HELP_VERSION = 1; &getopts('8cdhqrsu') || die("Usage: $0 [options]"); die( "Usage: $0 [options]\n Options: -8 use 8-bit controls -c use colons for separating parameter values in SGR 38/48 -d use rgb values rather than palette index -h display this message -q quieter output by merging all palette initialization -r display the reverse of the usual palette -s modify system colors, i.e., 0..15 -u use UTF-8 when emitting 8-bit controls " ) if ($opt_h); our $cube = 6; our (@steps); our ( $red, $green, $blue ); our ( $gray, $level, $color ); our ( $csi, $osc, $sep, $st ); our @rgb; sub map_cube($) { my $value = $_[0]; $value = ( 5 - $value ) if defined($opt_r); return $value; } sub map_gray($) { my $value = $_[0]; $value = ( 23 - $value ) if defined($opt_r); return $value; } sub define_color($$$$) { my $index = $_[0]; my $r = $_[1]; my $g = $_[2]; my $b = $_[3]; printf( "%s4", $osc ) unless ($opt_q); printf( ";%d;rgb:%2.2x/%2.2x/%2.2x", $index, $r, $g, $b ); printf( "%s", $st ) unless ($opt_q); $rgb[$index] = sprintf "%d%s%d%s%d", $r, $sep, $g, $sep, $b; } sub select_color($) { my $index = $_[0]; if ( $opt_d and defined( $rgb[$index] ) ) { printf "%s48;2%s%sm ", $csi, $sep, $rgb[$index]; } else { printf "%s48;5%s%sm ", $csi, $sep, $index; } } sub system_color($$$$) { my $color = shift; my $red = shift; my $green = shift; my $blue = shift; &define_color( 15 - $color, $red, $green, $blue ) if ($opt_r); &define_color( $color, $red, $green, $blue ) unless ($opt_r); } if ($opt_8) { $csi = "\x9b"; $osc = "\x9d"; $st = "\x9c"; } else { $csi = "\x1b["; $osc = "\x1b]"; $st = "\x1b\\"; } if ($opt_c) { $sep = ":"; } else { $sep = ";"; } if ( $opt_8 and $opt_u ) { my $lc_ctype = `locale 2>/dev/null | fgrep LC_CTYPE | sed -e 's/^.*=//'`; if ( $lc_ctype =~ /utf.?8/i ) { binmode( STDOUT, ":utf8" ); } } printf( "%s4", $osc ) if ($opt_q); if ($opt_s) { &system_color( 0, 0, 0, 0 ); &system_color( 1, 205, 0, 0 ); &system_color( 2, 0, 205, 0 ); &system_color( 3, 205, 205, 0 ); &system_color( 4, 0, 0, 238 ); &system_color( 5, 205, 0, 205 ); &system_color( 6, 0, 205, 205 ); &system_color( 7, 229, 229, 229 ); &system_color( 8, 127, 127, 127 ); &system_color( 9, 255, 0, 0 ); &system_color( 10, 0, 255, 0 ); &system_color( 11, 255, 255, 0 ); &system_color( 12, 92, 92, 255 ); &system_color( 13, 255, 0, 255 ); &system_color( 14, 0, 255, 255 ); &system_color( 15, 255, 255, 255 ); } # colors 16-231 are a 6x6x6 color cube @steps = ( 0, 95, 135, 175, 215, 255 ); for ( $red = 0 ; $red < $cube ; $red++ ) { for ( $green = 0 ; $green < $cube ; $green++ ) { for ( $blue = 0 ; $blue < $cube ; $blue++ ) { &define_color( 16 + ( map_cube($red) * $cube * $cube ) + ( map_cube($green) * $cube ) + map_cube($blue), int( $steps[$red] ), int( $steps[$green] ), int( $steps[$blue] ) ); } } } # colors 232-255 are a grayscale ramp, intentionally leaving out # black and white for ( $gray = 0 ; $gray < 24 ; $gray++ ) { $level = ( map_gray($gray) * 10 ) + 8; &define_color( 232 + $gray, $level, $level, $level ); } printf( "%s", $st ) if ($opt_q); # display the colors # first the system ones: print "System colors:\n"; for ( $color = 0 ; $color < 8 ; $color++ ) { &select_color($color); } printf "%s0m\n", $csi; for ( $color = 8 ; $color < 16 ; $color++ ) { &select_color($color); } printf "%s0m\n\n", $csi; # now the color cube print "Color cube, ${cube}x${cube}x${cube}:\n"; for ( $green = 0 ; $green < $cube ; $green++ ) { for ( $red = 0 ; $red < $cube ; $red++ ) { for ( $blue = 0 ; $blue < $cube ; $blue++ ) { $color = 16 + ( $red * $cube * $cube ) + ( $green * $cube ) + $blue; &select_color($color); } printf "%s0m ", $csi; } print "\n"; } # now the grayscale ramp print "Grayscale ramp:\n"; for ( $color = 232 ; $color < 256 ; $color++ ) { &select_color($color); } printf "%s0m\n", $csi; xterm-353/vttests/other-sgr.sh0000755000175100001440000001002613346313362015234 0ustar tomusers#!/bin/sh # $XTermId: other-sgr.sh,v 1.1 2018/09/12 22:45:06 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2018 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Show non-VTxx SGRs combined with the conventional VT100/VT220 SGRs ESC="" CMD='/bin/echo' OPT='-n' SUF='' TMP=/tmp/xterm$$ eval '$CMD $OPT >$TMP || echo fail >$TMP' 2>/dev/null ( test ! -f $TMP || test -s $TMP ) && for verb in printf print ; do rm -f $TMP eval '$verb "\c" >$TMP || echo fail >$TMP' 2>/dev/null if test -f $TMP ; then if test ! -s $TMP ; then CMD="$verb" OPT= SUF='\c' break fi fi done rm -f $TMP if ( trap "echo exit" EXIT 2>/dev/null ) >/dev/null then trap '$CMD $OPT ""; exit' EXIT HUP INT TRAP TERM else trap '$CMD $OPT ""; exit' 0 1 2 5 15 fi echo "" while true do # blink(5) and conceal(8) are omitted because they are distracting, but the # case-statement handles those if the for-statement includes them. for GRP in 0 1 4 7 do case $GRP in 0) attr="normal ";; 1) attr="bold ";; 4) attr="under ";; 5) attr="blink ";; 7) attr="reverse ";; 8) attr="conceal ";; esac for NUL in "0" "21" do for ROW in $NUL "2" "3" "9" "2;3" "2;9" "3;9" "2;3;9" do case $ROW in "0") rlabel="normal ";; "21") rlabel="double ";; "2") rlabel="dim ";; "3") rlabel="italic ";; "2;3") rlabel="di/it ";; "9") rlabel="crossout";; "2;9") rlabel="di/cr ";; "3;9") rlabel="it/cr ";; "2;3;9") rlabel="di/it/cr";; *) rlabel="UNKNOWN ";; esac # video attributes from the first two columns intentionally # "bleed through" to the other columns to help show some of # the possible combinations of attributes. $CMD $OPT "$GRP:[${GRP}m$attr" $CMD $OPT "[${ROW}m$rlabel" for COL in $NUL "3" "9" "2;3" "2;9" "3;9" "2;3;9" do END="" case $COL in "0") clabel="normal ";; "21") clabel="double "; END="";; "2") clabel="dim "; END="";; "3") clabel="italic "; END="";; "2;3") clabel="di/it "; END="";; "9") clabel="crossout"; END="";; "2;9") clabel="di/cr "; END="";; "3;9") clabel="it/cr "; END="";; "2;3;9") clabel="di/it/cr"; END="";; *) clabel="UNKNOWN ";; esac # The remaining columns (try to) reset their respective # attribute, to make the result somewhat readable. $CMD $OPT "[${COL}m$clabel${END}" done echo ":$GRP" done done [ -t 1 ] && sleep 3 done [ -t 1 ] || break done xterm-353/vttests/print-vt-chars.pl0000755000175100001440000002541713610650270016212 0ustar tomusers#!/usr/bin/perl -w # $Id: print-vt-chars.pl,v 1.22 2020/01/18 18:38:48 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2018,2020 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Print GL and GR, with the same charset (if possible) for testing. use strict; use warnings; use diagnostics; $| = 2; use Getopt::Std; our ( $opt_L, $opt_l, $opt_R, $opt_r, $opt_v ); our %charsets; our %caseless; our $vt_level; binmode STDOUT; sub NRC($) { printf "\033[?42%s", $_[0] ? "h" : "l"; } sub LS0($) { printf "\017"; } sub LS1() { printf "\016"; } sub LS1R() { printf "\033~"; } sub LS2() { printf "\033n"; } sub LS2R() { printf "\033}"; } sub LS3() { printf "\033o"; } sub LS3R($) { printf "\033|"; } sub G0($) { my %charset = %{ $_[0] }; printf "\033(%s", $charset{TAG} if ( $charset{HOW} == 0 ); } sub G1($) { my %charset = %{ $_[0] }; printf "\033)%s", $charset{TAG} if ( $charset{HOW} == 0 ); printf "\033-%s", $charset{TAG} if ( $charset{HOW} == 1 ); } sub G2($) { my %charset = %{ $_[0] }; printf "\033*%s", $charset{TAG} if ( $charset{HOW} == 0 ); printf "\033.%s", $charset{TAG} if ( $charset{HOW} == 1 ); } sub G3($) { my %charset = %{ $_[0] }; printf "\033+%s", $charset{TAG} if ( $charset{HOW} == 0 ); printf "\033/%s", $charset{TAG} if ( $charset{HOW} == 1 ); } sub init_charset($$$$$$) { my %charset; my $mixed = shift; $charset{WHO} = $mixed; $charset{HOW} = shift; $charset{TAG} = shift; $charset{MIN} = shift; $charset{MAX} = shift; $charset{NRC} = shift; $charsets{$mixed} = \%charset; my $lower = lc $charset{WHO}; $caseless{$lower} = $charset{WHO}; } sub find_charset($) { my $mixed = shift; my $lower = lc $mixed; my %result; if ( $caseless{$lower} ) { $mixed = $caseless{$lower}; %result = %{ $charsets{$mixed} }; undef %result if ( $result{MAX} < $vt_level or $result{MIN} > $vt_level ); } printf STDERR "? no match for $mixed with VT-level $vt_level\n" unless %result; return \%result; } sub failed($) { my $msg = shift; printf STDERR "? %s\n", $msg; exit 1; } sub valid_code($) { my $code = shift; my $result = 0; $result = 1 if ( $code =~ /^[0-3]$/ ); return $result; } sub valid_name($) { my $mixed = shift; my $lower = lc $mixed; my $result = 0; $result = 1 if ( defined( $caseless{$lower} ) ); return $result; } sub setup_charsets($$$$) { my $gl_code = shift; my $gl_name = shift; my $gr_code = shift; my $gr_name = shift; my %gl_data = %{ &find_charset($gl_name) }; my %gr_data = %{ &find_charset($gr_name) }; return 0 unless %gl_data; return 0 unless %gr_data; &NRC(1) if ( $gl_data{NRC} or $gr_data{NRC} ); if ( $gl_code == 0 ) { &G0( \%gl_data ); &LS0; } elsif ( $gl_code == 1 ) { &G1( \%gl_data ); &LS1; } elsif ( $gl_code == 2 ) { &G2( \%gl_data ); &LS2; } elsif ( $gl_code == 3 ) { &G3( \%gl_data ); &LS3; } if ( $gr_code == 0 ) { &G0( \%gr_data ); } elsif ( $gr_code == 1 ) { &G1( \%gr_data ); &LS1R; } elsif ( $gr_code == 2 ) { &G2( \%gr_data ); &LS2R; } elsif ( $gr_code == 3 ) { &G3( \%gr_data ); &LS3R; } return 1; } sub cleanup() { &setup_charsets( 0, "ASCII", 1, "ASCII" ); &NRC(0); } sub doit($$$$) { my $gl_code = shift; my $gl_name = shift; my $gr_code = shift; my $gr_name = shift; &failed("Illegal left-code $gl_code") unless &valid_code($gl_code); &failed("Illegal right-code $gr_code") unless &valid_code($gr_code); &failed("Unknown left-charset $gl_name") unless &valid_name($gl_name); &failed("Unknown right charset $gr_name") unless &valid_name($gr_name); printf "GL (G%d %s):\n", $gl_code, $gl_name; if ( &setup_charsets( $gl_code, $gl_name, $gr_code, $gr_name ) ) { for my $c ( 32 .. 127 ) { printf "%c", $c; printf "\n" if ( ( ( $c - 31 ) % 16 ) == 0 ); } printf "\n"; &cleanup; } printf "GR (G%d %s):\n", $gr_code, $gr_name; if ( &setup_charsets( $gl_code, $gl_name, $gr_code, $gr_name ) ) { for my $c ( 32 .. 127 ) { printf "%c", $c + 128; printf "\n" if ( ( ( $c - 31 ) % 16 ) == 0 ); } printf "\n"; &cleanup; } } sub main::HELP_MESSAGE() { printf STDERR < $vt_level ); $known[ ++$known ] = $key; $width = length($key) if ( length($key) > $width ); } $width += 3; my $cols = int( 78 / $width ); my $high = int( ( $known + $cols ) / $cols ); for my $y ( 0 .. $high - 1 ) { printf STDERR " "; for my $x ( 0 .. $cols - 1 ) { my $z = $x * $high + $y; next if ( $z > $known ); printf STDERR "%-*s", $width, $known[$z]; } printf STDERR "\n"; } exit 1; } &init_charset( "ASCII", 0, 'B', 1, 9, 0 ); &init_charset( "British", 0, 'A', 1, 9, 0 ); &init_charset( "DEC_Spec_Graphic", 0, '0', 1, 9, 0 ); &init_charset( "DEC_Alt_Chars", 0, '1', 1, 1, 0 ); &init_charset( "DEC_Alt_Graphics", 0, '2', 1, 1, 0 ); &init_charset( "DEC_Supp", 0, '<', 2, 9, 0 ); &init_charset( "Dutch", 0, '4', 2, 9, 1 ); &init_charset( "Finnish", 0, '5', 2, 9, 1 ); &init_charset( "Finnish2", 0, 'C', 2, 9, 1 ); &init_charset( "French", 0, 'R', 2, 9, 1 ); &init_charset( "French2", 0, 'f', 2, 9, 1 ); &init_charset( "French_Canadian", 0, 'Q', 2, 9, 1 ); &init_charset( "German", 0, 'K', 2, 9, 1 ); &init_charset( "Italian", 0, 'Y', 2, 9, 1 ); &init_charset( "Norwegian_Danish2", 0, 'E', 2, 9, 1 ); &init_charset( "Norwegian_Danish3", 0, '6', 2, 9, 1 ); &init_charset( "Spanish", 0, 'Z', 2, 9, 1 ); &init_charset( "Swedish", 0, '7', 2, 9, 1 ); &init_charset( "Swedish2", 0, 'H', 2, 9, 1 ); &init_charset( "Swiss", 0, '=', 2, 9, 1 ); &init_charset( "British_Latin_1", 0, 'A', 3, 9, 1 ); &init_charset( "DEC_Supp_Graphic", 0, '%5', 3, 9, 0 ); &init_charset( "DEC_Technical", 0, '>', 3, 9, 0 ); &init_charset( "French_Canadian2", 0, '9', 3, 9, 1 ); &init_charset( "Norwegian_Danish", 0, '`', 3, 9, 1 ); &init_charset( "Portuguese", 0, '%6', 3, 9, 1 ); &init_charset( "ISO_Greek_Supp", 1, 'F', 5, 9, 0 ); &init_charset( "ISO_Hebrew_Supp", 1, 'H', 5, 9, 0 ); &init_charset( "ISO_Latin_5_Supp", 1, 'M', 5, 9, 0 ); &init_charset( "ISO_Latin_Cyrillic", 1, 'L', 5, 9, 0 ); &init_charset( "Greek", 0, '">', 5, 9, 1 ); &init_charset( "DEC_Greek", 0, '"?', 5, 9, 1 ); &init_charset( "Cyrillic", 0, '&4', 5, 9, 0 ); &init_charset( "DEC_Hebrew", 0, '"4', 5, 9, 0 ); &init_charset( "Hebrew", 0, '%=', 5, 9, 1 ); &init_charset( "Russian", 0, '&5', 5, 9, 1 ); &init_charset( "SCS_NRCS", 0, '%3', 5, 9, 0 ); &init_charset( "Turkish", 0, '%2', 5, 9, 1 ); &init_charset( "DEC_Turkish", 0, '%0', 5, 9, 0 ); $vt_level = 1; # don't expect much if ( -t 0 and -t 1 ) { my $da2 = ` old=\$(stty -g); stty raw -echo min 0 time 5; printf '\033[>c' >/dev/tty; read response; stty \$old; echo "\$response"`; if ( $da2 =~ /^\033\[>\d+;\d+;\d+c$/ ) { my $Pp = $da2; $Pp =~ s/^.*>//; $Pp =~ s/;.*$//; if ( $Pp == 0 ) { $vt_level = 1; } elsif ( $Pp == 1 or $Pp == 2 ) { $vt_level = 2; } elsif ( $Pp == 18 or $Pp == 19 or $Pp == 24 ) { $vt_level = 3; } elsif ( $Pp == 41 ) { $vt_level = 4; } elsif ( $Pp == 61 or $Pp == 64 or $Pp == 65 ) { $vt_level = 5; } } } $Getopt::Std::STANDARD_HELP_VERSION = 1; &getopts('L:l:R:r:v:') || main::HELP_MESSAGE; $vt_level = $opt_v if ( defined $opt_v ); &failed("VT-level must be 1-5") if ( $vt_level < 1 or $vt_level > 5 ); if ( $#ARGV >= 0 ) { while ( $#ARGV >= 0 ) { my $name = shift @ARGV; &doit( defined($opt_L) ? $opt_L : 2, # defined($opt_l) ? $opt_l : $name, # defined($opt_R) ? $opt_R : 3, # defined($opt_r) ? $opt_r : $name ); last if ( defined($opt_L) # and defined($opt_l) # and defined($opt_R) # and defined($opt_r) ); } } else { &doit( defined($opt_L) ? $opt_L : 2, # defined($opt_l) ? $opt_l : "ASCII", # defined($opt_R) ? $opt_R : 3, # defined($opt_r) ? $opt_r : "ASCII" ); } 1; xterm-353/vttests/query-status.pl0000755000175100001440000001062013470215205016004 0ustar tomusers#!/usr/bin/env perl # $XTermId: query-status.pl,v 1.7 2019/05/19 08:57:41 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2017-2018,2019 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Test the status features of xterm using DECRQSS. # # TODO: use Term::ReadKey rather than system/stty use strict; use warnings; use Getopt::Std; use IO::Handle; our ($opt_8); $Getopt::Std::STANDARD_HELP_VERSION = 1; &getopts('8') || die( "Usage: $0 [options]\n Options:\n -8 use 8-bit controls Options which use C1 controls may not work with UTF-8. " ); our $ST = $opt_8 ? "\x9c" : "\x1b\\"; our %suffixes; $suffixes{DECSCA} = '"q'; $suffixes{DECSCL} = '"p'; $suffixes{DECSTBM} = 'r'; $suffixes{DECSLRM} = 's'; $suffixes{SGR} = 'm'; $suffixes{DECSCUSR} = ' q'; sub get_reply($) { open TTY, "+; close TTY; system "stty $old"; if ( defined $reply ) { die("^C received\n") if ( "$reply" eq "\003" ); } return $reply; } sub visible($) { my $reply = $_[0]; my $n; my $result = ""; for ( $n = 0 ; $n < length($reply) ; ) { my $c = substr( $reply, $n, 1 ); if ( $c =~ /[[:print:]]/ ) { $result .= $c; } else { my $k = ord substr( $reply, $n, 1 ); if ( ord $k == 0x1b ) { $result .= "\\E"; } elsif ( $k == 0x7f ) { $result .= "^?"; } elsif ( $k == 32 ) { $result .= "\\s"; } elsif ( $k < 32 ) { $result .= sprintf( "^%c", $k + 64 ); } elsif ( $k > 128 ) { $result .= sprintf( "\\%03o", $k ); } else { $result .= chr($k); } } $n += 1; } return $result; } sub query_one($) { my $name = shift; my $suffix = $suffixes{$name}; my $prefix = $opt_8 ? "\x90" : "\x1bP"; my $reply; my $n; my $st = $opt_8 ? "\x9c" : qr/\x1b\\/; my $DCS = qr/${prefix}/; my $match = qr/${DCS}.*${st}/; $reply = get_reply( $prefix . '$q' . $suffix . $ST ); printf "%-10s query{%s}%*s", $name, # &visible($suffix), # 4 - length($suffix), " "; if ( defined $reply ) { printf "%2d ", length($reply); if ( $reply =~ /${match}/ ) { $reply =~ s/^${DCS}//; $reply =~ s/^;//; $reply =~ s/${st}$//; } else { printf "? "; } printf "{%s}", visible($reply); } printf "\n"; } printf "\x1b G" if ($opt_8); if ( $#ARGV >= 0 ) { while ( $#ARGV >= 0 ) { &query_one( shift @ARGV ); } } else { for my $key ( sort keys %suffixes ) { &query_one($key); } } printf "\x1b F" if ($opt_8); xterm-353/vttests/fonts.sh0000755000175100001440000000514512562206331014455 0ustar tomusers#!/bin/sh # $XTermId: fonts.sh,v 1.12 2015/08/10 20:43:05 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 1999-2011,2015 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Demonstrate control sequence which sets relative fonts. ESC="" CMD='/bin/echo' OPT='-n' SUF='' TMP=/tmp/xterm$$ eval '$CMD $OPT >$TMP || echo fail >$TMP' 2>/dev/null ( test ! -f $TMP || test -s $TMP ) && for verb in printf print ; do rm -f $TMP eval '$verb "\c" >$TMP || echo fail >$TMP' 2>/dev/null if test -f $TMP ; then if test ! -s $TMP ; then CMD="$verb" OPT= SUF='\c' break fi fi done rm -f $TMP exec /dev/tty read original stty $old original="${original}${SUF}" if ( trap "echo exit" EXIT 2>/dev/null ) >/dev/null then trap '$CMD $OPT "$original" >/dev/tty; exit' EXIT HUP INT TRAP TERM else trap '$CMD $OPT "$original" >/dev/tty; exit' 0 1 2 5 15 fi F=1 D=1 T=6 while true do $CMD $OPT "${ESC}]50;#$F${SUF}" >/dev/tty #sleep 1 if test .$D = .1 ; then test $F = $T && D=-1 else test $F = 1 && D=1 fi F=`expr $F + $D` done xterm-353/vttests/dynamic.pl0000755000175100001440000000710513333324317014751 0ustar tomusers#!/usr/bin/env perl # $XTermId: dynamic.pl,v 1.5 2018/08/10 15:01:35 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2011-2017,2018 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Test the dynamic-color query option of xterm. # The programs xtermcontrol and xtermset provide more options. use strict; use warnings; use Getopt::Std; use IO::Handle; our @color_names = ( "VT100 text foreground", "VT100 text background", "text cursor", "mouse foreground", "mouse background", "Tektronix foreground", "Tektronix background", "highlight background", "Tektronix cursor", "highlight foreground" ); our ( $opt_c, $opt_r ); $Getopt::Std::STANDARD_HELP_VERSION = 1; &getopts('c:r') || die( "Usage: $0 [options]\n Options:\n -c XXX set cursor-color -r reset colors " ); sub no_reply($) { open TTY, "+; close TTY; system "stty $old"; if ( defined $reply ) { die("^C received\n") if ( "$reply" eq "\003" ); } return $reply; } sub query_color($) { my $code = $_[0]; my $param1 = $code + 10; my $reply; $reply = get_reply("\x1b]$param1;?\007"); return unless defined $reply; if ( $reply =~ /\x1b]$param1;.*\007/ ) { my $value = $reply; $value =~ s/^\x1b]$param1;//; $value =~ s/\007//; printf "%24s = %s\n", $color_names[$code], $value; } } sub query_colors() { my $n; for ( $n = 0 ; $n <= 9 ; ++$n ) { &query_color($n); } } sub reset_colors() { my $n; for ( $n = 0 ; $n <= 9 ; ++$n ) { my $code = 110 + $n; &no_reply("\x1b]$code\007"); } } if ( defined($opt_c) ) { &no_reply("\x1b]12;$opt_c\007"); } if ( defined($opt_r) ) { &reset_colors(); } &query_colors(); xterm-353/vttests/query-fonts.pl0000755000175100001440000001066413470215173015626 0ustar tomusers#!/usr/bin/env perl # $XTermId: query-fonts.pl,v 1.8 2019/05/19 08:57:31 tom Exp $ # ----------------------------------------------------------------------------- # this file is part of xterm # # Copyright 2010-2018,2019 by Thomas E. Dickey # # All Rights Reserved # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the # "Software"), to deal in the Software without restriction, including # without limitation the rights to use, copy, modify, merge, publish, # distribute, sublicense, and/or sell copies of the Software, and to # permit persons to whom the Software is furnished to do so, subject to # the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. # # Except as contained in this notice, the name(s) of the above copyright # holders shall not be used in advertising or otherwise to promote the # sale, use or other dealings in this Software without prior written # authorization. # ----------------------------------------------------------------------------- # Test the font-query features of xterm. # TODO: # test relative vs absolute font numbering # test all font-slots # test selection # test bold / wide / widebold # test actual fontname vs nominal # extend "CSI > Ps; Ps T" to query fontname in hex use strict; use warnings; use Getopt::Std; use IO::Handle; our ( $opt_a, $opt_r, $opt_s ); $Getopt::Std::STANDARD_HELP_VERSION = 1; &getopts('ars') || die( "Usage: $0 [options]\n Options:\n -a test using absolute numbers -r test using relative numbers -s use ^G rather than ST " ); our $ST = $opt_s ? "\007" : "\x1b\\"; sub get_reply($) { open TTY, "+; close TTY; system "stty $old"; if ( defined $reply ) { die("^C received\n") if ( "$reply" eq "\003" ); } return $reply; } sub query_font($) { my $param = $_[0]; my $reply; my $n; my $st = $opt_s ? qr/\007/ : qr/\x1b\\/; my $osc = qr/\x1b]50/; my $match = qr/${osc}.*${st}/; $reply = get_reply( "\x1b]50;?" . $param . $ST ); printf "query{%s}%*s", $param, 3 - length($param), " "; if ( defined $reply ) { printf "%2d ", length($reply); if ( $reply =~ /${match}/ ) { $reply =~ s/^${osc}//; $reply =~ s/^;//; $reply =~ s/${st}$//; } else { printf "? "; } my $result = ""; for ( $n = 0 ; $n < length($reply) ; ) { my $c = substr( $reply, $n, 1 ); if ( $c =~ /[[:print:]]/ ) { $result .= $c; } else { my $k = ord substr( $reply, $n, 1 ); if ( ord $k == 0x1b ) { $result .= "\\E"; } elsif ( $k == 0x7f ) { $result .= "^?"; } elsif ( $k == 32 ) { $result .= "\\s"; } elsif ( $k < 32 ) { $result .= sprintf( "^%c", $k + 64 ); } elsif ( $k > 128 ) { $result .= sprintf( "\\%03o", $k ); } else { $result .= chr($k); } } $n += 1; } printf "{%s}", $result; } printf "\n"; } if ($opt_r) { my $n; query_font("-"); foreach $n ( 0 .. 5 ) { query_font( sprintf "-%d", $n ); } query_font("+"); foreach $n ( 0 .. 5 ) { query_font( sprintf "+%d", $n ); } } if ($opt_a) { my $n; foreach $n ( 0 .. 5 ) { query_font( sprintf "%d", $n ); } } if ( not $opt_a and not $opt_r ) { query_font(""); } xterm-353/misc.c0000644000175100001440000051546013615275307012367 0ustar tomusers/* $XTermId: misc.c,v 1.926 2020/02/01 13:19:03 Jimmy.Aguilar.Mena Exp $ */ /* * Copyright 1999-2019,2020 by Thomas E. Dickey * * All Rights Reserved * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name(s) of the above copyright * holders shall not be used in advertising or otherwise to promote the * sale, use or other dealings in this Software without prior written * authorization. * * * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. * * All Rights Reserved * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, * provided that the above copyright notice appear in all copies and that * both that copyright notice and this permission notice appear in * supporting documentation, and that the name of Digital Equipment * Corporation not be used in advertising or publicity pertaining to * distribution of the software without specific, written prior permission. * * * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if HAVE_X11_SUNKEYSYM_H #include #endif #ifdef HAVE_LIBXPM #include #endif #ifdef HAVE_LANGINFO_CODESET #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifdef VMS #define XTERM_VMS_LOGFILE "SYS$SCRATCH:XTERM_LOG.TXT" #ifdef ALLOWLOGFILEEXEC #undef ALLOWLOGFILEEXEC #endif #endif /* VMS */ #if USE_DOUBLE_BUFFER #include #endif #if OPT_WIDE_CHARS #include #endif #if OPT_TEK4014 #define OUR_EVENT(event,Type) \ (event.type == Type && \ (event.xcrossing.window == XtWindow(XtParent(xw)) || \ (tekWidget && \ event.xcrossing.window == XtWindow(XtParent(tekWidget))))) #else #define OUR_EVENT(event,Type) \ (event.type == Type && \ (event.xcrossing.window == XtWindow(XtParent(xw)))) #endif #define VB_DELAY screen->visualBellDelay #define EVENT_DELAY TScreenOf(term)->nextEventDelay static Boolean xtermAllocColor(XtermWidget, XColor *, const char *); static Cursor make_hidden_cursor(XtermWidget); static char emptyString[] = ""; #if OPT_EXEC_XTERM /* Like readlink(2), but returns a malloc()ed buffer, or NULL on error; adapted from libc docs */ static char * Readlink(const char *filename) { char *buf = NULL; size_t size = 100; for (;;) { int n; char *tmp = TypeRealloc(char, size, buf); if (tmp == NULL) { free(buf); return NULL; } buf = tmp; memset(buf, 0, size); n = (int) readlink(filename, buf, size); if (n < 0) { free(buf); return NULL; } if ((unsigned) n < size) { return buf; } size *= 2; } } #endif /* OPT_EXEC_XTERM */ static void Sleep(int msec) { static struct timeval select_timeout; select_timeout.tv_sec = 0; select_timeout.tv_usec = msec * 1000; select(0, 0, 0, 0, &select_timeout); } static void selectwindow(XtermWidget xw, int flag) { TScreen *screen = TScreenOf(xw); TRACE(("selectwindow(%d) flag=%d\n", screen->select, flag)); #if OPT_TEK4014 if (TEK4014_ACTIVE(xw)) { if (!Ttoggled) TCursorToggle(tekWidget, TOGGLE); screen->select |= flag; if (!Ttoggled) TCursorToggle(tekWidget, TOGGLE); } else #endif { #if OPT_INPUT_METHOD TInput *input = lookupTInput(xw, (Widget) xw); if (input && input->xic) XSetICFocus(input->xic); #endif if (screen->cursor_state && CursorMoved(screen)) HideCursor(); screen->select |= flag; if (screen->cursor_state) ShowCursor(); } GetScrollLock(screen); } static void unselectwindow(XtermWidget xw, int flag) { TScreen *screen = TScreenOf(xw); TRACE(("unselectwindow(%d) flag=%d\n", screen->select, flag)); if (screen->hide_pointer && screen->pointer_mode < pFocused) { screen->hide_pointer = False; xtermDisplayCursor(xw); } if (!screen->always_highlight) { #if OPT_TEK4014 if (TEK4014_ACTIVE(xw)) { if (!Ttoggled) TCursorToggle(tekWidget, TOGGLE); screen->select &= ~flag; if (!Ttoggled) TCursorToggle(tekWidget, TOGGLE); } else #endif { #if OPT_INPUT_METHOD TInput *input = lookupTInput(xw, (Widget) xw); if (input && input->xic) XUnsetICFocus(input->xic); #endif screen->select &= ~flag; if (screen->cursor_state && CursorMoved(screen)) HideCursor(); if (screen->cursor_state) ShowCursor(); } } } static void DoSpecialEnterNotify(XtermWidget xw, XEnterWindowEvent *ev) { TScreen *screen = TScreenOf(xw); TRACE(("DoSpecialEnterNotify(%d)\n", screen->select)); TRACE_FOCUS(xw, ev); if (((ev->detail) != NotifyInferior) && ev->focus && !(screen->select & FOCUS)) selectwindow(xw, INWINDOW); } static void DoSpecialLeaveNotify(XtermWidget xw, XEnterWindowEvent *ev) { TScreen *screen = TScreenOf(xw); TRACE(("DoSpecialLeaveNotify(%d)\n", screen->select)); TRACE_FOCUS(xw, ev); if (((ev->detail) != NotifyInferior) && ev->focus && !(screen->select & FOCUS)) unselectwindow(xw, INWINDOW); } #ifndef XUrgencyHint #define XUrgencyHint (1L << 8) /* X11R5 does not define */ #endif static void setXUrgency(XtermWidget xw, Bool enable) { TScreen *screen = TScreenOf(xw); if (screen->bellIsUrgent) { XWMHints *h = XGetWMHints(screen->display, VShellWindow(xw)); if (h != 0) { if (enable && !(screen->select & FOCUS)) { h->flags |= XUrgencyHint; } else { h->flags &= ~XUrgencyHint; } XSetWMHints(screen->display, VShellWindow(xw), h); } } } void do_xevents(XtermWidget xw) { TScreen *screen = TScreenOf(xw); if (xtermAppPending() || #if defined(VMS) || defined(__VMS) screen->display->qlen > 0 #else GetBytesAvailable(ConnectionNumber(screen->display)) > 0 #endif ) xevents(xw); } void xtermDisplayCursor(XtermWidget xw) { TScreen *screen = TScreenOf(xw); if (screen->Vshow) { if (screen->hide_pointer) { TRACE(("Display hidden_cursor\n")); XDefineCursor(screen->display, VWindow(screen), screen->hidden_cursor); } else { TRACE(("Display pointer_cursor\n")); recolor_cursor(screen, screen->pointer_cursor, T_COLOR(screen, MOUSE_FG), T_COLOR(screen, MOUSE_BG)); XDefineCursor(screen->display, VWindow(screen), screen->pointer_cursor); } } } void xtermShowPointer(XtermWidget xw, Bool enable) { static int tried = -1; TScreen *screen = TScreenOf(xw); #if OPT_TEK4014 if (TEK4014_SHOWN(xw)) enable = True; #endif /* * Whether we actually hide the pointer depends on the pointer-mode and * the mouse-mode: */ if (!enable) { switch (screen->pointer_mode) { case pNever: enable = True; break; case pNoMouse: if (screen->send_mouse_pos != MOUSE_OFF) enable = True; break; case pAlways: case pFocused: break; } } if (enable) { if (screen->hide_pointer) { screen->hide_pointer = False; xtermDisplayCursor(xw); switch (screen->send_mouse_pos) { case ANY_EVENT_MOUSE: break; default: MotionOff(screen, xw); break; } } } else if (!(screen->hide_pointer) && (tried <= 0)) { if (screen->hidden_cursor == 0) { screen->hidden_cursor = make_hidden_cursor(xw); } if (screen->hidden_cursor == 0) { tried = 1; } else { tried = 0; screen->hide_pointer = True; xtermDisplayCursor(xw); MotionOn(screen, xw); } } } /* true if p contains q */ #define ExposeContains(p,q) \ ((p)->y <= (q)->y \ && (p)->x <= (q)->x \ && ((p)->y + (p)->height) >= ((q)->y + (q)->height) \ && ((p)->x + (p)->width) >= ((q)->x + (q)->width)) static XtInputMask mergeExposeEvents(XEvent *target) { XEvent next_event; XExposeEvent *p; XtAppNextEvent(app_con, target); p = (XExposeEvent *) target; while (XtAppPending(app_con) && XtAppPeekEvent(app_con, &next_event) && next_event.type == Expose) { Boolean merge_this = False; XExposeEvent *q = (XExposeEvent *) (&next_event); XtAppNextEvent(app_con, &next_event); TRACE_EVENT("pending", &next_event, (String *) 0, 0); /* * If either window is contained within the other, merge the events. * The traces show that there are also cases where a full repaint of * a window is broken into 3 or more rectangles, which do not arrive * in the same instant. We could merge those if xterm were modified * to skim several events ahead. */ if (p->window == q->window) { if (ExposeContains(p, q)) { TRACE(("pending Expose...merged forward\n")); merge_this = True; next_event = *target; } else if (ExposeContains(q, p)) { TRACE(("pending Expose...merged backward\n")); merge_this = True; } } if (!merge_this) { XtDispatchEvent(target); } *target = next_event; } XtDispatchEvent(target); return XtAppPending(app_con); } /* * On entry, we have peeked at the event queue and see a configure-notify * event. Remove that from the queue so we can look further. * * Then, as long as there is a configure-notify event in the queue, remove * that. If the adjacent events are for different windows, process the older * event and update the event used for comparing windows. If they are for the * same window, only the newer event is of interest. * * Finally, process the (remaining) configure-notify event. */ static XtInputMask mergeConfigureEvents(XEvent *target) { XEvent next_event; XConfigureEvent *p; XtAppNextEvent(app_con, target); p = (XConfigureEvent *) target; if (XtAppPending(app_con) && XtAppPeekEvent(app_con, &next_event) && next_event.type == ConfigureNotify) { Boolean merge_this = False; XConfigureEvent *q = (XConfigureEvent *) (&next_event); XtAppNextEvent(app_con, &next_event); TRACE_EVENT("pending", &next_event, (String *) 0, 0); if (p->window == q->window) { TRACE(("pending Configure...merged\n")); merge_this = True; } if (!merge_this) { TRACE(("pending Configure...skipped\n")); XtDispatchEvent(target); } *target = next_event; } XtDispatchEvent(target); return XtAppPending(app_con); } /* * Filter redundant Expose- and ConfigureNotify-events. This is limited to * adjacent events because there could be other event-loop processing. Absent * that limitation, it might be possible to scan ahead to find when the screen * would be completely updated, skipping unnecessary re-repainting before that * point. * * Note: all cases should allow doing XtAppNextEvent if result is true. */ XtInputMask xtermAppPending(void) { XtInputMask result = XtAppPending(app_con); XEvent this_event; Boolean found = False; while (result && XtAppPeekEvent(app_con, &this_event)) { found = True; TRACE_EVENT("pending", &this_event, (String *) 0, 0); if (this_event.type == Expose) { result = mergeExposeEvents(&this_event); } else if (this_event.type == ConfigureNotify) { result = mergeConfigureEvents(&this_event); } else { break; } } /* * With NetBSD, closing a shell results in closing the X input event * stream, which interferes with the "-hold" option. Wait a short time in * this case, to avoid max'ing the CPU. */ if (hold_screen && caught_intr && !found) { Sleep(EVENT_DELAY); } return result; } void xevents(XtermWidget xw) { TScreen *screen = TScreenOf(xw); XEvent event; XtInputMask input_mask; if (need_cleanup) NormalExit(); if (screen->scroll_amt) FlushScroll(xw); /* * process timeouts, relying on the fact that XtAppProcessEvent * will process the timeout and return without blockng on the * XEvent queue. Other sources i.e., the pty are handled elsewhere * with select(). */ while ((input_mask = xtermAppPending()) != 0) { if (input_mask & XtIMTimer) XtAppProcessEvent(app_con, (XtInputMask) XtIMTimer); #if OPT_SESSION_MGT /* * Session management events are alternative input events. Deal with * them in the same way. */ else if (input_mask & XtIMAlternateInput) XtAppProcessEvent(app_con, (XtInputMask) XtIMAlternateInput); #endif else break; } /* * If there are no XEvents, don't wait around... */ if ((input_mask & XtIMXEvent) != XtIMXEvent) return; do { /* * This check makes xterm hang when in mouse hilite tracking mode. * We simply ignore all events except for those not passed down to * this function, e.g., those handled in in_put(). */ if (screen->waitingForTrackInfo) { Sleep(EVENT_DELAY); return; } XtAppNextEvent(app_con, &event); /* * Hack to get around problems with the toolkit throwing away * eventing during the exclusive grab of the menu popup. By * looking at the event ourselves we make sure that we can * do the right thing. */ if (OUR_EVENT(event, EnterNotify)) { DoSpecialEnterNotify(xw, &event.xcrossing); } else if (OUR_EVENT(event, LeaveNotify)) { DoSpecialLeaveNotify(xw, &event.xcrossing); } else if (event.xany.type == MotionNotify && event.xcrossing.window == XtWindow(xw)) { switch (screen->send_mouse_pos) { case ANY_EVENT_MOUSE: #if OPT_DEC_LOCATOR case DEC_LOCATOR: #endif /* OPT_DEC_LOCATOR */ SendMousePosition(xw, &event); xtermShowPointer(xw, True); continue; case BTN_EVENT_MOUSE: SendMousePosition(xw, &event); xtermShowPointer(xw, True); } } /* * If the event is interesting (and not a keyboard event), turn the * mouse pointer back on. */ if (screen->hide_pointer) { if (screen->pointer_mode >= pFocused) { switch (event.xany.type) { case MotionNotify: xtermShowPointer(xw, True); break; } } else { switch (event.xany.type) { case KeyPress: case KeyRelease: case ButtonPress: case ButtonRelease: /* also these... */ case Expose: case GraphicsExpose: case NoExpose: case PropertyNotify: case ClientMessage: break; default: xtermShowPointer(xw, True); break; } } } if (!event.xany.send_event || screen->allowSendEvents || ((event.xany.type != KeyPress) && (event.xany.type != KeyRelease) && (event.xany.type != ButtonPress) && (event.xany.type != ButtonRelease))) { if (event.xany.type == MappingNotify) { XRefreshKeyboardMapping(&(event.xmapping)); VTInitModifiers(xw); } XtDispatchEvent(&event); } } while (xtermAppPending() & XtIMXEvent); } static Cursor make_hidden_cursor(XtermWidget xw) { TScreen *screen = TScreenOf(xw); Cursor c; Display *dpy = screen->display; XFontStruct *fn; static XColor dummy; /* * Prefer nil2 (which is normally available) to "fixed" (which is supposed * to be "always" available), since it's a smaller glyph in case the * server insists on drawing _something_. */ TRACE(("Ask for nil2 font\n")); if ((fn = XLoadQueryFont(dpy, "nil2")) == 0) { TRACE(("...Ask for fixed font\n")); fn = XLoadQueryFont(dpy, DEFFONT); } if (fn != 0) { /* a space character seems to work as a cursor (dots are not needed) */ c = XCreateGlyphCursor(dpy, fn->fid, fn->fid, 'X', ' ', &dummy, &dummy); XFreeFont(dpy, fn); } else { c = 0; } TRACE(("XCreateGlyphCursor ->%#lx\n", c)); return (c); } /* * Xlib uses Xcursor to customize cursor coloring, which interferes with * xterm's pointerColor resource. Work around this by providing our own * default theme. Testing seems to show that we only have to provide this * until the window is initialized. */ void init_colored_cursor(Display *dpy) { #ifdef HAVE_LIB_XCURSOR static const char theme[] = "index.theme"; static const char pattern[] = "xtermXXXXXX"; char *env = getenv("XCURSOR_THEME"); xterm_cursor_theme = 0; /* * The environment variable overrides a (possible) resource Xcursor.theme */ if (IsEmpty(env)) { env = XGetDefault(dpy, "Xcursor", "theme"); } /* * If neither found, provide our own default theme. */ if (IsEmpty(env)) { const char *tmp_dir; char *filename; size_t needed; if ((tmp_dir = getenv("TMPDIR")) == 0) { tmp_dir = P_tmpdir; } needed = strlen(tmp_dir) + 4 + strlen(theme) + strlen(pattern); if ((filename = malloc(needed)) != 0) { sprintf(filename, "%s/%s", tmp_dir, pattern); #ifdef HAVE_MKDTEMP xterm_cursor_theme = mkdtemp(filename); #else if (mktemp(filename) != 0 && mkdir(filename, 0700) == 0) { xterm_cursor_theme = filename; } #endif if (xterm_cursor_theme != filename) free(filename); /* * Actually, Xcursor does what _we_ want just by steering its * search path away from home. We are setting up the complete * theme just in case the library ever acquires a maintainer. */ if (xterm_cursor_theme != 0) { char *leaf = xterm_cursor_theme + strlen(xterm_cursor_theme); FILE *fp; strcat(leaf, "/"); strcat(leaf, theme); if ((fp = fopen(xterm_cursor_theme, "w")) != 0) { fprintf(fp, "[Icon Theme]\n"); fclose(fp); *leaf = '\0'; xtermSetenv("XCURSOR_PATH", xterm_cursor_theme); *leaf = '/'; } atexit(cleanup_colored_cursor); } } } #else (void) dpy; #endif /* HAVE_LIB_XCURSOR */ } /* * Once done, discard the file and directory holding it. */ void cleanup_colored_cursor(void) { #ifdef HAVE_LIB_XCURSOR if (xterm_cursor_theme != 0) { char *my_path = getenv("XCURSOR_PATH"); struct stat sb; if (!IsEmpty(my_path) && stat(my_path, &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFDIR) { unlink(xterm_cursor_theme); rmdir(my_path); free(xterm_cursor_theme); xterm_cursor_theme = 0; } } #endif /* HAVE_LIB_XCURSOR */ } Cursor make_colored_cursor(unsigned cursorindex, /* index into font */ unsigned long fg, /* pixel value */ unsigned long bg) /* pixel value */ { TScreen *screen = TScreenOf(term); Cursor c; Display *dpy = screen->display; c = XCreateFontCursor(dpy, cursorindex); if (c != None) { recolor_cursor(screen, c, fg, bg); } return (c); } /* ARGSUSED */ void HandleKeyPressed(Widget w GCC_UNUSED, XEvent *event, String *params GCC_UNUSED, Cardinal *nparams GCC_UNUSED) { TRACE(("Handle insert-seven-bit for %p\n", (void *) w)); Input(term, &event->xkey, False); } /* ARGSUSED */ void HandleEightBitKeyPressed(Widget w GCC_UNUSED, XEvent *event, String *params GCC_UNUSED, Cardinal *nparams GCC_UNUSED) { TRACE(("Handle insert-eight-bit for %p\n", (void *) w)); Input(term, &event->xkey, True); } /* ARGSUSED */ void HandleStringEvent(Widget w GCC_UNUSED, XEvent *event GCC_UNUSED, String *params, Cardinal *nparams) { if (*nparams != 1) return; if ((*params)[0] == '0' && (*params)[1] == 'x' && (*params)[2] != '\0') { const char *abcdef = "ABCDEF"; const char *xxxxxx; Char c; UString p; unsigned value = 0; for (p = (UString) (*params + 2); (c = CharOf(x_toupper(*p))) != '\0'; p++) { value *= 16; if (c >= '0' && c <= '9') value += (unsigned) (c - '0'); else if ((xxxxxx = (strchr) (abcdef, c)) != 0) value += (unsigned) (xxxxxx - abcdef) + 10; else break; } if (c == '\0') { Char hexval[2]; hexval[0] = (Char) value; hexval[1] = 0; StringInput(term, hexval, (size_t) 1); } } else { StringInput(term, (const Char *) *params, strlen(*params)); } } #if OPT_EXEC_XTERM #ifndef PROCFS_ROOT #define PROCFS_ROOT "/proc" #endif /* * Determine the current working directory of the child so that we can * spawn a new terminal in the same directory. * * If we cannot get the CWD of the child, just use our own. */ char * ProcGetCWD(pid_t pid) { char *child_cwd = NULL; if (pid) { char child_cwd_link[sizeof(PROCFS_ROOT) + 80]; sprintf(child_cwd_link, PROCFS_ROOT "/%lu/cwd", (unsigned long) pid); child_cwd = Readlink(child_cwd_link); } return child_cwd; } /* ARGSUSED */ void HandleSpawnTerminal(Widget w GCC_UNUSED, XEvent *event GCC_UNUSED, String *params, Cardinal *nparams) { TScreen *screen = TScreenOf(term); char *child_cwd = NULL; char *child_exe; pid_t pid; /* * Try to find the actual program which is running in the child process. * This works for Linux. If we cannot find the program, fall back to the * xterm program (which is usually adequate). Give up if we are given only * a relative path to xterm, since that would not always match $PATH. */ child_exe = Readlink(PROCFS_ROOT "/self/exe"); if (!child_exe) { if (strncmp(ProgramName, "./", (size_t) 2) && strncmp(ProgramName, "../", (size_t) 3)) { child_exe = xtermFindShell(ProgramName, True); } else { xtermWarning("Cannot exec-xterm given \"%s\"\n", ProgramName); } if (child_exe == 0) return; } child_cwd = ProcGetCWD(screen->pid); /* The reaper will take care of cleaning up the child */ pid = fork(); if (pid == -1) { xtermWarning("Could not fork: %s\n", SysErrorMsg(errno)); } else if (!pid) { /* We are the child */ if (child_cwd) { IGNORE_RC(chdir(child_cwd)); /* We don't care if this fails */ } if (setuid(screen->uid) == -1 || setgid(screen->gid) == -1) { xtermWarning("Cannot reset uid/gid\n"); } else { unsigned myargc = *nparams + 1; char **myargv = TypeMallocN(char *, myargc + 1); if (myargv != 0) { unsigned n = 0; myargv[n++] = child_exe; while (n < myargc) { myargv[n++] = (char *) *params++; } myargv[n] = 0; execv(child_exe, myargv); } /* If we get here, we've failed */ xtermWarning("exec of '%s': %s\n", child_exe, SysErrorMsg(errno)); } _exit(0); } /* We are the parent; clean up */ if (child_cwd) free(child_cwd); free(child_exe); } #endif /* OPT_EXEC_XTERM */ /* * Rather than sending characters to the host, put them directly into our * input queue. That lets a user have access to any of the control sequences * for a key binding. This is the equivalent of local function key support. * * NOTE: This code does not support the hexadecimal kludge used in * HandleStringEvent because it prevents us from sending an arbitrary string * (but it appears in a lot of examples - so we are stuck with it). The * standard string converter does recognize "\" for newline ("\n") and for * octal constants (e.g., "\007" for BEL). So we assume the user can make do * without a specialized converter. (Don't try to use \000, though). */ /* ARGSUSED */ void HandleInterpret(Widget w GCC_UNUSED, XEvent *event GCC_UNUSED, String *params, Cardinal *param_count) { if (*param_count == 1) { const char *value = params[0]; int need = (int) strlen(value); int used = (int) (VTbuffer->next - VTbuffer->buffer); int have = (int) (VTbuffer->last - VTbuffer->buffer); if (have - used + need < BUF_SIZE) { fillPtyData(term, VTbuffer, value, (int) strlen(value)); TRACE(("Interpret %s\n", value)); VTbuffer->update++; } } } /*ARGSUSED*/ void HandleEnterWindow(Widget w GCC_UNUSED, XtPointer eventdata GCC_UNUSED, XEvent *event GCC_UNUSED, Boolean *cont GCC_UNUSED) { /* NOP since we handled it above */ TRACE(("HandleEnterWindow ignored\n")); TRACE_FOCUS(w, event); } /*ARGSUSED*/ void HandleLeaveWindow(Widget w GCC_UNUSED, XtPointer eventdata GCC_UNUSED, XEvent *event GCC_UNUSED, Boolean *cont GCC_UNUSED) { /* NOP since we handled it above */ TRACE(("HandleLeaveWindow ignored\n")); TRACE_FOCUS(w, event); } /*ARGSUSED*/ void HandleFocusChange(Widget w GCC_UNUSED, XtPointer eventdata GCC_UNUSED, XEvent *ev, Boolean *cont GCC_UNUSED) { XFocusChangeEvent *event = (XFocusChangeEvent *) ev; XtermWidget xw = term; TScreen *screen = TScreenOf(xw); TRACE(("HandleFocusChange type=%s, mode=%s, detail=%s\n", visibleEventType(event->type), visibleNotifyMode(event->mode), visibleNotifyDetail(event->detail))); TRACE_FOCUS(xw, event); if (screen->quiet_grab && (event->mode == NotifyGrab || event->mode == NotifyUngrab)) { /* EMPTY */ ; } else if (event->type == FocusIn) { if (event->detail != NotifyPointer) { setXUrgency(xw, False); } /* * NotifyNonlinear only happens (on FocusIn) if the pointer was not in * one of our windows. Use this to reset a case where one xterm is * partly obscuring another, and X gets (us) confused about whether the * pointer was in the window. In particular, this can happen if the * user is resizing the obscuring window, causing some events to not be * delivered to the obscured window. */ if (event->detail == NotifyNonlinear && (screen->select & INWINDOW) != 0) { unselectwindow(xw, INWINDOW); } selectwindow(xw, ((event->detail == NotifyPointer) ? INWINDOW : FOCUS)); SendFocusButton(xw, event); } else { #if OPT_FOCUS_EVENT if (event->type == FocusOut) { SendFocusButton(xw, event); } #endif /* * XGrabKeyboard() will generate NotifyGrab event that we want to * ignore. */ if (event->mode != NotifyGrab) { unselectwindow(xw, ((event->detail == NotifyPointer) ? INWINDOW : FOCUS)); } if (screen->grabbedKbd && (event->mode == NotifyUngrab)) { Bell(xw, XkbBI_Info, 100); ReverseVideo(xw); screen->grabbedKbd = False; update_securekbd(); } } } static long lastBellTime; /* in milliseconds */ #if defined(HAVE_XKB_BELL_EXT) static Atom AtomBell(XtermWidget xw, int which) { #define DATA(name) { XkbBI_##name, XkbBN_##name } static struct { int value; const char *name; } table[] = { DATA(Info), DATA(MarginBell), DATA(MinorError), DATA(TerminalBell) }; #undef DATA Cardinal n; Atom result = None; for (n = 0; n < XtNumber(table); ++n) { if (table[n].value == which) { result = XInternAtom(XtDisplay(xw), table[n].name, False); break; } } return result; } #endif void xtermBell(XtermWidget xw, int which, int percent) { TScreen *screen = TScreenOf(xw); #if defined(HAVE_XKB_BELL_EXT) Atom tony = AtomBell(xw, which); #endif switch (which) { case XkbBI_Info: case XkbBI_MinorError: case XkbBI_MajorError: case XkbBI_TerminalBell: switch (screen->warningVolume) { case bvOff: percent = -100; break; case bvLow: break; case bvHigh: percent = 100; break; } break; case XkbBI_MarginBell: switch (screen->marginVolume) { case bvOff: percent = -100; break; case bvLow: break; case bvHigh: percent = 100; break; } break; default: break; } #if defined(HAVE_XKB_BELL_EXT) if (tony != None) { XkbBell(screen->display, VShellWindow(xw), percent, tony); } else #endif XBell(screen->display, percent); } void Bell(XtermWidget xw, int which, int percent) { TScreen *screen = TScreenOf(xw); struct timeval curtime; TRACE(("BELL %d %d%%\n", which, percent)); if (!XtIsRealized((Widget) xw)) { return; } setXUrgency(xw, True); /* has enough time gone by that we are allowed to ring the bell again? */ if (screen->bellSuppressTime) { long now_msecs; if (screen->bellInProgress) { do_xevents(xw); if (screen->bellInProgress) { /* even after new events? */ return; } } X_GETTIMEOFDAY(&curtime); now_msecs = 1000 * curtime.tv_sec + curtime.tv_usec / 1000; if (lastBellTime != 0 && now_msecs - lastBellTime >= 0 && now_msecs - lastBellTime < screen->bellSuppressTime) { return; } lastBellTime = now_msecs; } if (screen->visualbell) { VisualBell(); } else { xtermBell(xw, which, percent); } if (screen->poponbell) XRaiseWindow(screen->display, VShellWindow(xw)); if (screen->bellSuppressTime) { /* now we change a property and wait for the notify event to come back. If the server is suspending operations while the bell is being emitted (problematic for audio bell), this lets us know when the previous bell has finished */ Widget w = CURRENT_EMU(); XChangeProperty(XtDisplay(w), XtWindow(w), XA_NOTICE, XA_NOTICE, 8, PropModeAppend, NULL, 0); screen->bellInProgress = True; } } static void flashWindow(TScreen *screen, Window window, GC visualGC, unsigned width, unsigned height) { int y = 0; int x = 0; if (screen->flash_line) { y = CursorY(screen, screen->cur_row); height = (unsigned) FontHeight(screen); } XFillRectangle(screen->display, window, visualGC, x, y, width, height); XFlush(screen->display); Sleep(VB_DELAY); XFillRectangle(screen->display, window, visualGC, x, y, width, height); } void VisualBell(void) { XtermWidget xw = term; TScreen *screen = TScreenOf(xw); if (VB_DELAY > 0) { Pixel xorPixel = (T_COLOR(screen, TEXT_FG) ^ T_COLOR(screen, TEXT_BG)); XGCValues gcval; GC visualGC; gcval.function = GXxor; gcval.foreground = xorPixel; visualGC = XtGetGC((Widget) xw, GCFunction + GCForeground, &gcval); #if OPT_TEK4014 if (TEK4014_ACTIVE(xw)) { TekScreen *tekscr = TekScreenOf(tekWidget); flashWindow(screen, TWindow(tekscr), visualGC, TFullWidth(tekscr), TFullHeight(tekscr)); } else #endif { flashWindow(screen, VWindow(screen), visualGC, FullWidth(screen), FullHeight(screen)); } XtReleaseGC((Widget) xw, visualGC); } } /* ARGSUSED */ void HandleBellPropertyChange(Widget w GCC_UNUSED, XtPointer data GCC_UNUSED, XEvent *ev, Boolean *more GCC_UNUSED) { TScreen *screen = TScreenOf(term); if (ev->xproperty.atom == XA_NOTICE) { screen->bellInProgress = False; } } void xtermWarning(const char *fmt, ...) { int save_err = errno; va_list ap; fflush(stdout); #if OPT_TRACE va_start(ap, fmt); Trace("xtermWarning: "); TraceVA(fmt, ap); va_end(ap); #endif fprintf(stderr, "%s: ", ProgramName); va_start(ap, fmt); vfprintf(stderr, fmt, ap); (void) fflush(stderr); va_end(ap); errno = save_err; } void xtermPerror(const char *fmt, ...) { int save_err = errno; char *msg = strerror(errno); va_list ap; fflush(stdout); #if OPT_TRACE va_start(ap, fmt); Trace("xtermPerror: "); TraceVA(fmt, ap); va_end(ap); #endif fprintf(stderr, "%s: ", ProgramName); va_start(ap, fmt); vfprintf(stderr, fmt, ap); fprintf(stderr, ": %s\n", msg); (void) fflush(stderr); va_end(ap); errno = save_err; } Window WMFrameWindow(XtermWidget xw) { Window win_root, win_current, *children; Window win_parent = 0; unsigned int nchildren; win_current = XtWindow(xw); /* find the parent which is child of root */ do { if (win_parent) win_current = win_parent; XQueryTree(TScreenOf(xw)->display, win_current, &win_root, &win_parent, &children, &nchildren); XFree(children); } while (win_root != win_parent); return win_current; } #if OPT_DABBREV /* * The following code implements `dynamic abbreviation' expansion a la * Emacs. It looks in the preceding visible screen and its scrollback * to find expansions of a typed word. It compares consecutive * expansions and ignores one of them if they are identical. * (Tomasz J. Cholewo, t.cholewo@ieee.org) */ #define IS_WORD_CONSTITUENT(x) ((x) != ' ' && (x) != '\0') static int dabbrev_prev_char(TScreen *screen, CELL *cell, LineData **ld) { int result = -1; int firstLine = -(screen->savedlines); *ld = getLineData(screen, cell->row); while (cell->row >= firstLine) { if (--(cell->col) >= 0) { result = (int) (*ld)->charData[cell->col]; break; } if (--(cell->row) < firstLine) break; /* ...there is no previous line */ *ld = getLineData(screen, cell->row); cell->col = MaxCols(screen); if (!LineTstWrapped(*ld)) { result = ' '; /* treat lines as separate */ break; } } return result; } static char * dabbrev_prev_word(XtermWidget xw, CELL *cell, LineData **ld) { TScreen *screen = TScreenOf(xw); char *abword; int c; char *ab_end = (xw->work.dabbrev_data + MAX_DABBREV - 1); char *result = 0; abword = ab_end; *abword = '\0'; /* end of string marker */ while ((c = dabbrev_prev_char(screen, cell, ld)) >= 0 && IS_WORD_CONSTITUENT(c)) { if (abword > xw->work.dabbrev_data) /* store only the last chars */ *(--abword) = (char) c; } if (c >= 0) { result = abword; } else if (abword != ab_end) { result = abword; } if (result != 0) { while ((c = dabbrev_prev_char(screen, cell, ld)) >= 0 && !IS_WORD_CONSTITUENT(c)) { ; /* skip preceding spaces */ } (cell->col)++; /* can be | > screen->max_col| */ } return result; } static int dabbrev_expand(XtermWidget xw) { TScreen *screen = TScreenOf(xw); int pty = screen->respond; /* file descriptor of pty */ static CELL cell; static char *dabbrev_hint = 0, *lastexpansion = 0; static unsigned int expansions; char *expansion; size_t hint_len; int result = 0; LineData *ld; if (!screen->dabbrev_working) { /* initialize */ expansions = 0; cell.col = screen->cur_col; cell.row = screen->cur_row; if (dabbrev_hint != 0) free(dabbrev_hint); if ((dabbrev_hint = dabbrev_prev_word(xw, &cell, &ld)) != 0) { if (lastexpansion != 0) free(lastexpansion); if ((lastexpansion = strdup(dabbrev_hint)) != 0) { /* make own copy */ if ((dabbrev_hint = strdup(dabbrev_hint)) != 0) { screen->dabbrev_working = True; /* we are in the middle of dabbrev process */ } } else { return result; } } else { return result; } if (!screen->dabbrev_working) { if (lastexpansion != 0) { free(lastexpansion); lastexpansion = 0; } return result; } } if (dabbrev_hint == 0) return result; hint_len = strlen(dabbrev_hint); for (;;) { if ((expansion = dabbrev_prev_word(xw, &cell, &ld)) == 0) { if (expansions >= 2) { expansions = 0; cell.col = screen->cur_col; cell.row = screen->cur_row; continue; } break; } if (!strncmp(dabbrev_hint, expansion, hint_len) && /* empty hint matches everything */ strlen(expansion) > hint_len && /* trivial expansion disallowed */ strcmp(expansion, lastexpansion)) /* different from previous */ break; } if (expansion != 0) { Char *copybuffer; size_t del_cnt = strlen(lastexpansion) - hint_len; size_t buf_cnt = del_cnt + strlen(expansion) - hint_len; if ((copybuffer = TypeMallocN(Char, buf_cnt)) != 0) { /* delete previous expansion */ memset(copybuffer, screen->dabbrev_erase_char, del_cnt); memmove(copybuffer + del_cnt, expansion + hint_len, strlen(expansion) - hint_len); v_write(pty, copybuffer, (unsigned) buf_cnt); /* v_write() just reset our flag */ screen->dabbrev_working = True; free(copybuffer); free(lastexpansion); if ((lastexpansion = strdup(expansion)) != 0) { result = 1; expansions++; } } } return result; } /*ARGSUSED*/ void HandleDabbrevExpand(Widget w, XEvent *event GCC_UNUSED, String *params GCC_UNUSED, Cardinal *nparams GCC_UNUSED) { XtermWidget xw; TRACE(("Handle dabbrev-expand for %p\n", (void *) w)); if ((xw = getXtermWidget(w)) != 0) { if (!dabbrev_expand(xw)) Bell(xw, XkbBI_TerminalBell, 0); } } #endif /* OPT_DABBREV */ void xtermDeiconify(XtermWidget xw) { TScreen *screen = TScreenOf(xw); Display *dpy = screen->display; Window target = VShellWindow(xw); XEvent e; Atom atom_state = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); if (xtermIsIconified(xw)) { TRACE(("...de-iconify window %#lx\n", target)); XMapWindow(dpy, target); memset(&e, 0, sizeof(e)); e.xclient.type = ClientMessage; e.xclient.message_type = atom_state; e.xclient.display = dpy; e.xclient.window = target; e.xclient.format = 32; e.xclient.data.l[0] = 1; e.xclient.data.l[1] = CurrentTime; XSendEvent(dpy, DefaultRootWindow(dpy), False, SubstructureRedirectMask | SubstructureNotifyMask, &e); xevents(xw); } } void xtermIconify(XtermWidget xw) { TScreen *screen = TScreenOf(xw); Window target = VShellWindow(xw); if (!xtermIsIconified(xw)) { TRACE(("...iconify window %#lx\n", target)); XIconifyWindow(screen->display, target, DefaultScreen(screen->display)); xevents(xw); } } Boolean xtermIsIconified(XtermWidget xw) { XWindowAttributes win_attrs; TScreen *screen = TScreenOf(xw); Window target = VShellWindow(xw); Display *dpy = screen->display; Boolean result = False; if (xtermGetWinAttrs(dpy, target, &win_attrs)) { Atom actual_return_type; int actual_format_return = 0; unsigned long nitems_return = 0; unsigned long bytes_after_return = 0; unsigned char *prop_return = 0; long long_length = 1024; Atom requested_type = XA_ATOM; Atom is_hidden = XInternAtom(dpy, "_NET_WM_STATE_HIDDEN", False); Atom wm_state = XInternAtom(dpy, "_NET_WM_STATE", False); /* this works with non-EWMH */ result = (win_attrs.map_state != IsViewable) ? True : False; /* this is a convention used by some EWMH applications */ if (xtermGetWinProp(dpy, target, wm_state, 0L, long_length, requested_type, &actual_return_type, &actual_format_return, &nitems_return, &bytes_after_return, &prop_return) && prop_return != 0 && actual_return_type == requested_type && actual_format_return == 32) { unsigned long n; for (n = 0; n < nitems_return; ++n) { unsigned long check = (((unsigned long *) (void *) prop_return)[n]); if (check == is_hidden) { result = True; break; } } } } TRACE(("...window %#lx is%s iconified\n", target, result ? "" : " not")); return result; } #if OPT_MAXIMIZE /*ARGSUSED*/ void HandleDeIconify(Widget w, XEvent *event GCC_UNUSED, String *params GCC_UNUSED, Cardinal *nparams GCC_UNUSED) { XtermWidget xw; if ((xw = getXtermWidget(w)) != 0) { xtermDeiconify(xw); } } /*ARGSUSED*/ void HandleIconify(Widget w, XEvent *event GCC_UNUSED, String *params GCC_UNUSED, Cardinal *nparams GCC_UNUSED) { XtermWidget xw; if ((xw = getXtermWidget(w)) != 0) { xtermIconify(xw); } } int QueryMaximize(XtermWidget xw, unsigned *width, unsigned *height) { TScreen *screen = TScreenOf(xw); XSizeHints hints; long supp = 0; Window root_win; int root_x = -1; /* saved co-ordinates */ int root_y = -1; unsigned root_border; unsigned root_depth; int code; if (XGetGeometry(screen->display, RootWindowOfScreen(XtScreen(xw)), &root_win, &root_x, &root_y, width, height, &root_border, &root_depth)) { TRACE(("QueryMaximize: XGetGeometry position %d,%d size %d,%d border %d\n", root_x, root_y, *width, *height, root_border)); *width -= (root_border * 2); *height -= (root_border * 2); hints.flags = PMaxSize; if (XGetWMNormalHints(screen->display, VShellWindow(xw), &hints, &supp) && (hints.flags & PMaxSize) != 0) { TRACE(("QueryMaximize: WM hints max_w %#x max_h %#x\n", hints.max_width, hints.max_height)); if ((unsigned) hints.max_width < *width) *width = (unsigned) hints.max_width; if ((unsigned) hints.max_height < *height) *height = (unsigned) hints.max_height; } code = 1; } else { *width = 0; *height = 0; code = 0; } return code; } void RequestMaximize(XtermWidget xw, int maximize) { TScreen *screen = TScreenOf(xw); XWindowAttributes wm_attrs, vshell_attrs; unsigned root_width, root_height; Boolean success = False; TRACE(("RequestMaximize %d:%s\n", maximize, (maximize ? "maximize" : "restore"))); /* * Before any maximize, ensure that we can capture the current screensize * as well as the estimated root-window size. */ if (maximize && QueryMaximize(xw, &root_width, &root_height) && xtermGetWinAttrs(screen->display, WMFrameWindow(xw), &wm_attrs) && xtermGetWinAttrs(screen->display, VShellWindow(xw), &vshell_attrs)) { if (screen->restore_data != True || screen->restore_width != root_width || screen->restore_height != root_height) { screen->restore_data = True; screen->restore_x = wm_attrs.x; screen->restore_y = wm_attrs.y; screen->restore_width = (unsigned) vshell_attrs.width; screen->restore_height = (unsigned) vshell_attrs.height; TRACE(("RequestMaximize: save window position %d,%d size %d,%d\n", screen->restore_x, screen->restore_y, screen->restore_width, screen->restore_height)); } /* subtract wm decoration dimensions */ root_width -= (unsigned) (wm_attrs.width - vshell_attrs.width); root_height -= (unsigned) (wm_attrs.height - vshell_attrs.height); success = True; } else if (screen->restore_data) { success = True; maximize = 0; } if (success) { switch (maximize) { case 3: FullScreen(xw, 3); /* depends on EWMH */ break; case 2: FullScreen(xw, 2); /* depends on EWMH */ break; case 1: FullScreen(xw, 0); /* overrides any EWMH hint */ TRACE(("XMoveResizeWindow(Maximize): position %d,%d size %d,%d\n", 0, 0, root_width, root_height)); XMoveResizeWindow(screen->display, VShellWindow(xw), 0, /* x */ 0, /* y */ root_width, root_height); break; default: FullScreen(xw, 0); /* reset any EWMH hint */ if (screen->restore_data) { screen->restore_data = False; TRACE(("XMoveResizeWindow(Restore): position %d,%d size %d,%d\n", screen->restore_x, screen->restore_y, screen->restore_width, screen->restore_height)); XMoveResizeWindow(screen->display, VShellWindow(xw), screen->restore_x, screen->restore_y, screen->restore_width, screen->restore_height); } break; } } } /*ARGSUSED*/ void HandleMaximize(Widget w, XEvent *event GCC_UNUSED, String *params GCC_UNUSED, Cardinal *nparams GCC_UNUSED) { XtermWidget xw; if ((xw = getXtermWidget(w)) != 0) { RequestMaximize(xw, 1); } } /*ARGSUSED*/ void HandleRestoreSize(Widget w, XEvent *event GCC_UNUSED, String *params GCC_UNUSED, Cardinal *nparams GCC_UNUSED) { XtermWidget xw; if ((xw = getXtermWidget(w)) != 0) { RequestMaximize(xw, 0); } } #endif /* OPT_MAXIMIZE */ void Redraw(void) { XtermWidget xw = term; TScreen *screen = TScreenOf(xw); XExposeEvent event; TRACE(("Redraw\n")); event.type = Expose; event.display = screen->display; event.x = 0; event.y = 0; event.count = 0; if (VWindow(screen)) { event.window = VWindow(screen); event.width = xw->core.width; event.height = xw->core.height; (*xw->core.widget_class->core_class.expose) ((Widget) xw, (XEvent *) &event, NULL); if (ScrollbarWidth(screen)) { (screen->scrollWidget->core.widget_class->core_class.expose) (screen->scrollWidget, (XEvent *) &event, NULL); } } #if OPT_TEK4014 if (TEK4014_SHOWN(xw)) { TekScreen *tekscr = TekScreenOf(tekWidget); event.window = TWindow(tekscr); event.width = tekWidget->core.width; event.height = tekWidget->core.height; TekExpose((Widget) tekWidget, (XEvent *) &event, NULL); } #endif } #ifdef VMS #define TIMESTAMP_FMT "%s%d-%02d-%02d-%02d-%02d-%02d" #else #define TIMESTAMP_FMT "%s%d-%02d-%02d.%02d:%02d:%02d" #endif void timestamp_filename(char *dst, const char *src) { time_t tstamp; struct tm *tstruct; tstamp = time((time_t *) 0); tstruct = localtime(&tstamp); sprintf(dst, TIMESTAMP_FMT, src, (int) tstruct->tm_year + 1900, tstruct->tm_mon + 1, tstruct->tm_mday, tstruct->tm_hour, tstruct->tm_min, tstruct->tm_sec); } FILE * create_printfile(XtermWidget xw, const char *suffix) { TScreen *screen = TScreenOf(xw); char fname[1024]; int fd; FILE *fp; #ifdef VMS sprintf(fname, "sys$scratch:xterm%s", suffix); #elif defined(HAVE_STRFTIME) { char format[1024]; time_t now; struct tm *ltm; now = time((time_t *) 0); ltm = localtime(&now); sprintf(format, "xterm%s%s", FMT_TIMESTAMP, suffix); if (strftime(fname, sizeof fname, format, ltm) == 0) { sprintf(fname, "xterm%s", suffix); } } #else sprintf(fname, "xterm%s", suffix); #endif fd = open_userfile(screen->uid, screen->gid, fname, False); fp = (fd >= 0) ? fdopen(fd, "wb") : NULL; return fp; } int open_userfile(uid_t uid, gid_t gid, char *path, Bool append) { int fd; struct stat sb; #ifdef VMS if ((fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) { int the_error = errno; xtermWarning("cannot open %s: %d:%s\n", path, the_error, SysErrorMsg(the_error)); return -1; } chown(path, uid, gid); #else if ((access(path, F_OK) != 0 && (errno != ENOENT)) || (creat_as(uid, gid, append, path, 0644) <= 0) || ((fd = open(path, O_WRONLY | O_APPEND)) < 0)) { int the_error = errno; xtermWarning("cannot open %s: %d:%s\n", path, the_error, SysErrorMsg(the_error)); return -1; } #endif /* * Doublecheck that the user really owns the file that we've opened before * we do any damage, and that it is not world-writable. */ if (fstat(fd, &sb) < 0 || sb.st_uid != uid || (sb.st_mode & 022) != 0) { xtermWarning("you do not own %s\n", path); close(fd); return -1; } return fd; } #ifndef VMS /* * Create a file only if we could with the permissions of the real user id. * We could emulate this with careful use of access() and following * symbolic links, but that is messy and has race conditions. * Forking is messy, too, but we can't count on setreuid() or saved set-uids * being available. * * Note: When called for user logging, we have ensured that the real and * effective user ids are the same, so this remains as a convenience function * for the debug logs. * * Returns * 1 if we can proceed to open the file in relative safety, * -1 on error, e.g., cannot fork * 0 otherwise. */ int creat_as(uid_t uid, gid_t gid, Bool append, char *pathname, unsigned mode) { int fd; pid_t pid; int retval = 0; int childstat = 0; #ifndef HAVE_WAITPID int waited; void (*chldfunc) (int); chldfunc = signal(SIGCHLD, SIG_DFL); #endif /* HAVE_WAITPID */ TRACE(("creat_as(uid=%d/%d, gid=%d/%d, append=%d, pathname=%s, mode=%#o)\n", (int) uid, (int) geteuid(), (int) gid, (int) getegid(), append, pathname, mode)); if (uid == geteuid() && gid == getegid()) { fd = open(pathname, O_WRONLY | O_CREAT | (append ? O_APPEND : O_EXCL), mode); if (fd >= 0) close(fd); return (fd >= 0); } pid = fork(); switch (pid) { case 0: /* child */ if (setgid(gid) == -1 || setuid(uid) == -1) { /* we cannot report an error here via stderr, just quit */ retval = 1; } else { fd = open(pathname, O_WRONLY | O_CREAT | (append ? O_APPEND : O_EXCL), mode); if (fd >= 0) { close(fd); retval = 0; } else { retval = 1; } } _exit(retval); /* NOTREACHED */ case -1: /* error */ return retval; default: /* parent */ #ifdef HAVE_WAITPID while (waitpid(pid, &childstat, 0) < 0) { #ifdef EINTR if (errno == EINTR) continue; #endif /* EINTR */ #ifdef ERESTARTSYS if (errno == ERESTARTSYS) continue; #endif /* ERESTARTSYS */ break; } #else /* HAVE_WAITPID */ waited = wait(&childstat); signal(SIGCHLD, chldfunc); /* Since we had the signal handler uninstalled for a while, we might have missed the termination of our screen child. If we can check for this possibility without hanging, do so. */ do if (waited == TScreenOf(term)->pid) NormalExit(); while ((waited = nonblocking_wait()) > 0) ; #endif /* HAVE_WAITPID */ #ifndef WIFEXITED #define WIFEXITED(status) ((status & 0xff) != 0) #endif if (WIFEXITED(childstat)) retval = 1; return retval; } } #endif /* !VMS */ int xtermResetIds(TScreen *screen) { int result = 0; if (setgid(screen->gid) == -1) { xtermWarning("unable to reset group-id\n"); result = -1; } if (setuid(screen->uid) == -1) { xtermWarning("unable to reset user-id\n"); result = -1; } return result; } #ifdef ALLOWLOGGING /* * Logging is a security hole, since it allows a setuid program to write * arbitrary data to an arbitrary file. So it is disabled by default. */ #ifdef ALLOWLOGFILEEXEC static void handle_SIGPIPE(int sig GCC_UNUSED) { XtermWidget xw = term; TScreen *screen = TScreenOf(xw); DEBUG_MSG("handle:logpipe\n"); #ifdef SYSV (void) signal(SIGPIPE, SIG_IGN); #endif /* SYSV */ if (screen->logging) CloseLog(xw); } /* * Open a command to pipe log data to it. * Warning, enabling this "feature" allows arbitrary programs * to be run. If ALLOWLOGFILECHANGES is enabled, this can be * done through escape sequences.... You have been warned. */ static void StartLogExec(TScreen *screen) { int pid; int p[2]; static char *shell; struct passwd pw; if ((shell = x_getenv("SHELL")) == NULL) { if (x_getpwuid(screen->uid, &pw)) { char *name = x_getlogin(screen->uid, &pw); if (*(pw.pw_shell)) { shell = pw.pw_shell; } free(name); } } if (shell == 0) { static char dummy[] = "/bin/sh"; shell = dummy; } if (access(shell, X_OK) != 0) { xtermPerror("Can't execute `%s'\n", shell); return; } if (pipe(p) < 0) { xtermPerror("Can't make a pipe connection\n"); return; } else if ((pid = fork()) < 0) { xtermPerror("Can't fork...\n"); return; } if (pid == 0) { /* child */ /* * Close our output (we won't be talking back to the * parent), and redirect our child's output to the * original stderr. */ close(p[1]); dup2(p[0], 0); close(p[0]); dup2(fileno(stderr), 1); dup2(fileno(stderr), 2); close(fileno(stderr)); close(ConnectionNumber(screen->display)); close(screen->respond); signal(SIGHUP, SIG_DFL); signal(SIGCHLD, SIG_DFL); /* (this is redundant) */ if (xtermResetIds(screen) < 0) exit(ERROR_SETUID); execl(shell, shell, "-c", &screen->logfile[1], (void *) 0); xtermWarning("Can't exec `%s -c %s'\n", shell, &screen->logfile[1]); exit(ERROR_LOGEXEC); } close(p[0]); screen->logfd = p[1]; signal(SIGPIPE, handle_SIGPIPE); } #endif /* ALLOWLOGFILEEXEC */ /* * Generate a path for a logfile if no default path is given. */ static char * GenerateLogPath(void) { static char *log_default = NULL; /* once opened we just reuse the same log name */ if (log_default) return (log_default); #if defined(HAVE_GETHOSTNAME) && defined(HAVE_STRFTIME) { #define LEN_HOSTNAME 255 /* Internet standard limit (RFC 1035): ``To simplify implementations, * the total length of a domain name (i.e., label octets and label * length octets) is restricted to 255 octets or less.'' */ #define LEN_GETPID 9 /* * This is arbitrary... */ const char form[] = "Xterm.log.%s%s.%lu"; char where[LEN_HOSTNAME + 1]; char when[LEN_TIMESTAMP]; time_t now = time((time_t *) 0); struct tm *ltm = (struct tm *) localtime(&now); if ((gethostname(where, sizeof(where)) == 0) && (strftime(when, sizeof(when), FMT_TIMESTAMP, ltm) > 0) && ((log_default = (char *) malloc((sizeof(form) + strlen(where) + strlen(when) + LEN_GETPID))) != NULL)) { (void) sprintf(log_default, form, where, when, ((unsigned long) getpid()) % ((unsigned long) 1e10)); } } #else static const char log_def_name[] = "XtermLog.XXXXXX"; if ((log_default = x_strdup(log_def_name)) != NULL) { mktemp(log_default); } #endif return (log_default); } void StartLog(XtermWidget xw) { TScreen *screen = TScreenOf(xw); if (screen->logging || (screen->inhibit & I_LOG)) return; #ifdef VMS /* file name is fixed in VMS variant */ screen->logfd = open(XTERM_VMS_LOGFILE, O_CREAT | O_TRUNC | O_APPEND | O_RDWR, 0640); if (screen->logfd < 0) return; /* open failed */ #else /*VMS */ /* if we weren't supplied with a logfile path, generate one */ if (IsEmpty(screen->logfile)) screen->logfile = GenerateLogPath(); /* give up if we were unable to allocate the filename */ if (!screen->logfile) return; if (*screen->logfile == '|') { /* exec command */ #ifdef ALLOWLOGFILEEXEC StartLogExec(screen); #else Bell(xw, XkbBI_Info, 0); Bell(xw, XkbBI_Info, 0); return; #endif } else if (strcmp(screen->logfile, "-") == 0) { screen->logfd = STDOUT_FILENO; } else { if ((screen->logfd = open_userfile(screen->uid, screen->gid, screen->logfile, True)) < 0) return; } #endif /*VMS */ screen->logstart = VTbuffer->next; screen->logging = True; update_logging(); } void CloseLog(XtermWidget xw) { TScreen *screen = TScreenOf(xw); if (!screen->logging || (screen->inhibit & I_LOG)) return; FlushLog(xw); close(screen->logfd); screen->logging = False; update_logging(); } void FlushLog(XtermWidget xw) { TScreen *screen = TScreenOf(xw); if (screen->logging && !(screen->inhibit & I_LOG)) { Char *cp; int i; #ifdef VMS /* avoid logging output loops which otherwise occur sometimes when there is no output and cp/screen->logstart are 1 apart */ if (!tt_new_output) return; tt_new_output = False; #endif /* VMS */ cp = VTbuffer->next; if (screen->logstart != 0 && (i = (int) (cp - screen->logstart)) > 0) { IGNORE_RC(write(screen->logfd, screen->logstart, (size_t) i)); } screen->logstart = VTbuffer->next; } } #endif /* ALLOWLOGGING */ /***====================================================================***/ static unsigned maskToShift(unsigned long mask) { unsigned result = 0; if (mask != 0) { while ((mask & 1) == 0) { mask >>= 1; ++result; } } return result; } static unsigned maskToWidth(unsigned long mask) { unsigned result = 0; while (mask != 0) { if ((mask & 1) != 0) ++result; mask >>= 1; } return result; } int getVisualInfo(XtermWidget xw) { #define MYFMT "getVisualInfo \ depth %d, \ type %d (%s), \ size %d \ rgb masks (%04lx/%04lx/%04lx)\n" #define MYARG \ vi->depth,\ vi->class,\ ((vi->class & 1) ? "dynamic" : "static"),\ vi->colormap_size,\ vi->red_mask,\ vi->green_mask,\ vi->blue_mask TScreen *screen = TScreenOf(xw); Display *dpy = screen->display; XVisualInfo myTemplate; if (xw->visInfo == 0 && xw->numVisuals == 0) { myTemplate.visualid = XVisualIDFromVisual(DefaultVisual(dpy, XDefaultScreen(dpy))); xw->visInfo = XGetVisualInfo(dpy, (long) VisualIDMask, &myTemplate, &xw->numVisuals); if ((xw->visInfo != 0) && (xw->numVisuals > 0)) { XVisualInfo *vi = xw->visInfo; xw->rgb_widths[0] = maskToWidth(vi->red_mask); xw->rgb_widths[1] = maskToWidth(vi->green_mask); xw->rgb_widths[2] = maskToWidth(vi->blue_mask); xw->rgb_shifts[0] = maskToShift(vi->red_mask); xw->rgb_shifts[1] = maskToShift(vi->green_mask); xw->rgb_shifts[2] = maskToShift(vi->blue_mask); xw->has_rgb = ((vi->red_mask != 0) && (vi->green_mask != 0) && (vi->blue_mask != 0) && ((vi->red_mask & vi->green_mask) == 0) && ((vi->green_mask & vi->blue_mask) == 0) && ((vi->blue_mask & vi->red_mask) == 0)); if (resource.reportColors) { printf(MYFMT, MYARG); } TRACE((MYFMT, MYARG)); TRACE(("...shifts %u/%u/%u\n", xw->rgb_shifts[0], xw->rgb_shifts[1], xw->rgb_shifts[2])); } } return (xw->visInfo != 0) && (xw->numVisuals > 0); #undef MYFMT #undef MYARG } #if OPT_ISO_COLORS static Bool ReportAnsiColorRequest(XtermWidget xw, int opcode, int colornum, int final) { Bool result = False; if (AllowColorOps(xw, ecGetAnsiColor)) { XColor color; Colormap cmap = xw->core.colormap; char buffer[80]; TRACE(("ReportAnsiColorRequest %d\n", colornum)); color.pixel = GET_COLOR_RES(xw, TScreenOf(xw)->Acolors[colornum]); XQueryColor(TScreenOf(xw)->display, cmap, &color); sprintf(buffer, "%d;%d;rgb:%04x/%04x/%04x", opcode, (opcode == 5) ? (colornum - NUM_ANSI_COLORS) : colornum, color.red, color.green, color.blue); unparseputc1(xw, ANSI_OSC); unparseputs(xw, buffer); unparseputc1(xw, final); result = True; } return result; } static void getColormapInfo(XtermWidget xw, unsigned *typep, unsigned *sizep) { if (getVisualInfo(xw)) { *typep = (unsigned) xw->visInfo->class; *sizep = (unsigned) xw->visInfo->colormap_size; } else { *typep = 0; *sizep = 0; } } #define MAX_COLORTABLE 4096 /* * Make only one call to XQueryColors(), since it can be slow. */ static Boolean loadColorTable(XtermWidget xw, unsigned length) { Colormap cmap = xw->core.colormap; TScreen *screen = TScreenOf(xw); Boolean result = (screen->cmap_data != 0); if (!result && length != 0 && length < MAX_COLORTABLE) { screen->cmap_data = TypeMallocN(XColor, (size_t) length); if (screen->cmap_data != 0) { unsigned i; screen->cmap_size = length; for (i = 0; i < screen->cmap_size; i++) { screen->cmap_data[i].pixel = (unsigned long) i; } result = (Boolean) (XQueryColors(screen->display, cmap, screen->cmap_data, (int) screen->cmap_size) != 0); } } return result; } /* * Find closest color for "def" in "cmap". * Set "def" to the resulting color. * * Based on Monish Shah's "find_closest_color()" for Vim 6.0, * modified with ideas from David Tong's "noflash" library. * The code from Vim in turn was derived from FindClosestColor() in Tcl/Tk. * * Return False if not able to find or allocate a color. */ static Boolean allocateClosestRGB(XtermWidget xw, Colormap cmap, XColor *def) { TScreen *screen = TScreenOf(xw); Boolean result = False; unsigned cmap_type; unsigned cmap_size; getColormapInfo(xw, &cmap_type, &cmap_size); if ((cmap_type & 1) != 0) { if (loadColorTable(xw, cmap_size)) { char *tried = TypeCallocN(char, (size_t) cmap_size); if (tried != 0) { unsigned attempts; /* * Try (possibly each entry in the color map) to find the best * approximation to the requested color. */ for (attempts = 0; attempts < cmap_size; attempts++) { Boolean first = True; double bestRGB = 0.0; unsigned bestInx = 0; unsigned i; for (i = 0; i < cmap_size; i++) { if (!tried[bestInx]) { double diff, thisRGB = 0.0; /* * Look for the best match based on luminance. * Measure this by the least-squares difference of * the weighted R/G/B components from the color map * versus the requested color. Use the Y (luma) * component of the YIQ color space model for * weights that correspond to the luminance. */ #define AddColorWeight(weight, color) \ diff = weight * (int) ((def->color) - screen->cmap_data[i].color); \ thisRGB += diff * diff AddColorWeight(0.30, red); AddColorWeight(0.61, green); AddColorWeight(0.11, blue); if (first || (thisRGB < bestRGB)) { first = False; bestInx = i; bestRGB = thisRGB; } } } if (XAllocColor(screen->display, cmap, &screen->cmap_data[bestInx]) != 0) { *def = screen->cmap_data[bestInx]; TRACE(("...closest %x/%x/%x\n", def->red, def->green, def->blue)); result = True; break; } /* * It failed - either the color map entry was readonly, or * another client has allocated the entry. Mark the entry * so we will ignore it */ tried[bestInx] = True; } free(tried); } } } return result; } #ifndef ULONG_MAX #define ULONG_MAX (unsigned long)(~(0L)) #endif #define CheckColor(result, value) \ result = 0; \ if (value.red) \ result |= 1; \ if (value.green) \ result |= 2; \ if (value.blue) \ result |= 4 #define SelectColor(state, value, result) \ switch (state) { \ default: \ case 1: \ result = value.red; \ break; \ case 2: \ result = value.green; \ break; \ case 4: \ result = value.blue; \ break; \ } /* * Check if the color map consists of values in exactly one of the red, green * or blue columns. If it is not, we do not know how to use it for the exact * match. */ static int simpleColors(XColor *colortable, unsigned length) { unsigned n; int state = 0; int check; for (n = 0; n < length; ++n) { if (state > 0) { CheckColor(check, colortable[n]); if (check > 0 && check != state) { state = 0; break; } } else { CheckColor(state, colortable[n]); } } switch (state) { case 1: case 2: case 4: break; default: state = 0; break; } return state; } /* * Shift the mask left or right to put its most significant bit at the 16-bit * mark. */ static unsigned normalizeMask(unsigned mask) { while (mask < 0x8000) { mask <<= 1; } while (mask >= 0x10000) { mask >>= 1; } return mask; } static unsigned searchColors(XColor *colortable, unsigned mask, unsigned length, unsigned color, int state) { unsigned result = 0; unsigned n; unsigned long best = ULONG_MAX; unsigned value; mask = normalizeMask(mask); for (n = 0; n < length; ++n) { unsigned long diff; SelectColor(state, colortable[n], value); diff = ((color & mask) - (value & mask)); diff *= diff; if (diff < best) { #if 0 TRACE(("...%d:looking for %x, found %x/%x/%x (%lx)\n", n, color, colortable[n].red, colortable[n].green, colortable[n].blue, diff)); #endif result = n; best = diff; } } SelectColor(state, colortable[result], value); return value; } /* * This is a workaround for a longstanding defect in the X libraries. * * According to * http://www.unix.com/man-page/all/3x/XAllocColoA/ * * XAllocColor() acts differently on static and dynamic visuals. On Pseu- * doColor, DirectColor, and GrayScale visuals, XAllocColor() fails if * there are no unallocated colorcells and no allocated read-only cell * exactly matches the requested RGB values. On StaticColor, TrueColor, * and StaticGray visuals, XAllocColor() returns the closest RGB values * available in the colormap. The colorcell_in_out structure returns the * actual RGB values allocated. * * That is, XAllocColor() should suffice unless the color map is full. In that * case, allocateClosestRGB() is useful for the dynamic display classes such as * PseudoColor. It is not useful for TrueColor, since XQueryColors() does not * return regular RGB triples (unless a different scheme was used for * specifying the pixel values); only the blue value is filled in. However, it * is filled in with the colors that the server supports. * * Also (the reason for this function), XAllocColor() does not really work as * described. For some TrueColor configurations it merely returns a close * approximation, but not the closest. */ static Boolean allocateExactRGB(XtermWidget xw, Colormap cmap, XColor *def) { XColor save = *def; TScreen *screen = TScreenOf(xw); Boolean result = (Boolean) (XAllocColor(screen->display, cmap, def) != 0); /* * If this is a statically allocated display with too many items to store * in our array, i.e., TrueColor, see if we can improve on the result by * using the color values actually supported by the server. */ if (result) { unsigned cmap_type; unsigned cmap_size; getColormapInfo(xw, &cmap_type, &cmap_size); if (cmap_type == TrueColor) { XColor temp = *def; int state; if (loadColorTable(xw, cmap_size) && (state = simpleColors(screen->cmap_data, cmap_size)) > 0) { #define SearchColors(which) \ temp.which = (unsigned short) searchColors(screen->cmap_data, \ (unsigned) xw->visInfo->which##_mask,\ cmap_size, \ save.which, \ state) SearchColors(red); SearchColors(green); SearchColors(blue); if (XAllocColor(screen->display, cmap, &temp) != 0) { #if OPT_TRACE if (temp.red != save.red || temp.green != save.green || temp.blue != save.blue) { TRACE(("...improved %x/%x/%x ->%x/%x/%x\n", save.red, save.green, save.blue, temp.red, temp.green, temp.blue)); } else { TRACE(("...no improvement for %x/%x/%x\n", save.red, save.green, save.blue)); } #endif *def = temp; } } } } return result; } /* * Allocate a color for the "ANSI" colors. That actually includes colors up * to 256. * * Returns * -1 on error * 0 on no change * 1 if a new color was allocated. */ static int AllocateAnsiColor(XtermWidget xw, ColorRes * res, const char *spec) { int result; XColor def; if (xtermAllocColor(xw, &def, spec)) { if ( #if OPT_COLOR_RES res->mode == True && #endif EQL_COLOR_RES(res, def.pixel)) { result = 0; } else { result = 1; SET_COLOR_RES(res, def.pixel); res->red = def.red; res->green = def.green; res->blue = def.blue; TRACE(("AllocateAnsiColor[%d] %s (rgb:%04x/%04x/%04x, pixel 0x%06lx)\n", (int) (res - TScreenOf(xw)->Acolors), spec, def.red, def.green, def.blue, def.pixel)); #if OPT_COLOR_RES if (!res->mode) result = 0; res->mode = True; #endif } } else { TRACE(("AllocateAnsiColor %s (failed)\n", spec)); result = -1; } return (result); } #if OPT_COLOR_RES Pixel xtermGetColorRes(XtermWidget xw, ColorRes * res) { Pixel result = 0; if (res->mode) { result = res->value; } else { TRACE(("xtermGetColorRes for Acolors[%d]\n", (int) (res - TScreenOf(xw)->Acolors))); if (res >= TScreenOf(xw)->Acolors) { assert(res - TScreenOf(xw)->Acolors < MAXCOLORS); if (AllocateAnsiColor(xw, res, res->resource) < 0) { res->value = TScreenOf(xw)->Tcolors[TEXT_FG].value; res->mode = -True; xtermWarning("Cannot allocate color \"%s\"\n", NonNull(res->resource)); } result = res->value; } else { result = 0; } } return result; } #endif static int ChangeOneAnsiColor(XtermWidget xw, int color, const char *name) { int code; if (color < 0 || color >= MAXCOLORS) { code = -1; } else { ColorRes *res = &(TScreenOf(xw)->Acolors[color]); TRACE(("ChangeAnsiColor for Acolors[%d]\n", color)); code = AllocateAnsiColor(xw, res, name); } return code; } /* * Set or query entries in the Acolors[] array by parsing pairs of color/name * values from the given buffer. * * The color can be any legal index into Acolors[], which consists of the * 16/88/256 "ANSI" colors, followed by special color values for the various * colorXX resources. The indices for the special color values are not * simple to work with, so an alternative is to use the calls which pass in * 'first' set to the beginning of those indices. * * If the name is "?", report to the host the current value for the color. */ static Bool ChangeAnsiColorRequest(XtermWidget xw, int opcode, char *buf, int first, int final) { int repaint = False; int code; int last = (MAXCOLORS - first); int queried = 0; TRACE(("ChangeAnsiColorRequest string='%s'\n", buf)); while (buf && *buf) { int color; char *name = strchr(buf, ';'); if (name == NULL) break; *name = '\0'; name++; color = atoi(buf); if (color < 0 || color >= last) break; /* quit on any error */ buf = strchr(name, ';'); if (buf) { *buf = '\0'; buf++; } if (!strcmp(name, "?")) { if (ReportAnsiColorRequest(xw, opcode, color + first, final)) ++queried; } else { code = ChangeOneAnsiColor(xw, color + first, name); if (code < 0) { /* stop on any error */ break; } else if (code > 0) { repaint = True; } /* FIXME: free old color somehow? We aren't for the other color * change style (dynamic colors). */ } } if (queried) unparse_end(xw); return (repaint); } static Bool ResetOneAnsiColor(XtermWidget xw, int color, int start) { Bool repaint = False; int last = MAXCOLORS - start; if (color >= 0 && color < last) { ColorRes *res = &(TScreenOf(xw)->Acolors[color + start]); if (res->mode) { /* a color has been allocated for this slot - test further... */ if (ChangeOneAnsiColor(xw, color + start, res->resource) > 0) { repaint = True; } } } return repaint; } int ResetAnsiColorRequest(XtermWidget xw, char *buf, int start) { int repaint = 0; int color; TRACE(("ResetAnsiColorRequest(%s)\n", buf)); if (*buf != '\0') { /* reset specific colors */ while (!IsEmpty(buf)) { char *next; color = (int) (strtol) (buf, &next, 10); if (!PartS2L(buf, next) || (color < 0)) break; /* no number at all */ if (next != 0) { if (strchr(";", *next) == 0) break; /* unexpected delimiter */ ++next; } if (ResetOneAnsiColor(xw, color, start)) { ++repaint; } buf = next; } } else { TRACE(("...resetting all %d colors\n", MAXCOLORS)); for (color = 0; color < MAXCOLORS; ++color) { if (ResetOneAnsiColor(xw, color, start)) { ++repaint; } } } TRACE(("...ResetAnsiColorRequest ->%d\n", repaint)); return repaint; } #else #define allocateClosestRGB(xw, cmap, def) 0 #define allocateExactRGB(xw, cmap, def) XAllocColor(TScreenOf(xw)->display, cmap, def) #endif /* OPT_ISO_COLORS */ Boolean allocateBestRGB(XtermWidget xw, XColor *def) { Colormap cmap = xw->core.colormap; return allocateExactRGB(xw, cmap, def) || allocateClosestRGB(xw, cmap, def); } static Boolean xtermAllocColor(XtermWidget xw, XColor *def, const char *spec) { Boolean result = False; TScreen *screen = TScreenOf(xw); Colormap cmap = xw->core.colormap; if (XParseColor(screen->display, cmap, spec, def)) { XColor save_def = *def; if (resource.reportColors) { printf("color %04x/%04x/%04x = \"%s\"\n", def->red, def->green, def->blue, spec); } if (allocateBestRGB(xw, def)) { if (resource.reportColors) { if (def->red != save_def.red || def->green != save_def.green || def->blue != save_def.blue) { printf("color %04x/%04x/%04x ~ \"%s\"\n", def->red, def->green, def->blue, spec); } } TRACE(("xtermAllocColor -> %x/%x/%x\n", def->red, def->green, def->blue)); result = True; } } return result; } /* * This provides an approximation (the closest color from xterm's palette) * rather than the "exact" color (whatever the display could provide, actually) * because of the context in which it is used. */ #define ColorDiff(given,cache) ((long) ((cache) >> 8) - (long) (given)) int xtermClosestColor(XtermWidget xw, int find_red, int find_green, int find_blue) { int result = -1; #if OPT_COLOR_RES && OPT_ISO_COLORS int n; int best_index = -1; unsigned long best_value = 0; unsigned long this_value; long diff_red, diff_green, diff_blue; TRACE(("xtermClosestColor(%x/%x/%x)\n", find_red, find_green, find_blue)); for (n = NUM_ANSI_COLORS - 1; n >= 0; --n) { ColorRes *res = &(TScreenOf(xw)->Acolors[n]); /* ensure that we have a value for each of the colors */ if (!res->mode) { (void) AllocateAnsiColor(xw, res, res->resource); } /* find the closest match */ if (res->mode == True) { TRACE2(("...lookup %lx -> %x/%x/%x\n", res->value, res->red, res->green, res->blue)); diff_red = ColorDiff(find_red, res->red); diff_green = ColorDiff(find_green, res->green); diff_blue = ColorDiff(find_blue, res->blue); this_value = (unsigned long) ((diff_red * diff_red) + (diff_green * diff_green) + (diff_blue * diff_blue)); if (best_index < 0 || this_value < best_value) { best_index = n; best_value = this_value; } } } TRACE(("...best match at %d with diff %lx\n", best_index, best_value)); result = best_index; #else (void) xw; (void) find_red; (void) find_green; (void) find_blue; #endif return result; } #if OPT_DIRECT_COLOR int getDirectColor(XtermWidget xw, int red, int green, int blue) { #define nRGB(name,shift) \ ((unsigned long)(name << xw->rgb_shifts[shift]) \ & xw->visInfo->name ##_mask) MyPixel result = (MyPixel) (nRGB(red, 0) | nRGB(green, 1) | nRGB(blue, 2)); return (int) result; } static void formatDirectColor(char *target, XtermWidget xw, unsigned value) { #define fRGB(name, shift) \ (value & xw->visInfo->name ## _mask) >> xw->rgb_shifts[shift] sprintf(target, "%lu:%lu:%lu", fRGB(red, 0), fRGB(green, 1), fRGB(blue, 2)); } #endif /* OPT_DIRECT_COLOR */ #define fg2SGR(n) \ (n) >= 8 ? 9 : 3, \ (n) >= 8 ? (n) - 8 : (n) #define bg2SGR(n) \ (n) >= 8 ? 10 : 4, \ (n) >= 8 ? (n) - 8 : (n) #define EndOf(s) (s) + strlen(s) char * xtermFormatSGR(XtermWidget xw, char *target, unsigned attr, int fg, int bg) { TScreen *screen = TScreenOf(xw); char *msg = target; strcpy(target, "0"); if (attr & BOLD) strcat(msg, ";1"); if (attr & UNDERLINE) strcat(msg, ";4"); if (attr & BLINK) strcat(msg, ";5"); if (attr & INVERSE) strcat(msg, ";7"); if (attr & INVISIBLE) strcat(msg, ";8"); #if OPT_WIDE_ATTRS if (attr & ATR_FAINT) strcat(msg, ";2"); if (attr & ATR_ITALIC) strcat(msg, ";3"); if (attr & ATR_STRIKEOUT) strcat(msg, ";9"); if (attr & ATR_DBL_UNDER) strcat(msg, ";21"); #endif #if OPT_256_COLORS || OPT_88_COLORS if_OPT_ISO_COLORS(screen, { if (attr & FG_COLOR) { if_OPT_DIRECT_COLOR2_else(screen, hasDirectFG(attr), { strcat(msg, ";38:2::"); formatDirectColor(EndOf(msg), xw, (unsigned) fg); }) if (fg >= 16) { sprintf(EndOf(msg), ";38:5:%d", fg); } else { sprintf(EndOf(msg), ";%d%d", fg2SGR(fg)); } } if (attr & BG_COLOR) { if_OPT_DIRECT_COLOR2_else(screen, hasDirectBG(attr), { strcat(msg, ";48:2::"); formatDirectColor(EndOf(msg), xw, (unsigned) bg); }) if (bg >= 16) { sprintf(EndOf(msg), ";48:5:%d", bg); } else { sprintf(EndOf(msg), ";%d%d", bg2SGR(bg)); } } }); #elif OPT_ISO_COLORS if_OPT_ISO_COLORS(screen, { if (attr & FG_COLOR) { sprintf(EndOf(msg), ";%d%d", fg2SGR(fg)); } if (attr & BG_COLOR) { sprintf(EndOf(msg), ";%d%d", bg2SGR(bg)); } }); #else (void) screen; (void) fg; (void) bg; #endif return target; } #if OPT_PASTE64 static void ManipulateSelectionData(XtermWidget xw, TScreen *screen, char *buf, int final) { #define PDATA(a,b) { a, #b } static struct { char given; String result; } table[] = { PDATA('s', SELECT), PDATA('p', PRIMARY), PDATA('q', SECONDARY), PDATA('c', CLIPBOARD), PDATA('0', CUT_BUFFER0), PDATA('1', CUT_BUFFER1), PDATA('2', CUT_BUFFER2), PDATA('3', CUT_BUFFER3), PDATA('4', CUT_BUFFER4), PDATA('5', CUT_BUFFER5), PDATA('6', CUT_BUFFER6), PDATA('7', CUT_BUFFER7), }; const char *base = buf; Cardinal j, n = 0; TRACE(("Manipulate selection data\n")); while (*buf != ';' && *buf != '\0') { ++buf; } if (*buf == ';') { char *used; *buf++ = '\0'; if (*base == '\0') base = "s0"; if ((used = x_strdup(base)) != 0) { String *select_args; if ((select_args = TypeCallocN(String, 2 + strlen(base))) != 0) { while (*base != '\0') { for (j = 0; j < XtNumber(table); ++j) { if (*base == table[j].given) { used[n] = *base; select_args[n++] = table[j].result; TRACE(("atom[%d] %s\n", n, table[j].result)); break; } } ++base; } used[n] = 0; if (!strcmp(buf, "?")) { if (AllowWindowOps(xw, ewGetSelection)) { TRACE(("Getting selection\n")); unparseputc1(xw, ANSI_OSC); unparseputs(xw, "52"); unparseputc(xw, ';'); unparseputs(xw, used); unparseputc(xw, ';'); /* Tell xtermGetSelection data is base64 encoded */ screen->base64_paste = n; screen->base64_final = final; screen->selection_time = XtLastTimestampProcessed(TScreenOf(xw)->display); /* terminator will be written in this call */ xtermGetSelection((Widget) xw, screen->selection_time, select_args, n, NULL); /* * select_args is used via SelectionReceived, cannot * free it here. */ } else { free(select_args); } } else { if (AllowWindowOps(xw, ewSetSelection)) { char *old = buf; TRACE(("Setting selection(%s) with %s\n", used, buf)); screen->selection_time = XtLastTimestampProcessed(TScreenOf(xw)->display); for (j = 0, buf = old; j < n; ++j) { ClearSelectionBuffer(screen, select_args[j]); while (*buf != '\0') { AppendToSelectionBuffer(screen, CharOf(*buf++), select_args[j]); } } CompleteSelection(xw, select_args, n); } free(select_args); } } free(used); } } } #endif /* OPT_PASTE64 */ /***====================================================================***/ #define IsSetUtf8Title(xw) (IsTitleMode(xw, tmSetUtf8) \ || (xw->screen.utf8_title) \ || (xw->screen.c1_printable)) static Bool xtermIsPrintable(XtermWidget xw, Char **bufp, Char *last) { TScreen *screen = TScreenOf(xw); Bool result = False; Char *cp = *bufp; Char *next = cp; (void) screen; (void) last; #if OPT_WIDE_CHARS if (xtermEnvUTF8() && IsSetUtf8Title(xw)) { PtyData data; if (decodeUtf8(screen, fakePtyData(&data, cp, last))) { if (data.utf_data != UCS_REPL && (data.utf_data >= 128 || ansi_table[data.utf_data] == CASE_PRINT)) { next += (data.utf_size - 1); result = True; } else { result = False; } } else { result = False; } } else #endif #if OPT_C1_PRINT if (screen->c1_printable && (*cp >= 128 && *cp < 160)) { result = True; } else #endif if (ansi_table[*cp] == CASE_PRINT) { result = True; } *bufp = next; return result; } /***====================================================================***/ /* * Enum corresponding to the actual OSC codes rather than the internal * array indices. Compare with TermColors. */ typedef enum { OSC_TEXT_FG = 10 ,OSC_TEXT_BG ,OSC_TEXT_CURSOR ,OSC_MOUSE_FG ,OSC_MOUSE_BG #if OPT_TEK4014 ,OSC_TEK_FG = 15 ,OSC_TEK_BG #endif #if OPT_HIGHLIGHT_COLOR ,OSC_HIGHLIGHT_BG = 17 #endif #if OPT_TEK4014 ,OSC_TEK_CURSOR = 18 #endif #if OPT_HIGHLIGHT_COLOR ,OSC_HIGHLIGHT_FG = 19 #endif ,OSC_NCOLORS } OscTextColors; /* * Map codes to OSC controls that can reset colors. */ #define OSC_RESET 100 #define OSC_Reset(code) (code) + OSC_RESET static Bool GetOldColors(XtermWidget xw) { if (xw->work.oldColors == NULL) { int i; xw->work.oldColors = TypeXtMalloc(ScrnColors); if (xw->work.oldColors == NULL) { xtermWarning("allocation failure in GetOldColors\n"); return (False); } xw->work.oldColors->which = 0; for (i = 0; i < NCOLORS; i++) { xw->work.oldColors->colors[i] = 0; xw->work.oldColors->names[i] = NULL; } GetColors(xw, xw->work.oldColors); } return (True); } static int oppositeColor(XtermWidget xw, int n) { Boolean reversed = (xw->misc.re_verse); switch (n) { case TEXT_FG: n = reversed ? TEXT_FG : TEXT_BG; break; case TEXT_BG: n = reversed ? TEXT_BG : TEXT_FG; break; case MOUSE_FG: n = MOUSE_BG; break; case MOUSE_BG: n = MOUSE_FG; break; #if OPT_TEK4014 case TEK_FG: n = reversed ? TEK_FG : TEK_BG; break; case TEK_BG: n = reversed ? TEK_BG : TEK_FG; break; #endif #if OPT_HIGHLIGHT_COLOR case HIGHLIGHT_FG: n = HIGHLIGHT_BG; break; case HIGHLIGHT_BG: n = HIGHLIGHT_FG; break; #endif default: break; } return n; } static Bool ReportColorRequest(XtermWidget xw, int ndx, int final) { Bool result = False; if (AllowColorOps(xw, ecGetColor)) { XColor color; Colormap cmap = xw->core.colormap; char buffer[80]; /* * ChangeColorsRequest() has "always" chosen the opposite color when * reverse-video is set. Report this as the original color index, but * reporting the opposite color which would be used. */ int i = (xw->misc.re_verse) ? oppositeColor(xw, ndx) : ndx; GetOldColors(xw); color.pixel = xw->work.oldColors->colors[ndx]; XQueryColor(TScreenOf(xw)->display, cmap, &color); sprintf(buffer, "%d;rgb:%04x/%04x/%04x", i + 10, color.red, color.green, color.blue); TRACE(("ReportColorRequest #%d: 0x%06lx as %s\n", ndx, xw->work.oldColors->colors[ndx], buffer)); unparseputc1(xw, ANSI_OSC); unparseputs(xw, buffer); unparseputc1(xw, final); result = True; } return result; } static Bool UpdateOldColors(XtermWidget xw GCC_UNUSED, ScrnColors * pNew) { int i; /* if we were going to free old colors, this would be the place to * do it. I've decided not to (for now), because it seems likely * that we'd have a small set of colors we use over and over, and that * we could save some overhead this way. The only case in which this * (clearly) fails is if someone is trying a boatload of colors, in * which case they can restart xterm */ for (i = 0; i < NCOLORS; i++) { if (COLOR_DEFINED(pNew, i)) { if (xw->work.oldColors->names[i] != NULL) { XtFree(xw->work.oldColors->names[i]); xw->work.oldColors->names[i] = NULL; } if (pNew->names[i]) { xw->work.oldColors->names[i] = pNew->names[i]; } xw->work.oldColors->colors[i] = pNew->colors[i]; } } return (True); } /* * OSC codes are constant, but the indices for the color arrays depend on how * xterm is compiled. */ static int OscToColorIndex(OscTextColors mode) { int result = 0; #define CASE(name) case OSC_##name: result = name; break switch (mode) { CASE(TEXT_FG); CASE(TEXT_BG); CASE(TEXT_CURSOR); CASE(MOUSE_FG); CASE(MOUSE_BG); #if OPT_TEK4014 CASE(TEK_FG); CASE(TEK_BG); #endif #if OPT_HIGHLIGHT_COLOR CASE(HIGHLIGHT_BG); CASE(HIGHLIGHT_FG); #endif #if OPT_TEK4014 CASE(TEK_CURSOR); #endif case OSC_NCOLORS: break; } return result; } static Bool ChangeColorsRequest(XtermWidget xw, int start, char *names, int final) { Bool result = False; ScrnColors newColors; TRACE(("ChangeColorsRequest start=%d, names='%s'\n", start, names)); if (GetOldColors(xw)) { int i; int queried = 0; newColors.which = 0; for (i = 0; i < NCOLORS; i++) { newColors.names[i] = NULL; } for (i = start; i < OSC_NCOLORS; i++) { int ndx = OscToColorIndex((OscTextColors) i); if (xw->misc.re_verse) ndx = oppositeColor(xw, ndx); if (IsEmpty(names)) { newColors.names[ndx] = NULL; } else { char *thisName = ((names[0] == ';') ? NULL : names); names = strchr(names, ';'); if (names != NULL) { *names++ = '\0'; } if (thisName != 0) { if (!strcmp(thisName, "?")) { if (ReportColorRequest(xw, ndx, final)) ++queried; } else if (!xw->work.oldColors->names[ndx] || strcmp(thisName, xw->work.oldColors->names[ndx])) { AllocateTermColor(xw, &newColors, ndx, thisName, False); } } } } if (newColors.which != 0) { ChangeColors(xw, &newColors); UpdateOldColors(xw, &newColors); } else if (queried) { unparse_end(xw); } result = True; } return result; } static Bool ResetColorsRequest(XtermWidget xw, int code) { Bool result = False; (void) xw; (void) code; TRACE(("ResetColorsRequest code=%d\n", code)); #if OPT_COLOR_RES if (GetOldColors(xw)) { ScrnColors newColors; const char *thisName; int ndx = OscToColorIndex((OscTextColors) (code - OSC_RESET)); if (xw->misc.re_verse) ndx = oppositeColor(xw, ndx); thisName = xw->screen.Tcolors[ndx].resource; newColors.which = 0; newColors.names[ndx] = NULL; if (thisName != 0 && xw->work.oldColors->names[ndx] != 0 && strcmp(thisName, xw->work.oldColors->names[ndx])) { AllocateTermColor(xw, &newColors, ndx, thisName, False); if (newColors.which != 0) { ChangeColors(xw, &newColors); UpdateOldColors(xw, &newColors); } } result = True; } #endif return result; } #if OPT_SHIFT_FONTS /* * Initially, 'source' points to '#' or '?'. * * Look for an optional sign and optional number. If those are found, lookup * the corresponding menu font entry. */ static int ParseShiftedFont(XtermWidget xw, String source, String *target) { TScreen *screen = TScreenOf(xw); int num = screen->menu_font_number; int rel = 0; if (*++source == '+') { rel = 1; source++; } else if (*source == '-') { rel = -1; source++; } if (isdigit(CharOf(*source))) { int val = atoi(source); if (rel > 0) rel = val; else if (rel < 0) rel = -val; else num = val; } if (rel != 0) { num = lookupRelativeFontSize(xw, screen->menu_font_number, rel); } TRACE(("ParseShiftedFont(%s) ->%d (%s)\n", *target, num, source)); *target = source; return num; } static void QueryFontRequest(XtermWidget xw, String buf, int final) { if (AllowFontOps(xw, efGetFont)) { TScreen *screen = TScreenOf(xw); Bool success = True; int num; String base = buf + 1; const char *name = 0; num = ParseShiftedFont(xw, buf, &buf); if (num < 0 || num > fontMenu_lastBuiltin) { Bell(xw, XkbBI_MinorError, 0); success = False; } else { #if OPT_RENDERFONT if (UsingRenderFont(xw)) { name = getFaceName(xw, False); } else #endif if ((name = screen->MenuFontName(num)) == 0) { success = False; } } unparseputc1(xw, ANSI_OSC); unparseputs(xw, "50"); if (success) { unparseputc(xw, ';'); if (buf >= base) { /* identify the font-entry, unless it is the current one */ if (*buf != '\0') { char temp[10]; unparseputc(xw, '#'); sprintf(temp, "%d", num); unparseputs(xw, temp); if (*name != '\0') unparseputc(xw, ' '); } } unparseputs(xw, name); } unparseputc1(xw, final); unparse_end(xw); } } static void ChangeFontRequest(XtermWidget xw, String buf) { if (AllowFontOps(xw, efSetFont)) { TScreen *screen = TScreenOf(xw); Bool success = True; int num; VTFontNames fonts; char *name; /* * If the font specification is a "#", followed by an optional sign and * optional number, lookup the corresponding menu font entry. * * Further, if the "#", etc., is followed by a font name, use that * to load the font entry. */ if (*buf == '#') { num = ParseShiftedFont(xw, buf, &buf); if (num < 0 || num > fontMenu_lastBuiltin) { Bell(xw, XkbBI_MinorError, 0); success = False; } else { /* * Skip past the optional number, and any whitespace to look * for a font specification within the control. */ while (isdigit(CharOf(*buf))) { ++buf; } while (isspace(CharOf(*buf))) { ++buf; } #if OPT_RENDERFONT if (UsingRenderFont(xw)) { /* EMPTY */ /* there is only one font entry to load */ ; } else #endif { /* * Normally there is no font specified in the control. * But if there is, simply overwrite the font entry. */ if (*buf == '\0') { if ((buf = screen->MenuFontName(num)) == 0) { success = False; } } } } } else { num = screen->menu_font_number; } name = x_strtrim(buf); if (screen->EscapeFontName()) { FREE_STRING(screen->EscapeFontName()); screen->EscapeFontName() = 0; } if (success && !IsEmpty(name)) { #if OPT_RENDERFONT if (UsingRenderFont(xw)) { setFaceName(xw, name); xtermUpdateFontInfo(xw, True); } else #endif { memset(&fonts, 0, sizeof(fonts)); fonts.f_n = name; SetVTFont(xw, num, True, &fonts); if (num == screen->menu_font_number && num != fontMenu_fontescape) { screen->EscapeFontName() = x_strdup(name); } } } else { Bell(xw, XkbBI_MinorError, 0); } update_font_escape(); free(name); } } #endif /* OPT_SHIFT_FONTS */ /***====================================================================***/ void do_osc(XtermWidget xw, Char *oscbuf, size_t len, int final) { TScreen *screen = TScreenOf(xw); int mode; Char *cp; int state = 0; char *buf = 0; char temp[2]; #if OPT_ISO_COLORS int ansi_colors = 0; #endif Bool need_data = True; Bool optional_data = False; TRACE(("do_osc %s\n", oscbuf)); (void) screen; /* * Lines should be of the form number ; string , however * older xterms can accept as a final character. We will respond * with the same final character as the application sends to make this * work better with shell scripts, which may have trouble reading an * , which is the 7-bit equivalent to . */ mode = 0; for (cp = oscbuf; *cp != '\0'; cp++) { switch (state) { case 0: if (isdigit(*cp)) { mode = 10 * mode + (*cp - '0'); if (mode > 65535) { TRACE(("do_osc found unknown mode %d\n", mode)); return; } break; } else { switch (*cp) { case 'I': xtermLoadIcon(xw, (char *) ++cp); return; case 'l': ChangeTitle(xw, (char *) ++cp); return; case 'L': ChangeIconName(xw, (char *) ++cp); return; } } /* FALLTHRU */ case 1: if (*cp != ';') { TRACE(("do_osc did not find semicolon offset %d\n", (int) (cp - oscbuf))); return; } state = 2; break; case 2: buf = (char *) cp; state = 3; /* FALLTHRU */ default: if (!xtermIsPrintable(xw, &cp, oscbuf + len)) { switch (mode) { case 0: case 1: case 2: break; default: TRACE(("do_osc found nonprinting char %02X offset %d\n", CharOf(*cp), (int) (cp - oscbuf))); return; } } } } /* * Check if the palette changed and there are no more immediate changes * that could be deferred to the next repaint. */ if (xw->work.palette_changed) { switch (mode) { case 03: /* change X property */ case 30: /* Konsole (unused) */ case 31: /* Konsole (unused) */ case 50: /* font operations */ case 51: /* Emacs (unused) */ #if OPT_PASTE64 case 52: /* selection data */ #endif TRACE(("forced repaint after palette changed\n")); xw->work.palette_changed = False; xtermRepaint(xw); break; } } /* * Most OSC controls other than resets require data. Handle the others as * a special case. */ switch (mode) { case 50: #if OPT_ISO_COLORS case OSC_Reset(4): case OSC_Reset(5): need_data = False; optional_data = True; break; case OSC_Reset(OSC_TEXT_FG): case OSC_Reset(OSC_TEXT_BG): case OSC_Reset(OSC_TEXT_CURSOR): case OSC_Reset(OSC_MOUSE_FG): case OSC_Reset(OSC_MOUSE_BG): #if OPT_HIGHLIGHT_COLOR case OSC_Reset(OSC_HIGHLIGHT_BG): case OSC_Reset(OSC_HIGHLIGHT_FG): #endif #if OPT_TEK4014 case OSC_Reset(OSC_TEK_FG): case OSC_Reset(OSC_TEK_BG): case OSC_Reset(OSC_TEK_CURSOR): #endif need_data = False; break; #endif default: break; } /* * Check if we have data when we want, and not when we do not want it. * Either way, that is a malformed control sequence, and will be ignored. */ if (IsEmpty(buf)) { if (need_data) { TRACE(("do_osc found no data\n")); return; } temp[0] = '\0'; buf = temp; } else if (!need_data && !optional_data) { TRACE(("do_osc found unwanted data\n")); return; } switch (mode) { case 0: /* new icon name and title */ ChangeIconName(xw, buf); ChangeTitle(xw, buf); break; case 1: /* new icon name only */ ChangeIconName(xw, buf); break; case 2: /* new title only */ ChangeTitle(xw, buf); break; case 3: /* change X property */ if (AllowWindowOps(xw, ewSetXprop)) ChangeXprop(buf); break; #if OPT_ISO_COLORS case 5: ansi_colors = NUM_ANSI_COLORS; /* FALLTHRU */ case 4: if (ChangeAnsiColorRequest(xw, mode, buf, ansi_colors, final)) xw->work.palette_changed = True; break; case 6: /* FALLTHRU */ case OSC_Reset(6): TRACE(("parse colorXXMode:%s\n", buf)); while (*buf != '\0') { long which = 0; long value = 0; char *next; if (*buf == ';') { ++buf; } else { which = strtol(buf, &next, 10); if (!PartS2L(buf, next) || (which < 0)) break; buf = next; if (*buf == ';') ++buf; } if (*buf == ';') { ++buf; } else { value = strtol(buf, &next, 10); if (!PartS2L(buf, next) || (value < 0)) break; buf = next; if (*buf == ';') ++buf; } TRACE(("updating colorXXMode which=%ld, value=%ld\n", which, value)); switch (which) { case 0: screen->colorBDMode = (value != 0); break; case 1: screen->colorULMode = (value != 0); break; case 2: screen->colorBLMode = (value != 0); break; case 3: screen->colorRVMode = (value != 0); break; #if OPT_WIDE_ATTRS case 4: screen->colorITMode = (value != 0); break; #endif default: TRACE(("...unknown colorXXMode\n")); break; } } break; case OSC_Reset(5): ansi_colors = NUM_ANSI_COLORS; /* FALLTHRU */ case OSC_Reset(4): if (ResetAnsiColorRequest(xw, buf, ansi_colors)) xw->work.palette_changed = True; break; #endif case OSC_TEXT_FG: case OSC_TEXT_BG: case OSC_TEXT_CURSOR: case OSC_MOUSE_FG: case OSC_MOUSE_BG: #if OPT_HIGHLIGHT_COLOR case OSC_HIGHLIGHT_BG: case OSC_HIGHLIGHT_FG: #endif #if OPT_TEK4014 case OSC_TEK_FG: case OSC_TEK_BG: case OSC_TEK_CURSOR: #endif if (xw->misc.dynamicColors) { ChangeColorsRequest(xw, mode, buf, final); } break; case OSC_Reset(OSC_TEXT_FG): case OSC_Reset(OSC_TEXT_BG): case OSC_Reset(OSC_TEXT_CURSOR): case OSC_Reset(OSC_MOUSE_FG): case OSC_Reset(OSC_MOUSE_BG): #if OPT_HIGHLIGHT_COLOR case OSC_Reset(OSC_HIGHLIGHT_BG): case OSC_Reset(OSC_HIGHLIGHT_FG): #endif #if OPT_TEK4014 case OSC_Reset(OSC_TEK_FG): case OSC_Reset(OSC_TEK_BG): case OSC_Reset(OSC_TEK_CURSOR): #endif if (xw->misc.dynamicColors) { ResetColorsRequest(xw, mode); } break; case 30: case 31: /* reserved for Konsole (Stephan Binner ) */ break; #ifdef ALLOWLOGGING case 46: /* new log file */ #ifdef ALLOWLOGFILECHANGES /* * Warning, enabling this feature allows people to overwrite * arbitrary files accessible to the person running xterm. */ if (strcmp(buf, "?")) { char *bp; if ((bp = x_strdup(buf)) != NULL) { if (screen->logfile) free(screen->logfile); screen->logfile = bp; break; } } #endif Bell(xw, XkbBI_Info, 0); Bell(xw, XkbBI_Info, 0); break; #endif /* ALLOWLOGGING */ case 50: #if OPT_SHIFT_FONTS if (*buf == '?') { QueryFontRequest(xw, buf, final); } else if (xw->misc.shift_fonts) { ChangeFontRequest(xw, buf); } #endif /* OPT_SHIFT_FONTS */ break; case 51: /* reserved for Emacs shell (Rob Mayoff ) */ break; #if OPT_PASTE64 case 52: ManipulateSelectionData(xw, screen, buf, final); break; #endif /* * One could write code to send back the display and host names, * but that could potentially open a fairly nasty security hole. */ default: TRACE(("do_osc - unrecognized code\n")); break; } unparse_end(xw); } /* * Parse one nibble of a hex byte from the OSC string. We have removed the * string-terminator (replacing it with a null), so the only other delimiter * that is expected is semicolon. Ignore other characters (Ray Neuman says * "real" terminals accept commas in the string definitions). */ static int udk_value(const char **cp) { int result = -1; for (;;) { int c; if ((c = **cp) != '\0') *cp = *cp + 1; if (c == ';' || c == '\0') break; if ((result = x_hex2int(c)) >= 0) break; } return result; } void reset_decudk(XtermWidget xw) { int n; for (n = 0; n < MAX_UDK; n++) { if (xw->work.user_keys[n].str != 0) { free(xw->work.user_keys[n].str); xw->work.user_keys[n].str = 0; xw->work.user_keys[n].len = 0; } } } /* * Parse the data for DECUDK (user-defined keys). */ static void parse_decudk(XtermWidget xw, const char *cp) { while (*cp) { const char *base = cp; char *str = TextAlloc(strlen(cp) + 2); unsigned key = 0; int len = 0; if (str == NULL) break; while (isdigit(CharOf(*cp))) key = (key * 10) + (unsigned) (*cp++ - '0'); if (*cp == '/') { int lo, hi; cp++; while ((hi = udk_value(&cp)) >= 0 && (lo = udk_value(&cp)) >= 0) { str[len++] = (char) ((hi << 4) | lo); } } if (len > 0 && key < MAX_UDK) { str[len] = '\0'; if (xw->work.user_keys[key].str != 0) free(xw->work.user_keys[key].str); xw->work.user_keys[key].str = str; xw->work.user_keys[key].len = len; TRACE(("parse_decudk %d:%.*s\n", key, len, str)); } else { free(str); } if (*cp == ';') cp++; if (cp == base) /* badly-formed sequence - bail out */ break; } } /* * Parse numeric parameters. Normally we use a state machine to simplify * interspersing with control characters, but have the string already. */ static void parse_ansi_params(ANSI *params, const char **string) { const char *cp = *string; ParmType nparam = 0; int last_empty = 1; memset(params, 0, sizeof(*params)); while (*cp != '\0') { Char ch = CharOf(*cp++); if (isdigit(ch)) { last_empty = 0; if (nparam < NPARAM) { params->a_param[nparam] = (ParmType) ((params->a_param[nparam] * 10) + (ch - '0')); } } else if (ch == ';') { last_empty = 1; nparam++; } else if (ch < 32) { /* EMPTY */ ; } else { /* should be 0x30 to 0x7e */ params->a_final = ch; break; } } *string = cp; if (!last_empty) nparam++; if (nparam > NPARAM) params->a_nparam = NPARAM; else params->a_nparam = nparam; } #if OPT_TRACE #define SOFT_WIDE 10 #define SOFT_HIGH 20 static void parse_decdld(ANSI *params, const char *string) { char DscsName[8]; int len; int Pfn = params->a_param[0]; int Pcn = params->a_param[1]; int Pe = params->a_param[2]; int Pcmw = params->a_param[3]; int Pw = params->a_param[4]; int Pt = params->a_param[5]; int Pcmh = params->a_param[6]; int Pcss = params->a_param[7]; int start_char = Pcn + 0x20; int char_wide = ((Pcmw == 0) ? (Pcss ? 6 : 10) : (Pcmw > 4 ? Pcmw : (Pcmw + 3))); int char_high = ((Pcmh == 0) ? ((Pcmw >= 2 && Pcmw <= 4) ? 10 : 20) : Pcmh); Char ch; Char bits[SOFT_HIGH][SOFT_WIDE]; Bool first = True; Bool prior = False; int row = 0, col = 0; TRACE(("Parsing DECDLD\n")); TRACE((" font number %d\n", Pfn)); TRACE((" starting char %d\n", Pcn)); TRACE((" erase control %d\n", Pe)); TRACE((" char-width %d\n", Pcmw)); TRACE((" font-width %d\n", Pw)); TRACE((" text/full %d\n", Pt)); TRACE((" char-height %d\n", Pcmh)); TRACE((" charset-size %d\n", Pcss)); if (Pfn > 1 || Pcn > 95 || Pe > 2 || Pcmw > 10 || Pcmw == 1 || Pt > 2 || Pcmh > 20 || Pcss > 1 || char_wide > SOFT_WIDE || char_high > SOFT_HIGH) { TRACE(("DECDLD illegal parameter\n")); return; } len = 0; while (*string != '\0') { ch = CharOf(*string++); if (ch >= ANSI_SPA && ch <= 0x2f) { if (len < 2) DscsName[len++] = (char) ch; } else if (ch >= 0x30 && ch <= 0x7e) { DscsName[len++] = (char) ch; break; } } DscsName[len] = 0; TRACE((" Dscs name '%s'\n", DscsName)); TRACE((" character matrix %dx%d\n", char_high, char_wide)); while (*string != '\0') { if (first) { TRACE(("Char %d:\n", start_char)); if (prior) { for (row = 0; row < char_high; ++row) { TRACE(("%.*s\n", char_wide, bits[row])); } } prior = False; first = False; for (row = 0; row < char_high; ++row) { for (col = 0; col < char_wide; ++col) { bits[row][col] = '.'; } } row = col = 0; } ch = CharOf(*string++); if (ch >= 0x3f && ch <= 0x7e) { int n; ch = CharOf(ch - 0x3f); for (n = 0; n < 6; ++n) { bits[row + n][col] = CharOf((ch & (1 << n)) ? '*' : '.'); } col += 1; prior = True; } else if (ch == '/') { row += 6; col = 0; } else if (ch == ';') { first = True; ++start_char; } } } #else #define parse_decdld(p,q) /* nothing */ #endif #if OPT_DEC_RECTOPS static const char * skip_params(const char *cp) { while (*cp == ';' || (*cp >= '0' && *cp <= '9')) ++cp; return cp; } static int parse_int_param(const char **cp) { int result = 0; const char *s = *cp; while (*s != '\0') { if (*s == ';') { ++s; break; } else if (*s >= '0' && *s <= '9') { result = (result * 10) + (*s++ - '0'); } else { s += strlen(s); } } TRACE(("parse-int %s ->%d, %#x->%s\n", *cp, result, result, s)); *cp = s; return result; } static int parse_chr_param(const char **cp) { int result = 0; const char *s = *cp; if (*s != '\0') { if ((result = CharOf(*s++)) != 0) { if (*s == ';') { ++s; } else if (*s != '\0') { result = 0; } } } TRACE(("parse-chr %s ->%d, %#x->%s\n", *cp, result, result, s)); *cp = s; return result; } static void restore_DECCIR(XtermWidget xw, const char *cp) { TScreen *screen = TScreenOf(xw); int value; /* row */ if ((value = parse_int_param(&cp)) <= 0 || value > MaxRows(screen)) return; screen->cur_row = (value - 1); /* column */ if ((value = parse_int_param(&cp)) <= 0 || value > MaxCols(screen)) return; screen->cur_col = (value - 1); /* page */ if ((value = parse_int_param(&cp)) != 1) return; /* rendition */ if (((value = parse_chr_param(&cp)) & 0xf0) != 0x40) return; UIntClr(xw->flags, (INVERSE | BLINK | UNDERLINE | BOLD)); xw->flags |= (value & 8) ? INVERSE : 0; xw->flags |= (value & 4) ? BLINK : 0; xw->flags |= (value & 2) ? UNDERLINE : 0; xw->flags |= (value & 1) ? BOLD : 0; /* attributes */ if (((value = parse_chr_param(&cp)) & 0xfe) != 0x40) return; screen->protected_mode &= ~DEC_PROTECT; screen->protected_mode |= (value & 1) ? DEC_PROTECT : 0; /* flags */ if (((value = parse_chr_param(&cp)) & 0xf0) != 0x40) return; screen->do_wrap = (value & 8) ? True : False; screen->curss = (Char) ((value & 4) ? 3 : ((value & 2) ? 2 : 0)); UIntClr(xw->flags, ORIGIN); xw->flags |= (value & 1) ? ORIGIN : 0; if ((value = (parse_chr_param(&cp) - '0')) < 0 || value >= NUM_GSETS) return; screen->curgl = (Char) value; if ((value = (parse_chr_param(&cp) - '0')) < 0 || value >= NUM_GSETS) return; screen->curgr = (Char) value; /* character-set size */ if ((value = parse_chr_param(&cp)) != 0x4f) /* works for xterm */ return; /* SCS designators */ for (value = 0; value < NUM_GSETS; ++value) { if (*cp == '%') { xtermDecodeSCS(xw, value, '%', *++cp); } else if (*cp != '\0') { xtermDecodeSCS(xw, value, '\0', *cp); } else { return; } cp++; } TRACE(("...done DECCIR\n")); } static void restore_DECTABSR(XtermWidget xw, const char *cp) { int stop = 0; Bool fail = False; TabZonk(xw->tabs); while (*cp != '\0' && !fail) { if ((*cp) >= '0' && (*cp) <= '9') { stop = (stop * 10) + ((*cp) - '0'); } else if (*cp == '/') { --stop; if (OkTAB(stop)) { TabSet(xw->tabs, stop); stop = 0; } else { fail = True; } } else { fail = True; } ++cp; } --stop; if (OkTAB(stop)) TabSet(xw->tabs, stop); TRACE(("...done DECTABSR\n")); } #endif void do_dcs(XtermWidget xw, Char *dcsbuf, size_t dcslen) { TScreen *screen = TScreenOf(xw); char reply[BUFSIZ]; const char *cp = (const char *) dcsbuf; Bool okay; ANSI params; #if OPT_DEC_RECTOPS char psarg = '0'; #endif TRACE(("do_dcs(%s:%lu)\n", (char *) dcsbuf, (unsigned long) dcslen)); if (dcslen != strlen(cp)) /* shouldn't have nulls in the string */ return; switch (*cp) { /* intermediate character, or parameter */ case '$': /* DECRQSS */ okay = True; cp++; if (*cp == 'q') { *reply = '\0'; cp++; if (!strcmp(cp, "\"q")) { /* DECSCA */ TRACE(("DECRQSS -> DECSCA\n")); sprintf(reply, "%d%s", (screen->protected_mode == DEC_PROTECT) && (xw->flags & PROTECTED) ? 1 : 0, cp); } else if (!strcmp(cp, "\"p")) { /* DECSCL */ if (screen->vtXX_level < 2) { /* actually none of DECRQSS is valid for vt100's */ break; } TRACE(("DECRQSS -> DECSCL\n")); sprintf(reply, "%d%s%s", (screen->vtXX_level ? screen->vtXX_level : 1) + 60, (screen->vtXX_level >= 2) ? (screen->control_eight_bits ? ";0" : ";1") : "", cp); } else if (!strcmp(cp, "r")) { /* DECSTBM */ TRACE(("DECRQSS -> DECSTBM\n")); sprintf(reply, "%d;%dr", screen->top_marg + 1, screen->bot_marg + 1); } else if (!strcmp(cp, "s")) { /* DECSLRM */ if (screen->vtXX_level >= 4) { /* VT420 */ TRACE(("DECRQSS -> DECSLRM\n")); sprintf(reply, "%d;%ds", screen->lft_marg + 1, screen->rgt_marg + 1); } else { okay = False; } } else if (!strcmp(cp, "m")) { /* SGR */ TRACE(("DECRQSS -> SGR\n")); xtermFormatSGR(xw, reply, xw->flags, xw->cur_foreground, xw->cur_background); strcat(reply, "m"); } else if (!strcmp(cp, " q")) { /* DECSCUSR */ int code = STEADY_BLOCK; if (isCursorUnderline(screen)) code = STEADY_UNDERLINE; else if (isCursorBar(screen)) code = STEADY_BAR; #if OPT_BLINK_CURS if (screen->cursor_blink_esc != 0) code -= 1; #endif TRACE(("reply DECSCUSR\n")); sprintf(reply, "%d%s", code, cp); } else if (!strcmp(cp, "t")) { /* DECSLPP */ sprintf(reply, "%d%s", ((screen->max_row > 24) ? screen->max_row : 24), cp); TRACE(("reply DECSLPP\n")); } else if (!strcmp(cp, "$|")) { /* DECSCPP */ TRACE(("reply DECSCPP\n")); sprintf(reply, "%d%s", ((xw->flags & IN132COLUMNS) ? 132 : 80), cp); } else if (!strcmp(cp, "*|")) { /* DECSNLS */ TRACE(("reply DECSNLS\n")); sprintf(reply, "%d%s", screen->max_row + 1, cp); } else { okay = False; } unparseputc1(xw, ANSI_DCS); unparseputc(xw, okay ? '1' : '0'); unparseputc(xw, '$'); unparseputc(xw, 'r'); cp = reply; unparseputs(xw, cp); unparseputc1(xw, ANSI_ST); } else { unparseputc(xw, ANSI_CAN); } break; case '+': cp++; switch (*cp) { #if OPT_TCAP_QUERY case 'p': if (AllowTcapOps(xw, etSetTcap)) { set_termcap(xw, cp + 1); } break; case 'q': if (AllowTcapOps(xw, etGetTcap)) { Bool fkey; unsigned state; int code; const char *tmp; const char *parsed = ++cp; code = xtermcapKeycode(xw, &parsed, &state, &fkey); unparseputc1(xw, ANSI_DCS); unparseputc(xw, code >= 0 ? '1' : '0'); unparseputc(xw, '+'); unparseputc(xw, 'r'); while (*cp != 0 && (code >= -1)) { if (cp == parsed) break; /* no data found, error */ for (tmp = cp; tmp != parsed; ++tmp) unparseputc(xw, *tmp); if (code >= 0) { unparseputc(xw, '='); screen->tc_query_code = code; screen->tc_query_fkey = fkey; #if OPT_ISO_COLORS /* XK_COLORS is a fake code for the "Co" entry (maximum * number of colors) */ if (code == XK_COLORS) { unparseputn(xw, (unsigned) NUM_ANSI_COLORS); } else #if OPT_DIRECT_COLOR if (code == XK_RGB) { if (TScreenOf(xw)->direct_color && xw->has_rgb) { if (xw->rgb_widths[0] == xw->rgb_widths[1] && xw->rgb_widths[1] == xw->rgb_widths[2]) { unparseputn(xw, xw->rgb_widths[0]); } else { char temp[1024]; sprintf(temp, "%d/%d/%d", xw->rgb_widths[0], xw->rgb_widths[1], xw->rgb_widths[2]); unparseputs(xw, temp); } } else { unparseputs(xw, "-1"); } } else #endif #endif if (code == XK_TCAPNAME) { unparseputs(xw, resource.term_name); } else { XKeyEvent event; memset(&event, 0, sizeof(event)); event.state = state; Input(xw, &event, False); } screen->tc_query_code = -1; } else { break; /* no match found, error */ } cp = parsed; if (*parsed == ';') { unparseputc(xw, *parsed++); cp = parsed; code = xtermcapKeycode(xw, &parsed, &state, &fkey); } } unparseputc1(xw, ANSI_ST); } break; #endif #if OPT_XRES_QUERY case 'Q': ++cp; if (AllowXResOps(xw)) { Boolean first = True; while (*cp != '\0') { const char *parsed = 0; const char *tmp; char *name = x_decode_hex(cp, &parsed); char *value; char *result; if (cp == parsed || name == NULL) { free(name); break; /* no data found, error */ } TRACE(("query-feature '%s'\n", name)); if ((value = vt100ResourceToString(xw, name)) != 0) { okay = True; /* valid */ } else { okay = False; /* invalid */ } if (first) { unparseputc1(xw, ANSI_DCS); unparseputc(xw, okay ? '1' : '0'); unparseputc(xw, '+'); unparseputc(xw, 'R'); first = False; } for (tmp = cp; tmp != parsed; ++tmp) unparseputc(xw, *tmp); if (value != 0) { unparseputc1(xw, '='); result = x_encode_hex(value); unparseputs(xw, result); } else { result = NULL; } free(name); free(value); free(result); cp = parsed; if (*parsed == ';') { unparseputc(xw, *parsed++); cp = parsed; } } if (!first) unparseputc1(xw, ANSI_ST); } break; #endif } break; #if OPT_DEC_RECTOPS case '1': /* FALLTHRU */ case '2': if (*skip_params(cp) == '$') { psarg = *cp++; if ((*cp++ == '$') && (*cp++ == 't') && (screen->vtXX_level >= 3)) { switch (psarg) { case '1': TRACE(("DECRSPS (DECCIR)\n")); restore_DECCIR(xw, cp); break; case '2': TRACE(("DECRSPS (DECTABSR)\n")); restore_DECTABSR(xw, cp); break; } } break; } #endif /* FALLTHRU */ default: if (screen->terminal_id == 125 || screen->vtXX_level >= 2) { /* VT220 */ parse_ansi_params(¶ms, &cp); switch (params.a_final) { case 'p': #if OPT_REGIS_GRAPHICS if (screen->terminal_id == 125 || screen->terminal_id == 240 || screen->terminal_id == 241 || screen->terminal_id == 330 || screen->terminal_id == 340) { parse_regis(xw, ¶ms, cp); } #else TRACE(("ignoring ReGIS graphic (compilation flag not enabled)\n")); #endif break; case 'q': #if OPT_SIXEL_GRAPHICS if (screen->terminal_id == 125 || screen->terminal_id == 240 || screen->terminal_id == 241 || screen->terminal_id == 330 || screen->terminal_id == 340 || screen->terminal_id == 382) { (void) parse_sixel(xw, ¶ms, cp); } #else TRACE(("ignoring sixel graphic (compilation flag not enabled)\n")); #endif break; case '|': /* DECUDK */ if (screen->vtXX_level >= 2) { /* VT220 */ if (params.a_param[0] == 0) reset_decudk(xw); parse_decudk(xw, cp); } break; case L_CURL: /* DECDLD */ if (screen->vtXX_level >= 2) { /* VT220 */ parse_decdld(¶ms, cp); } break; } } break; } unparse_end(xw); } #if OPT_DEC_RECTOPS enum { mdUnknown = 0, mdMaybeSet = 1, mdMaybeReset = 2, mdAlwaysSet = 3, mdAlwaysReset = 4 }; #define MdBool(bool) ((bool) ? mdMaybeSet : mdMaybeReset) #define MdFlag(mode,flag) MdBool((mode) & (flag)) /* * Reply is the same format as the query, with pair of mode/value: * 0 - not recognized * 1 - set * 2 - reset * 3 - permanently set * 4 - permanently reset * Only one mode can be reported at a time. */ void do_ansi_rqm(XtermWidget xw, int nparams, int *params) { ANSI reply; int count = 0; TRACE(("do_ansi_rqm %d:%d\n", nparams, params[0])); memset(&reply, 0, sizeof(reply)); if (nparams >= 1) { int result = mdUnknown; /* DECRQM can only ask about one mode at a time */ switch (params[0]) { case 1: /* GATM */ result = mdAlwaysReset; break; case 2: result = MdFlag(xw->keyboard.flags, MODE_KAM); break; case 3: /* CRM */ result = mdMaybeReset; break; case 4: result = MdFlag(xw->flags, INSERT); break; case 5: /* SRTM */ case 7: /* VEM */ case 10: /* HEM */ case 11: /* PUM */ result = mdAlwaysReset; break; case 12: result = MdFlag(xw->keyboard.flags, MODE_SRM); break; case 13: /* FEAM */ case 14: /* FETM */ case 15: /* MATM */ case 16: /* TTM */ case 17: /* SATM */ case 18: /* TSM */ case 19: /* EBM */ result = mdAlwaysReset; break; case 20: result = MdFlag(xw->flags, LINEFEED); break; } reply.a_param[count++] = (ParmType) params[0]; reply.a_param[count++] = (ParmType) result; } reply.a_type = ANSI_CSI; reply.a_nparam = (ParmType) count; reply.a_inters = '$'; reply.a_final = 'y'; unparseseq(xw, &reply); } void do_dec_rqm(XtermWidget xw, int nparams, int *params) { ANSI reply; int count = 0; TRACE(("do_dec_rqm %d:%d\n", nparams, params[0])); memset(&reply, 0, sizeof(reply)); if (nparams >= 1) { TScreen *screen = TScreenOf(xw); int result = mdUnknown; /* DECRQM can only ask about one mode at a time */ switch ((DECSET_codes) params[0]) { case srm_DECCKM: result = MdFlag(xw->keyboard.flags, MODE_DECCKM); break; case srm_DECANM: /* ANSI/VT52 mode */ #if OPT_VT52_MODE result = MdBool(screen->vtXX_level >= 1); #else result = mdMaybeSet; #endif break; case srm_DECCOLM: result = MdFlag(xw->flags, IN132COLUMNS); break; case srm_DECSCLM: /* (slow scroll) */ result = MdFlag(xw->flags, SMOOTHSCROLL); break; case srm_DECSCNM: result = MdFlag(xw->flags, REVERSE_VIDEO); break; case srm_DECOM: result = MdFlag(xw->flags, ORIGIN); break; case srm_DECAWM: result = MdFlag(xw->flags, WRAPAROUND); break; case srm_DECARM: result = mdAlwaysReset; break; case srm_X10_MOUSE: /* X10 mouse */ result = MdBool(screen->send_mouse_pos == X10_MOUSE); break; #if OPT_TOOLBAR case srm_RXVT_TOOLBAR: result = MdBool(resource.toolBar); break; #endif #if OPT_BLINK_CURS case srm_ATT610_BLINK: /* AT&T 610: Start/stop blinking cursor */ result = MdBool(screen->cursor_blink_esc); break; case srm_CURSOR_BLINK_OPS: switch (screen->cursor_blink) { case cbTrue: result = mdMaybeSet; break; case cbFalse: result = mdMaybeReset; break; case cbAlways: result = mdAlwaysSet; break; case cbLAST: /* FALLTHRU */ case cbNever: result = mdAlwaysReset; break; } break; case srm_XOR_CURSOR_BLINKS: result = (screen->cursor_blink_xor ? mdAlwaysSet : mdAlwaysReset); break; #endif case srm_DECPFF: /* print form feed */ result = MdBool(PrinterOf(screen).printer_formfeed); break; case srm_DECPEX: /* print extent */ result = MdBool(PrinterOf(screen).printer_extent); break; case srm_DECTCEM: /* Show/hide cursor (VT200) */ result = MdBool(screen->cursor_set); break; case srm_RXVT_SCROLLBAR: result = MdBool(screen->fullVwin.sb_info.width != OFF); break; #if OPT_SHIFT_FONTS case srm_RXVT_FONTSIZE: result = MdBool(xw->misc.shift_fonts); break; #endif #if OPT_TEK4014 case srm_DECTEK: result = MdBool(TEK4014_ACTIVE(xw)); break; #endif case srm_132COLS: result = MdBool(screen->c132); break; case srm_CURSES_HACK: result = MdBool(screen->curses); break; case srm_DECNRCM: /* national charset (VT220) */ if (screen->vtXX_level >= 2) { result = MdFlag(xw->flags, NATIONAL); } else { result = 0; } break; case srm_MARGIN_BELL: /* margin bell */ result = MdBool(screen->marginbell); break; case srm_REVERSEWRAP: /* reverse wraparound */ result = MdFlag(xw->flags, REVERSEWRAP); break; #ifdef ALLOWLOGGING case srm_ALLOWLOGGING: /* logging */ #ifdef ALLOWLOGFILEONOFF result = MdBool(screen->logging); #else result = ((MdBool(screen->logging) == mdMaybeSet) ? mdAlwaysSet : mdAlwaysReset); #endif /* ALLOWLOGFILEONOFF */ break; #endif case srm_OPT_ALTBUF_CURSOR: /* alternate buffer & cursor */ /* FALLTHRU */ case srm_OPT_ALTBUF: /* FALLTHRU */ case srm_ALTBUF: result = MdBool(screen->whichBuf); break; case srm_DECNKM: result = MdFlag(xw->keyboard.flags, MODE_DECKPAM); break; case srm_DECBKM: result = MdFlag(xw->keyboard.flags, MODE_DECBKM); break; case srm_DECLRMM: if (screen->vtXX_level >= 4) { /* VT420 */ result = MdFlag(xw->flags, LEFT_RIGHT); } else { result = 0; } break; #if OPT_SIXEL_GRAPHICS case srm_DECSDM: result = MdFlag(xw->keyboard.flags, MODE_DECSDM); break; #endif case srm_DECNCSM: if (screen->vtXX_level >= 5) { /* VT510 */ result = MdFlag(xw->flags, NOCLEAR_COLM); } else { result = 0; } break; case srm_VT200_MOUSE: /* xterm bogus sequence */ result = MdBool(screen->send_mouse_pos == VT200_MOUSE); break; case srm_VT200_HIGHLIGHT_MOUSE: /* xterm sequence w/hilite tracking */ result = MdBool(screen->send_mouse_pos == VT200_HIGHLIGHT_MOUSE); break; case srm_BTN_EVENT_MOUSE: result = MdBool(screen->send_mouse_pos == BTN_EVENT_MOUSE); break; case srm_ANY_EVENT_MOUSE: result = MdBool(screen->send_mouse_pos == ANY_EVENT_MOUSE); break; #if OPT_FOCUS_EVENT case srm_FOCUS_EVENT_MOUSE: result = MdBool(screen->send_focus_pos); break; #endif case srm_EXT_MODE_MOUSE: /* FALLTHRU */ case srm_SGR_EXT_MODE_MOUSE: /* FALLTHRU */ case srm_URXVT_EXT_MODE_MOUSE: result = MdBool(screen->extend_coords == params[0]); break; case srm_ALTERNATE_SCROLL: result = MdBool(screen->alternateScroll); break; case srm_RXVT_SCROLL_TTY_OUTPUT: result = MdBool(screen->scrollttyoutput); break; case srm_RXVT_SCROLL_TTY_KEYPRESS: result = MdBool(screen->scrollkey); break; case srm_EIGHT_BIT_META: result = MdBool(screen->eight_bit_meta); break; #if OPT_NUM_LOCK case srm_REAL_NUMLOCK: result = MdBool(xw->misc.real_NumLock); break; case srm_META_SENDS_ESC: result = MdBool(screen->meta_sends_esc); break; #endif case srm_DELETE_IS_DEL: result = MdBool(xtermDeleteIsDEL(xw)); break; #if OPT_NUM_LOCK case srm_ALT_SENDS_ESC: result = MdBool(screen->alt_sends_esc); break; #endif case srm_KEEP_SELECTION: result = MdBool(screen->keepSelection); break; case srm_SELECT_TO_CLIPBOARD: result = MdBool(screen->selectToClipboard); break; case srm_BELL_IS_URGENT: result = MdBool(screen->bellIsUrgent); break; case srm_POP_ON_BELL: result = MdBool(screen->poponbell); break; case srm_KEEP_CLIPBOARD: result = MdBool(screen->keepClipboard); break; case srm_ALLOW_ALTBUF: result = MdBool(xw->misc.titeInhibit); break; case srm_SAVE_CURSOR: result = MdBool(screen->sc[screen->whichBuf].saved); break; #if OPT_TCAP_FKEYS case srm_TCAP_FKEYS: result = MdBool(xw->keyboard.type == keyboardIsTermcap); break; #endif #if OPT_SUN_FUNC_KEYS case srm_SUN_FKEYS: result = MdBool(xw->keyboard.type == keyboardIsSun); break; #endif #if OPT_HP_FUNC_KEYS case srm_HP_FKEYS: result = MdBool(xw->keyboard.type == keyboardIsHP); break; #endif #if OPT_SCO_FUNC_KEYS case srm_SCO_FKEYS: result = MdBool(xw->keyboard.type == keyboardIsSCO); break; #endif case srm_LEGACY_FKEYS: result = MdBool(xw->keyboard.type == keyboardIsLegacy); break; #if OPT_SUNPC_KBD case srm_VT220_FKEYS: result = MdBool(xw->keyboard.type == keyboardIsVT220); break; #endif #if OPT_PASTE64 || OPT_READLINE case srm_PASTE_IN_BRACKET: result = MdBool(SCREEN_FLAG(screen, paste_brackets)); break; #endif #if OPT_READLINE case srm_BUTTON1_MOVE_POINT: result = MdBool(SCREEN_FLAG(screen, click1_moves)); break; case srm_BUTTON2_MOVE_POINT: result = MdBool(SCREEN_FLAG(screen, paste_moves)); break; case srm_DBUTTON3_DELETE: result = MdBool(SCREEN_FLAG(screen, dclick3_deletes)); break; case srm_PASTE_QUOTE: result = MdBool(SCREEN_FLAG(screen, paste_quotes)); break; case srm_PASTE_LITERAL_NL: result = MdBool(SCREEN_FLAG(screen, paste_literal_nl)); break; #endif /* OPT_READLINE */ #if OPT_GRAPHICS case srm_PRIVATE_COLOR_REGISTERS: result = MdBool(screen->privatecolorregisters); break; #endif #if OPT_SIXEL_GRAPHICS case srm_SIXEL_SCROLLS_RIGHT: result = MdBool(screen->sixel_scrolls_right); break; #endif default: TRACE(("DATA_ERROR: requested report for unknown private mode %d\n", params[0])); } reply.a_param[count++] = (ParmType) params[0]; reply.a_param[count++] = (ParmType) result; TRACE(("DECRPM(%d) = %d\n", params[0], result)); } reply.a_type = ANSI_CSI; reply.a_pintro = '?'; reply.a_nparam = (ParmType) count; reply.a_inters = '$'; reply.a_final = 'y'; unparseseq(xw, &reply); } #endif /* OPT_DEC_RECTOPS */ char * udk_lookup(XtermWidget xw, int keycode, int *len) { char *result = NULL; if (keycode >= 0 && keycode < MAX_UDK) { *len = xw->work.user_keys[keycode].len; result = xw->work.user_keys[keycode].str; TRACE(("udk_lookup(%d) = %.*s\n", keycode, *len, result)); } else { TRACE(("udk_lookup(%d) = \n", keycode)); } return result; } #if OPT_REPORT_ICONS void report_icons(const char *fmt, ...) { if (resource.reportIcons) { va_list ap; va_start(ap, fmt); vfprintf(stdout, fmt, ap); va_end(ap); #if OPT_TRACE va_start(ap, fmt); TraceVA(fmt, ap); va_end(ap); #endif } } #endif #ifdef HAVE_LIBXPM #ifndef PIXMAP_ROOTDIR #define PIXMAP_ROOTDIR "/usr/share/pixmaps/" #endif typedef struct { const char *name; const char *const *data; } XPM_DATA; static char * x_find_icon(char **work, int *state, const char *filename, const char *suffix) { const char *prefix = PIXMAP_ROOTDIR; const char *larger = "_48x48"; char *result = 0; if (*state >= 0) { if ((*state & 1) == 0) suffix = ""; if ((*state & 2) == 0) larger = ""; if ((*state & 4) == 0) { prefix = ""; } else if (!strncmp(filename, "/", (size_t) 1) || !strncmp(filename, "./", (size_t) 2) || !strncmp(filename, "../", (size_t) 3)) { *state = -1; } else if (*state >= 8) { *state = -1; } } if (*state >= 0) { size_t length; if (*work) { free(*work); *work = 0; } length = 3 + strlen(prefix) + strlen(filename) + strlen(larger) + strlen(suffix); if ((result = malloc(length)) != 0) { sprintf(result, "%s%s%s%s", prefix, filename, larger, suffix); *work = result; } *state += 1; } TRACE(("x_find_icon %d:%s ->%s\n", *state, filename, NonNull(result))); return result; } #if OPT_BUILTIN_XPMS static const XPM_DATA * built_in_xpm(const XPM_DATA * table, Cardinal length, const char *find) { const XPM_DATA *result = 0; if (!IsEmpty(find)) { Cardinal n; for (n = 0; n < length; ++n) { if (!x_strcasecmp(find, table[n].name)) { result = table + n; ReportIcons(("use builtin-icon %s\n", table[n].name)); break; } } /* * As a fallback, check if the icon name matches without the lengths, * which are all _HHxWW format. */ if (result == 0) { const char *base = table[0].name; const char *last = strchr(base, '_'); if (last != 0 && !x_strncasecmp(find, base, (unsigned) (last - base))) { result = table + length - 1; ReportIcons(("use builtin-icon %s\n", table[0].name)); } } } return result; } #define BuiltInXPM(name) built_in_xpm(name, XtNumber(name), icon_hint) #endif /* OPT_BUILTIN_XPMS */ typedef enum { eHintDefault = 0 /* use the largest builtin-icon */ ,eHintNone ,eHintSearch } ICON_HINT; #endif /* HAVE_LIBXPM */ int getVisualDepth(XtermWidget xw) { int result = 0; if (getVisualInfo(xw)) { result = xw->visInfo->depth; } return result; } /* * WM_ICON_SIZE should be honored if possible. */ void xtermLoadIcon(XtermWidget xw, const char *icon_hint) { #ifdef HAVE_LIBXPM Display *dpy = XtDisplay(xw); Pixmap myIcon = 0; Pixmap myMask = 0; char *workname = 0; ICON_HINT hint = eHintDefault; #include ReportIcons(("load icon (hint: %s)\n", NonNull(icon_hint))); if (!IsEmpty(icon_hint)) { if (!x_strcasecmp(icon_hint, "none")) { hint = eHintNone; } else { hint = eHintSearch; } } if (hint == eHintSearch) { int state = 0; while (x_find_icon(&workname, &state, icon_hint, ".xpm") != 0) { Pixmap resIcon = 0; Pixmap shapemask = 0; XpmAttributes attributes; struct stat sb; attributes.depth = (unsigned) getVisualDepth(xw); attributes.valuemask = XpmDepth; if (IsEmpty(workname) || lstat(workname, &sb) != 0 || !S_ISREG(sb.st_mode)) { TRACE(("...failure (no such file)\n")); } else { int rc = XpmReadFileToPixmap(dpy, DefaultRootWindow(dpy), workname, &resIcon, &shapemask, &attributes); if (rc == XpmSuccess) { myIcon = resIcon; myMask = shapemask; TRACE(("...success\n")); ReportIcons(("found/loaded icon-file %s\n", workname)); break; } else { TRACE(("...failure (%s)\n", XpmGetErrorString(rc))); } } } } /* * If no external file was found, look for the name in the built-in table. * If that fails, just use the biggest mini-icon. */ if (myIcon == 0 && hint != eHintNone) { char **data; #if OPT_BUILTIN_XPMS const XPM_DATA *myData = 0; myData = BuiltInXPM(mini_xterm_xpms); if (myData == 0) myData = BuiltInXPM(filled_xterm_xpms); if (myData == 0) myData = BuiltInXPM(xterm_color_xpms); if (myData == 0) myData = BuiltInXPM(xterm_xpms); if (myData == 0) myData = &mini_xterm_xpms[XtNumber(mini_xterm_xpms) - 1]; data = (char **) myData->data; #else data = (char **) &mini_xterm_48x48_xpm; #endif if (XpmCreatePixmapFromData(dpy, DefaultRootWindow(dpy), data, &myIcon, &myMask, 0) == 0) { ReportIcons(("loaded built-in pixmap icon\n")); } else { myIcon = 0; myMask = 0; } } if (myIcon != 0) { XWMHints *hints = XGetWMHints(dpy, VShellWindow(xw)); if (!hints) hints = XAllocWMHints(); if (hints) { hints->flags |= IconPixmapHint; hints->icon_pixmap = myIcon; if (myMask) { hints->flags |= IconMaskHint; hints->icon_mask = myMask; } XSetWMHints(dpy, VShellWindow(xw), hints); XFree(hints); ReportIcons(("updated window-manager hints\n")); } } if (workname != 0) free(workname); #else (void) xw; (void) icon_hint; #endif } void ChangeGroup(XtermWidget xw, const char *attribute, char *value) { Arg args[1]; Boolean changed = True; Widget w = CURRENT_EMU(); Widget top = SHELL_OF(w); char *my_attr = NULL; char *old_value = value; #if OPT_WIDE_CHARS Boolean titleIsUTF8; #endif if (!AllowTitleOps(xw)) return; /* * Ignore empty or too-long requests. */ if (value == 0 || strlen(value) > 1000) return; if (IsTitleMode(xw, tmSetBase16)) { const char *temp; char *test; /* this allocates a new string, if no error is detected */ value = x_decode_hex(value, &temp); if (value == 0 || *temp != '\0') { free(value); return; } for (test = value; *test != '\0'; ++test) { if (CharOf(*test) < 32) { *test = '\0'; break; } } } #if OPT_WIDE_CHARS /* * By design, xterm uses the XtNtitle resource of the X Toolkit for setting * the WM_NAME property, rather than doing this directly. That relies on * the application to tell it if the format should be something other than * STRING, i.e., by setting the XtNtitleEncoding resource. * * The ICCCM says that WM_NAME is TEXT (i.e., uninterpreted). In X11R6, * the ICCCM listed STRING and COMPOUND_TEXT as possibilities; XFree86 * added UTF8_STRING (the documentation for that was discarded by an Xorg * developer, although the source-code provides this feature). * * Since X11R5, if the X11 library fails to store a text property as * STRING, it falls back to COMPOUND_TEXT. For best interoperability, we * prefer to use STRING if the data fits, or COMPOUND_TEXT. In either * case, limit the resulting characters to the printable ISO-8859-1 set. */ titleIsUTF8 = isValidUTF8((Char *) value); if (IsSetUtf8Title(xw) && titleIsUTF8) { char *testc = malloc(strlen(value) + 1); Char *nextc = (Char *) value; Boolean ok8bit = True; if (testc != NULL) { /* * Check if the data fits in STRING. Along the way, replace * control characters. */ Char *lastc = (Char *) testc; while (*nextc != '\0') { unsigned ch; nextc = convertFromUTF8(nextc, &ch); if (ch > 255) { ok8bit = False; } else if (!IsLatin1(ch)) { ch = OnlyLatin1(ch); } *lastc++ = (Char) ch; } *lastc = '\0'; if (ok8bit) { TRACE(("ChangeGroup: UTF-8 converted to ISO-8859-1\n")); if (value != old_value) free(value); value = testc; titleIsUTF8 = False; } else { TRACE(("ChangeGroup: UTF-8 NOT converted to ISO-8859-1:\n" "\t%s\n", value)); free(testc); nextc = (Char *) value; while (*nextc != '\0') { unsigned ch; Char *skip = convertFromUTF8(nextc, &ch); if (iswcntrl((wint_t) ch)) { memset(nextc, BAD_ASCII, (size_t) (skip - nextc)); } nextc = skip; } } } } else #endif { Char *c1 = (Char *) value; TRACE(("ChangeGroup: assume ISO-8859-1\n")); for (c1 = (Char *) value; *c1 != '\0'; ++c1) { *c1 = (Char) OnlyLatin1(*c1); } } my_attr = x_strdup(attribute); ReportIcons(("ChangeGroup(attribute=%s, value=%s)\n", my_attr, value)); #if OPT_WIDE_CHARS /* * If we're running in UTF-8 mode, and have not been told that the * title string is in UTF-8, it is likely that non-ASCII text in the * string will be rejected because it is not printable in the current * locale. So we convert it to UTF-8, allowing the X library to * convert it back. */ TRACE(("ChangeGroup: value is %sUTF-8\n", titleIsUTF8 ? "" : "NOT ")); if (xtermEnvUTF8() && !titleIsUTF8) { size_t limit = strlen(value); Char *c1 = (Char *) value; int n; for (n = 0; c1[n] != '\0'; ++n) { if (c1[n] > 127) { Char *converted; if ((converted = TypeMallocN(Char, 1 + (6 * limit))) != 0) { Char *temp = converted; while (*c1 != 0) { temp = convertToUTF8(temp, *c1++); } *temp = 0; if (value != old_value) free(value); value = (char *) converted; ReportIcons(("...converted{%s}\n", value)); } break; } } } #endif #if OPT_SAME_NAME /* If the attribute isn't going to change, then don't bother... */ if (resource.sameName) { char *buf = 0; XtSetArg(args[0], my_attr, &buf); XtGetValues(top, args, 1); TRACE(("...comparing{%s}\n", NonNull(buf))); if (buf != 0 && strcmp(value, buf) == 0) changed = False; } #endif /* OPT_SAME_NAME */ if (changed) { ReportIcons(("...updating %s\n", my_attr)); ReportIcons(("...value is %s\n", value)); XtSetArg(args[0], my_attr, value); XtSetValues(top, args, 1); } #if OPT_WIDE_CHARS if (xtermEnvUTF8()) { Display *dpy = XtDisplay(xw); const char *propname = (!strcmp(my_attr, XtNtitle) ? "_NET_WM_NAME" : "_NET_WM_ICON_NAME"); Atom my_atom = XInternAtom(dpy, propname, False); if (my_atom != None) { changed = True; if (IsSetUtf8Title(xw)) { #if OPT_SAME_NAME if (resource.sameName) { Atom actual_type; Atom requested_type = XA_UTF8_STRING(dpy); int actual_format = 0; long long_length = 1024; unsigned long nitems = 0; unsigned long bytes_after = 0; unsigned char *prop = 0; if (xtermGetWinProp(dpy, VShellWindow(xw), my_atom, 0L, long_length, requested_type, &actual_type, &actual_format, &nitems, &bytes_after, &prop) && actual_type == requested_type && actual_format == 8 && prop != 0 && nitems == strlen(value) && memcmp(value, prop, nitems) == 0) { changed = False; } } #endif /* OPT_SAME_NAME */ if (changed) { ReportIcons(("...updating %s\n", propname)); ReportIcons(("...value is %s\n", value)); XChangeProperty(dpy, VShellWindow(xw), my_atom, XA_UTF8_STRING(dpy), 8, PropModeReplace, (Char *) value, (int) strlen(value)); } } else { ReportIcons(("...deleting %s\n", propname)); XDeleteProperty(dpy, VShellWindow(xw), my_atom); } } } #endif if (value != old_value) { free(value); } free(my_attr); return; } void ChangeIconName(XtermWidget xw, char *name) { if (name == 0) { name = emptyString; } if (!showZIconBeep(xw, name)) ChangeGroup(xw, XtNiconName, name); } void ChangeTitle(XtermWidget xw, char *name) { ChangeGroup(xw, XtNtitle, name); } #define Strlen(s) strlen((const char *)(s)) void ChangeXprop(char *buf) { Display *dpy = XtDisplay(toplevel); Window w = XtWindow(toplevel); XTextProperty text_prop; Atom aprop; Char *pchEndPropName = (Char *) strchr(buf, '='); if (pchEndPropName) *pchEndPropName = '\0'; aprop = XInternAtom(dpy, buf, False); if (pchEndPropName == NULL) { /* no "=value" given, so delete the property */ XDeleteProperty(dpy, w, aprop); } else { text_prop.value = pchEndPropName + 1; text_prop.encoding = XA_STRING; text_prop.format = 8; text_prop.nitems = Strlen(text_prop.value); XSetTextProperty(dpy, w, &text_prop, aprop); } } /***====================================================================***/ /* * This is part of ReverseVideo(). It reverses the data stored for the old * "dynamic" colors that might have been retrieved using OSC 10-18. */ void ReverseOldColors(XtermWidget xw) { ScrnColors *pOld = xw->work.oldColors; Pixel tmpPix; char *tmpName; if (pOld) { /* change text cursor, if necessary */ if (pOld->colors[TEXT_CURSOR] == pOld->colors[TEXT_FG]) { pOld->colors[TEXT_CURSOR] = pOld->colors[TEXT_BG]; if (pOld->names[TEXT_CURSOR]) { XtFree(xw->work.oldColors->names[TEXT_CURSOR]); pOld->names[TEXT_CURSOR] = NULL; } if (pOld->names[TEXT_BG]) { if ((tmpName = x_strdup(pOld->names[TEXT_BG])) != 0) { pOld->names[TEXT_CURSOR] = tmpName; } } } EXCHANGE(pOld->colors[TEXT_FG], pOld->colors[TEXT_BG], tmpPix); EXCHANGE(pOld->names[TEXT_FG], pOld->names[TEXT_BG], tmpName); EXCHANGE(pOld->colors[MOUSE_FG], pOld->colors[MOUSE_BG], tmpPix); EXCHANGE(pOld->names[MOUSE_FG], pOld->names[MOUSE_BG], tmpName); #if OPT_TEK4014 EXCHANGE(pOld->colors[TEK_FG], pOld->colors[TEK_BG], tmpPix); EXCHANGE(pOld->names[TEK_FG], pOld->names[TEK_BG], tmpName); #endif } return; } Bool AllocateTermColor(XtermWidget xw, ScrnColors * pNew, int ndx, const char *name, Bool always) { Bool result = False; if (always || AllowColorOps(xw, ecSetColor)) { XColor def; char *newName; result = True; if (!x_strcasecmp(name, XtDefaultForeground)) { def.pixel = xw->old_foreground; } else if (!x_strcasecmp(name, XtDefaultBackground)) { def.pixel = xw->old_background; } else if (!xtermAllocColor(xw, &def, name)) { result = False; } if (result && (newName = x_strdup(name)) != 0) { if (COLOR_DEFINED(pNew, ndx)) { free(pNew->names[ndx]); } SET_COLOR_VALUE(pNew, ndx, def.pixel); SET_COLOR_NAME(pNew, ndx, newName); TRACE(("AllocateTermColor #%d: %s (pixel 0x%06lx)\n", ndx, newName, def.pixel)); } else { TRACE(("AllocateTermColor #%d: %s (failed)\n", ndx, name)); result = False; } } return result; } /***====================================================================***/ /* ARGSUSED */ void Panic(const char *s GCC_UNUSED, int a GCC_UNUSED) { if_DEBUG({ xtermWarning(s, a); }); } const char * SysErrorMsg(int code) { static const char unknown[] = "unknown error"; char *s = strerror(code); return s ? s : unknown; } const char * SysReasonMsg(int code) { /* *INDENT-OFF* */ static const struct { int code; const char *name; } table[] = { { ERROR_FIONBIO, "main: ioctl() failed on FIONBIO" }, { ERROR_F_GETFL, "main: ioctl() failed on F_GETFL" }, { ERROR_F_SETFL, "main: ioctl() failed on F_SETFL", }, { ERROR_OPDEVTTY, "spawn: open() failed on /dev/tty", }, { ERROR_TIOCGETP, "spawn: ioctl() failed on TIOCGETP", }, { ERROR_PTSNAME, "spawn: ptsname() failed", }, { ERROR_OPPTSNAME, "spawn: open() failed on ptsname", }, { ERROR_PTEM, "spawn: ioctl() failed on I_PUSH/\"ptem\"" }, { ERROR_CONSEM, "spawn: ioctl() failed on I_PUSH/\"consem\"" }, { ERROR_LDTERM, "spawn: ioctl() failed on I_PUSH/\"ldterm\"" }, { ERROR_TTCOMPAT, "spawn: ioctl() failed on I_PUSH/\"ttcompat\"" }, { ERROR_TIOCSETP, "spawn: ioctl() failed on TIOCSETP" }, { ERROR_TIOCSETC, "spawn: ioctl() failed on TIOCSETC" }, { ERROR_TIOCSETD, "spawn: ioctl() failed on TIOCSETD" }, { ERROR_TIOCSLTC, "spawn: ioctl() failed on TIOCSLTC" }, { ERROR_TIOCLSET, "spawn: ioctl() failed on TIOCLSET" }, { ERROR_INIGROUPS, "spawn: initgroups() failed" }, { ERROR_FORK, "spawn: fork() failed" }, { ERROR_EXEC, "spawn: exec() failed" }, { ERROR_PTYS, "get_pty: not enough ptys" }, { ERROR_PTY_EXEC, "waiting for initial map" }, { ERROR_SETUID, "spawn: setuid() failed" }, { ERROR_INIT, "spawn: can't initialize window" }, { ERROR_TIOCKSET, "spawn: ioctl() failed on TIOCKSET" }, { ERROR_TIOCKSETC, "spawn: ioctl() failed on TIOCKSETC" }, { ERROR_LUMALLOC, "luit: command-line malloc failed" }, { ERROR_SELECT, "in_put: select() failed" }, { ERROR_VINIT, "VTInit: can't initialize window" }, { ERROR_KMMALLOC1, "HandleKeymapChange: malloc failed" }, { ERROR_TSELECT, "Tinput: select() failed" }, { ERROR_TINIT, "TekInit: can't initialize window" }, { ERROR_BMALLOC2, "SaltTextAway: malloc() failed" }, { ERROR_LOGEXEC, "StartLog: exec() failed" }, { ERROR_XERROR, "xerror: XError event" }, { ERROR_XIOERROR, "xioerror: X I/O error" }, { ERROR_SCALLOC, "Alloc: calloc() failed on base" }, { ERROR_SCALLOC2, "Alloc: calloc() failed on rows" }, { ERROR_SAVE_PTR, "ScrnPointers: malloc/realloc() failed" }, }; /* *INDENT-ON* */ Cardinal n; const char *result = "?"; for (n = 0; n < XtNumber(table); ++n) { if (code == table[n].code) { result = table[n].name; break; } } return result; } void SysError(int code) { int oerrno = errno; fprintf(stderr, "%s: Error %d, errno %d: ", ProgramName, code, oerrno); fprintf(stderr, "%s\n", SysErrorMsg(oerrno)); fprintf(stderr, "Reason: %s\n", SysReasonMsg(code)); Cleanup(code); } void NormalExit(void) { static Bool cleaning; /* * Process "-hold" and session cleanup only for a normal exit. */ if (cleaning) { hold_screen = 0; return; } cleaning = True; need_cleanup = False; if (hold_screen) { hold_screen = 2; while (hold_screen) { xtermFlushDbe(term); xevents(term); Sleep(EVENT_DELAY); } } #if OPT_SESSION_MGT if (resource.sessionMgt) { XtVaSetValues(toplevel, XtNjoinSession, False, (void *) 0); } #endif Cleanup(0); } #if USE_DOUBLE_BUFFER void xtermFlushDbe(XtermWidget xw) { TScreen *screen = TScreenOf(xw); if (resource.buffered && screen->needSwap) { XdbeSwapInfo swap; swap.swap_window = VWindow(screen); swap.swap_action = XdbeCopied; XdbeSwapBuffers(XtDisplay(xw), &swap, 1); XFlush(XtDisplay(xw)); screen->needSwap = 0; ScrollBarDrawThumb(xw, 2); X_GETTIMEOFDAY(&screen->buffered_at); } } void xtermTimedDbe(XtermWidget xw) { if (resource.buffered) { TScreen *screen = TScreenOf(xw); struct timeval now; long elapsed; long limit = DbeMsecs(xw); X_GETTIMEOFDAY(&now); if (screen->buffered_at.tv_sec) { elapsed = (1000L * (now.tv_sec - screen->buffered_at.tv_sec) + (now.tv_usec - screen->buffered_at.tv_usec) / 1000L); } else { elapsed = limit; } if (elapsed >= limit) { xtermNeedSwap(xw, 1); xtermFlushDbe(xw); } } } #endif /* * cleanup by sending SIGHUP to client processes */ void Cleanup(int code) { TScreen *screen = TScreenOf(term); TRACE(("Cleanup %d\n", code)); if (screen->pid > 1) { (void) kill_process_group(screen->pid, SIGHUP); } Exit(code); } #ifndef S_IXOTH #define S_IXOTH 1 #endif Boolean validProgram(const char *pathname) { Boolean result = False; struct stat sb; if (!IsEmpty(pathname) && *pathname == '/' && strstr(pathname, "/..") == 0 && stat(pathname, &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFREG && (sb.st_mode & S_IXOTH) != 0) { result = True; } return result; } #ifndef VMS #ifndef PATH_MAX #define PATH_MAX 512 /* ... is not defined consistently in Xos.h */ #endif char * xtermFindShell(char *leaf, Bool warning) { char *s0; char *s; char *d; char *tmp; char *result = leaf; Bool allocated = False; TRACE(("xtermFindShell(%s)\n", leaf)); if (!strncmp("./", result, (size_t) 2) || !strncmp("../", result, (size_t) 3)) { size_t need = PATH_MAX; size_t used = strlen(result) + 2; char *buffer = malloc(used + need); if (buffer != 0) { if (getcwd(buffer, need) != 0) { sprintf(buffer + strlen(buffer), "/%s", result); result = buffer; allocated = True; } else { free(buffer); } } } else if (*result != '\0' && strchr("+/-", *result) == 0) { /* find it in $PATH */ if ((s = s0 = x_getenv("PATH")) != 0) { if ((tmp = TypeMallocN(char, strlen(leaf) + strlen(s) + 2)) != 0) { Bool found = False; while (*s != '\0') { strcpy(tmp, s); for (d = tmp;; ++d) { if (*d == ':' || *d == '\0') { int skip = (*d != '\0'); *d = '/'; strcpy(d + 1, leaf); if (skip) ++d; s += (d - tmp); if (validProgram(tmp)) { result = x_strdup(tmp); found = True; allocated = True; } break; } } if (found) break; } free(tmp); } free(s0); } } TRACE(("...xtermFindShell(%s)\n", result)); if (!validProgram(result)) { if (warning) xtermWarning("No absolute path found for shell: %s\n", result); if (allocated) free(result); result = 0; } /* be consistent, so that caller can always free the result */ if (result != 0 && !allocated) result = x_strdup(result); return result; } #endif /* VMS */ #define ENV_HUNK(n) (unsigned) ((((n) + 1) | 31) + 1) /* * If we do not have unsetenv(), make consistent updates for environ[]. * This could happen on some older machines due to the uneven standardization * process for the two functions. * * That is, putenv() makes a copy of environ, and some implementations do not * update the environ pointer, so the fallback when unsetenv() is missing would * not work as intended. Likewise, the reverse could be true, i.e., unsetenv * could copy environ. */ #if defined(HAVE_PUTENV) && !defined(HAVE_UNSETENV) #undef HAVE_PUTENV #elif !defined(HAVE_PUTENV) && defined(HAVE_UNSETENV) #undef HAVE_UNSETENV #endif /* * copy the environment before Setenv'ing. */ void xtermCopyEnv(char **oldenv) { #ifdef HAVE_PUTENV (void) oldenv; #else unsigned size; char **newenv; for (size = 0; oldenv[size] != NULL; size++) { ; } newenv = TypeCallocN(char *, ENV_HUNK(size)); memmove(newenv, oldenv, size * sizeof(char *)); environ = newenv; #endif } #if !defined(HAVE_PUTENV) || !defined(HAVE_UNSETENV) static int findEnv(const char *var, int *lengthp) { char *test; int envindex = 0; size_t len = strlen(var); int found = -1; TRACE(("findEnv(%s=..)\n", var)); while ((test = environ[envindex]) != NULL) { if (strncmp(test, var, len) == 0 && test[len] == '=') { found = envindex; break; } envindex++; } *lengthp = envindex; return found; } #endif /* * sets the value of var to be arg in the Unix 4.2 BSD environment env. * Var should end with '=' (bindings are of the form "var=value"). * This procedure assumes the memory for the first level of environ * was allocated using calloc, with enough extra room at the end so not * to have to do a realloc(). */ void xtermSetenv(const char *var, const char *value) { if (value != 0) { #ifdef HAVE_PUTENV char *both = malloc(2 + strlen(var) + strlen(value)); TRACE(("xtermSetenv(%s=%s)\n", var, value)); if (both) { sprintf(both, "%s=%s", var, value); putenv(both); } #else size_t len = strlen(var); int envindex; int found = findEnv(var, &envindex); TRACE(("xtermSetenv(%s=%s)\n", var, value)); if (found < 0) { unsigned need = ENV_HUNK(envindex + 1); unsigned have = ENV_HUNK(envindex); if (need > have) { char **newenv; newenv = TypeMallocN(char *, need); if (newenv == 0) { xtermWarning("Cannot increase environment\n"); return; } memmove(newenv, environ, have * sizeof(*newenv)); free(environ); environ = newenv; } found = envindex; environ[found + 1] = NULL; environ = environ; } environ[found] = TextAlloc(1 + len + strlen(value)); if (environ[found] == 0) { xtermWarning("Cannot allocate environment %s\n", var); return; } sprintf(environ[found], "%s=%s", var, value); #endif } } void xtermUnsetenv(const char *var) { TRACE(("xtermUnsetenv(%s)\n", var)); #ifdef HAVE_UNSETENV unsetenv(var); #else { int ignore; int item = findEnv(var, &ignore); if (item >= 0) { while ((environ[item] = environ[item + 1]) != 0) { ++item; } } } #endif } /*ARGSUSED*/ int xerror(Display *d, XErrorEvent *ev) { xtermWarning("warning, error event received:\n"); TRACE_X_ERR(d, ev); (void) XmuPrintDefaultErrorMessage(d, ev, stderr); Exit(ERROR_XERROR); return 0; /* appease the compiler */ } void ice_error(IceConn iceConn) { (void) iceConn; xtermWarning("ICE IO error handler doing an exit(), pid = %ld, errno = %d\n", (long) getpid(), errno); Exit(ERROR_ICEERROR); } /*ARGSUSED*/ int xioerror(Display *dpy) { int the_error = errno; xtermWarning("fatal IO error %d (%s) or KillClient on X server \"%s\"\r\n", the_error, SysErrorMsg(the_error), DisplayString(dpy)); Exit(ERROR_XIOERROR); return 0; /* appease the compiler */ } void xt_error(String message) { xtermWarning("Xt error: %s\n", message); /* * Check for the obvious - Xt does a poor job of reporting this. */ if (x_getenv("DISPLAY") == 0) { xtermWarning("DISPLAY is not set\n"); } exit(1); } int XStrCmp(char *s1, char *s2) { if (s1 && s2) return (strcmp(s1, s2)); if (s1 && *s1) return (1); if (s2 && *s2) return (-1); return (0); } #if OPT_TEK4014 static void withdraw_window(Display *dpy, Window w, int scr) { TRACE(("withdraw_window %#lx\n", (long) w)); (void) XmuUpdateMapHints(dpy, w, NULL); XWithdrawWindow(dpy, w, scr); return; } #endif void set_vt_visibility(Bool on) { XtermWidget xw = term; TScreen *screen = TScreenOf(xw); TRACE(("set_vt_visibility(%d)\n", on)); if (on) { if (!screen->Vshow && xw) { VTInit(xw); XtMapWidget(XtParent(xw)); #if OPT_TOOLBAR /* we need both of these during initialization */ XtMapWidget(SHELL_OF(xw)); ShowToolbar(resource.toolBar); #endif screen->Vshow = True; } } #if OPT_TEK4014 else { if (screen->Vshow && xw) { withdraw_window(XtDisplay(xw), VShellWindow(xw), XScreenNumberOfScreen(XtScreen(xw))); screen->Vshow = False; } } set_vthide_sensitivity(); set_tekhide_sensitivity(); update_vttekmode(); update_tekshow(); update_vtshow(); #endif return; } #if OPT_TEK4014 void set_tek_visibility(Bool on) { XtermWidget xw = term; TRACE(("set_tek_visibility(%d)\n", on)); if (on) { if (!TEK4014_SHOWN(xw)) { if (tekWidget == 0) { TekInit(); /* will exit on failure */ } if (tekWidget != 0) { Widget tekParent = SHELL_OF(tekWidget); XtRealizeWidget(tekParent); XtMapWidget(XtParent(tekWidget)); #if OPT_TOOLBAR /* we need both of these during initialization */ XtMapWidget(tekParent); XtMapWidget(tekWidget); #endif XtOverrideTranslations(tekParent, XtParseTranslationTable ("WM_PROTOCOLS: DeleteWindow()")); (void) XSetWMProtocols(XtDisplay(tekParent), XtWindow(tekParent), &wm_delete_window, 1); TEK4014_SHOWN(xw) = True; } } } else { if (TEK4014_SHOWN(xw) && tekWidget) { withdraw_window(XtDisplay(tekWidget), TShellWindow, XScreenNumberOfScreen(XtScreen(tekWidget))); TEK4014_SHOWN(xw) = False; } } set_tekhide_sensitivity(); set_vthide_sensitivity(); update_vtshow(); update_tekshow(); update_vttekmode(); return; } void end_tek_mode(void) { XtermWidget xw = term; if (TEK4014_ACTIVE(xw)) { FlushLog(xw); TEK4014_ACTIVE(xw) = False; xtermSetWinSize(xw); longjmp(Tekend, 1); } return; } void end_vt_mode(void) { XtermWidget xw = term; if (!TEK4014_ACTIVE(xw)) { FlushLog(xw); set_tek_visibility(True); TEK4014_ACTIVE(xw) = True; TekSetWinSize(tekWidget); longjmp(VTend, 1); } return; } void switch_modes(Bool tovt) /* if true, then become vt mode */ { if (tovt) { if (tekRefreshList) TekRefresh(tekWidget); end_tek_mode(); /* WARNING: this does a longjmp... */ } else { end_vt_mode(); /* WARNING: this does a longjmp... */ } } void hide_vt_window(void) { set_vt_visibility(False); if (!TEK4014_ACTIVE(term)) switch_modes(False); /* switch to tek mode */ } void hide_tek_window(void) { set_tek_visibility(False); tekRefreshList = (TekLink *) 0; if (TEK4014_ACTIVE(term)) switch_modes(True); /* does longjmp to vt mode */ } #endif /* OPT_TEK4014 */ static const char * skip_punct(const char *s) { while (*s == '-' || *s == '/' || *s == '+' || *s == '#' || *s == '%') { ++s; } return s; } static int cmp_options(const void *a, const void *b) { const char *s1 = skip_punct(((const OptionHelp *) a)->opt); const char *s2 = skip_punct(((const OptionHelp *) b)->opt); return strcmp(s1, s2); } static int cmp_resources(const void *a, const void *b) { return strcmp(((const XrmOptionDescRec *) a)->option, ((const XrmOptionDescRec *) b)->option); } XrmOptionDescRec * sortedOptDescs(XrmOptionDescRec * descs, Cardinal res_count) { static XrmOptionDescRec *res_array = 0; #ifdef NO_LEAKS if (descs == 0) { if (res_array != 0) { free(res_array); res_array = 0; } } else #endif if (res_array == 0) { Cardinal j; /* make a sorted index to 'resources' */ res_array = TypeCallocN(XrmOptionDescRec, res_count); if (res_array != 0) { for (j = 0; j < res_count; j++) res_array[j] = descs[j]; qsort(res_array, (size_t) res_count, sizeof(*res_array), cmp_resources); } } return res_array; } /* * The first time this is called, construct sorted index to the main program's * list of options, taking into account the on/off options which will be * compressed into one token. It's a lot simpler to do it this way than * maintain the list in sorted form with lots of ifdef's. */ OptionHelp * sortedOpts(OptionHelp * options, XrmOptionDescRec * descs, Cardinal numDescs) { static OptionHelp *opt_array = 0; #ifdef NO_LEAKS if (descs == 0 && opt_array != 0) { sortedOptDescs(descs, numDescs); free(opt_array); opt_array = 0; return 0; } else if (options == 0 || descs == 0) { return 0; } #endif if (opt_array == 0) { size_t opt_count, j; #if OPT_TRACE Cardinal k; XrmOptionDescRec *res_array = sortedOptDescs(descs, numDescs); int code; const char *mesg; #else (void) descs; (void) numDescs; #endif /* count 'options' and make a sorted index to it */ for (opt_count = 0; options[opt_count].opt != 0; ++opt_count) { ; } opt_array = TypeCallocN(OptionHelp, opt_count + 1); for (j = 0; j < opt_count; j++) opt_array[j] = options[j]; qsort(opt_array, opt_count, sizeof(OptionHelp), cmp_options); /* supply the "turn on/off" strings if needed */ #if OPT_TRACE for (j = 0; j < opt_count; j++) { if (!strncmp(opt_array[j].opt, "-/+", (size_t) 3)) { char temp[80]; const char *name = opt_array[j].opt + 3; for (k = 0; k < numDescs; ++k) { const char *value = res_array[k].value; if (res_array[k].option[0] == '-') { code = -1; } else if (res_array[k].option[0] == '+') { code = 1; } else { code = 0; } sprintf(temp, "%.*s", (int) sizeof(temp) - 2, opt_array[j].desc); if (x_strindex(temp, "inhibit") != 0) code = -code; if (code != 0 && res_array[k].value != 0 && !strcmp(name, res_array[k].option + 1)) { if (((code < 0) && !strcmp(value, "on")) || ((code > 0) && !strcmp(value, "off")) || ((code > 0) && !strcmp(value, "0"))) { mesg = "turn on/off"; } else { mesg = "turn off/on"; } if (strncmp(mesg, opt_array[j].desc, strlen(mesg))) { if (strncmp(opt_array[j].desc, "turn ", (size_t) 5)) { char *s = TextAlloc(strlen(mesg) + 1 + strlen(opt_array[j].desc)); if (s != 0) { sprintf(s, "%s %s", mesg, opt_array[j].desc); opt_array[j].desc = s; } } else { TRACE(("OOPS ")); } } TRACE(("%s: %s %s: %s (%s)\n", mesg, res_array[k].option, res_array[k].value, opt_array[j].opt, opt_array[j].desc)); break; } } } } #endif } return opt_array; } /* * Report the character-type locale that xterm was started in. */ String xtermEnvLocale(void) { static String result; if (result == 0) { if ((result = x_nonempty(setlocale(LC_CTYPE, 0))) == 0) { result = x_strdup("C"); } else { result = x_strdup(result); } TRACE(("xtermEnvLocale ->%s\n", result)); } return result; } char * xtermEnvEncoding(void) { static char *result; if (result == 0) { #ifdef HAVE_LANGINFO_CODESET result = nl_langinfo(CODESET); #else char *locale = xtermEnvLocale(); if (!strcmp(locale, "C") || !strcmp(locale, "POSIX")) { result = x_strdup("ASCII"); } else { result = x_strdup("ISO-8859-1"); } #endif TRACE(("xtermEnvEncoding ->%s\n", result)); } return result; } #if OPT_WIDE_CHARS /* * Tell whether xterm was started in a locale that uses UTF-8 encoding for * characters. That environment is inherited by subprocesses and used in * various library calls. */ Bool xtermEnvUTF8(void) { static Bool init = False; static Bool result = False; if (!init) { init = True; #ifdef HAVE_LANGINFO_CODESET result = (strcmp(xtermEnvEncoding(), "UTF-8") == 0); #else { char *locale = x_strdup(xtermEnvLocale()); int n; for (n = 0; locale[n] != 0; ++n) { locale[n] = x_toupper(locale[n]); } if (strstr(locale, "UTF-8") != 0) result = True; else if (strstr(locale, "UTF8") != 0) result = True; free(locale); } #endif TRACE(("xtermEnvUTF8 ->%s\n", BtoS(result))); } return result; } #endif /* OPT_WIDE_CHARS */ /* * Check if the current widget, or any parent, is the VT100 "xterm" widget. */ XtermWidget getXtermWidget(Widget w) { XtermWidget xw; if (w == 0) { xw = (XtermWidget) CURRENT_EMU(); if (!IsXtermWidget(xw)) { xw = 0; } } else if (IsXtermWidget(w)) { xw = (XtermWidget) w; } else { xw = getXtermWidget(XtParent(w)); } TRACE2(("getXtermWidget %p -> %p\n", w, xw)); return xw; } #if OPT_SESSION_MGT static void die_callback(Widget w GCC_UNUSED, XtPointer client_data GCC_UNUSED, XtPointer call_data GCC_UNUSED) { NormalExit(); } static void save_callback(Widget w GCC_UNUSED, XtPointer client_data GCC_UNUSED, XtPointer call_data) { XtCheckpointToken token = (XtCheckpointToken) call_data; /* we have nothing to save */ token->save_success = True; } static void icewatch(IceConn iceConn, IcePointer clientData GCC_UNUSED, Bool opening, IcePointer * watchData GCC_UNUSED) { if (opening) { ice_fd = IceConnectionNumber(iceConn); TRACE(("got IceConnectionNumber %d\n", ice_fd)); } else { ice_fd = -1; TRACE(("reset IceConnectionNumber\n")); } } void xtermOpenSession(void) { if (resource.sessionMgt) { TRACE(("Enabling session-management callbacks\n")); XtAddCallback(toplevel, XtNdieCallback, die_callback, NULL); XtAddCallback(toplevel, XtNsaveCallback, save_callback, NULL); } } void xtermCloseSession(void) { IceRemoveConnectionWatch(icewatch, NULL); } #endif /* OPT_SESSION_MGT */ Widget xtermOpenApplication(XtAppContext * app_context_return, String my_class, XrmOptionDescRec * options, Cardinal num_options, int *argc_in_out, char **argv_in_out, String *fallback_resources, WidgetClass widget_class, ArgList args, Cardinal num_args) { Widget result; XtSetErrorHandler(xt_error); #if OPT_SESSION_MGT result = XtOpenApplication(app_context_return, my_class, options, num_options, argc_in_out, argv_in_out, fallback_resources, widget_class, args, num_args); IceAddConnectionWatch(icewatch, NULL); #else (void) widget_class; (void) args; (void) num_args; result = XtAppInitialize(app_context_return, my_class, options, num_options, argc_in_out, argv_in_out, fallback_resources, NULL, 0); #endif /* OPT_SESSION_MGT */ init_colored_cursor(XtDisplay(result)); XtSetErrorHandler(NULL); return result; } static int x11_errors; static int catch_x11_error(Display *display, XErrorEvent *error_event) { (void) display; (void) error_event; ++x11_errors; return 0; } Boolean xtermGetWinAttrs(Display *dpy, Window win, XWindowAttributes * attrs) { Boolean result = False; Status code; memset(attrs, 0, sizeof(*attrs)); if (win != None) { XErrorHandler save = XSetErrorHandler(catch_x11_error); x11_errors = 0; code = XGetWindowAttributes(dpy, win, attrs); XSetErrorHandler(save); result = (Boolean) ((code != 0) && !x11_errors); if (result) { TRACE_WIN_ATTRS(attrs); } else { xtermWarning("invalid window-id %ld\n", (long) win); } } return result; } Boolean xtermGetWinProp(Display *display, Window win, Atom property, long long_offset, long long_length, Atom req_type, Atom *actual_type_return, int *actual_format_return, unsigned long *nitems_return, unsigned long *bytes_after_return, unsigned char **prop_return) { Boolean result = False; if (win != None) { XErrorHandler save = XSetErrorHandler(catch_x11_error); x11_errors = 0; if (XGetWindowProperty(display, win, property, long_offset, long_length, False, req_type, actual_type_return, actual_format_return, nitems_return, bytes_after_return, prop_return) == Success && x11_errors == 0) { result = True; } XSetErrorHandler(save); } return result; } void xtermEmbedWindow(Window winToEmbedInto) { Display *dpy = XtDisplay(toplevel); XWindowAttributes attrs; TRACE(("checking winToEmbedInto %#lx\n", winToEmbedInto)); if (xtermGetWinAttrs(dpy, winToEmbedInto, &attrs)) { XtermWidget xw = term; TScreen *screen = TScreenOf(xw); XtRealizeWidget(toplevel); TRACE(("...reparenting toplevel %#lx into %#lx\n", XtWindow(toplevel), winToEmbedInto)); XReparentWindow(dpy, XtWindow(toplevel), winToEmbedInto, 0, 0); screen->embed_high = (Dimension) attrs.height; screen->embed_wide = (Dimension) attrs.width; } } void free_string(String value) { free((void *) value); } /* Set tty's idea of window size, using the given file descriptor 'fd'. */ void update_winsize(int fd, int rows, int cols, int height, int width) { #ifdef TTYSIZE_STRUCT TTYSIZE_STRUCT ts; int code; setup_winsize(ts, rows, cols, height, width); TRACE_RC(code, SET_TTYSIZE(fd, ts)); trace_winsize(ts, "from SET_TTYSIZE"); (void) code; #endif (void) rows; (void) cols; (void) height; (void) width; } /* * Update stty settings to match the values returned by dtterm window * manipulation 18 and 19. */ void xtermSetWinSize(XtermWidget xw) { #if OPT_TEK4014 if (!TEK4014_ACTIVE(xw)) #endif if (XtIsRealized((Widget) xw)) { TScreen *screen = TScreenOf(xw); TRACE(("xtermSetWinSize\n")); update_winsize(screen->respond, MaxRows(screen), MaxCols(screen), Height(screen), Width(screen)); } } #if OPT_XTERM_SGR #if OPT_TRACE static char * traceIFlags(IFlags flags) { static char result[1000]; result[0] = '\0'; #define DATA(name) if (flags & name) { strcat(result, " " #name); } DATA(INVERSE); DATA(UNDERLINE); DATA(BOLD); DATA(BLINK); DATA(INVISIBLE); DATA(BG_COLOR); DATA(FG_COLOR); #if OPT_WIDE_ATTRS DATA(ATR_FAINT); DATA(ATR_ITALIC); DATA(ATR_STRIKEOUT); DATA(ATR_DBL_UNDER); DATA(ATR_DIRECT_FG); DATA(ATR_DIRECT_BG); #endif #undef DATA return result; } static char * traceIStack(unsigned flags) { static char result[1000]; result[0] = '\0'; #define DATA(name) if (flags & xBIT(ps##name - 1)) { strcat(result, " " #name); } DATA(INVERSE); DATA(UNDERLINE); DATA(BOLD); DATA(BLINK); DATA(INVISIBLE); #if OPT_ISO_COLORS DATA(BG_COLOR); DATA(FG_COLOR); #endif #if OPT_WIDE_ATTRS DATA(ATR_FAINT); DATA(ATR_ITALIC); DATA(ATR_STRIKEOUT); DATA(ATR_DBL_UNDER); /* direct-colors are a special case of ISO-colors (see above) */ #endif #undef DATA return result; } #endif void xtermPushSGR(XtermWidget xw, int value) { SavedSGR *s = &(xw->saved_sgr); TRACE(("xtermPushSGR %d mask %#x %s\n", s->used + 1, (unsigned) value, traceIStack((unsigned) value))); if (s->used < MAX_SAVED_SGR) { s->stack[s->used].mask = (IFlags) value; #define PUSH_FLAG(name) \ s->stack[s->used].name = xw->name;\ TRACE(("...may pop %s 0x%04X %s\n", #name, xw->name, traceIFlags(xw->name))) #define PUSH_DATA(name) \ s->stack[s->used].name = xw->name;\ TRACE(("...may pop %s %d\n", #name, xw->name)) PUSH_FLAG(flags); #if OPT_ISO_COLORS PUSH_DATA(sgr_foreground); PUSH_DATA(sgr_background); PUSH_DATA(sgr_38_xcolors); #endif } s->used++; } #define IAttrClr(dst,bits) dst = dst & (IAttr) ~(bits) void xtermReportSGR(XtermWidget xw, XTermRect *value) { TScreen *screen = TScreenOf(xw); char reply[BUFSIZ]; CellData working; int row, col; Boolean first = True; TRACE(("xtermReportSGR %d,%d - %d,%d\n", value->top, value->left, value->bottom, value->right)); memset(&working, 0, sizeof(working)); for (row = value->top - 1; row < value->bottom; ++row) { LineData *ld = getLineData(screen, row); if (ld == 0) continue; for (col = value->left - 1; col < value->right; ++col) { if (first) { first = False; saveCellData(screen, &working, 0, ld, NULL, col); } working.attribs &= ld->attribs[col]; #if OPT_ISO_COLORS if (working.attribs & FG_COLOR && GetCellColorFG(working.color) != GetCellColorFG(ld->color[col])) { IAttrClr(working.attribs, FG_COLOR); } if (working.attribs & BG_COLOR && GetCellColorBG(working.color) != GetCellColorBG(ld->color[col])) { IAttrClr(working.attribs, BG_COLOR); } #endif } } xtermFormatSGR(xw, reply, working.attribs, GetCellColorFG(working.color), GetCellColorBG(working.color)); unparseputc1(xw, ANSI_CSI); unparseputs(xw, reply); unparseputc(xw, 'm'); unparse_end(xw); } void xtermPopSGR(XtermWidget xw) { SavedSGR *s = &(xw->saved_sgr); TRACE(("xtermPopSGR %d\n", s->used)); if (s->used > 0) { if (s->used-- <= MAX_SAVED_SGR) { IFlags mask = s->stack[s->used].mask; Boolean changed = False; TRACE(("...mask %#x %s\n", mask, traceIStack(mask))); TRACE(("...old: %s\n", traceIFlags(xw->flags))); TRACE(("...new: %s\n", traceIFlags(s->stack[s->used].flags))); #define POP_FLAG(name) \ if (xBIT(ps##name - 1) & mask) { \ if ((xw->flags & name) ^ (s->stack[s->used].flags & name)) { \ changed = True; \ UIntClr(xw->flags, name); \ UIntSet(xw->flags, (s->stack[s->used].flags & name)); \ TRACE(("...pop " #name " = %s\n", BtoS(xw->flags & name))); \ } \ } #define POP_FLAG2(name,part) \ if (xBIT(ps##name - 1) & mask) { \ if ((xw->flags & part) ^ (s->stack[s->used].flags & part)) { \ changed = True; \ UIntClr(xw->flags, part); \ UIntSet(xw->flags, (s->stack[s->used].flags & part)); \ TRACE(("...pop " #part " = %s\n", BtoS(xw->flags & part))); \ } \ } #define POP_DATA(name,value) \ if (xBIT(ps##name - 1) & mask) { \ Bool always = False; \ if ((xw->flags & name) ^ (s->stack[s->used].flags & name)) { \ always = changed = True; \ UIntClr(xw->flags, name); \ UIntSet(xw->flags, (s->stack[s->used].flags & name)); \ TRACE(("...pop " #name " = %s\n", BtoS(xw->flags & name))); \ } \ if (always || (xw->value != s->stack[s->used].value)) { \ TRACE(("...pop " #name " %d => %d\n", xw->value, s->stack[s->used].value)); \ xw->value = s->stack[s->used].value; \ changed = True; \ } \ } POP_FLAG(BOLD); POP_FLAG(UNDERLINE); POP_FLAG(BLINK); POP_FLAG(INVERSE); POP_FLAG(INVISIBLE); #if OPT_WIDE_ATTRS if (xBIT(psATR_ITALIC - 1) & mask) { xtermUpdateItalics(xw, s->stack[s->used].flags, xw->flags); } POP_FLAG(ATR_ITALIC); POP_FLAG(ATR_FAINT); POP_FLAG(ATR_STRIKEOUT); POP_FLAG(ATR_DBL_UNDER); #endif #if OPT_ISO_COLORS POP_DATA(FG_COLOR, sgr_foreground); POP_DATA(BG_COLOR, sgr_background); POP_DATA(BG_COLOR, sgr_38_xcolors); #if OPT_DIRECT_COLOR POP_FLAG2(FG_COLOR, ATR_DIRECT_FG); POP_FLAG2(BG_COLOR, ATR_DIRECT_BG); #endif if (changed) { setExtendedColors(xw); } #else (void) changed; #endif } #if OPT_ISO_COLORS TRACE(("xtermP -> flags%s, fg=%d bg=%d%s\n", traceIFlags(xw->flags), xw->sgr_foreground, xw->sgr_background, xw->sgr_38_xcolors ? " (SGR 38)" : "")); #else TRACE(("xtermP -> flags%s\n", traceIFlags(xw->flags))); #endif } } #endif /* OPT_XTERM_SGR */ xterm-353/trace.h0000644000175100001440000002016213614351570012521 0ustar tomusers/* $XTermId: trace.h,v 1.91 2020/01/29 18:48:24 tom Exp $ */ /* * Copyright 1997-2019,2020 by Thomas E. Dickey * * All Rights Reserved * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name(s) of the above copyright * holders shall not be used in advertising or otherwise to promote the * sale, use or other dealings in this Software without prior written * authorization. */ /* * Common/useful definitions for XTERM application */ #ifndef included_trace_h #define included_trace_h /* *INDENT-OFF* */ #include #if OPT_TRACE #include extern void Trace ( const char *, ... ) GCC_PRINTFLIKE(1,2); extern void TraceVA ( const char *fmt, va_list ap ); extern void TraceXError (Display *d, XErrorEvent *ev); #undef TRACE #define TRACE(p) Trace p #undef TRACE_VA #define TRACE_VA(p) TraceVA p #define TRACE_X_ERR(d,e) TraceXError(d,e) extern void TraceClose (void); #undef TRACE_CLOSE #define TRACE_CLOSE TraceClose #if OPT_TRACE > 1 #define TRACE2(p) Trace p #endif extern const char * visibleChars(const Char * /* buf */, unsigned /* len */); extern const char * visibleEventMode(EventMode); extern const char * visibleIChars(const IChar * /* buf */, unsigned /* len */); extern const char * visibleUChar(unsigned); extern const char * visibleDblChrset(unsigned /* chrset */); extern const char * visibleEventType (int); extern const char * visibleMappingMode (int); extern const char * visibleNotifyDetail(int /* code */); extern const char * visibleNotifyMode (int /* code */); extern const char * visibleScsCode(DECNRCM_codes /* chrset */); extern const char * visibleSelectionTarget(Display * /* d */, Atom /* a */); extern const char * visibleTekparse (int); extern const char * visibleVTparse (int); extern const char * visibleXError (int /* code */); extern const char * TraceAtomName(Display * /* d */, Atom /* a */); extern void TraceArgv(const char * /* tag */, char ** /* argv */); #undef TRACE_ARGV #define TRACE_ARGV(tag,argv) TraceArgv(tag,argv) extern const char *trace_who; #undef TRACE_CHILD #define TRACE_CHILD int tracing_child = (trace_who = "child") != 0; (void) tracing_child; extern void TraceEvent(const char *, XEvent *, String *, Cardinal *); #undef TRACE_EVENT #define TRACE_EVENT(t,e,s,n) TraceEvent(t, (XEvent *)e, s, n) #undef TRACE_FALLBACK #if OPT_RENDERFONT && OPT_WIDE_CHARS extern void TraceFallback(XtermWidget, const char *, unsigned, int, XftFont *); #define TRACE_FALLBACK(w,t,c,n,f) TraceFallback(w, t, c, n, f) #else #define TRACE_FALLBACK(w,t,c,n,f) /*nothing*/ #endif extern void TraceFocus(Widget, XEvent *); #undef TRACE_FOCUS #define TRACE_FOCUS(w,e) TraceFocus((Widget)w, (XEvent *)e) extern void TraceSizeHints(XSizeHints *); #undef TRACE_HINTS #define TRACE_HINTS(hints) TraceSizeHints(hints) extern void TraceIds(const char * /* fname */, int /* lnum */); #undef TRACE_IDS #define TRACE_IDS TraceIds(__FILE__, __LINE__) extern void TraceTime(const char * /* fname */, int /* lnum */); #undef TRACE_TIME #define TRACE_TIME TraceTime(__FILE__, __LINE__) extern void TraceOptions(OptionHelp * /* options */, XrmOptionDescRec * /* resources */, Cardinal /* count */); #undef TRACE_OPTS #define TRACE_OPTS(opts,ress,lens) TraceOptions(opts,ress,lens) extern void TraceTranslations(const char *, Widget); #undef TRACE_TRANS #define TRACE_TRANS(name,w) TraceTranslations(name,w) extern void TraceWindowAttributes(XWindowAttributes *); #undef TRACE_WIN_ATTRS #define TRACE_WIN_ATTRS(a) TraceWindowAttributes(a) extern void TraceWMSizeHints(XtermWidget); #undef TRACE_WM_HINTS #define TRACE_WM_HINTS(w) TraceWMSizeHints(w) extern void TraceXtermResources(void); #undef TRACE_XRES #define TRACE_XRES() TraceXtermResources() extern XtGeometryResult TraceResizeRequest(const char * /* fn */, int /* ln */, Widget /* w */, unsigned /* reqwide */, unsigned /* reqhigh */, Dimension * /* gotwide */, Dimension * /* gothigh */); #undef REQ_RESIZE #define REQ_RESIZE(w, reqwide, reqhigh, gotwide, gothigh) \ TraceResizeRequest(__FILE__, __LINE__, w, \ (reqwide), (reqhigh), \ (gotwide), (gothigh)) extern const char * ModifierName(unsigned /* modifier */); #define FMT_MODIFIER_NAMES "%s%s%s%s%s%s%s%s" #define ARG_MODIFIER_NAMES(state) \ ModifierName(state & ShiftMask), \ ModifierName(state & LockMask), \ ModifierName(state & ControlMask), \ ModifierName(state & Mod1Mask), \ ModifierName(state & Mod2Mask), \ ModifierName(state & Mod3Mask), \ ModifierName(state & Mod4Mask), \ ModifierName(state & Mod5Mask) #else #define REQ_RESIZE(w, reqwide, reqhigh, gotwide, gothigh) \ XtMakeResizeRequest((Widget) (w), \ (Dimension) (reqwide), (Dimension) (reqhigh), \ (gotwide), (gothigh)) #define TRACE(p) /*nothing*/ #define TRACE_CLOSE() /*nothing*/ #define TRACE_ARGV(tag,argv) /*nothing*/ #define TRACE_CHILD /*nothing*/ #define TRACE_EVENT(t,e,s,n) /*nothing*/ #define TRACE_FALLBACK(w,t,c,n,f) /*nothing*/ #define TRACE_FOCUS(w,e) /*nothing*/ #define TRACE_HINTS(hints) /*nothing*/ #define TRACE_IDS /*nothing*/ #define TRACE_OPTS(opts,ress,lens) /*nothing*/ #define TRACE_TRANS(name,w) /*nothing*/ #define TRACE_WIN_ATTRS(w) /*nothing*/ #define TRACE_WM_HINTS(w) /*nothing*/ #define TRACE_X_ERR(d,e) /*nothing*/ #define TRACE_XRES() /*nothing*/ #endif #ifndef TRACE2 #define TRACE2(p) /*nothing*/ #endif extern void TraceScreen(XtermWidget /* xw */, int /* whichBuf */); /* * The whole wnew->screen struct is zeroed in VTInitialize. Use these macros * where applicable for copying the pieces from the request widget into the * new widget. We do not have to use them for wnew->misc, but the associated * traces are very useful for debugging. */ #if OPT_TRACE #define init_Bres(name) \ TRACE(("init " #name " = %s\n", \ BtoS(wnew->name = request->name))) #define init_Dres(name) \ TRACE(("init " #name " = %f\n", \ wnew->name = request->name)) #define init_Dres2(name,i) \ TRACE(("init " #name "[%d] = %f\n", i, \ wnew->name[i] = request->name[i])) #define init_Ires(name) \ TRACE(("init " #name " = %d\n", \ wnew->name = request->name)) #define init_Mres(name) \ TRACE(("init " #name " = %s\n", \ MtoS(wnew->name = request->name))) #define init_Sres(name) \ TRACE(("init " #name " = \"%s\"\n", \ (wnew->name = x_strtrim(request->name)) != NULL \ ? wnew->name : "")) #define init_Sres2(name,i) \ TRACE(("init " #name "[%d] = \"%s\"\n", i, \ (wnew->name(i) = x_strtrim(request->name(i))) != NULL \ ? wnew->name(i) : "")) #define init_Tres(offset) \ TRACE(("init screen.Tcolors[" #offset "] = %#lx\n", \ fill_Tres(wnew, request, offset))) #else #define init_Bres(name) wnew->name = request->name #define init_Dres(name) wnew->name = request->name #define init_Dres2(name,i) wnew->name[i] = request->name[i] #define init_Ires(name) wnew->name = request->name #define init_Mres(name) wnew->name = request->name #define init_Sres(name) wnew->name = x_strtrim(request->name) #define init_Sres2(name,i) wnew->name(i) = x_strtrim(request->name(i)) #define init_Tres(offset) fill_Tres(wnew, request, offset) #endif /* *INDENT-ON* */ #endif /* included_trace_h */ xterm-353/graphics_sixel.c0000644000175100001440000004547113610650241014425 0ustar tomusers/* $XTermId: graphics_sixel.c,v 1.19 2020/01/18 18:38:25 tom Exp $ */ /* * Copyright 2014-2016,2020 by Ross Combs * * All Rights Reserved * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name(s) of the above copyright * holders shall not be used in advertising or otherwise to promote the * sale, use or other dealings in this Software without prior written * authorization. */ #include #include #include #include #include #include #include #include #include #include /***====================================================================***/ /* * Parse numeric parameters which have the operator as a prefix rather than a * suffix as in ANSI format. * * # 0 * #1 1 * #1; 1 * "1;2;640;480 4 * #1;2;0;0;0 5 */ static void parse_prefixedtype_params(ANSI *params, const char **string) { const char *cp = *string; ParmType nparam = 0; int last_empty = 1; memset(params, 0, sizeof(*params)); params->a_final = CharOf(*cp); if (*cp != '\0') cp++; while (*cp != '\0') { Char ch = CharOf(*cp); if (isdigit(ch)) { last_empty = 0; if (nparam < NPARAM) { params->a_param[nparam] = (ParmType) ((params->a_param[nparam] * 10) + (ch - '0')); } } else if (ch == ';') { last_empty = 1; nparam++; } else if (ch == ' ' || ch == '\r' || ch == '\n') { /* EMPTY */ ; } else { break; } cp++; } *string = cp; if (!last_empty) nparam++; if (nparam > NPARAM) params->a_nparam = NPARAM; else params->a_nparam = nparam; } typedef struct { RegisterNum current_register; RegisterNum background; /* current background color register or hole */ int aspect_vertical; int aspect_horizontal; int declared_width; /* size as reported by the application */ int declared_height; /* size as reported by the application */ int row; /* context used during parsing */ int col; /* context used during parsing */ } SixelContext; /* sixel scrolling: * VK100/GIGI ? (did it even support Sixel?) * VT125 unsupported * VT240 unsupported * VT241 unsupported * VT330 mode setting * VT382 ? * VT340 mode setting * dxterm ? */ static void init_sixel_background(Graphic *graphic, SixelContext const *context) { const int mw = graphic->max_width; int r, c; TRACE(("initializing sixel background to size=%dx%d bgcolor=%hu\n", context->declared_width, context->declared_height, context->background)); if (context->background == COLOR_HOLE) return; for (r = 0; r < graphic->actual_height; r++) { for (c = 0; c < graphic->actual_width; c++) { graphic->pixels[r * mw + c] = context->background; } } graphic->color_registers_used[context->background] = 1; } static void set_sixel(Graphic *graphic, SixelContext const *context, int sixel) { const int mh = graphic->max_height; const int mw = graphic->max_width; RegisterNum color; int pix; color = context->current_register; TRACE(("drawing sixel at pos=%d,%d color=%hu (hole=%d, [%d,%d,%d])\n", context->col, context->row, color, color == COLOR_HOLE, ((color != COLOR_HOLE) ? (unsigned) graphic->color_registers[color].r : 0U), ((color != COLOR_HOLE) ? (unsigned) graphic->color_registers[color].g : 0U), ((color != COLOR_HOLE) ? (unsigned) graphic->color_registers[color].b : 0U))); for (pix = 0; pix < 6; pix++) { if (context->col < mw && context->row + pix < mh) { if (sixel & (1 << pix)) { if (context->col + 1 > graphic->actual_width) { graphic->actual_width = context->col + 1; } if (context->row + pix + 1 > graphic->actual_height) { graphic->actual_height = context->row + pix + 1; } graphic->pixels[((context->row + pix) * mw) + context->col] = color; } } else { TRACE(("sixel pixel %d out of bounds\n", pix)); } } } static void update_sixel_aspect(SixelContext const *context, Graphic *graphic) { /* We want to keep the ratio accurate but would like every pixel to have * the same size so keep these as whole numbers. */ /* FIXME: DEC terminals had pixels about twice as tall as they were wide, * and it seems the VT125 and VT24x only used data from odd graphic rows. * This means it basically cancels out if we ignore both, except that * the even rows of pixels may not be written by the application such that * they are suitable for display. In practice this doesn't seem to be * an issue but I have very few test files/programs. */ if (context->aspect_vertical < context->aspect_horizontal) { graphic->pixw = 1; graphic->pixh = ((context->aspect_vertical + context->aspect_horizontal - 1) / context->aspect_horizontal); } else { graphic->pixw = ((context->aspect_horizontal + context->aspect_vertical - 1) / context->aspect_vertical); graphic->pixh = 1; } TRACE(("sixel aspect ratio: an=%d ad=%d -> pixw=%d pixh=%d\n", context->aspect_vertical, context->aspect_horizontal, graphic->pixw, graphic->pixh)); } static int finished_parsing(XtermWidget xw, Graphic *graphic) { TScreen *screen = TScreenOf(xw); /* Update the screen scrolling and do a refresh. * The refresh may not cover the whole graphic. */ if (screen->scroll_amt) FlushScroll(xw); if (xw->keyboard.flags & MODE_DECSDM) { int new_row, new_col; if (screen->sixel_scrolls_right) { new_row = (graphic->charrow + (((graphic->actual_height * graphic->pixh) + FontHeight(screen) - 1) / FontHeight(screen)) - 1); new_col = (graphic->charcol + (((graphic->actual_width * graphic->pixw) + FontWidth(screen) - 1) / FontWidth(screen))); } else { /* FIXME: At least of the VT382 the vertical position appears to be * truncated (rounded toward zero after converting to character row. * This code rounds up, which seems more useful, but it would be * better to be compatible. Verify this is true on a VT3[34]0 as * well. */ new_row = (graphic->charrow + (((graphic->actual_height * graphic->pixh) + FontHeight(screen) - 1) / FontHeight(screen))); new_col = 0; } TRACE(("setting text position after %dx%d graphic starting on row=%d col=%d: cursor new_row=%d new_col=%d\n", graphic->actual_width * graphic->pixw, graphic->actual_height * graphic->pixh, graphic->charrow, graphic->charcol, new_row, new_col)); if (new_col > screen->rgt_marg) { new_col = screen->lft_marg; new_row++; TRACE(("column past left margin, overriding to row=%d col=%d\n", new_row, new_col)); } while (new_row > screen->bot_marg) { xtermScroll(xw, 1); new_row--; TRACE(("bottom row was past screen. new start row=%d, cursor row=%d\n", graphic->charrow, new_row)); } if (new_row < 0) { /* FIXME: this was triggering, now it isn't */ TRACE(("new row is going to be negative (%d); skipping position update!", new_row)); } else { set_cur_row(screen, new_row); set_cur_col(screen, new_col <= screen->rgt_marg ? new_col : screen->rgt_marg); } } graphic->dirty = 1; refresh_modified_displayed_graphics(xw); TRACE(("DONE parsed sixel data\n")); dump_graphic(graphic); return 0; } /* * Interpret sixel graphics sequences. * * Resources: * http://vt100.net/docs/vt3xx-gp/chapter14.html * ftp://ftp.cs.utk.edu/pub/shuford/terminal/sixel_graphics_news.txt * ftp://ftp.cs.utk.edu/pub/shuford/terminal/all_about_sixels.txt */ int parse_sixel(XtermWidget xw, ANSI *params, char const *string) { TScreen *screen = TScreenOf(xw); Graphic *graphic; SixelContext context; switch (screen->terminal_id) { case 240: case 241: case 330: case 340: context.aspect_vertical = 2; context.aspect_horizontal = 1; break; case 382: context.aspect_vertical = 1; context.aspect_horizontal = 1; break; default: context.aspect_vertical = 2; context.aspect_horizontal = 1; break; } context.declared_width = 0; context.declared_height = 0; context.row = 0; context.col = 0; /* default isn't white on the VT240, but not sure what it is */ context.current_register = 3; /* FIXME: using green, but not sure what it should be */ if (xw->keyboard.flags & MODE_DECSDM) { TRACE(("sixel scrolling enabled: inline positioning for graphic at %d,%d\n", screen->cur_row, screen->cur_col)); graphic = get_new_graphic(xw, screen->cur_row, screen->cur_col, 0U); } else { TRACE(("sixel scrolling disabled: inline positioning for graphic at %d,%d\n", 0, 0)); graphic = get_new_graphic(xw, 0, 0, 0U); } { int Pmacro = params->a_param[0]; int Pbgmode = params->a_param[1]; int Phgrid = params->a_param[2]; int Pan = params->a_param[3]; int Pad = params->a_param[4]; int Ph = params->a_param[5]; int Pv = params->a_param[6]; (void) Phgrid; TRACE(("sixel bitmap graphics sequence: params=%d (Pmacro=%d Pbgmode=%d Phgrid=%d) scroll_amt=%d\n", params->a_nparam, Pmacro, Pbgmode, Phgrid, screen->scroll_amt)); switch (params->a_nparam) { case 7: if (Pan == 0 || Pad == 0) { TRACE(("DATA_ERROR: invalid raster ratio %d/%d\n", Pan, Pad)); return -1; } context.aspect_vertical = Pan; context.aspect_horizontal = Pad; if (Ph <= 0 || Pv <= 0) { TRACE(("DATA_ERROR: raster image dimensions are invalid %dx%d\n", Ph, Pv)); return -1; } if (Ph > graphic->max_width || Pv > graphic->max_height) { TRACE(("DATA_ERROR: raster image dimensions are too large %dx%d\n", Ph, Pv)); return -1; } context.declared_width = Ph; context.declared_height = Pv; if (context.declared_width > graphic->actual_width) { graphic->actual_width = context.declared_width; } if (context.declared_height > graphic->actual_height) { graphic->actual_height = context.declared_height; } break; case 3: case 2: case 1: switch (Pmacro) { case 0: /* keep default aspect settings */ break; case 1: case 5: case 6: context.aspect_vertical = 2; context.aspect_horizontal = 1; break; case 2: context.aspect_vertical = 5; context.aspect_horizontal = 1; break; case 3: case 4: context.aspect_vertical = 3; context.aspect_horizontal = 1; break; case 7: case 8: case 9: context.aspect_vertical = 1; context.aspect_horizontal = 1; break; default: TRACE(("DATA_ERROR: unknown sixel macro mode parameter\n")); return -1; } break; case 0: break; default: TRACE(("DATA_ERROR: unexpected parameter count (found %d)\n", params->a_nparam)); return -1; } if (Pbgmode == 1) { context.background = COLOR_HOLE; } else { /* FIXME: is the default background register always zero? what about in light background mode? */ context.background = 0; } /* Ignore the grid parameter because it seems only printers paid attention to it. * The VT3xx was always 0.0195 cm. */ } update_sixel_aspect(&context, graphic); for (;;) { Char ch = CharOf(*string); if (ch == '\0') break; if (ch >= 0x3f && ch <= 0x7e) { int sixel = ch - 0x3f; TRACE(("sixel=%x (%c)\n", sixel, (char) ch)); if (!graphic->valid) { init_sixel_background(graphic, &context); graphic->valid = 1; } set_sixel(graphic, &context, sixel); context.col++; } else if (ch == '$') { /* DECGCR */ /* ignore DECCRNLM in sixel mode */ TRACE(("sixel CR\n")); context.col = 0; } else if (ch == '-') { /* DECGNL */ int scroll_lines; TRACE(("sixel NL\n")); scroll_lines = 0; while (graphic->charrow - scroll_lines + (((context.row + 6) * graphic->pixh + FontHeight(screen) - 1) / FontHeight(screen)) > screen->bot_marg) { scroll_lines++; } context.col = 0; context.row += 6; /* If we hit the bottom margin on the graphics page (well, we just use the * text margin for now), the behavior is to either scroll or to discard * the remainder of the graphic depending on this setting. */ if (scroll_lines > 0) { if (xw->keyboard.flags & MODE_DECSDM) { Display *display = screen->display; xtermScroll(xw, scroll_lines); XSync(display, False); TRACE(("graphic scrolled the screen %d lines. screen->scroll_amt=%d screen->topline=%d, now starting row is %d\n", scroll_lines, screen->scroll_amt, screen->topline, graphic->charrow)); } else { break; } } } else if (ch == '!') { /* DECGRI */ int Pcount; const char *start; int sixel; int i; start = ++string; for (;;) { ch = CharOf(*string); if (ch != '0' && ch != '1' && ch != '2' && ch != '3' && ch != '4' && ch != '5' && ch != '6' && ch != '7' && ch != '8' && ch != '9' && ch != ' ' && ch != '\r' && ch != '\n') break; string++; } if (ch == '\0') { TRACE(("DATA_ERROR: sixel data string terminated in the middle of a repeat operator\n")); return finished_parsing(xw, graphic); } if (string == start) { TRACE(("DATA_ERROR: sixel data string contains a repeat operator with empty count\n")); return finished_parsing(xw, graphic); } Pcount = atoi(start); sixel = ch - 0x3f; TRACE(("sixel repeat operator: sixel=%d (%c), count=%d\n", sixel, (char) ch, Pcount)); if (!graphic->valid) { init_sixel_background(graphic, &context); graphic->valid = 1; } for (i = 0; i < Pcount; i++) { set_sixel(graphic, &context, sixel); context.col++; } } else if (ch == '#') { /* DECGCI */ ANSI color_params; int Pregister; parse_prefixedtype_params(&color_params, &string); Pregister = color_params.a_param[0]; if (Pregister >= (int) graphic->valid_registers) { TRACE(("DATA_WARNING: sixel color operator uses out-of-range register %d\n", Pregister)); /* FIXME: supposedly the DEC terminals wrapped register indices -- verify */ while (Pregister >= (int) graphic->valid_registers) Pregister -= (int) graphic->valid_registers; TRACE(("DATA_WARNING: converted to %d\n", Pregister)); } if (color_params.a_nparam > 2 && color_params.a_nparam <= 5) { int Pspace = color_params.a_param[1]; int Pc1 = color_params.a_param[2]; int Pc2 = color_params.a_param[3]; int Pc3 = color_params.a_param[4]; short r, g, b; TRACE(("sixel set color register=%d space=%d color=[%d,%d,%d] (nparams=%d)\n", Pregister, Pspace, Pc1, Pc2, Pc3, color_params.a_nparam)); switch (Pspace) { case 1: /* HLS */ if (Pc1 > 360 || Pc2 > 100 || Pc3 > 100) { TRACE(("DATA_ERROR: sixel set color operator uses out-of-range HLS color coordinates %d,%d,%d\n", Pc1, Pc2, Pc3)); return finished_parsing(xw, graphic); } hls2rgb(Pc1, Pc2, Pc3, &r, &g, &b); break; case 2: /* RGB */ if (Pc1 > 100 || Pc2 > 100 || Pc3 > 100) { TRACE(("DATA_ERROR: sixel set color operator uses out-of-range RGB color coordinates %d,%d,%d\n", Pc1, Pc2, Pc3)); return finished_parsing(xw, graphic); } r = (short) Pc1; g = (short) Pc2; b = (short) Pc3; break; default: /* unknown */ TRACE(("DATA_ERROR: sixel set color operator uses unknown color space %d\n", Pspace)); return finished_parsing(xw, graphic); } update_color_register(graphic, (RegisterNum) Pregister, r, g, b); } else if (color_params.a_nparam == 1) { TRACE(("sixel switch to color register=%d (nparams=%d)\n", Pregister, color_params.a_nparam)); context.current_register = (RegisterNum) Pregister; } else { TRACE(("DATA_ERROR: sixel switch color operator with unexpected parameter count (nparams=%d)\n", color_params.a_nparam)); return finished_parsing(xw, graphic); } continue; } else if (ch == '"') /* DECGRA */ { ANSI raster_params; parse_prefixedtype_params(&raster_params, &string); if (raster_params.a_nparam < 2) { TRACE(("DATA_ERROR: sixel raster attribute operator with incomplete parameters (found %d, expected 2 or 4)\n", raster_params.a_nparam)); return finished_parsing(xw, graphic); } { int Pan = raster_params.a_param[0]; int Pad = raster_params.a_param[1]; TRACE(("sixel raster attribute with h:w=%d:%d\n", Pan, Pad)); if (Pan == 0 || Pad == 0) { TRACE(("DATA_ERROR: invalid raster ratio %d/%d\n", Pan, Pad)); return finished_parsing(xw, graphic); } context.aspect_vertical = Pan; context.aspect_horizontal = Pad; update_sixel_aspect(&context, graphic); } if (raster_params.a_nparam >= 4) { int Ph = raster_params.a_param[2]; int Pv = raster_params.a_param[3]; TRACE(("sixel raster attribute with h=%d v=%d\n", Ph, Pv)); if (Ph <= 0 || Pv <= 0) { TRACE(("DATA_ERROR: raster image dimensions are invalid %dx%d\n", Ph, Pv)); return finished_parsing(xw, graphic); } if (Ph > graphic->max_width || Pv > graphic->max_height) { TRACE(("DATA_ERROR: raster image dimensions are too large %dx%d\n", Ph, Pv)); return finished_parsing(xw, graphic); } context.declared_width = Ph; context.declared_height = Pv; if (context.declared_width > graphic->actual_width) { graphic->actual_width = context.declared_width; } if (context.declared_height > graphic->actual_height) { graphic->actual_height = context.declared_height; } } continue; } else if (ch == ' ' || ch == '\r' || ch == '\n') { /* EMPTY */ ; } else { TRACE(("DATA_ERROR: skipping unknown sixel command %04x (%c)\n", (int) ch, ch)); } string++; } return finished_parsing(xw, graphic); } xterm-353/xterm.man0000644000175100001440000111242713607163010013105 0ustar tomusers'\" t .\" $XTermId: xterm.man,v 1.806 2020/01/13 21:50:00 tom Exp $ .\" .\" Copyright 1996-2019,2020 by Thomas E. Dickey .\" .\" All Rights Reserved .\" .\" Permission is hereby granted, free of charge, to any person obtaining a .\" copy of this software and associated documentation files (the .\" "Software"), to deal in the Software without restriction, including .\" without limitation the rights to use, copy, modify, merge, publish, .\" distribute, sublicense, and/or sell copies of the Software, and to .\" permit persons to whom the Software is furnished to do so, subject to .\" the following conditions: .\" .\" The above copyright notice and this permission notice shall be included .\" in all copies or substantial portions of the Software. .\" .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS .\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF .\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. .\" IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY .\" CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, .\" TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE .\" SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. .\" .\" Except as contained in this notice, the name(s) of the above copyright .\" holders shall not be used in advertising or otherwise to promote the .\" sale, use or other dealings in this Software without prior written .\" authorization. .\" .\" .\" Copyright 1989 X Consortium .\" .\" Permission to use, copy, modify, distribute, and sell this software and its .\" documentation for any purpose is hereby granted without fee, provided that .\" the above copyright notice appear in all copies and that both that .\" copyright notice and this permission notice appear in supporting .\" documentation. .\" .\" The above copyright notice and this permission notice shall be included .\" in all copies or substantial portions of the Software. .\" .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS .\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF .\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. .\" IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR .\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, .\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR .\" OTHER DEALINGS IN THE SOFTWARE. .\" .\" Except as contained in this notice, the name of the X Consortium shall .\" not be used in advertising or otherwise to promote the sale, use or .\" other dealings in this Software without prior written authorization .\" from the X Consortium. .\" .\" Updated by Thomas E. Dickey for XFree86, July 1996 - February 2006. .\" .ds N Xterm .ds n xterm .\" .\" Bulleted paragraph .de bP .ie n .IP \(bu 4 .el .IP \(bu 2 .. .\" these would be fallbacks for DS/DE, .\" but groff changed the meaning of the macros. .de NS .ie n .sp .el .sp .5 .ie n .in +4 .el .in +2 .nf .ft C \" Courier .. .de NE .fi .ft R .ie n .in -4 .el .in -2 .. .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds AQ \(aq .el .ds AQ ' .ie \n(.g .ds `` \(lq .el .ds `` `` .ie \n(.g .ds '' \(rq .el .ds '' '' .TH XTERM 1 "__app_date__" "__app_version__" "X Window System" .SH NAME xterm \- terminal emulator for X .if n .hy 0 .if n .nh .if n .na .SH SYNOPSIS .B \*n [\-\fItoolkitoption\fP \&...\&] [\-\fIoption\fP \&...\&] [\fIshell\fP] .SH DESCRIPTION .hy 0 .nh The \fI\*n\fP program is a terminal emulator for the X Window System. It provides DEC VT102/VT220 and selected features from higher-level terminals such as VT320/VT420/VT520 (VT\fIxxx\fP). It also provides Tektronix 4014 emulation for programs that cannot use the window system directly. If the underlying operating system supports terminal resizing capabilities (for example, the SIGWINCH signal in systems derived from 4.3BSD), \fI\*n\fP will use the facilities to notify programs running in the window whenever it is resized. . .PP The VT\fIxxx\fP and Tektronix 4014 terminals each have their own window so that you can edit text in one and look at graphics in the other at the same time. To maintain the correct aspect ratio (height/width), Tektronix graphics will be restricted to the largest box with a 4014's aspect ratio that will fit in the window. This box is located in the upper left area of the window. . .PP Although both windows may be displayed at the same time, one of them is considered the \*(``active\*('' window for receiving keyboard input and terminal output. This is the window that contains the text cursor. The active window can be chosen through escape sequences, the \fBVT Options\fP menu in the VT\fIxxx\fP window, and the \fBTek Options\fP menu in the 4014 window. . .SH EMULATIONS \fI\*N\fP provides usable emulations of related DEC terminals: .bP VT52 emulation is complete. .bP VT102 emulation is fairly complete, but does not support autorepeat (because that would affect the keyboard used by other X clients). .IP Double-size characters are displayed properly if your font server supports scalable bitmap fonts. .bP VT220 emulation does not support soft fonts, it is otherwise complete. .bP VT420 emulation (the default) supports controls for manipulating rectangles of characters as well as left/right margins. .IP \fI\*N\fP does not support some other features which are not suitable for emulation, e.g., two-sessions. .PP Terminal database (\fIterminfo\fP (5) or \fItermcap\fP (5)) entries that work with \fI\*n\fP include .IP an optional platform-specific entry (\*(``__default_termname__\*(''), .br \*(``xterm\*('', .br \*(``vt102\*('', .br \*(``vt100\*('', .br \*(``ansi\*('' and .br \*(``dumb\*('' .PP \fI\*N\fP automatically searches the terminal database in this order for these entries and then sets the \*(``TERM\*('' variable (and the \*(``TERMCAP\*('' environment variable on a few older systems). The alternatives after \*(``xterm\*('' are very old, from the late 1980s. .PP VT100 and VT102 emulations are commonly equated, though they actually differ. The VT102 provided controls for inserting and deleting lines. .PP Similarly, \*(``ansi\*('' and \*(``vt100\*('' are often equated. These are not really the same. For instance, they use different controls for scrolling (but \fI\*n\fP supports both). These features differ in an \*(``ansi\*('' terminal description from \fI\*n\fP: .TP 8 .B acsc .br Pseudo-graphics (line-drawing) uses a different mapping. .TP 8 .B xenl .br \fI\*N\fP wraps text at the right margin using the VT100 \*(``newline glitch\*('' behavior. .PP Because of the wrapping behavior, you would occasionally have to repaint the screen when using a text editor with the \*(``ansi\*('' description. .PP You may also use descriptions corresponding to the various supported emulations such as \*(``vt220\*('' or \*(``vt420\*('', but should set the terminal emulation level with the \fBdecTerminalID\fP resource. .PP On most systems, \fI\*n\fP will use the terminfo database. Some older systems use termcap. (The \*(``TERMCAP\*('' environment variable is not set if \fI\*n\fP is linked against a terminfo library, since the requisite information is not provided by the termcap emulation of terminfo libraries). . .PP Many of the special \fI\*n\fP features may be modified under program control through a set of escape sequences different from the standard VT\fIxxx\fP escape sequences (see \fIXterm Control Sequences\fP). . .PP The Tektronix 4014 emulation is also fairly good. It supports 12-bit graphics addressing, scaled to the window size. Four different font sizes and five different lines types are supported. There is no write-through or defocused mode support. The Tektronix text and graphics commands are recorded internally by \fI\*n\fP and may be written to a file by sending the COPY escape sequence (or through the \fBTektronix\fP menu; see below). The name of the file will be .NS \*(``COPY\fIyyyy\fR\-\fIMM\fR\-\fIdd\fR.\fIhh\fR:\fImm\fR:\fIss\fR\*('' .NE .PP where .IR yyyy , .IR MM , .IR dd , .IR hh , .I mm and .I ss are the year, month, day, hour, minute and second when the COPY was performed (the file is created in the directory \fI\*n\fP is started in, or the home directory for a login \fI\*n\fP). . .PP Not all of the features described in this manual are necessarily available in this version of \fI\*n\fP. Some (e.g., the non-VT220 extensions) are available only if they were compiled in, though the most commonly-used are in the default configuration. . .SH "OTHER FEATURES" \fI\*N\fP automatically highlights the text cursor when the pointer enters the window (selected) and unhighlights it when the pointer leaves the window (unselected). If the window is the focus window, then the text cursor is highlighted no matter where the pointer is. . .PP In VT\fIxxx\fP mode, there are escape sequences to activate and deactivate an alternate screen buffer, which is the same size as the display area of the window. When activated, the current screen is saved and replaced with the alternate screen. Saving of lines scrolled off the top of the window is disabled until the normal screen is restored. The usual terminal description for \fI\*n\fP allows the visual editor .IR vi (1) to switch to the alternate screen for editing and to restore the screen on exit. A popup menu entry makes it simple to switch between the normal and alternate screens for cut and paste. . .PP In either VT\fIxxx\fP or Tektronix mode, there are escape sequences to change the name of the windows. Additionally, in VT\fIxxx\fP mode, \fI\*n\fP implements the window-manipulation control sequences from \fIdtterm\fP, such as resizing the window, setting its location on the screen. . .PP \fI\*N\fP allows character-based applications to receive mouse events (currently button-press and release events, and button-motion events) as keyboard control sequences. See \fIXterm Control Sequences\fP for details. . .\" *************************************************************************** .SH OPTIONS Because \fI\*n\fP uses the X Toolkit library, it accepts the standard X Toolkit command line options. \fI\*N\fP also accepts many application-specific options. .PP By convention, if an option begins with a \*(``\fB+\fP\*('' instead of a \*(``\fB\-\fP\*('', the option is restored to its default value. .\" *************************************************************************** .PP Most of the \fI\*n\fP options are actually parsed by the X Toolkit, which sets resource values, and overrides corresponding resource-settings in your X resource files. \fI\*N\fP provides the X Toolkit with a table of options. A few of these are marked, telling the X Toolkit to ignore them (\fB\-help\fP, \fB\-version\fP, \fB\-class\fP, \fB\-e\fP, and \fB\-into\fP). After the X Toolkit has parsed the command-line parameters, it removes those which it handles, leaving the specially-marked parameters for \fI\*n\fP to handle. .\" *************************************************************************** .PP These options do not set a resource value, and are handled specially: .TP 8 .B \-version This causes \fI\*n\fP to print a version number to the standard output, and then exit. .TP 8 .B \-help This causes \fI\*n\fP to print out a verbose message describing its options, one per line. The message is written to the standard output. After printing the message, \fI\*n\fP exits. \fI\*N\fP generates this message, sorting it and noting whether a \*(``\fB\-\fR\fIoption\fP\*('' or a \*(``\fB+\fR\fIoption\fP\*('' turns the feature on or off, since some features historically have been one or the other. \fI\*N\fP generates a concise help message (multiple options per line) when an unknown option is used, e.g., .NS \*n \-z .NE .IP If the logic for a particular option such as logging is not compiled into \fI\*n\fP, the help text for that option also is not displayed by the \fB\-help\fP option. .PP The \fB\-version\fP and \fB\-help\fP options are interpreted even if \fI\*n\fP cannot open the display, and are useful for testing and configuration scripts. Along with \fB\-class\fP, they are checked before other options. To do this, \fI\*n\fP has its own (much simpler) argument parser, along with a table of the X Toolkit's built-in list of options. .PP Relying upon the X Toolkit to parse the options and associated values has the advantages of simplicity and good integration with the X resource mechanism. There are a few drawbacks .bP \fI\*N\fP cannot tell easily whether a resource value was set by one of the external resource- or application-defaults files, whether it was set using \fBxrdb\fP(1), or if it was set through the \fB\-xrm\fP option or via some directly relevant command-line option. \fI\*N\fP sees only the end-result: a value supplied when creating its widgets. .bP \fI\*N\fP does not know the order in which particular options and items in resource files are evaluated. Rather, it sees all of the values for a given widget at the same time. In the design of these options, some are deemed more important, and can override other options. .IP The X Toolkit uses patterns (constants and wildcards) to match resources. Once a particular pattern has been used, it will not modify it. To override a given setting, a more-specific pattern must be used, e.g., replacing \*(``*\*('' with \*(``.\*(''. Some poorly-designed resource files are too specific to allow the command-line options to affect the relevant widget values. .bP In a few cases, the X Toolkit combines its standard options in ways which do not work well with \fI\*n\fP. This happens with the color (\fB\-fg\fP, \fB\-bg\fP) and reverse (\fB\-rv\fP) options. \fI\*N\fP makes a special case of these and adjusts its sense of \*(``reverse\*('' to lessen user surprise. .\" *************************************************************************** .PP One parameter (after all options) may be given. That overrides \fI\*n\fP's built-in choice of shell program: .bP If the parameter is not a relative path, i.e., beginning with \*(``./\*('' or \*(``../\*('', \fI\*n\fP looks for the file in the user's PATH. In either case, this check fails if \fI\*n\fP cannot construct an absolute path. .bP If that check fails (or if no such parameter is given), \fI\*n\fP next checks the \*(``SHELL\*('' variable. If that specifies an executable file, \fI\*n\fP will attempt to start that. However, \fI\*n\fP additionally checks if it is a valid shell, and will unset \*(``SHELL\*('' if it is not. .bP If \*(``SHELL\*('' is not set to an executable file, \fI\*n\fP tries to use the shell program specified in the user's password file entry. As before, \fI\*n\fP verifies if this is a valid shell. .bP Finally, if the password file entry does not specify a valid shell, \fI\*n\fP uses \fI/bin/sh\fP. .PP The \fB\-e\fP option cannot be used with this parameter since it uses all parameters following the option. .PP \fI\*N\fP validates shell programs by finding their pathname in the text file \fB/etc/shells\fP. It treats the environment variable \*(``SHELL\*('' specially because (like \*(``TERM\*(''), \fI\*n\fP both reads and updates the variable, and because the program started by \fI\*n\fP is not necessarily a shell. .\" *************************************************************************** .PP The other options are used to control the appearance and behavior. Not all options are necessarily configured into your copy of \fI\*n\fP: .TP 8 .B \-132 Normally, the VT102 DECCOLM escape sequence that switches between 80 and 132 column mode is ignored. This option causes the DECCOLM escape sequence to be recognized, and the \fI\*n\fP window will resize appropriately. .TP 8 .B \-ah This option indicates that \fI\*n\fP should always highlight the text cursor. By default, \fI\*n\fP will display a hollow text cursor whenever the focus is lost or the pointer leaves the window. .TP 8 .B +ah This option indicates that \fI\*n\fP should do text cursor highlighting based on focus. .TP 8 .B \-ai This option disables active icon support if that feature was compiled into \fI\*n\fP. This is equivalent to setting the \fIvt100\fP resource \fBactiveIcon\fP to \*(``false\*(''. .TP 8 .B +ai This option enables active icon support if that feature was compiled into \fI\*n\fP. This is equivalent to setting the \fIvt100\fP resource \fBactiveIcon\fP to \*(``true\*(''. .TP 8 .B \-aw This option indicates that auto-wraparound should be allowed, and is equivalent to setting the \fIvt100\fP resource \fBautoWrap\fP to \*(``true\*(''. .IP Auto-wraparound allows the cursor to automatically wrap to the beginning of the next line when it is at the rightmost position of a line and text is output. .TP 8 .B +aw This option indicates that auto-wraparound should not be allowed, and is equivalent to setting the \fIvt100\fP resource \fBautoWrap\fP to \*(``false\*(''. .TP 8 .BI \-b " number" This option specifies the size of the inner border (the distance between the outer edge of the characters and the window border) in pixels. That is the \fIvt100\fP \fBinternalBorder\fP resource. The default is \*(``2\*(''. .TP 8 .BI \-baudrate " number" Set the line-speed, used to test the behavior of applications that use the line-speed when optimizing their output to the screen. The default is \*(``38400\*(''. .TP 8 .B +bc turn off text cursor blinking. This overrides the \fBcursorBlink\fR resource. .TP 8 .B \-bc turn on text cursor blinking. This overrides the \fBcursorBlink\fR resource. .TP 8 .BI \-bcf " milliseconds" set the amount of time text cursor is off when blinking via the \fBcursorOffTime\fP resource. .TP 8 .BI \-bcn " milliseconds" set the amount of time text cursor is on when blinking via the \fBcursorOnTime\fP resource. .TP 8 .B "\-bdc" Set the \fIvt100\fP resource \fBcolorBDMode\fR to \*(``false\*('', disabling the display of characters with bold attribute as color. .TP 8 .B "+bdc" Set the \fIvt100\fP resource \fBcolorBDMode\fR to \*(``true\*('', enabling the display of characters with bold attribute as color rather than bold. .TP 8 .B "\-cb" Set the \fIvt100\fP resource \fBcutToBeginningOfLine\fP to \*(``false\*(''. .TP 8 .B "+cb" Set the \fIvt100\fP resource \fBcutToBeginningOfLine\fP to \*(``true\*(''. .TP 8 .B "\-cc \fIcharacterclassrange\fP:\fIvalue\fP[, \&...\&]" This sets classes indicated by the given ranges for using in selecting by words (see \fBCHARACTER CLASSES\fP and the \fBcharClass\fP resource). .TP 8 .B "\-cjk_width" Set the \fBcjkWidth\fP resource to \*(``true\*(''. When turned on, characters with East Asian Ambiguous (A) category in UTR 11 have a column width of 2. Otherwise, they have a column width of 1. This may be useful for some legacy CJK text terminal-based programs assuming box drawings and others to have a column width of 2. It also should be turned on when you specify a TrueType CJK double-width (bi-width/monospace) font either with \fB\-fa\fP at the command line or \fBfaceName\fP resource. The default is \*(``false\*('' .TP 8 .B "+cjk_width" Reset the \fBcjkWidth\fP resource. .TP 8 .BI \-class " string" This option allows you to override \fI\*n\fP's resource class. Normally it is \*(``__default_class__\*('', but can be set to another class such as \*(``U__default_class__\*('' to override selected resources. .IP X Toolkit sets the \fBWM_CLASS\fP property using the instance name and this class value. .TP 8 .B "\-cm" This option disables recognition of ANSI color-change escape sequences. It sets the \fBcolorMode\fP resource to \*(``false\*(''. .TP 8 .B "+cm" This option enables recognition of ANSI color-change escape sequences. This is the same as the \fIvt100\fP resource \fBcolorMode\fP. .TP 8 .B "\-cn" This option indicates that newlines should not be cut in line-mode selections. It sets the \fBcutNewline\fP resource to \*(``false\*(''. .TP 8 .B +cn This option indicates that newlines should be cut in line-mode selections. It sets the \fBcutNewline\fP resource to \*(``true\*(''. .TP 8 .BI \-cr " color" This option specifies the color to use for text cursor. The default is to use the same foreground color that is used for text. It sets the \fBcursorColor\fP resource according to the parameter. .TP 8 .B \-cu This option indicates that \fI\*n\fP should work around a bug in the .IR more (1) program that causes it to incorrectly display lines that are exactly the width of the window and are followed by a line beginning with a tab (the leading tabs are not displayed). This option is so named because it was originally thought to be a bug in the .IR curses (3x) cursor motion package. .TP 8 .B +cu This option indicates that \fI\*n\fP should not work around the .IR more (1) bug mentioned above. .TP 8 .B "\-dc" This option disables the escape sequence to change dynamic colors: the vt100 foreground and background colors, its text cursor color, the pointer cursor foreground and background colors, the Tektronix emulator foreground and background colors, its text cursor color and highlight color. The option sets the \fBdynamicColors\fP option to \*(``false\*(''. .TP 8 .B "+dc" This option enables the escape sequence to change dynamic colors. The option sets the \fBdynamicColors\fP option to \*(``true\*(''. .TP 8 .BI \-e "\fI program \fP[ \fIarguments \fP\&.\|.\|.\& ]\fI" This option specifies the program (and its command line arguments) to be run in the \fI\*n\fP window. It also sets the window title and icon name to be the basename of the program being executed if neither \fI\-T\fP nor \fI\-n\fP are given on the command line. .IP \fBNOTE:\fP This must be the \fBlast option\fP on the command line. .TP 8 .BI \-en " encoding" This option determines the encoding on which \fI\*n\fP runs. It sets the \fBlocale\fR resource. Encodings other than UTF-8 are supported by using \fIluit\fR. The \fB\-lc\fR option should be used instead of \fB\-en\fR for systems with locale support. .TP 8 .BI \-fb " font" This option specifies a font to be used when displaying bold text. It sets the \fBboldFont\fR resource. .IP This font must be the same height and width as the normal font, otherwise it is ignored. If only one of the normal or bold fonts is specified, it will be used as the normal font and the bold font will be produced by overstriking this font. .IP See also the discussion of \fBboldMode\fP and \fBalwaysBoldMode\fP resources. .TP 8 .BI \-fa " pattern" This option sets the pattern for fonts selected from the FreeType library if support for that library was compiled into \fI\*n\fP. This corresponds to the \fBfaceName\fP resource. When a CJK double-width font is specified, you also need to turn on the \fBcjkWidth\fP resource. .IP If you specify both \fB\-fa\fP and the X Toolkit option \fB\-fn\fP, the \fB\-fa\fP setting overrides the latter. .IP See also the \fBrenderFont\fP resource, which combines with this to determine whether FreeType fonts are initially active. .TP 8 .B \-fbb This option indicates that \fI\*n\fP should compare normal and bold fonts bounding boxes to ensure they are compatible. It sets the \fBfreeBoldBox\fP resource to \*(``false\*(''. .TP 8 .B +fbb This option indicates that \fI\*n\fP should not compare normal and bold fonts bounding boxes to ensure they are compatible. It sets the \fBfreeBoldBox\fP resource to \*(``true\*(''. .TP 8 .B \-fbx This option indicates that \fI\*n\fP should not assume that the normal and bold fonts have VT100 line-drawing characters. If any are missing, \fI\*n\fP will draw the characters directly. It sets the \fBforceBoxChars\fP resource to \*(``false\*(''. .TP 8 .B +fbx This option indicates that \fI\*n\fP should assume that the normal and bold fonts have VT100 line-drawing characters. It sets the \fBforceBoxChars\fP resource to \*(``true\*(''. .TP 8 .BI \-fd " pattern" This option sets the pattern for double-width fonts selected from the FreeType library if support for that library was compiled into \fI\*n\fP. This corresponds to the \fBfaceNameDoublesize\fP resource. .TP 8 .BI \-fi " font" This option sets the font for active icons if that feature was compiled into \fI\*n\fP. .IP See also the discussion of the \fBiconFont\fP resource. .TP 8 .BI \-fs " size" This option sets the pointsize for fonts selected from the FreeType library if support for that library was compiled into \fI\*n\fP. This corresponds to the \fBfaceSize\fP resource. .TP 8 .B \-fullscreen This option indicates that \fI\*n\fP should ask the window manager to let it use the full-screen for display, e.g., without window decorations. It sets the \fBfullscreen\fP resource to \*(``true\*(''. .TP 8 .B +fullscreen This option indicates that \fI\*n\fP should not ask the window manager to let it use the full-screen for display. It sets the \fBfullscreen\fP resource to \*(``false\*(''. .TP 8 .B \-fw \fIfont\fP This option specifies the font to be used for displaying wide text. By default, it will attempt to use a font twice as wide as the font that will be used to draw normal text. If no double-width font is found, it will improvise, by stretching the normal font. This corresponds to the \fBwideFont\fP resource. .TP 8 .B \-fwb \fIfont\fP This option specifies the font to be used for displaying bold wide text. By default, it will attempt to use a font twice as wide as the font that will be used to draw bold text. If no double-width font is found, it will improvise, by stretching the bold font. This corresponds to the \fBwideBoldFont\fP resource. .TP 8 .B \-fx \fIfont\fP This option specifies the font to be used for displaying the preedit string in the \*(``OverTheSpot\*('' input method. .IP See also the discussion of the \fBximFont\fP resource. .TP 8 .BI \-hc " color" (see \fB\-selbg\fP). .TP 8 .B \-hf This option indicates that HP function key escape codes should be generated for function keys. It sets the \fBhpFunctionKeys\fP resource to \*(``true\*(''. .TP 8 .B +hf This option indicates that HP function key escape codes should not be generated for function keys. It sets the \fBhpFunctionKeys\fP resource to \*(``false\*(''. .TP 8 .B \-hm Tells \fI\*n\fP to use \fBhighlightTextColor\fP and \fBhighlightColor\fP to override the reversed foreground/background colors in a selection. It sets the \fBhighlightColorMode\fP resource to \*(``true\*(''. .TP 8 .B +hm Tells \fI\*n\fP not to use \fBhighlightTextColor\fP and \fBhighlightColor\fP to override the reversed foreground/background colors in a selection. It sets the \fBhighlightColorMode\fP resource to \*(``false\*(''. .TP 8 .B \-hold Turn on the \fBhold\fP resource, i.e., \fI\*n\fP will not immediately destroy its window when the shell command completes. It will wait until you use the window manager to destroy/kill the window, or if you use the menu entries that send a signal, e.g., HUP or KILL. .TP 8 .B +hold Turn off the \fBhold\fP resource, i.e., \fI\*n\fP will immediately destroy its window when the shell command completes. .TP 8 .B \-ie Turn on the \fBptyInitialErase\fP resource, i.e., use the pseudo-terminal's sense of the \fIstty\fP erase value. .TP 8 .B +ie Turn off the \fBptyInitialErase\fP resource, i.e., set the \fIstty\fP erase value using the \fBkb\fP string from the termcap entry as a reference, if available. .TP 8 .B \-im Turn on the \fBuseInsertMode\fP resource, which forces use of insert mode by adding appropriate entries to the TERMCAP environment variable. (This option is ignored on most systems, because TERMCAP is not used). .TP 8 .B +im Turn off the \fBuseInsertMode\fP resource. .TP 8 .BI \-into " windowId" Given an X window identifier (an integer, which can be hexadecimal, octal or decimal according to whether it begins with "0x", "0" or neither), \fI\*n\fP will reparent its top-level shell widget to that window. This is used to embed \fI\*n\fP within other applications. .IP For instance, there are scripts for Tcl/Tk and Gtk which can be used to demonstrate the feature. When using Gtk, there is a limitation of that toolkit which requires that \fI\*n\fP's \fBallowSendEvents\fP resource is enabled. .TP 8 .B "\-itc" Set the \fIvt100\fP resource \fBcolorITMode\fR to \*(``false\*('', disabling the display of characters with italic attribute as color. .TP 8 .B "+itc" Set the \fIvt100\fP resource \fBcolorITMode\fR to \*(``true\*('', enabling the display of characters with italic attribute as color rather than italic. .TP 8 .B \-j This option indicates that \fI\*n\fP should do jump scrolling. It corresponds to the \fBjumpScroll\fP resource. Normally, text is scrolled one line at a time; this option allows \fI\*n\fP to move multiple lines at a time so that it does not fall as far behind. Its use is strongly recommended since it makes \fI\*n\fP much faster when scanning through large amounts of text. The VT100 escape sequences for enabling and disabling smooth scroll as well as the \fBVT Options\fP menu can be used to turn this feature on or off. .TP 8 .B +j This option indicates that \fI\*n\fP should not do jump scrolling. .TP 8 .B \-k8 This option sets the \fBallowC1Printable\fP resource. When \fBallowC1Printable\fP is set, \fI\*n\fP overrides the mapping of C1 control characters (code 128\(en159) to treat them as printable. .TP 8 .B +k8 This option resets the \fBallowC1Printable\fP resource. .TP 8 .BI \-kt " keyboardtype" This option sets the \fBkeyboardType\fP resource. Possible values include: \*(``unknown\*('', \*(``default\*('', \*(``legacy\*('', \*(``hp\*('', \*(``sco\*('', \*(``sun\*('', \*(``tcap\*('' and \*(``vt220\*(''. .IP The value \*(``unknown\*('', causes the corresponding resource to be ignored. .IP The value \*(``default\*('', suppresses the associated resources .IP \fBhpFunctionKeys\fP, .br \fBscoFunctionKeys\fP, .br \fBsunFunctionKeys\fP, .br \fBtcapFunctionKeys\fP, .br \fBoldXtermFKeys\fP and .br \fBsunKeyboard\fP, .IP using the Sun/PC keyboard layout. .TP 8 .B \-l Turn logging on, unless disabled by the \fBlogInhibit\fP resource. .IP Some versions of \fI\*n\fP may have logging enabled. However, normally logging is not supported, due to security concerns in the early 1990s. That was a problem in X11R4 \fBxterm\fP (1989) which was addressed by a patch to X11R5 late in 1993. X11R6 included these fixes. The older version (when running with \fIroot\fP privilege) would create the log file using \fIroot\fP privilege. The reason why \fI\*n\fP ran with \fIroot\fP privileges was to open pseudo-terminals. Those privileges are now needed only on very old systems: Unix98 pseudo-terminals made the BSD scheme unnecessary. .IP Unless overridden by the \fB\-lf\fP option or the \fBlogFile\fP resource: .RS .bP If the filename is \*(``-\*('', then logging is sent to the standard output. .bP Otherwise a filename is generated, and the log file is written to the directory from which \fI\*n\fP is invoked. .bP The generated filename is of the form .NS XtermLog.\fIXXXXXX\fR .NE .IP or .NS Xterm.log.\fIhostname.yyyy.mm.dd.hh.mm.ss.XXXXXX\fR .NE .IP depending on how \fI\*n\fP was built. .RE .TP 8 .B +l Turn logging off. .TP 8 .B \-lc Turn on support of various encodings according to the users' locale setting, i.e., LC_ALL, LC_CTYPE, or LANG environment variables. This is achieved by turning on UTF-8 mode and by invoking \fIluit\fR for conversion between locale encodings and UTF-8. (\fIluit\fR is not invoked in UTF-8 locales.) This corresponds to the \fBlocale\fR resource. .IP The actual list of encodings which are supported is determined by \fIluit\fR. Consult the \fIluit\fR manual page for further details. .IP See also the discussion of the \fB\-u8\fP option which supports UTF-8 locales. .TP 8 .B +lc Turn off support of automatic selection of locale encodings. Conventional 8bit mode or, in UTF-8 locales or with \fB\-u8\fP option, UTF-8 mode will be used. .TP 8 .BI \-lcc " path" File name for the encoding converter from/to locale encodings and UTF-8 which is used with \fB\-lc\fP option or \fBlocale\fR resource. This corresponds to the \fBlocaleFilter\fR resource. .TP 8 .B \-leftbar Force scrollbar to the left side of VT100 screen. This is the default, unless you have set the rightScrollBar resource. .TP 8 .BI \-lf " filename" Specify the log filename. This sets the \fBlogFile\fP resource. If set to \*(``-\*('', \fI\*n\fP writes its log to the standard output. See the \fB\-l\fP option. .TP 8 .B \-ls This option indicates that the shell that is started in the \fI\*n\fP window will be a login shell (i.e., the first character of argv[0] will be a dash, indicating to the shell that it should read the user's \&.login or \&.profile). .IP The \fB\-ls\fP flag and the \fBloginShell\fP resource are ignored if \fB\-e\fP is also given, because \fI\*n\fP does not know how to make the shell start the given command after whatever it does when it is a login shell \- the user's shell of choice need not be a Bourne shell after all. Also, \fI\*n\ \-e\fP is supposed to provide a consistent functionality for other applications that need to start text-mode programs in a window, and if \fBloginShell\fP were not ignored, the result of ~/.profile might interfere with that. .IP If you do want the effect of \fB\-ls\fP and \fB\-e\fP simultaneously, you may get away with something like .NS 15 \*n \-e /bin/bash \-l \-c "my command here" .NE .IP Finally, \fB\-ls\fP is not completely ignored, because \fI\*n\ \-ls\ \-e\fP does write a \fI/etc/wtmp\fP entry (if configured to do so), whereas \fI\*n\ \-e\fP does not. .TP 8 .B \-maximized This option indicates that \fI\*n\fP should ask the window manager to maximize its layout on startup. This corresponds to the \fBmaximized\fP resource. .IP Maximizing is not the reverse of iconifying; it is possible to do both with certain window managers. .TP 8 .B +maximized This option indicates that \fI\*n\fP should ask the window manager to not maximize its layout on startup. .TP 8 .B +ls This option indicates that the shell that is started should not be a login shell (i.e., it will be a normal \*(``subshell\*(''). .TP 8 .B \-mb This option indicates that \fI\*n\fP should ring a margin bell when the user types near the right end of a line. .TP 8 .B +mb This option indicates that margin bell should not be rung. .TP 8 .BI \-mc " milliseconds" This option specifies the maximum time between multi-click selections. .TP 8 .B \-mesg Turn off the \fBmessages\fP resource, i.e., disallow write access to the terminal. .TP 8 .B +mesg Turn on the \fBmessages\fP resource, i.e., allow write access to the terminal. .TP 8 .B "\-mk_width" Set the \fBmkWidth\fP resource to \*(``true\*(''. This makes \fI\*n\fP use a built-in version of the wide-character width calculation. The default is \*(``false\*('' .TP 8 .B "+mk_width" Reset the \fBmkWidth\fP resource. .TP 8 .BI \-ms " color" This option specifies the color to be used for the pointer cursor. The default is to use the foreground color. This sets the \fBpointerColor\fP resource. .TP 8 .BI \-nb " number" This option specifies the number of characters from the right end of a line at which the margin bell, if enabled, will ring. The default is \*(``10\*(''. .TP 8 .B "\-nul" This option disables the display of underlining. .TP 8 .B "+nul" This option enables the display of underlining. .TP 8 .B \-pc This option enables the PC-style use of bold colors (see \fBboldColors\fP resource). .TP 8 .B +pc This option disables the PC-style use of bold colors. .TP 8 .B \-pob This option indicates that the window should be raised whenever a Control-G is received. .TP 8 .B +pob This option indicates that the window should not be raised whenever a Control-G is received. .TP 8 .B \-report\-charclass Print a report to the standard output showing information about the character-classes which can be altered using the \fBcharClass\fP resource. .TP 8 .B \-report\-colors Print a report to the standard output showing information about colors as \fI\*n\fP allocates them. This corresponds to the \fBreportColors\fP resource. .TP 8 .B \-report\-fonts Print a report to the standard output showing information about fonts which are loaded. This corresponds to the \fBreportFonts\fP resource. .TP 8 .B \-report\-icons Print a report to the standard output showing information about pixmap-icons which are loaded. This corresponds to the \fBreportIcons\fP resource. .TP 8 .B \-report\-xres Print a report to the standard output showing the values of boolean, numeric or string X resources for the VT100 widget when initialization is complete. This corresponds to the \fBreportXRes\fP resource. .TP 8 .B \-rightbar Force scrollbar to the right side of VT100 screen. .TP 8 .B "\-rvc" This option disables the display of characters with reverse attribute as color. .TP 8 .B "+rvc" This option enables the display of characters with reverse attribute as color. .TP 8 .B \-rw This option indicates that reverse-wraparound should be allowed. This allows the cursor to back up from the leftmost column of one line to the rightmost column of the previous line. This is very useful for editing long shell command lines and is encouraged. This option can be turned on and off from the \fBVT Options\fP menu. .TP 8 .B +rw This option indicates that reverse-wraparound should not be allowed. .TP 8 .B \-s This option indicates that \fI\*n\fP may scroll asynchronously, meaning that the screen does not have to be kept completely up to date while scrolling. This allows \fI\*n\fP to run faster when network latencies are very high and is typically useful when running across a very large internet or many gateways. .TP 8 .B +s This option indicates that \fI\*n\fP should scroll synchronously. .TP 8 .B \-samename Does not send title and icon name change requests when the request would have no effect: the name is not changed. This has the advantage of preventing flicker and the disadvantage of requiring an extra round trip to the server to find out the previous value. In practice this should never be a problem. .TP 8 .B +samename Always send title and icon name change requests. .TP 8 .B \-sb This option indicates that some number of lines that are scrolled off the top of the window should be saved and that a scrollbar should be displayed so that those lines can be viewed. This option may be turned on and off from the \fBVT Options\fP menu. .TP 8 .B +sb This option indicates that a scrollbar should not be displayed. .TP 8 .BI \-selbg " color" This option specifies the color to use for the background of selected text. If not specified, reverse video is used. See the discussion of the \fBhighlightColor\fP resource. .TP 8 .BI \-selfg " color" This option specifies the color to use for selected text. If not specified, reverse video is used. See the discussion of the \fBhighlightTextColor\fP resource. .TP 8 .B \-sf This option indicates that Sun function key escape codes should be generated for function keys. .TP 8 .B +sf This option indicates that the standard escape codes should be generated for function keys. .TP 8 .BI \-sh " number" scale line-height values by the given number. See the discussion of the \fBscaleHeight\fP resource. .TP 8 .B \-si This option indicates that output to a window should not automatically reposition the screen to the bottom of the scrolling region. This option can be turned on and off from the \fBVT Options\fP menu. .TP 8 .B +si This option indicates that output to a window should cause it to scroll to the bottom. .TP 8 .B \-sk This option indicates that pressing a key while using the scrollbar to review previous lines of text should cause the window to be repositioned automatically in the normal position at the bottom of the scroll region. .TP 8 .B +sk This option indicates that pressing a key while using the scrollbar should not cause the window to be repositioned. .TP 8 .BI \-sl " number" This option specifies the number of lines to save that have been scrolled off the top of the screen. This corresponds to the \fBsaveLines\fP resource. The default is \*(``1024\*(''. .TP 8 .B \-sm This option, corresponding to the \fBsessionMgt\fR resource, indicates that \fI\*n\fR should set up session manager callbacks. .TP 8 .B +sm This option indicates that \fI\*n\fR should not set up session manager callbacks. .TP 8 .B \-sp This option indicates that Sun/PC keyboard should be assumed, providing mapping for keypad \*(``+\*('' to \*(``,\*('', and CTRL-F1 to F13, CTRL-F2 to F14, etc. .TP 8 .B +sp This option indicates that the standard escape codes should be generated for keypad and function keys. .TP 8 .B \-t This option indicates that \fI\*n\fP should start in Tektronix mode, rather than in VT\fIxxx\fP mode. Switching between the two windows is done using the \*(``Options\*('' menus. .IP Terminal database (\fIterminfo\fP (5) or \fItermcap\fP (5)) entries that work with \fI\*n\fR are: .IP \*(``tek4014\*('', .br \*(``tek4015\*('', .br \*(``tek4012\*('', .br \*(``tek4013\*('', .br \*(``tek4010\*('', and .br \*(``dumb\*(''. .IP \fI\*N\fP automatically searches the terminal database in this order for these entries and then sets the \*(``TERM\*('' variable (and the \*(``TERMCAP\*('' environment variable, if relevant). .TP 8 .B +t This option indicates that \fI\*n\fP should start in VT\fIxxx\fP mode. .TP 8 .B \-tb This option, corresponding to the \fBtoolBar\fR resource, indicates that \fI\*n\fR should display a toolbar (or menubar) at the top of its window. The buttons in the toolbar correspond to the popup menus, e.g., control/left/mouse for \fBMain Options\fP. .TP 8 .B +tb This option indicates that \fI\*n\fR should not set up a toolbar. .TP 8 .BI \-ti " term_id" Specify the name used by \fI\*n\fP to select the correct response to terminal ID queries. It also specifies the emulation level, used to determine the type of response to a DA control sequence. Valid values include vt52, vt100, vt101, vt102, vt220, and vt240 (the \*(``vt\*('' is optional). The default is \*(``vt__default_termid__\*(''. The \fIterm_id\fP argument specifies the terminal ID to use. (This is the same as the \fBdecTerminalID\fP resource). .TP 8 .BI \-tm " string" This option specifies a series of terminal setting keywords followed by the characters that should be bound to those functions, similar to the \fIstty\fP program. The keywords and their values are described in detail in the \fBttyModes\fP resource. .TP 8 .BI \-tn " name" This option specifies the name of the terminal type to be set in the TERM environment variable. It corresponds to the \fBtermName\fP resource. This terminal type must exist in the terminal database (termcap or terminfo, depending on how \fI\*n\fP is built) and should have \fIli#\fP and \fIco#\fP entries. If the terminal type is not found, \fI\*n\fP uses the built-in list \*(``xterm\*('', \*(``vt102\*('', etc. .TP 8 .B \-u8 This option sets the \fButf8\fP resource. When \fButf8\fP is set, \fI\*n\fP interprets incoming data as UTF-8. This sets the \fBwideChars\fP resource as a side-effect, but the UTF-8 mode set by this option prevents it from being turned off. If you must turn UTF-8 encoding on and off, use the \fB\-wc\fP option or the corresponding \fBwideChars\fP resource, rather than the \fB\-u8\fP option. .IP This option and the \fButf8\fR resource are overridden by the \fB\-lc\fP and \fB\-en\fP options and \fBlocale\fR resource. That is, if \fI\*n\fP has been compiled to support \fIluit\fR, and the \fBlocale\fP resource is not \*(``false\*('' this option is ignored. We recommend using the \fB\-lc\fR option or the \*(``\fBlocale:\ true\fR\*('' resource in UTF-8 locales when your operating system supports locale, or \fB\-en\ UTF-8\fP option or the \*(``\fBlocale:\ UTF-8\fR\*('' resource when your operating system does not support locale. .TP 8 .B +u8 This option resets the \fButf8\fP resource. .TP 8 .B "\-uc" This option makes the cursor underlined instead of a box. .TP 8 .B "+uc" This option makes the cursor a box instead of underlined. .TP 8 .B "\-ulc" This option disables the display of characters with underline attribute as color rather than with underlining. .TP 8 .B "+ulc" This option enables the display of characters with underline attribute as color rather than with underlining. .TP 8 .B "\-ulit" This option, corresponding to the \fBitalicULMode\fP resource, disables the display of characters with underline attribute as italics rather than with underlining. .TP 8 .B "+ulit" This option, corresponding to the \fBitalicULMode\fP resource, enables the display of characters with underline attribute as italics rather than with underlining. .TP 8 .B \-ut This option indicates that \fI\*n\fP should not write a record into the system \fIutmp\fP log file. .TP 8 .B +ut This option indicates that \fI\*n\fP should write a record into the system \fIutmp\fP log file. .TP 8 .B \-vb This option indicates that a visual bell is preferred over an audible one. Instead of ringing the terminal bell whenever a Control-G is received, the window will be flashed. .TP 8 .B +vb This option indicates that a visual bell should not be used. .TP 8 .B \-wc This option sets the \fBwideChars\fP resource. .IP When \fBwideChars\fP is set, \fI\*n\fP maintains internal structures for 16-bit characters. If \fI\*n\fP is not started in UTF-8 mode (or if this resource is not set), initially it maintains those structures to support 8-bit characters. \fI\*N\fP can later be switched, using a menu entry or control sequence, causing it to reallocate those structures to support 16-bit characters. .IP The default is \*(``false\*(''. .TP 8 .B +wc This option resets the \fBwideChars\fP resource. .TP 8 .B \-wf This option indicates that \fI\*n\fP should wait for the window to be mapped the first time before starting the subprocess so that the initial terminal size settings and environment variables are correct. It is the application's responsibility to catch subsequent terminal size changes. .TP 8 .B +wf This option indicates that \fI\*n\fP should not wait before starting the subprocess. .TP 8 .B \-ziconbeep \fIpercent\fP Same as \fBzIconBeep\fP resource. If percent is non-zero, xterms that produce output while iconified will cause an XBell sound at the given volume and have \*(``***\*('' prepended to their icon titles. Most window managers will detect this change immediately, showing you which window has the output. (A similar feature was in x10 \fI\*n\fP.) .TP 8 .B \-C This option indicates that this window should receive console output. This is not supported on all systems. To obtain console output, you must be the owner of the console device, and you must have read and write permission for it. If you are running X under \fIxdm\fP on the console screen you may need to have the session startup and reset programs explicitly change the ownership of the console device in order to get this option to work. .TP 8 .B \-S\fIccn\fP This option allows \fI\*n\fP to be used as an input and output channel for an existing program and is sometimes used in specialized applications. The option value specifies the last few letters of the name of a pseudo-terminal to use in slave mode, plus the number of the inherited file descriptor. If the option contains a \*(``/\*('' character, that delimits the characters used for the pseudo-terminal name from the file descriptor. Otherwise, exactly two characters are used from the option for the pseudo-terminal name, the remainder is the file descriptor. Examples (the first two are equivalent since the descriptor follows the last \*(``/\*(''): .NS 15 \-S/dev/pts/123/45 \-S123/45 \-Sab34 .NE .IP Note that \fI\*n\fP does not close any file descriptor which it did not open for its own use. It is possible (though probably not portable) to have an application which passes an open file descriptor down to \fI\*n\fP past the initialization or the \fB\-S\fP option to a process running in the \fI\*n\fP. .SS Old Options .PP The following command line arguments are provided for compatibility with older versions. They may not be supported in the next release as the X Toolkit provides standard options that accomplish the same task. .TP 8 .B "%\fIgeom\fP" This option specifies the preferred size and position of the Tektronix window. It is shorthand for specifying the \*(``\fBtekGeometry\fP\*('' resource. .TP 8 .B "#\fIgeom\fP" This option specifies the preferred position of the icon window. It is shorthand for specifying the \*(``\fBiconGeometry\fP\*('' resource. .TP 8 .BI \-T " string" This option specifies the title for \fI\*n\fP's windows. It is equivalent to \fB\-title\fP. .TP 8 .BI \-n " string" This option specifies the icon name for \fI\*n\fP's windows. It is shorthand for specifying the \*(``\fBiconName\fP\*('' resource. Note that this is not the same as the toolkit option \fB\-name\fP. The default icon name is the application name. .IP If no suitable icon is found, \fI\*n\fP provides a compiled-in pixmap. .IP X Toolkit sets the \fBWM_ICON_NAME\fP property using this value. .TP 8 .B \-r This option indicates that reverse video should be simulated by swapping the foreground and background colors. It is equivalent to \fB\-rv\fP. .TP 8 .BI \-w " number" This option specifies the width in pixels of the border surrounding the window. It is equivalent to \fB\-borderwidth\fP or \fB\-bw\fP. . .SS X Toolkit Options .PP The following standard X Toolkit command line arguments are commonly used with \fI\*n\fP: .TP 8 .B \-bd \fIcolor\fP This option specifies the color to use for the border of the window. The corresponding resource name is \fBborderColor\fP. \fI\*N\fP uses the X Toolkit default, which is \*(``XtDefaultForeground\*(''. .IP \fI\*N\fP's VT100 window has two borders: the \fIinner\fP border \fBinternalBorder\fP and the \fIouter\fP border \fBborderWidth\fP, managed by the X Toolkit. .IP Normally \fI\*n\fP fills the inner border using the VT100 window's background color. If the \fBcolorInnerBorder\fP resource is enabled, then \fI\*n\fP may fill the inner border using the \fBborderColor\fP resource. .TP 8 .B \-bg \fIcolor\fP This option specifies the color to use for the background of the window. The corresponding resource name is \fIbackground\fP. The default is \*(``XtDefaultBackground\*(''. .TP 8 .B \-bw \fInumber\fP This option specifies the width in pixels of the border surrounding the window. .IP This appears to be a legacy of older X releases. It sets the \fBborderWidth\fP resource of the shell widget, and may provide advice to your window manager to set the thickness of the window frame. Most window managers do not use this information. See the \fB\-b\fP option, which controls the inner border of the \fI\*n\fP window. .TP 8 .B \-display \fIdisplay\fP This option specifies the X server to contact; see X(__miscmansuffix__). .TP 8 .B \-fg \fIcolor\fP This option specifies the color to use for displaying text. The corresponding resource name is \fIforeground\fP. The default is \*(``XtDefaultForeground\*(''. .TP 8 .B \-fn \fIfont\fP This option specifies the font to be used for displaying normal text. The corresponding resource name is \fIfont\fP. The resource value default is \fIfixed\fP. .TP 8 .B \-font \fIfont\fP This is the same as \fB\-fn\fP. .TP 8 .B \-geometry \fIgeometry\fP This option specifies the preferred size and position of the VT\fIxxx\fP window; see X(__miscmansuffix__). .IP The normal geometry specification can be suffixed with \fB@\fP followed by a Xinerama screen specification; it can be either \fBg\fP for the global screen (default), \fBc\fP for the current screen or a screen number. .TP 8 .B \-iconic .br This option indicates that \fI\*n\fP should ask the window manager to start it as an icon rather than as the normal window. The corresponding resource name is \fIiconic\fP. .TP 8 .B \-name \fIname\fP This option specifies the application name under which resources are to be obtained, rather than the default executable file name. \fIName\fP should not contain \*(``.\*('' or \*(``*\*('' characters. .TP 8 .B \-rv This option indicates that reverse video should be simulated by swapping the foreground and background colors. The corresponding resource name is \fBreverseVideo\fP. .TP 8 .B +rv Disable the simulation of reverse video by swapping foreground and background colors. .TP 8 .B \-title \fIstring\fP This option specifies the window title string, which may be displayed by window managers if the user so chooses. It is shorthand for specifying the \*(``\fBtitle\fP\*('' resource. The default title is the command line specified after the \fB\-e\fP option, if any, otherwise the application name. .IP X Toolkit sets the \fBWM_NAME\fP property using this value. .TP 8 .B \-xrm \fIresourcestring\fP This option specifies a resource string to be used. This is especially useful for setting resources that do not have separate command line options. .PP X Toolkit accepts alternate names for a few of these options, e.g., .bP \*(``\fB\-background\fP\*('' for \*(``\fB\-bg\fP\*('' .bP \*(``\fB\-font\fP\*('' for \*(``\fB\-fn\fP\*('' .bP \*(``\fB\-foreground\fP\*('' for \*(``\fB\-fg\fP\*('' .PP Abbreviated options also are supported, e.g., \*(``\fB\-v\fP\*('' for \*(``\fB\-verbose\fP.\*('' . . .SH RESOURCES \fI\*N\fP understands all of the core X Toolkit resource names and classes. Application specific resources (e.g., \*(``\fB__default_class__.\fP\fINAME\fP\*('') follow: .SS Application Resources .TP 8 .B "backarrowKeyIsErase\fP (class\fB BackarrowKeyIsErase\fP)" Tie the VT\fIxxx\fP \fBbackarrowKey\fP and \fBptyInitialErase\fP resources together by setting the DECBKM state according to whether the \fIinitial erase\fP character is a backspace (8) or delete (127) character. A \*(``false\*('' value disables this feature. The default is \*(``__backarrow_is_erase__\*(''. .IP Here are tables showing how the initial settings for .RS .bP .B backarrowKeyIsErase\fP (BKIE), .bP .B backarrowKey\fP (BK), and .bP .B ptyInitialErase\fP (PIE), along with the .bP \fIstty\fP erase character (^H for backspace, ^?\& for delete) .RE .IP will affect DECBKM. First, \fI\*n\fP obtains the initial \fIerase\fP character: .RS .bP \fI\*n\fP's internal value is ^H .bP \fI\*n\fP asks the operating system for the value which \fBstty\fP shows .bP the \fBttyModes\fP resource may override \fIerase\fP .bP if \fBptyInitialErase\fP is false, \fI\*n\fP will look in the terminal database .RE .IP Summarizing that as a table: .TS l l l l _ _ _ _ l c c c. \fBPIE\fR \fBstty\fR \fBtermcap\fR \fIerase\fP false ^H ^H ^H false ^H ^? ^? false ^? ^H ^H false ^? ^? ^? true ^H ^H ^H true ^H ^? ^H true ^? ^H ^? true ^? ^? ^? .TE .IP Using that \fIerase\fP character, \fI\*n\fP allows further choices: .RS .bP if \fBbackarrowKeyIsErase\fP is true, \fI\*n\fP uses the \fIerase\fP character for the initial state of \fBDECBKM\fP .bP if \fBbackarrowKeyIsErase\fP is false, \fI\*n\fP sets \fBDECBKM\fP to 2 (internal). This ties together \fBbackarrowKey\fP and the control sequence for \fBDECBKM\fP. .bP applications can send a control sequence to set/reset \fBDECBKM\fP control set .bP the \*(``Backarrow Key (BS/DEL)\*('' menu entry toggles \fBDECBKM\fP .RE .IP Summarizing the initialization details: .TS l l l l l _ _ _ _ _ c l l c c. \fIerase\fR \fBBKIE\fR \fBBK\fR \fBDECBKM\fP \fIresult\fP ^? false false 2 ^H ^? false true 2 ^? ^? true false 0 ^? ^? true true 1 ^? ^H false false 2 ^H ^H false true 2 ^? ^H true false 0 ^H ^H true true 1 ^H .TE .TP 8 .B "buffered\fP (class\fB Buffered\fP)" Normally \fI\*n\fP is built with double-buffer support. This resource can be used to turn it on or off. Setting the resource to \*(``true\*('' turns double-buffering on. The default value is \*(``__double_buffer__\*(''. .TP 8 .B "bufferedFPS\fP (class\fB BufferedFPS\fP)" When \fI\*n\fP is built with double-buffer support, this gives the maximum number of frames/second. The default is \*(``40\*('' and is limited to the range 1 through 100. .TP 8 .B "fullscreen\fP (class\fB Fullscreen\fP)" Specifies whether or not \fI\*n\fP should ask the window manager to use a fullscreen layout on startup. \fI\*N\fP accepts either a keyword (ignoring case) or the number shown in parentheses: .RS .TP 3 false (0) Fullscreen layout is not used initially, but may be later via menu-selection or control sequence. .TP 3 true (1) Fullscreen layout is used initially, but may be disabled later via menu-selection or control sequence. .TP 3 always (2) Fullscreen layout is used initially, and cannot be disabled later via menu-selection or control sequence. .TP 3 never (3) Fullscreen layout is not used, and cannot be enabled later via menu-selection or control sequence. .RE .IP The default is \*(``false\*(''. .TP 8 .B "hold\fP (class\fB Hold\fP)" If true, \fI\*n\fP will not immediately destroy its window when the shell command completes. It will wait until you use the window manager to destroy/kill the window, or if you use the menu entries that send a signal, e.g., HUP or KILL. You may scroll back, select text, etc., to perform most graphical operations. Resizing the display will lose data, however, since this involves interaction with the shell which is no longer running. .TP 8 .B "hpFunctionKeys\fP (class\fB HpFunctionKeys\fP)" Specifies whether or not HP function key escape codes should be generated for function keys. The default is \*(``false\*('', i.e., this feature is disabled. .IP The \fBkeyboardType\fP resource is the preferred mechanism for selecting this mode. .TP 8 .B "iconGeometry\fP (class\fB IconGeometry\fP)" Specifies the preferred size and position of the application when iconified. It is not necessarily obeyed by all window managers. .TP 8 .B "iconHint\fP (class\fB IconHint\fP)" Specifies an icon which will be added to the window manager hints. \fI\*N\fP provides no default value. .IP Set this resource to \*(``none\*('' to omit the hint entirely, using whatever the window manager may decide. .IP If the \fBiconHint\fP resource is given (or is set via the \fB\-n\fP option) \fI\*n\fP searches for a pixmap file with that name, in the current directory as well as in __pixmapsdir__. if the resource does not specify an absolute pathname. In each case, \fI\*n\fP adds \*(``_48x48\*('' and/or \*(``.xpm\*('' to the filename after trying without those suffixes. If it is able to load the file, \fI\*n\fP sets the window manager hint for the icon-pixmap. These pixmaps are distributed with \fI\*n\fP, and can optionally be compiled-in: .RS .bP mini.\*n_16x16, mini.\*n_32x32, mini.\*n_48x48 .bP filled-\*n_16x16, filled-\*n_32x32, filled-\*n_48x48 .bP \*n_16x16, \*n_32x32, \*n_48x48 .bP \*n-color_16x16, \*n-color_32x32, \*n-color_48x48 .RE .IP In either case, \fI\*n\fP allows for adding a \*(``_48x48\*('' to specify the largest of the pixmaps as a default. That is, \*(``mini.\*n\*('' is the same as \*(``mini.\*n_48x48\*(''. .IP If no explicit \fBiconHint\fP resource is given (or if none of the compiled-in names matches), \fI\*n\fP uses \*(``mini.\*n\*('' (which is always compiled-in). .IP The \fBiconHint\fP resource has no effect on \*(``desktop\*('' files, including \*(``panel\*('' and \*(``menu\*(''. Those are typically set via a \*(``.desktop\*('' file; \fI\*n\fP provides samples for itself (and the \fIu\*n\fP script). The more capable desktop systems allow changing the icon on a per-user basis. .TP 8 .B "iconName\fP (class\fB IconName\fP)" Specifies a label for \fI\*n\fP when iconified. \fI\*N\fP provides no default value; some window managers may assume the application name, e.g., \*(``\*n\*(''. .IP Setting the \fBiconName\fP resource sets the icon label unless overridden by \fBzIconBeep\fP or the control sequences which change the window and icon labels. .TP 8 .B "keyboardType\fP (class\fB KeyboardType\fP)" Enables one (or none) of the various keyboard-type resources: \fBhpFunctionKeys\fP, \fBscoFunctionKeys\fP, \fBsunFunctionKeys\fP, \fBtcapFunctionKeys\fP, \fBoldXtermFKeys\fP and \fBsunKeyboard\fP. .IP The resource's value should be one of the corresponding strings \*(``hp\*('', \*(``sco\*('', \*(``sun\*('', \*(``tcap\*('', \*(``legacy\*('' or \*(``vt220\*('', respectively. .IP The individual resources are provided for legacy support; this resource is simpler to use. \fI\*N\fP will use only one keyboard-type, but if multiple resources are set, it warns and uses the last one it checks. .IP The default is \*(``unknown\*('', i.e., none of the associated resources are set via this resource. .TP 8 .B "maxBufSize\fP (class\fB MaxBufSize\fP)" Specify the maximum size of the input buffer. The default is \*(``32768\*(''. You cannot set this to a value less than the \fBminBufSize\fR resource. It will be increased as needed to make that value evenly divide this one. .IP On some systems you may want to increase one or both of the \fBmaxBufSize\fP and \fBminBufSize\fP resource values to achieve better performance if the operating system prefers larger buffer sizes. .TP 8 .B "maximized\fP (class\fB Maximized\fP)" Specifies whether or not \fI\*n\fP should ask the window manager to maximize its layout on startup. The default is \*(``false\*(''. .TP 8 .B "menuHeight\fP (class\fB MenuHeight\fP)" Specifies the height of the toolbar, which may be increased by the X toolkit layout widget depending upon the fontsize used. The default is \*(``25\*(''. .TP 8 .B "messages\fP (class\fB Messages\fP)" Specifies whether write access to the terminal is allowed initially. See \fBmesg\fP(1). The default is \*(``true\*(''. .TP 8 .B "menuLocale\fP (class\fB MenuLocale\fP)" Specify the locale used for character-set computations when loading the popup menus. Use this to improve initialization performance of the Athena popup menus, which may load unnecessary (and very large) fonts, e.g., in a locale having UTF-8 encoding. The default is \*(``C\*('' (POSIX). .IP To use the current locale (only useful if you have localized the resource settings for the menu entries), set the resource to an empty string. .TP 8 .B "minBufSize\fP (class\fB MinBufSize\fP)" Specify the minimum size of the input buffer, i.e., the amount of data that \fI\*n\fR requests on each read. The default is \*(``4096\*(''. You cannot set this to a value less than 64. .TP 8 .B "omitTranslation\fP (class\fB OmitTranslation\fP)" Selectively omit one or more parts of \fI\*n\fP's default translations at startup. The resource value is a comma-separated list of keywords, which may be abbreviated: .RS .TP default ignore (mouse) button-down events which were not handled by other translations .TP fullscreen assigns a key-binding to the \fBfullscreen()\fP action. .TP keypress assigns keypresses by default to the \fBinsert-seven-bit()\fP and \fBinsert-eight-bit()\fP actions. .TP paging assigns key bindings to the \fBscroll-back()\fP and \fBscroll-forw()\fP actions. .TP popup-menu assigns mouse-buttons with the \fIcontrol\fP modifier to the popup-menus. .TP reset assigns mouse-button 2 with the \fImeta\fP modifier to the \fBclear-saved-lines\fP action. .TP scroll-lock assigns a key-binding to the \fBscroll-lock()\fP action. .TP select assigns mouse- and keypress-combinations to actions which manipulate the selection. .TP shift-fonts assigns key-bindings to \fBlarger-vt-font()\fP and \fBsmaller-vt-font()\fP actions. .TP wheel-mouse assigns buttons 4 and 5 with different modifiers to the \fBscroll-back()\fP and \fBscroll-forw()\fP actions. .RE .TP 8 .B ptyHandshake\fP (class\fB PtyHandshake\fP) If \*(``true\*('', \fI\*n\fP will perform handshaking during initialization to ensure that the parent and child processes update the \fIutmp\fP and \fIstty\fP state. .IP See also \fBwaitForMap\fP which waits for the pseudo-terminal's notion of the screen size, and \fBptySttySize\fP which resets the screen size after other terminal initialization is complete. The default is \*(``true\*(''. .TP 8 .B ptyInitialErase\fP (class\fB PtyInitialErase\fP) If \*(``true\*('', \fI\*n\fP will use the pseudo-terminal's sense of the \fIstty\fP erase value. If \*(``false\*('', \fI\*n\fP will set the \fIstty\fP erase value to match its own configuration, using the \fBkb\fP string from the termcap entry as a reference, if available. .IP In either case, the result is applied to the TERMCAP variable which \fI\*n\fP sets, if the system uses TERMCAP. .IP See also the \fBttyModes\fP resource, which may override this. The default is \*(``__initial_erase__\*(''. .TP 8 .B ptySttySize\fP (class\fB PtySttySize\fP) If \*(``true\*('', \fI\*n\fP will reset the screen size after terminal initialization is complete. This is needed for some systems whose pseudo-terminals cannot propagate terminal characteristics. Where it is not needed, it can interfere with other methods for setting the initial screen size, e.g., via window manager interaction. .IP See also \fBwaitForMap\fP which waits for a handshake-message giving the pseudo-terminal's notion of the screen size. The default is \*(``false\*('' on Linux and macOS systems, \*(``true\*('' otherwise. .TP 8 .B "reportColors\fP (class\fB ReportColors\fP)" If true, \fI\*n\fP will print to the standard output a summary of colors as it allocates them. The default is \*(``false\*(''. .TP 8 .B "reportFonts\fP (class\fB ReportFonts\fP)" If true, \fI\*n\fP will print to the standard output a summary of each font's metrics (size, number of glyphs, etc.), as it loads them. The default is \*(``false\*(''. .TP 8 .B "reportIcons\fP (class\fB ReportIcons\fP)" If true, \fI\*n\fP will print to the standard output a summary of each pixmap icon as it loads them. The default is \*(``false\*(''. .TP 8 .B "reportXRes\fP (class\fB ReportXRes\fP)" If true, \fI\*n\fP will print to the standard output a list of the boolean, numeric and string X resources for the VT100 widget after initialization. The default is \*(``false\*(''. .TP 8 .B "sameName\fP (class\fB SameName\fP)" If the value of this resource is \*(``true\*('', \fI\*n\fP does not send title and icon name change requests when the request would have no effect: the name is not changed. This has the advantage of preventing flicker and the disadvantage of requiring an extra round trip to the server to find out the previous value. In practice this should never be a problem. The default is \*(``true\*(''. .TP 8 .B "scaleHeight\fP (class\fB ScaleHeight\fP)" Scale line-height values by the resource value, which is limited to \*(``0.9\*('' to \*(``1.5\*(''. The default value is \*(``1.0\*('', .IP While this resource applies to either bitmap or TrueType fonts, its main purpose is to help work around incompatible changes in the Xft library's font metrics. \fI\*N\fP checks the font metrics to find what the library claims are the bounding boxes for each glyph (character). However, some of Xft's features (such as the autohinter) can cause the glyphs to be scaled larger than the bounding boxes, and be partly overwritten by the next row. .IP See \fBuseClipping\fP for a related resource. .TP 8 .B "scoFunctionKeys\fP (class\fB ScoFunctionKeys\fP)" Specifies whether or not SCO function key escape codes should be generated for function keys. The default is \*(``false\*('', i.e., this feature is disabled. .IP The \fBkeyboardType\fP resource is the preferred mechanism for selecting this mode. .TP 8 .B "sessionMgt\fP (class\fB SessionMgt\fP)" If the value of this resource is \*(``true\*('', \fI\*n\fP sets up session manager callbacks for \fBXtNdieCallback\fR and \fBXtNsaveCallback\fR. The default is \*(``true\*(''. .TP 8 .B "sunFunctionKeys\fP (class\fB SunFunctionKeys\fP)" Specifies whether or not Sun function key escape codes should be generated for function keys. The default is \*(``false\*('', i.e., this feature is disabled. .IP The \fBkeyboardType\fP resource is the preferred mechanism for selecting this mode. .TP 8 .B "sunKeyboard\fP (class\fB SunKeyboard\fP)" \fI\*N\fP translates certain key symbols based on its assumptions about your keyboard. This resource specifies whether or not Sun/PC keyboard layout (i.e., the PC keyboard's numeric keypad together with 12 function keys) should be assumed rather than DEC VT220. This causes the keypad \*(``+\*('' to be mapped to \*(``,\*(''. and CTRL F1-F10 to F11-F20, depending on the setting of the \fBctrlFKeys\fP resource, so \fI\*n\fP emulates a DEC VT220 more accurately. Otherwise (the default, with \fBsunKeyboard\fP set to \*(``false\*(''), \fI\*n\fP uses PC-style bindings for the function keys and keypad. .IP PC-style bindings use the Shift, Alt, Control and Meta keys as modifiers for function-keys and keypad (see \fIXterm Control Sequences\fP for details). The PC-style bindings are analogous to PCTerm, but not the same thing. Normally these bindings do not conflict with the use of the Meta key as described for the \fBeightBitInput\fP resource. If they do, note that the PC-style bindings are evaluated first. .IP See also the \fBkeyboardType\fP resource. .TP 8 .B "tcapFunctionKeys\fP (class\fB TcapFunctionKeys\fP)" Specifies whether or not function key escape codes read from the termcap/terminfo entry corresponding to the \fBTERM\fP environment variable should be generated for function keys instead of those configured using \fBsunKeyboard\fP and \fBkeyboardType\fP. The default is \*(``false\*('', i.e., this feature is disabled. .IP The \fBkeyboardType\fP resource is the preferred mechanism for selecting this mode. .TP 8 .B "termName\fP (class\fB TermName\fP)" Specifies the terminal type name to be set in the TERM environment variable. .TP 8 .B "title\fP (class\fB Title\fP)" Specifies a string that may be used by the window manager when displaying this application. .TP 8 .B "toolBar\fP (class\fB ToolBar\fP)" Specifies whether or not the toolbar should be displayed. The default is \*(``true\*(''. .TP 8 .B "ttyModes\fP (class\fB TtyModes\fP)" Specifies a string containing terminal setting keywords. Except where noted, they may be bound to \fIcharacters\fP. Other keywords set \fImodes\fP. Not all keywords are supported on a given system. Allowable keywords include: .TS l l l _ _ _ l l l. \fBKeyword\fR \fBPOSIX?\fR \fBNotes\fR brk no T{ \fICHAR\fP may send an \*(``interrupt\*('' signal, as well as ending the input-line. T} dsusp no T{ \fICHAR\fP will send a terminal \*(``stop\*('' signal after input is flushed. T} eof yes T{ \fICHAR\fP will terminate input (i.e., an end of file). T} eol yes \fICHAR\fP will end the line. eol2 no alternate \fICHAR\fP for ending the line. erase yes \fICHAR\fP will erase the last character typed. erase2 no T{ alternate \fICHAR\fP for erasing the last input-character. T} flush no T{ \fICHAR\fP will cause output to be discarded until another \fBflush\fP character is typed. T} intr yes \fICHAR\fP will send an \*(``interrupt\*('' signal. kill yes \fICHAR\fP will erase the current line. lnext no \fICHAR\fP will enter the next character quoted. quit yes \fPCHAR\fP will send a \*(``quit\*('' signal. rprnt no \fICHAR\fP will redraw the current line. start yes T{ \fICHAR\fP will \fIrestart\fP the output after stopping it. T} status no T{ \fICHAR\fP will cause a system-generated status line to be printed. T} stop yes \fICHAR\fP will stop the output. susp yes \fICHAR\fP will send a terminal \*(``stop\*('' signal swtch no \fICHAR\fP will switch to a different shell layer. tabs yes \fIMode\fP disables tab-expansion. -tabs yes \fIMode\fP enables tab-expansion. weras no \fICHAR\fP will erase the last word typed. .TE .IP Control characters may be specified as ^char (e.g., ^c or ^u) and \fB^?\fP may be used to indicate delete (127). Use \fB^\-\fP to denote \fIundef\fP. Use \fB\\034\fP to represent \fB^\\\fP, since a literal backslash in an X resource escapes the next character. .IP This is very useful for overriding the default terminal settings without having to run \fIstty\fP every time an \fI\*n\fP is started. Note, however, that the \fIstty\fP program on a given host may use different keywords; \fI\*n\fR's table is built in. The \fIPOSIX\fP column in the table indicates which keywords are supported by a standard \fIstty\fP program. .IP If the \fBttyModes\fP resource specifies a value for \fBerase\fP, that overrides the \fBptyInitialErase\fP resource setting, i.e., \fI\*n\fP initializes the terminal to match that value. .TP 8 .B "useInsertMode\fP (class\fB UseInsertMode\fP)" Force use of insert mode by adding appropriate entries to the TERMCAP environment variable. This is useful if the system termcap is broken. (This resource is ignored on most systems, because TERMCAP is not used). The default is \*(``false\*(''. .TP 8 .B "utmpDisplayId\fP (class\fB UtmpDisplayId\fP)" Specifies whether or not \fI\*n\fP should try to record the display identifier (display number and screen number) as well as the hostname in the system \fIutmp\fP log file. The default is \*(``true\*(''. .TP 8 .B "utmpInhibit\fP (class\fB UtmpInhibit\fP)" Specifies whether or not \fI\*n\fP should try to record the user's terminal in the system \fIutmp\fP log file. If true, \fI\*n\fP will not try. The default is \*(``false\*(''. .TP 8 .B "validShells\fP (class\fB ValidShells\fP)" Augment (add to) the system's \fI/etc/shells\fP, when determining whether to set the \*(``SHELL\*('' environment variable when running a given program. .IP The resource value is a list of lines (separated by newlines). Each line holds one pathname. \fI\*N\fP ignores any line beginning with \*(``#\*('' after trimming leading/trailing whitespace from each line. .IP The default is an empty string. .TP 8 .B "waitForMap\fP (class\fB WaitForMap\fP)" Specifies whether or not \fI\*n\fP should wait for the initial window map before starting the subprocess. This is part of the \fBptyHandshake\fP logic. When \fI\*n\fP is directed to wait in this fashion, it passes the terminal size from the display end of the pseudo-terminal to the terminal I/O connection, e.g., using the size according to the window manager. Otherwise, it uses the size as given in resource values or command-line option \fB\-geometry\fP. The default is \*(``false\*(''. .TP 8 .B "zIconBeep\fP (class\fB ZIconBeep\fP)" Same as \-ziconbeep command line argument. If the value of this resource is non-zero, xterms that produce output while iconified will cause an XBell sound at the given volume and have \*(``***\ \*('' prepended to their icon titles. Most window managers will detect this change immediately, showing you which window has the output. (A similar feature was in x10 \fI\*n\fR.) The default is \*(``false\*(''. .TP 8 .B "zIconTitleFormat\fP (class\fB ZIconTitleFormat\fP)" Allow customization of the string used in the \fBzIconBeep\fP feature. The default value is \*(``***\ %s\*(''. .IP If the resource value contains a \*(``%s\*('', then \fI\*n\fP inserts the icon title at that point rather than prepending the string to the icon title. (Only the first \*(``%s\*('' is used). .\" .SS VT100 Widget Resources .PP The following resources are specified as part of the \fIvt100\fP widget (class \fIVT100\fP). They are specified by patterns such as \*(``\fB__default_class__.vt100.\fP\fINAME\fP\*(''. .PP If your \fI\*n\fP is configured to support the \*(``toolbar\*('', then those patterns need an extra level for the form-widget which holds the toolbar and vt100 widget. A wildcard between the top-level \*(``__default_class__\*('' and the \*(``vt100\*('' widget makes the resource settings work for either, e.g., \*(``\fB__default_class__*vt100.\fP\fINAME\fP\*(''. .TP 8 .B "activeIcon\fP (class\fB ActiveIcon\fP)" Specifies whether or not active icon windows are to be used when the \fI\*n\fP window is iconified, if this feature is compiled into \fI\*n\fR. The active icon is a miniature representation of the content of the window and will update as the content changes. Not all window managers necessarily support application icon windows. Some window managers will allow you to enter keystrokes into the active icon window. The default is \*(``default\*(''. .IP \fI\*N\fP accepts either a keyword (ignoring case) or the number shown in parentheses: .RS .TP false (0) No active icon is shown. .TP true (1) The active icon is shown. If you are using \fItwm\fP, use this setting to enable active-icons. .TP default (2) \fI\*N\fP checks at startup, and shows an active icon only for window managers which it can identify and which are known to support the feature. These are \fIfvwm\fP (full support), and \fIwindow maker\fP (limited). A few other windows managers (such as \fItwm\fP and \fIctwm\fP) support active icons, but do not support the extensions which allow \fI\*n\fP to identify the window manager. .RE .TP 8 .B "allowBoldFonts\fP (class\fB AllowBoldFonts\fP)" When set to \*(``false\*('', \fI\*n\fP will not use bold fonts. This overrides both the \fBalwaysBoldMode\fP and the \fBboldMode\fP resources. .TP 8 .B "allowC1Printable\fP (class\fB AllowC1Printable\fP)" If true, overrides the mapping of C1 controls (codes 128\(en159) to make them be treated as if they were printable characters. Although this corresponds to no particular standard, some users insist it is a VT100. The default is \*(``false\*(''. .TP .B "allowColorOps\fP (class\fB AllowColorOps\fP)" Specifies whether control sequences that set/query the dynamic colors should be allowed. ANSI colors are unaffected by this resource setting. The default is \*(``true\*(''. .TP .B "allowFontOps\fP (class\fB AllowFontOps\fP)" Specifies whether control sequences that set/query the font should be allowed. The default is \*(``true\*(''. .TP .B "allowMouseOps\fP (class\fB AllowMouseOps\fP)" Specifies whether control sequences that enable \fI\*n\fP to send escape sequences to the host on mouse-clicks and movement. The default is \*(``true\*(''. .TP 8 .B "allowPasteControls\fP (class\fB AllowPasteControls\fP)" If true, allow control characters such as BEL and CAN to be pasted. Formatting characters (tab, newline) are always allowed. Other C0 control characters are suppressed unless this resource is enabled. The exact set of control characters (C0 and C1) depends upon whether UTF-8 encoding is used, as well as the \fBallowC1Printable\fP resource. The default is \*(``false\*(''. .TP 8 .B "allowScrollLock\fP (class\fB AllowScrollLock\fP)" Specifies whether control sequences that set/query the Scroll Lock key should be allowed, as well as whether the Scroll Lock key responds to user's keypress. The default is \*(``false\*(''. .IP When this feature is enabled, \fI\*n\fP will sense the state of the Scroll Lock key each time it acquires focus. Pressing the Scroll Lock key toggles \fI\*n\fP's internal state, as well as toggling the associated LED. While the Scroll Lock is active, \fI\*n\fP attempts to keep a viewport on the same set of lines. If the current viewport is scrolled past the limit set by the \fBsaveLines\fP resource, then Scroll Lock has no further effect. .IP The reason for setting the default to \*(``false\*('' is to avoid user surprise. This key is generally unused in keyboard configurations, and has not acquired a standard meaning even when it is used in that manner. Consequently, users have assigned it for ad hoc purposes. .TP 8 .B "allowSendEvents\fP (class\fB AllowSendEvents\fP)" Specifies whether or not synthetic key and button events (generated using the X protocol SendEvent request) should be interpreted or discarded. The default is \*(``false\*('' meaning they are discarded. Note that allowing such events would create a very large security hole, therefore enabling this resource forcefully disables the \fBallow\fP\fIXXX\fP\fBOps\fR resources. The default is \*(``false\*(''. .TP .B "allowTcapOps\fP (class\fB AllowTcapOps\fP)" Specifies whether control sequences that query the terminal's notion of its function-key strings, as termcap or terminfo capabilities should be allowed. The default is \*(``true\*(''. .IP A few programs, e.g., \fIvim\fP, use this feature to get an accurate description of the terminal's capabilities, independent of the termcap/terminfo setting: .RS .bP \fI\*N\fP can tell the querying program how many colors it supports. This is a constant, depending on how it is compiled, typically 16. It does not change if you alter resource settings, e.g., the \fBboldColors\fP resource. .bP \fI\*N\fP can tell the querying program what strings are sent by modified (shift-, control-, alt-) function- and keypad-keys. Reporting control- and alt-modifiers is a feature that relies on the \fIncurses\fP extended naming. .RE .TP .B "allowTitleOps\fP (class\fB AllowTitleOps\fP)" Specifies whether control sequences that modify the window title or icon name should be allowed. The default is \*(``true\*(''. .TP .B "allowWindowOps\fP (class\fB AllowWindowOps\fP)" Specifies whether extended window control sequences (as used in \fIdtterm\fP) should be allowed. These include several control sequences which manipulate the window size or position, as well as reporting these values and the title or icon name. Each of these can be abused in a script; curiously enough most terminal emulators that implement these restrict only a small part of the repertoire. For fine-tuning, see \fBdisallowedWindowOps\fP. The default is \*(``false\*(''. .TP 8 .B "altIsNotMeta\fP (class\fB AltIsNotMeta\fP)" If \*(``true\*('', treat the Alt-key as if it were the Meta-key. Your keyboard may happen to be configured so they are the same. But if they are not, this allows you to use the same prefix- and shifting operations with the Alt-key as with the Meta-key. See \fBaltSendsEscape\fP and \fBmetaSendsEscape\fP. The default is \*(``false\*(''. .TP 8 .B "altSendsEscape\fP (class\fB AltSendsEscape\fP)" This is an additional keyboard operation that may be processed after the logic for \fBmetaSendsEscape\fP. It is only available if the \fBaltIsNotMeta\fP resource is set. .RS .bP If \*(``true\*('', Alt characters (a character combined with the modifier associated with left/right Alt-keys) are converted into a two-character sequence with the character itself preceded by ESC. This applies as well to function key control sequences, unless \fI\*n\fP sees that \fBAlt\fP is used in your key translations. .bP If \*(``false\*('', Alt characters input from the keyboard cause a shift to 8-bit characters (just like \fBmetaSendsEscape\fP). By combining the Alt- and Meta-modifiers, you can create corresponding combinations of ESC-prefix and 8-bit characters. .RE .IP The default is \*(``__alt_sends_esc__\*(''. \fI\*N\fP provides a menu option for toggling this resource. .TP 8 .B "alternateScroll\fP (class\fB ScrollCond\fP)" If \*(``true\*('', the \fBscroll-back\fP and \fBscroll-forw\fP actions send cursor\-up and \-down keys when \fI\*n\fP is displaying the alternate screen. The default is \*(``false\*(''. .IP The \fBalternateScroll\fP state can also be set using a control sequence. .TP 8 .B "alwaysBoldMode\fP (class\fB AlwaysBoldMode\fP)" Specifies whether \fI\*n\fP should check if the normal and bold fonts are distinct before deciding whether to use overstriking to simulate bold fonts. If this resource is true, \fI\*n\fP does not make the check for distinct fonts when deciding how to handle the \fBboldMode\fP resource. The default is \*(``false\*(''. .ne 9 .TS l l l l _ _ _ _ l l l l. \fIboldMode\fR \fIalwaysBoldMode\fR \fIComparison\fR \fIAction\fP false false ignored use font false true ignored use font true false same overstrike true false different use font true true ignored overstrike .TE .RS .LP This resource is used only for bitmap fonts: .bP When using bitmap fonts, it is possible that the font server will approximate the bold font by rescaling it from a different font size than expected. The \fBalwaysBoldMode\fP resource allows the user to override the (sometimes poor) resulting bold font with overstriking (which is at least consistent). .bP The problem does not occur with TrueType fonts (though there can be other unnecessary issues such as different coverage of the normal and bold fonts). .RE .IP As an alternative, setting the \fBallowBoldFonts\fP resource to false overrides both the \fBalwaysBoldMode\fP and the \fBboldMode\fP resources. .TP 8 .B "alwaysHighlight\fP (class\fB AlwaysHighlight\fP)" Specifies whether or not \fI\*n\fP should always display a highlighted text cursor. By default (if this resource is false), a hollow text cursor is displayed whenever the pointer moves out of the window or the window loses the input focus. The default is \*(``false\*(''. .TP 8 .B "alwaysUseMods\fP (class\fB AlwaysUseMods\fP)" Override the \fBnumLock\fP resource, telling \fI\*n\fR to use the Alt and Meta modifiers to construct parameters for function key sequences even if those modifiers appear in the translations resource. Normally \fI\*n\fP checks if Alt or Meta is used in a translation that would conflict with function key modifiers, and will ignore these modifiers in that special case. The default is \*(``false\*(''. .TP 8 .B "answerbackString\fP (class\fB AnswerbackString\fP)" Specifies the string that \fI\*n\fR sends in response to an ENQ (control/E) character from the host. The default is a blank string, i.e., \*(``\*(''. A hardware VT100 implements this feature as a setup option. .TP 8 .B "appcursorDefault\fP (class\fB AppcursorDefault\fP)" If \*(``true\*('', the cursor keys are initially in application mode. This is the same as the VT102 private DECCKM mode, The default is \*(``false\*(''. .TP 8 .B "appkeypadDefault\fP (class\fB AppkeypadDefault\fP)" If \*(``true\*('', the keypad keys are initially in application mode. The default is \*(``false\*(''. .TP 8 .B "assumeAllChars\fP (class\fB AssumeAllChars\fP)" If \*(``true\*('', this enables a special case in bitmap fonts to allow the font server to choose how to display missing glyphs. The default is \*(``true\*(''. .IP The reason for this resource is to help with certain quasi-automatically generated fonts (such as the ISO-10646-1 encoding of Terminus) which have incorrect font-metrics. .TP 8 .B "autoWrap\fP (class\fB AutoWrap\fP)" Specifies whether or not auto-wraparound should be enabled. This is the same as the VT102 DECAWM. The default is \*(``true\*(''. .TP 8 .B "awaitInput\fP (class\fB AwaitInput\fP)" Specifies whether or not \fI\*n\fR uses a 50 millisecond timeout to await input (i.e., to support the Xaw3d arrow scrollbar). The default is \*(``false\*(''. .TP 8 .B "backarrowKey\fP (class\fB BackarrowKey\fP)" Specifies whether the backarrow key transmits a backspace (8) or delete (127) character. This corresponds to the DECBKM control sequence. A \*(``true\*('' value specifies backspace. The default is \*(``__backarrow_is_bs__\*(''. Pressing the control key toggles this behavior. .TP 8 .B "background\fP (class\fB Background\fP)" Specifies the color to use for the background of the window. The default is \*(``XtDefaultBackground\*(''. .TP 8 .B "bellIsUrgent\fP (class\fB BellIsUrgent\fP)" Specifies whether to set the Urgency hint for the window manager when making a bell sound. The default is \*(``false\*(''. .TP 8 .B "bellOnReset\fP (class\fB BellOnReset\fP)" Specifies whether to sound a bell when doing a hard reset. The default is \*(``true\*(''. .TP 8 .B "bellSuppressTime\fP (class\fB BellSuppressTime\fP)" Number of milliseconds after a bell command is sent during which additional bells will be suppressed. Default is 200. If set non-zero, additional bells will also be suppressed until the server reports that processing of the first bell has been completed; this feature is most useful with the visible bell. .TP 8 .B "boldColors\fP (class\fB ColorMode\fP)" Specifies whether to combine bold attribute with colors like the IBM PC, i.e., map colors 0 through 7 to colors 8 through 15. These normally are the brighter versions of the first 8 colors, hence bold. The default is \*(``true\*(''. .TP 8 .B "boldFont\fP (class\fB BoldFont\fP)" Specifies the name of the bold font to use instead of overstriking. There is no default for this resource. .IP This font must be the same height and width as the normal font, otherwise it is ignored. If only one of the normal or bold fonts is specified, it will be used as the normal font and the bold font will be produced by overstriking this font. .IP See also the discussion of \fBboldMode\fP and \fBalwaysBoldMode\fP resources. .TP 8 .B "boldMode\fP (class\fB BoldMode\fP)" This specifies whether or not text with the bold attribute should be overstruck to simulate bold fonts if the resolved bold font is the same as the normal font. It may be desirable to disable bold fonts when color is being used for the bold attribute. .IP Note that \fI\*n\fP has one bold font which you may set explicitly. \fI\*N\fP attempts to derive a bold font for the other font selections (\fBfont1\fP through \fBfont6\fP). If it cannot find a bold font, it will use the normal font. In each case (whether the explicit resource or the derived font), if the normal and bold fonts are distinct, this resource has no effect. The default is \*(``true\*(''. .IP See the \fBalwaysBoldMode\fP resource which can modify the behavior of this resource. .IP Although \fI\*n\fP attempts to derive a bold font for other font selections, the font server may not cooperate. Since X11R6, bitmap fonts have been scaled. The font server claims to provide the bold font that \fI\*n\fP requests, but the result is not always readable. XFree86 introduced a feature which can be used to suppress the scaling. In the X server's configuration file (e.g., \*(``/etc/X11/XFree86\*('' or \*(``/etc/X11/xorg.conf\*(''), you can add \*(``:unscaled\*('' to the end of the directory specification for the \*(``misc\*('' fonts, which comprise the fixed-pitch fonts that are used by \fI\*n\fP. For example .NS FontPath "/usr/lib/X11/fonts/misc/" .NE .IP would become .NS FontPath "/usr/lib/X11/fonts/misc/:unscaled" .NE .IP Depending on your configuration, the font server may have its own configuration file. The same \*(``:unscaled\*('' can be added to its configuration file at the end of the directory specification for \*(``misc\*(''. .IP The bitmap scaling feature is also used by \fI\*n\fP to implement VT102 double-width and double-height characters. .TP 8 .B "brokenLinuxOSC\fP (class\fB BrokenLinuxOSC\fP)" If true, \fI\*n\fP applies a workaround to ignore malformed control sequences that a Linux script might send. Compare the palette control sequences documented in \fIconsole_codes\fR with ECMA-48. The default is \*(``true\*(''. .TP 8 .B "brokenSelections\fP (class\fB BrokenSelections\fP)" If true, \fI\*n\fP in 8-bit mode will interpret \fBSTRING\fP selections as carrying text in the current locale's encoding. Normally \fBSTRING\fP selections carry ISO-8859-1 encoded text. Setting this resource to \*(``true\*('' violates the ICCCM; it may, however, be useful for interacting with some broken X clients. The default is \*(``false\*(''. .TP 8 .B "brokenStringTerm\fP (class\fB BrokenStringTerm\fP)" provides a work-around for some ISDN routers which start an application control string without completing it. Set this to \*(``true\*('' if \fI\*n\fP appears to freeze when connecting. The default is \*(``false\*(''. .IP \fI\*N\fP's state parser recognizes several types of control strings which can contain text, e.g., .sp .RS \fBAPC\fP (Application Program Command), .br \fBDCS\fP (Device Control String), .br \fBOSC\fP (Operating System Command), .br \fBPM\fP (Privacy Message), and .br \fBSOS\fP (Start of String), .RE .IP Each should end with a string-terminator (a special character which cannot appear in these strings). Ordinary control characters found within the string are not ignored; they are processed without interfering with the process of accumulating the control string's content. \fI\*N\fP recognizes these controls in all modes, although some of the functions may be suppressed after parsing the control. .IP When enabled, this feature allows the user to exit from an unterminated control string when any of these ordinary control characters are found: .sp .RS control/D (used as an end of file in many shells), .br control/H (backspace), .br control/I (tab-feed), .br control/J (line feed aka newline), .br control/K (vertical tab), .br control/L (form feed), .br control/M (carriage return), .br control/N (shift-out), .br control/O (shift-in), .br control/Q (XOFF), .br control/X (cancel) .RE .TP 8 .B "c132\fP (class\fB C132\fP)" Specifies whether or not the VT102 DECCOLM escape sequence, used to switch between 80 and 132 columns, should be honored. The default is \*(``false\*(''. .TP 8 .B "cacheDoublesize\fP (class\fB CacheDoublesize\fP)" Tells whether to cache double-sized fonts by \fI\*n\fR. Set this to zero to disable double-sized fonts altogether. .TP 8 .B "cdXtraScroll\fP (class\fB CdXtraScroll\fP)" Specifies whether \fI\*n\fP should scroll to a new page when clearing the whole screen. Like \fBtiXtraScroll\fP, the intent of this option is to provide a picture of the full-screen application's display on the scrollback before wiping out the text. The default for this resource is \*(``false\*(''. .TP 8 .B "charClass\fP (class\fB CharClass\fP)" Specifies comma-separated lists of character class bindings of the form .NS \fIlow\fP[\-\fIhigh]\fP[:\fIvalue\fP]. .NE .IP These are used in determining which sets of characters should be treated the same when doing cut and paste. See the \fBCHARACTER CLASSES\fP section. .TP 8 .B "checksumExtension\fP (class\fB ChecksumExtension\fP)" DEC VT420 and up support a control sequence \fBDECRQCRA\fP which reports the checksum of the characters in a rectangle. \fI\*N\fP supports this, with extensions that can be configured with bits of the \fBchecksumExtension\fP: .RS .TP 5 0 do not negate the result. .TP 5 1 do not report the VT100 video attributes. .TP 5 2 do not omit checksum for blanks. .TP 5 3 omit checksum for cells not explicitly initialized. .TP 5 4 do not mask cell value to 8 bits or ignore combining characters. .TP 5 5 do not mask cell value to 7 bits. .RE .IP With the default value (0), \fI\*n\fP matches the behavior of DEC's terminals. To use all extensions, set all bits, \*(``-1\*('' for example. .TP 8 .B "cjkWidth\fP (class\fB CjkWidth\fP)" Specifies whether \fI\*n\fP should follow the traditional East Asian width convention. When turned on, characters with East Asian Ambiguous (A) category in UTR 11 have a column width of 2. You may have to set this option to \*(``true\*('' if you have some old East Asian terminal based programs that assume that line-drawing characters have a column width of 2. If this resource is false, the \fBmkWidth\fP resource controls the choice between the system's \fBwcwidth\fP and \fI\*n\fP's built-in tables. The default is \*(``false\*(''. .TP 8 .B "color0\fP (class\fB Color0\fP)" .TP 8 .B "color1\fP (class\fB Color1\fP)" .TP 8 .B "color2\fP (class\fB Color2\fP)" .TP 8 .B "color3\fP (class\fB Color3\fP)" .TP 8 .B "color4\fP (class\fB Color4\fP)" .TP 8 .B "color5\fP (class\fB Color5\fP)" .TP 8 .B "color6\fP (class\fB Color6\fP)" .TP 8 .B "color7\fP (class\fB Color7\fP)" These specify the colors for the ISO-6429 extension. The defaults are, respectively, black, red3, green3, yellow3, a customizable dark blue, magenta3, cyan3, and gray90. The default shades of color are chosen to allow the colors 8\(en15 to be used as brighter versions. .TP 8 .B "color8\fP (class\fB Color8\fP)" .TP 8 .B "color9\fP (class\fB Color9\fP)" .TP 8 .B "color10\fP (class\fB Color10\fP)" .TP 8 .B "color11\fP (class\fB Color11\fP)" .TP 8 .B "color12\fP (class\fB Color12\fP)" .TP 8 .B "color13\fP (class\fB Color13\fP)" .TP 8 .B "color14\fP (class\fB Color14\fP)" .TP 8 .B "color15\fP (class\fB Color15\fP)" These specify the colors for the ISO-6429 extension if the bold attribute is also enabled. The default resource values are respectively, gray50, red, green, yellow, a customized light blue, magenta, cyan, and white. .TP 8 .B "color16\fP (class\fB Color16\fP)" .TP 8 through .TP 8 .B "color255\fP (class\fB Color255\fP)" These specify the colors for the 256-color extension. The default resource values are for .RS .bP colors 16 through 231 to make a 6x6x6 color cube, and .bP colors 232 through 255 to make a grayscale ramp. .RE .IP Resources past \fBcolor15\fP are available as a compile-time option. Due to a hardcoded limit in the X libraries on the total number of resources (to 400), the resources for 256-colors are omitted when wide-character support and \fIluit\fP are enabled. Besides inconsistent behavior if only part of the resources were allowed, determining the exact cutoff is difficult, and the X libraries tend to crash if the number of resources exceeds the limit. The color palette is still initialized to the same default values, and can be modified via control sequences. .IP On the other hand, the resource limit does permit including the entire range for 88-colors. .TP 8 .B "colorAttrMode\fP (class\fB ColorAttrMode\fP)" Specifies whether \fBcolorBD\fP, \fBcolorBL\fP, \fBcolorRV\fP, and \fBcolorUL\fP should override ANSI colors. If not, these are displayed only when no ANSI colors have been set for the corresponding position. The default is \*(``false\*(''. .TP 8 .B "colorBD\fP (class\fB ColorBD\fP)" This specifies the color to use to display bold characters if the \*(``colorBDMode\*('' resource is enabled. The default is \*(``XtDefaultForeground\*(''. .IP See also the \fBveryBoldColors\fP resource which allows combining bold and color. .TP 8 .B "colorBDMode\fP (class\fB ColorAttrMode\fP)" Specifies whether characters with the bold attribute should be displayed in color or as bold characters. Note that setting \fBcolorMode\fR off disables all colors, including bold. The default is \*(``false\*(''. .TP 8 .B "colorBL\fP (class\fB ColorBL\fP)" This specifies the color to use to display blink characters if the \*(``colorBLMode\*('' resource is enabled. The default is \*(``XtDefaultForeground\*(''. .IP See also the \fBveryBoldColors\fP resource which allows combining underline and color. .TP 8 .B "colorBLMode\fP (class\fB ColorAttrMode\fP)" Specifies whether characters with the blink attribute should be displayed in color. Note that setting \fBcolorMode\fR off disables all colors, including this. The default is \*(``false\*(''. .TP 8 .B "colorIT\fP (class\fB ColorIT\fP)" This specifies the color to use to display italic characters if the \*(``colorITMode\*('' resource is enabled. The default is \*(``XtDefaultForeground\*(''. .IP See also the \fBveryBoldColors\fP resource which allows combining attributes and color. .TP 8 .B "colorITMode\fP (class\fB ColorAttrMode\fP)" Specifies whether characters with the italic attribute should be displayed in color or as italic characters. The default is \*(``false\*(''. .IP Note that: .RS .bP Setting \fBcolorMode\fR off disables all colors, including italic. .bP The \fBitalicULMode\fP resource overrides \fBcolorITMode\fP. .RE .TP 8 .B "colorInnerBorder\fP (class\fB ColorInnerBorder\fP)" Normally, \fI\*n\fP fills the VT100 window's inner border using the background color. .IP If the \fBcolorInnerBorder\fP resource is enabled, at startup \fI\*n\fP will compare the \fBborderColor\fP and the window's background color. If those are different, \fI\*n\fP will use the \fBborderColor\fP resource to fill the inner border. Otherwise, it will use the window's background color. .IP The default is \*(``false\*(''. .TP 8 .B "colorMode\fP (class\fB ColorMode\fP)" Specifies whether or not recognition of ANSI (ISO-6429) color change escape sequences should be enabled. The default is \*(``true\*(''. .TP 8 .B "colorRV\fP (class\fB ColorRV\fP)" This specifies the color to use to display reverse characters if the \*(``colorRVMode\*('' resource is enabled. The default is \*(``XtDefaultForeground\*(''. .IP See also the \fBveryBoldColors\fP resource which allows combining reverse and color. .TP 8 .B "colorRVMode\fP (class\fB ColorAttrMode\fP)" Specifies whether characters with the reverse attribute should be displayed in color. Note that setting \fBcolorMode\fR off disables all colors, including this. The default is \*(``false\*(''. .TP 8 .B "colorUL\fP (class\fB ColorUL\fP)" This specifies the color to use to display underlined characters if the \*(``colorULMode\*('' resource is enabled. The default is \*(``XtDefaultForeground\*(''. .IP See also the \fBveryBoldColors\fP resource which allows combining underline and color. .TP 8 .B "colorULMode\fP (class\fB ColorAttrMode\fP)" Specifies whether characters with the underline attribute should be displayed in color or as underlined characters. Note that setting \fBcolorMode\fR off disables all colors, including underlining. The default is \*(``false\*(''. .TP 8 .B "combiningChars\fP (class\fB CombiningChars\fP)" Specifies the number of wide-characters which can be stored in a cell to overstrike (combine) with the base character of the cell. This can be set to values in the range 0 to 5. The default is \*(``2\*(''. .TP 8 .B "ctrlFKeys\fP (class\fB CtrlFKeys\fP)" In VT220 keyboard mode (see \fBsunKeyboard\fP resource), specifies the amount by which to shift F1-F12 given a control modifier (CTRL). This allows you to generate key symbols for F10-F20 on a Sun/PC keyboard. The default is \*(``10\*('', which means that CTRL F1 generates the key symbol for F11. .TP 8 .B "curses\fP (class\fB Curses\fP)" Specifies whether or not the last column bug in .IR more (1) should be worked around. See the \fB\-cu\fP option for details. The default is \*(``false\*(''. .TP 8 .B "cursorBlink\fP (class\fB CursorBlink\fP)" Specifies whether to make the cursor blink. \fI\*N\fP accepts either a keyword (ignoring case) or the number shown in parentheses: .RS .TP 3 false (0) The cursor will not blink, but may be combined with escape sequences according to the \fBcursorBlinkXOR\fP resource. .TP 3 true (1) The cursor will blink, but may be combined with escape sequences according to the \fBcursorBlinkXOR\fP resource. .TP 3 always (2) The cursor will always blink, ignoring escape sequences. The menu entry will be disabled. .TP 3 never (3) The cursor will never blink, ignoring escape sequences. The menu entry will be disabled. .RE .IP The default is \*(``false\*(''. .TP 8 .B "cursorBlinkXOR\fP (class\fB CursorBlinkXOR\fP)" \fI\*N\fP uses two inputs to determine whether the cursor blinks: .RS .bP The \fBcursorBlink\fP resource (which can be altered with a menu entry). .bP Control sequences (private mode 12 and DECSCUSR). .RE .IP The \fBcursorBlinkXOR\fP resource determines how those inputs are combined: .RS .TP 5 false .br \fI\*N\fP uses the logical-OR of the two variables. If either is set, \fI\*n\fP makes the cursor blink. .TP 5 true .br \fI\*N\fP uses the logical-XOR of the two variables. If only one is set, \fI\*n\fP makes the cursor blink. .RE .IP The default is \*(``true\*(''. .TP 8 .B "cursorColor\fP (class\fB CursorColor\fP)" Specifies the color to use for the text cursor. The default is \*(``XtDefaultForeground\*(''. By default, \fI\*n\fP attempts to keep this color from being the same as the background color, since it draws the cursor by filling the background of a text cell. The same restriction applies to control sequences which may change this color. .IP Setting this resource overrides most of \fI\*n\fP's adjustments to cursor color. It will still use reverse-video to disallow some cases, such as a black cursor on a black background. .TP 8 .B "cursorOffTime\fP (class\fB CursorOffTime\fP)" Specifies the duration of the \*(``off\*('' part of the cursor blink cycle-time in milliseconds. The same timer is used for text blinking. The default is \*(``300\*(''. .TP 8 .B "cursorOnTime\fP (class\fB CursorOnTime\fP)" Specifies the duration of the \*(``on\*('' part of the cursor blink cycle-time, in milliseconds. The same timer is used for text blinking. The default is \*(``600\*(''. .TP 8 .B "cursorUnderLine\fP (class\fB CursorUnderLine\fP)" Specifies whether to make the cursor underlined or a box. The default is \*(``false\*(''. .TP 8 .B "cutNewline\fP (class\fB CutNewline\fP)" If \*(``false\*('', triple clicking to select a line does not include the \fInewline\fP at the end of the line. If \*(``true\*('', the Newline is selected. The default is \*(``true\*(''. .TP 8 .B "cutToBeginningOfLine\fP (class\fB CutToBeginningOfLine\fP)" If \*(``false\*('', triple clicking to select a line selects only from the current word forward. If \*(``true\*('', the entire line is selected. The default is \*(``true\*(''. .TP 8 .B "decTerminalID\fP (class\fB DecTerminalID\fP)" Specifies the emulation level (100=VT100, 220=VT220, etc.), used to determine the type of response to a DA control sequence. Leading non-digit characters are ignored, e.g., \*(``vt100\*('' and \*(``100\*('' are the same. The default is \*(``__default_termid__\*(''. .TP 8 .B "defaultString\fP (class\fB DefaultString\fP)" Specify the character (or string) which \fI\*n\fP will substitute when pasted text includes a character which cannot be represented in the current encoding. For instance, pasting UTF-8 text into a display of ISO-8859-1 characters will only be able to display codes 0\(en255, while UTF-8 text can include Unicode values above 255. The default is \*(``#\*('' (a single pound sign). .IP If the undisplayable text would be double-width, \fI\*n\fP will add a space after the \*(``#\*('' character, to give roughly the same layout on the screen as the original text. .TP 8 .B "deleteIsDEL\fP (class\fB DeleteIsDEL\fP)" Specifies what the \fIDelete\fP key on the editing keypad should send when pressed. The resource value is a string, evaluated as a boolean after startup. \fI\*N\fP uses it in conjunction with the \fBkeyboardType\fP resource: .RS .bP If the keyboard type is \*(``default\*('', or \*(``vt220\*('' and the resource is either \*(``true\*('' or \*(``maybe\*('' send the VT220-style \fIRemove\fP escape sequence. Otherwise, send DEL (127). .bP If the keyboard type is \*(``legacy\*('', and the resource is \*(``true\*('' send DEL. Otherwise, send the \fIRemove\fP sequence. .bP Otherwise, if the keyboard type is none of these special cases, send DEL (127). .RE .IP The default is \*(``__delete_is_del__\*(''. The resource is allowed to be a non-boolean \*(``maybe\*('' so that the popup menu \fBDelete is DEL\fP entry does not override the keyboard type. .TP 8 .B "directColor\fP (class\fB DirectColor\fP)" Specifies whether to handle direct-color control sequences using the X server's available colors, or to approximate those using a color map with 256 entries. A \*(``true\*('' value enables the former. The default is \*(``true\*(''. .TP 8 .B "disallowedColorOps\fP (class\fB DisallowedColorOps\fP)" Specify which features will be disabled if \fBallowColorOps\fP is false. This is a comma-separated list of names. The default value is .RS SetColor,GetColor,GetAnsiColor .RE .IP The names are listed below. \fI\*N\fP ignores capitalization, but they are shown in mixed-case for clarity. .RS .TP 5 SetColor Set a specific dynamic color. .TP 5 GetColor Report the current setting of a given dynamic color. .TP 5 GetAnsiColor Report the current setting of a given ANSI color (actually any of the colors set via ANSI-style controls). .RE .TP 8 .B "disallowedFontOps\fP (class\fB DisallowedFontOps\fP)" Specify which features will be disabled if \fBallowFontOps\fP is false. This is a comma-separated list of names. The default value is .NS SetFont,GetFont .NE .IP The names are listed below. \fI\*N\fP ignores capitalization, but they are shown in mixed-case for clarity. .RS .TP 5 SetFont Set the specified font. .TP 5 GetFont Report the specified font. .RE .TP 8 .B "disallowedMouseOps\fP (class\fB DisallowedMouseOps\fP)" Specify which features will be disabled if \fBallowMouseOps\fP is false. This is a comma-separated list of names. The default value is \*(``*\*('' which matches all names. The names are listed below. \fI\*N\fP ignores capitalization, but they are shown in mixed-case for clarity. .RS .TP 5 X10 The original X10 mouse protocol. .TP 5 Locator DEC locator mode .TP 5 VT200Click X11 mouse-clicks only. .TP 5 VT200Hilite X11 mouse-clicks and highlighting. .TP 5 AnyButton XFree86 \fI\*n\fP any-button mode sends button-clicks as well as motion events while the button is pressed. .TP 5 AnyEvent XFree86 \fI\*n\fP any-event mode sends button-clicks as well as motion events whether or not a button is pressed. .TP 5 FocusEvent Send FocusIn/FocusOut events. .TP 5 Extended The first extension beyond X11 mouse protocol, this encodes the coordinates in UTF-8. It is deprecated in favor of \fISGR\fP, but provided for compatibility. .TP 5 SGR This is the recommended extension for mouse-coordinates .TP 5 URXVT Like \fIExtended\fP, this is provided for compatibility. .TP 5 AlternateScroll This overrides the \fBalternateScroll\fP resource. .RE .TP 8 .B "disallowedPasteControls\fP (class\fB DisallowedPasteControls\fP)" The \fBallowPasteControls\fP resource is normally used to prevent pasting C1 controls, as well as non-formatting C0 controls such as the ASCII escape character. Those characters are simply ignored. This resource further extends the set of control characters which cannot be pasted, converting each into a space. .IP The resource value is a comma-separated list of names. \fI\*N\fP ignores capitalization. The default value is .NS BS,HT,DEL,ESC .NE .IP The names are listed below: .RS .TP 5 C0 all ASCII control characters. .TP 5 BS ASCII backspace .TP 5 CR ASCII carriage-return .TP 5 DEL ASCII delete .TP 5 ESC ASCII escape .TP 5 FF ASCII form-feed .TP 5 HT ASCII tab .TP 5 NL ASCII line-feed, i.e., \*(``newline\*(''. .RE .TP 8 .B "disallowedTcapOps\fP (class\fB DisallowedTcapOps\fP)" Specify which features will be disabled if \fBallowTcapOps\fP is false. This is a comma-separated list of names. The default value is .NS SetTcap,GetTcap .NE .IP The names are listed below. \fI\*N\fP ignores capitalization, but they are shown in mixed-case for clarity. .RS .TP 5 SetTcap (not implemented) .TP 5 GetTcap Report specified function- and other special keys. .RE .TP 8 .B "disallowedWindowOps\fP (class\fB DisallowedWindowOps\fP)" Specify which features will be disabled if \fBallowWindowOps\fP is false. This is a comma-separated list of names, or (for the controls adapted from \fIdtterm\fP the operation number). The default value is .NS 20,21,SetXprop,SetSelection (i.e.\& no operations are allowed). .NE .IP The names are listed below. \fI\*N\fP ignores capitalization, but they are shown in mixed-case for clarity. Where a number can be used as an alternative, it is given in parentheses after the name. .RS .TP 5 GetChecksum Report checksum of characters in a rectangular region. .TP 5 GetIconTitle (20) Report \fI\*n\fP window's icon label as a string. .TP 5 GetScreenSizeChars (19) Report the size of the screen in characters as numbers. .TP 5 GetSelection Report selection data as a base64 string. .TP 5 GetWinPosition (13) Report \fI\*n\fP window position as numbers. .TP 5 GetWinSizeChars (18) Report the size of the text area in characters as numbers. .TP 5 GetWinSizePixels (14) Report \fI\*n\fP window in pixels as numbers. .TP 5 GetWinState (11) Report \fI\*n\fP window state as a number. .TP 5 GetWinTitle (21) Report \fI\*n\fP window's title as a string. .TP 5 LowerWin (6) Lower the \fI\*n\fP window to the bottom of the stacking order. .TP 5 MaximizeWin (9) Maximize window (i.e., resize to screen size). .TP 5 FullscreenWin (10) Use full screen (i.e., resize to screen size, without window decorations). .TP 5 MinimizeWin (2) Iconify window. .TP 5 PopTitle (23) Pop title from internal stack. .TP 5 PushTitle (22) Push title to internal stack. .TP 5 RaiseWin (5) Raise the \fI\*n\fP window to the front of the stacking order. .TP 5 RefreshWin (7) Refresh the \fI\*n\fP window. .TP 5 RestoreWin (1) De-iconify window. .TP 5 SetChecksum Modify algorithm for reporting checksum of characters in a rectangular region. .TP 5 SetSelection Set selection data. .TP 5 SetWinLines Resize to a given number of lines, at least 24. .TP 5 SetWinPosition (3) Move window to given coordinates. .TP 5 SetWinSizeChars (8) Resize the text area to given size in characters. .TP 5 SetWinSizePixels (4) Resize the \fI\*n\fP window to given size in pixels. .TP 5 SetXprop Set X property on top-level window. .RE .TP 8 .B "dynamicColors\fP (class\fB DynamicColors\fP)" Specifies whether or not escape sequences to change colors assigned to different attributes are recognized. .TP 8 .B "eightBitControl\fP (class\fB EightBitControl\fP)" Specifies whether or not control sequences sent by the terminal should be eight-bit characters or escape sequences. The default is \*(``false\*(''. .TP 8 .B "eightBitInput\fP (class\fB EightBitInput\fP)" If \*(``true\*('', Meta characters (a single-byte character combined with the \fIMeta\fP modifier key) input from the keyboard are presented as a single character, modified according to the \fBeightBitMeta\fP resource. If \*(``false\*('', Meta characters are converted into a two-character sequence with the character itself preceded by ESC. The default is \*(``true\*(''. .IP The \fBmetaSendsEscape\fP and \fBaltSendsEscape\fP resources may override this feature. Generally keyboards do not have a key labeled \*(``Meta\*('', but \*(``Alt\*('' keys are common, and they are conventionally used for \*(``Meta\*(''. If they were synonymous, it would have been reasonable to name this resource \*(``\fBaltSendsEscape\fP\*('', reversing its sense. For more background on this, see the \fBmeta\fP(3x) function in curses. .IP Note that the \fIAlt\fP key is not necessarily the same as the \fIMeta\fP modifier. The \fIxmodmap\fP utility lists your key modifiers. X defines modifiers for shift, (caps) lock and control, as well as 5 additional modifiers which are generally used to configure key modifiers. \fI\*N\fP inspects the same information to find the modifier associated with either \fIMeta\fP key (left or right), and uses that key as the \fIMeta\fP modifier. It also looks for the NumLock key, to recognize the modifier which is associated with that. .IP If your \fIxmodmap\fP configuration uses the same keycodes for Alt- and Meta-keys, \fI\*n\fP will only see the Alt-key definitions, since those are tested before Meta-keys. NumLock is tested first. It is important to keep these keys distinct; otherwise some of \fI\*n\fP's functionality is not available. .IP The \fBeightBitInput\fP resource is tested at startup time. If \*(``true\*('', the \fI\*n\fP tries to put the terminal into 8-bit mode. If \*(``false\*('', on startup, \fI\*n\fP tries to put the terminal into 7-bit mode. For some configurations this is unsuccessful; failure is ignored. After startup, \fI\*n\fP does not change the terminal between 8-bit and 7-bit mode. .IP As originally implemented in X11, the resource value did not change after startup. However (since patch #216 in 2006) \fI\*n\fP can modify \fBeightBitInput\fP after startup via a control sequence. The corresponding terminfo capabilities \fBsmm\fP (set meta mode) and \fBrmm\fP (reset meta mode) have been recognized by \fIbash\fP for some time. Interestingly enough, \fIbash\fP's notion of \*(``meta mode\*('' differs from the standard definition (in the \fIterminfo\fP manual), which describes the change to the eighth bit of a character. It happens that \fIbash\fP views \*(``meta mode\*('' as the ESC character that \fI\*n\fP puts before a character when a special meta key is pressed. \fIbash\fP's early documentation talks about the ESC character and ignores the eighth bit. .TP 8 .B "eightBitMeta\fP (class\fB EightBitMeta\fP)" This controls the way \fI\*n\fP modifies the eighth bit of a single-byte key when the \fBeightBitInput\fP resource is set. The default is \*(``locale\*(''. .IP The resource value is a string, evaluated as a boolean after startup. .RS .TP 5 false The key is sent unmodified. .TP 5 locale The key is modified only if the locale uses eight-bit encoding. .TP 5 true The key is sent modified. .TP 5 never The key is always sent unmodified. .RE .IP Except for the \fBnever\fP choice, \fI\*n\fP honors the terminfo capabilities \fBsmm\fP (set meta mode) and \fBrmm\fP (reset meta mode), allowing the feature to be turned on or off dynamically. .IP If \fBeightBitMeta\fP is enabled when the locale uses UTF-8, \fI\*n\fP encodes the value as UTF-8 (since patch #183 in 2003). .TP 8 .B "eightBitOutput\fP (class\fB EightBitOutput\fP)" Specifies whether or not eight-bit characters sent from the host should be accepted as is or stripped when printed. The default is \*(``true\*('', which means that they are accepted as is. .TP 8 .B "eightBitSelectTypes\fP (class\fB EightBitSelectTypes\fP)" Override \fI\*n\fP's default selection target list (see \fBSELECT/PASTE\fP) for selections in normal (ISO-8859-1) mode. The default is an empty string, i.e., \*(``\*('', which does not override anything. .TP 8 .B "eraseSavedLines\fP (class\fB EraseSavedLines\fP)" Specifies whether or not to allow \fI\*n\fP extended ED/DECSED control sequences to erase the saved-line buffer. The default is \*(``true\*(''. .TP 8 .B "faceName\fP (class\fB FaceName\fP)" Specify the pattern for scalable fonts selected from the FreeType library if support for that library was compiled into \fI\*n\fR. There is no default value. .IP One or more fonts can be specified, separated by commas. If prefixed with \*(``x:\*('' or \*(``x11:\*('' the specification applies to the XLFD \fBfont\fP resource. A \*(``xft:\*('' prefix is accepted but unnecessary since a missing prefix for \fBfaceName\fP means that it will be used for TrueType. For example, .NS XTerm*faceName: x:fixed,xft:Bitstream Vera Sans Mono .NE .IP If no \fBfaceName\fP resource is specified, or if there is no match for both TrueType normal and bold fonts, \fI\*n\fR uses the XLFD (bitmap) \fBfont\fP and related resources. .IP It is possible to select suitable bitmap fonts using a script such as this: .NS \&#!/bin/sh \&FONT=`xfontsel \-print` \&test \-n "$FONT" && xfd \-fn "$FONT" .NE .IP However (even though \fIxfd\fP accepts a \*(``\fB\-fa\fP\*('' option to denote FreeType fonts), \fIxfontsel\fP has not been similarly extended. As a workaround, you may try .NS fc\-list :scalable=true:spacing=mono: family .NE .IP to find a list of scalable fixed-pitch fonts which may be used for the \fBfaceName\fP resource value. .TP 8 .B "faceNameDoublesize\fP (class\fB FaceNameDoublesize\fP)" Specify a double-width scalable font for cases where an application requires this, e.g., in CJK applications. There is no default value. .IP Like the \fBfaceName\fP resource, this allows one or more comma-separated font specifications to be applied to the \fIwide\fP TrueType or XLFD fonts. .IP If the application uses double-wide characters and this resource is not given, \fI\*n\fP will use a scaled version of the font given by \fBfaceName\fP. .TP 8 .B "faceSize\fP (class\fB FaceSize\fP)" Specify the pointsize for fonts selected from the FreeType library if support for that library was compiled into \fI\*n\fR. The default is \*(``8.0\*('' On the \fBVT\ Fonts\fP menu, this corresponds to the \fIDefault\fP entry. .IP Although the default is \*(``8.0\*('', this may not be the same as the pointsize for the default bitmap font, i.e., that assigned with the \fB\-fn\fP option, or the \fBfont\fP resource. The default value of \fBfaceSize\fP is chosen to match the size of the \*(``fixed\*('' font, making switching between bitmap and TrueType fonts via the font menu give comparable sizes for the window. If your \fB\-fn\fP option uses a different pointsize, you might want to adjust the \fBfaceSize\fP resource to match. .IP You can specify the pointsize for TrueType fonts selected with the other size-related menu entries such as Medium, Huge, etc., by using one of the following resource values. If you do not specify a value, they default to \*(``0.0\*('', which causes \fI\*n\fP to use the ratio of font sizes from the corresponding bitmap font resources to obtain a TrueType pointsize. .IP If all of the \fBfaceSize\fP resources are set, then \fI\*n\fP will use this information to determine the next smaller/larger TrueType font for the \fBlarger-vt-font()\fP and \fBsmaller-vt-font()\fP actions. If any are not set, \fI\*n\fP will use only the areas of the bitmap fonts. .TP 8 .B "faceSize1\fP (class\fB FaceSize1\fP)" Specifies the pointsize of the first alternative font. .TP 8 .B "faceSize2\fP (class\fB FaceSize2\fP)" Specifies the pointsize of the second alternative font. .TP 8 .B "faceSize3\fP (class\fB FaceSize3\fP)" Specifies the pointsize of the third alternative font. .TP 8 .B "faceSize4\fP (class\fB FaceSize4\fP)" Specifies the pointsize of the fourth alternative font. .TP 8 .B "faceSize5\fP (class\fB FaceSize5\fP)" Specifies the pointsize of the fifth alternative font. .TP 8 .B "faceSize6\fP (class\fB FaceSize6\fP)" Specifies the pointsize of the sixth alternative font. .TP 8 .B "font\fP (class\fB Font\fP)" Specifies the name of the normal font. The default is \*(``fixed\*(''. .IP See the discussion of the \fBlocale\fP resource, which describes how this font may be overridden. .IP NOTE: some resource files use patterns such as .NS *font: fixed .NE .IP which are overly broad, affecting both .NS xterm.vt100.font .NE .IP and .NS xterm.vt100.utf8Fonts.font .NE .IP which is probably not what you intended. .TP 8 .B "fastScroll\fP (class\fB FastScroll\fP)" Modifies the effect of jump scroll (\fBjumpScroll\fP) by suppressing screen refreshes for the special case when output to the screen has completely shifted the contents off-screen. For instance, \fIcat\fP'ing a large file to the screen does this. .TP 8 .B "font1\fP (class\fB Font1\fP)" Specifies the name of the first alternative font, corresponding to \*(``Unreadable\*('' in the standard menu. .TP 8 .B "font2\fP (class\fB Font2\fP)" Specifies the name of the second alternative font, corresponding to \*(``Tiny\*('' in the standard menu. .TP 8 .B "font3\fP (class\fB Font3\fP)" Specifies the name of the third alternative font, corresponding to \*(``Small\*('' in the standard menu. .TP 8 .B "font4\fP (class\fB Font4\fP)" Specifies the name of the fourth alternative font, corresponding to \*(``Medium\*('' in the standard menu. .TP 8 .B "font5\fP (class\fB Font5\fP)" Specifies the name of the fifth alternative font, corresponding to \*(``Large\*('' in the standard menu. .TP 8 .B "font6\fP (class\fB Font6\fP)" Specifies the name of the sixth alternative font, corresponding to \*(``Huge\*('' in the standard menu. .TP 8 .B "fontDoublesize\fP (class\fB FontDoublesize\fP)" Specifies whether \fI\*n\fP should attempt to use font scaling to draw double-sized characters. Some older font servers cannot do this properly, will return misleading font metrics. The default is \*(``true\*(''. If disabled, \fI\*n\fP will simulate double-sized characters by drawing normal characters with spaces between them. .TP 8 .B "fontWarnings\fP (class\fB FontWarnings\fP)" Specify whether \fI\*n\fP should report an error if it fails to load a font: .RS .TP 5 0 Never report an error (though the X libraries may). .TP 5 1 Report an error if the font name was given as a resource setting. .TP 5 2 Always report an error on failure to load a font. .RE .IP The default is \*(``1\*(''. .TP 8 .B "forceBoxChars\fP (class\fB ForceBoxChars\fP)" Specifies whether \fI\*n\fP should assume the normal and bold fonts have VT100 line-drawing characters: .RS .bP The fixed-pitch ISO-8859-*-encoded fonts used by \fI\*n\fP normally have the VT100 line-drawing glyphs in cells 1\(en31. Other fixed-pitch fonts may be more attractive, but lack these glyphs. .bP When using an ISO-10646-1 font and the \fBwideChars\fP resource is true, \fI\*n\fP uses the Unicode glyphs which match the VT100 line-drawing glyphs. .RE .IP If \*(``false\*('', \fI\*n\fP checks for missing glyphs in the font and makes line-drawing characters directly as needed. If \*(``true\*('', \fI\*n\fP assumes the font does not contain the line-drawing characters, and draws them directly. The default is \*(``false\*(''. .IP The VT100 line-drawing character set (also known as the \fIDEC Special Character and Line Drawing Set\fP) is shown in this table. It includes a few \fIspecial\fP characters which are not used for drawing lines: .TS l l l _ _ _ l l l. \fICell\fR \fIUnicode\fR \fIDescription\fP 0 U+25AE black vertical rectangle 1 U+25C6 black diamond 2 U+2592 medium shade 3 U+2409 symbol for horizontal tabulation 4 U+240C symbol for form feed 5 U+240D symbol for carriage return 6 U+240A symbol for line feed 7 U+00B0 degree sign 8 U+00B1 plus-minus sign 9 U+2424 symbol for newline 10 U+240B symbol for vertical tabulation 11 U+2518 box drawings light up and left 12 U+2510 box drawings light down and left 13 U+250C box drawings light down and right 14 U+2514 box drawings light up and right 15 U+253C box drawings light vertical and horizontal 16 U+23BA box drawings scan 1 17 U+23BB box drawings scan 3 18 U+2500 box drawings light horizontal 19 U+23BC box drawings scan 7 20 U+23BD box drawings scan 9 21 U+251C box drawings light vertical and right 22 U+2524 box drawings light vertical and left 23 U+2534 box drawings light up and horizontal 24 U+252C box drawings light down and horizontal 25 U+2502 box drawings light vertical 26 U+2264 less-than or equal to 27 U+2265 greater-than or equal to 28 U+03C0 greek small letter pi 29 U+2260 not equal to 30 U+00A3 pound sign 31 U+00B7 middle dot _ .TE .TP 8 .B "forcePackedFont\fP (class\fB ForcePackedFont\fP)" Specifies whether \fI\*n\fP should use the maximum or minimum glyph width when displaying using a bitmap font. Use the maximum width to help with proportional fonts. The default is \*(``true\*('', denoting the minimum width. .TP 8 .B "foreground\fP (class\fB Foreground\fP)" Specifies the color to use for displaying text in the window. Setting the class name instead of the instance name is an easy way to have everything that would normally appear in the text color change color. The default is \*(``XtDefaultForeground\*(''. .TP 8 .B "formatOtherKeys\fP (class\fB FormatOtherKeys\fP)" Overrides the format of the escape sequence used to report modified keys with the \fBmodifyOtherKeys\fP resource. .RS .TP 3 0 send modified keys as parameters for function-key 27 (default). .TP 3 1 send modified keys as parameters for CSI\ u. .RE .TP 8 .B "freeBoldBox\fP (class\fB FreeBoldBox\fP)" Specifies whether \fI\*n\fP should assume the bounding boxes for normal and bold fonts are compatible. If \*(``false\*('', \fI\*n\fP compares them and will reject choices of bold fonts that do not match the size of the normal font. The default is \*(``false\*('', which means that the comparison is performed. .TP 8 .B "geometry\fP (class\fB Geometry\fP)" Specifies the preferred size and position of the VT\fIxxx\fP window. There is no default for this resource. .TP 8 .B "highlightColor\fP (class\fB HighlightColor\fP)" Specifies the color to use for the background of selected (highlighted) text. If not specified (i.e., matching the default foreground), reverse video is used. The default is \*(``XtDefaultForeground\*(''. .TP 8 .B "highlightColorMode\fP (class\fB HighlightColorMode\fP)" Specifies whether \fI\*n\fP should use \fBhighlightTextColor\fP and \fBhighlightColor\fP to override the reversed foreground/background colors in a selection. The default is unspecified: at startup, \fI\*n\fP checks if those resources are set to something other than the default foreground and background colors. Setting this resource disables the check. .IP The following table shows the interaction of the highlighting resources, abbreviated as shown to fit in this page: .RS .TP 3 .I HCM highlightColorMode .TP 3 .I HR highlightReverse .TP 3 .I HBG highlightColor .TP 3 .I HFG highlightTextColor .RE .IP .ne 34 .TS l l l l l _ _ _ _ _ l l l l l. \fIHCM\fR \fIHR\fR \fIHBG\fR \fIHFG\fR \fIHighlight\fP false false default default bg/fg false false default set bg/fg false false set default fg/HBG false false set set fg/HBG = false true default default bg/fg false true default set bg/fg false true set default fg/HBG false true set set fg/HBG = true false default default bg/fg true false default set HFG/fg true false set default bg/HBG true false set set HFG/HBG = true true default default bg/fg true true default set HFG/fg true true set default fg/HBG true true set set HFG/HBG = default false default default bg/fg default false default set bg/fg default false set default fg/HBG default false set set HFG/HBG = default true default default bg/fg default true default set bg/fg default true set default fg/HBG default true set set HFG/HBG = .TE .TP 8 .B "highlightReverse\fP (class\fB HighlightReverse\fP)" Specifies whether \fI\*n\fP should reverse the selection foreground and background colors when selecting text with reverse-video attribute. This applies only to the \fBhighlightColor\fP and \fBhighlightTextColor\fP resources, e.g., to match the color scheme of \fIxwsh\fP. If \*(``true\*('', \fI\*n\fP reverses the colors, If \*(``false\*('', \fI\*n\fP does not reverse colors, The default is \*(``true\*(''. .TP 8 .B "highlightSelection\fP (class\fB HighlightSelection\fP)" Tells \fI\*n\fP whether to highlight all of the selected positions, or only the selected text: .RS .bP If \*(``false\*('', selecting with the mouse highlights all positions on the screen between the beginning of the selection and the current position. .bP If \*(``true\*('', \fI\*n\fP highlights only the positions that contain text that can be selected. .RE .IP The default is \*(``false\*(''. .IP Depending on the way your applications write to the screen, there may be trailing blanks on a line. \fI\*N\fP stores data as it is shown on the screen. Erasing the display changes the internal state of each cell so it is not considered a blank for the purpose of selection. Blanks written since the last erase are selectable. If you do not wish to have trailing blanks in a selection, use the \fBtrimSelection\fP resource. .TP 8 .B "highlightTextColor\fP (class\fB HighlightTextColor\fP)" Specifies the color to use for the foreground of selected (highlighted) text. If not specified (i.e., matching the default background), reverse video is used. The default is \*(``XtDefaultBackground\*(''. .TP 8 .B "hpLowerleftBugCompat\fP (class\fB HpLowerleftBugCompat\fP)" Specifies whether to work around a bug in HP's \fIxdb\fP, which ignores termcap and always sends ESC F to move to the lower left corner. \*(``true\*('' causes \fI\*n\fP to interpret ESC F as a request to move to the lower left corner of the screen. The default is \*(``false\*(''. .TP 8 .B "i18nSelections\fP (class\fB I18nSelections\fP)" If false, \fI\*n\fP will not request the targets \fBCOMPOUND_TEXT\fP or \fBTEXT\fP. The default is \*(``true\*(''. It may be set to false in order to work around ICCCM violations by other X clients. .TP 8 .B "iconBorderColor\fP (class\fB BorderColor\fP)" Specifies the border color for the active icon window if this feature is compiled into \fI\*n\fR. Not all window managers will make the icon border visible. .TP 8 .B "iconBorderWidth\fP (class\fB BorderWidth\fP)" Specifies the border width for the active icon window if this feature is compiled into \fI\*n\fR. The default is \*(``2\*(''. Not all window managers will make the border visible. .TP 8 .B "iconFont\fP (class\fB IconFont\fP)" Specifies the font for the miniature active icon window, if this feature is compiled into \fI\*n\fR. The default is \*(``nil2\*(''. .TP 8 .B "initialFont\fP (class\fB InitialFont\fP)" Specifies which of the VT100 fonts to use initially. Values are the same as for the \fBset-vt-font\fP action. The default is \*(``d\*('', i.e., \*(``default\*(''. .TP 8 .B "inputMethod\fP (class\fB InputMethod\fP)" Tells \fI\*n\fP which type of input method to use. There is no default method. .TP 8 .B "internalBorder\fP (class\fB BorderWidth\fP)" Specifies the number of pixels between the characters and the window border. The default is \*(``2\*(''. .TP 8 .B "italicULMode\fP (class\fB ColorAttrMode\fP)" Specifies whether characters with the underline attribute should be displayed in an italic font or as underlined characters. It is implemented only for TrueType fonts. .TP 8 .B "jumpScroll\fP (class\fB JumpScroll\fP)" Specifies whether or not jump scroll should be used. This corresponds to the VT102 DECSCLM private mode. The default is \*(``true\*(''. See \fBfastScroll\fP for a variation. .TP 8 .B "keepClipboard\fP (class\fB KeepClipboard\fP)" Specifies whether \fI\*n\fR will reuse the selection data which it copied to the clipboard rather than asking the clipboard for its current contents when told to provide the selection. The default is \*(``false\*(''. .IP The menu entry \fBKeep Clipboard\fP allows you to change this at runtime. .TP 8 .B "keepSelection\fP (class\fB KeepSelection\fP)" Specifies whether \fI\*n\fR will keep the selection even after the selected area was touched by some output to the terminal. The default is \*(``true\*(''. .IP The menu entry \fBKeep Selection\fP allows you to change this at runtime. .TP 8 .B "keyboardDialect\fP (class\fB KeyboardDialect\fP)" Specifies the initial keyboard dialect, as well as the default value when the terminal is reset. The value given is the same as the final character in the control sequences which change character sets. The default is \*(``B\*('', which corresponds to US ASCII. .TP 8 .B "\fIname\fP\fBKeymap\fP (class\fB \fIName\fP\fBKeymap\fP)" See the discussion of the \fBkeymap()\fP action. .TP 8 .B "limitFontsets\fP (class\fB LimitFontsets\fP)" Limits the number of TrueType fallback fonts (i.e., fontset) which can be used. The default is \*(``50\*(''. .IP This limits the number of fallback fonts which \fI\*n\fP uses to display characters. Because TrueType fonts typically are small, \fI\*n\fP may open several fonts for good coverage, and may open additional fonts to obtain information. You can see which font-files \fI\*n\fP opens by setting the environment variable \fBXFT_DEBUG\fP to 3. The Xft library and \fI\*n\fP write this debugging trace to the standard output. .IP Set this to \*(``0\*('' to disable fallbacks entirely. .TP 8 .B "limitResize\fP (class\fB LimitResize\fP)" Limits resizing of the screen via control sequence to a given multiple of the display dimensions. The default is \*(``1\*(''. .TP 8 .B "limitResponse\fP (class\fB LimitResponse\fP)" Limits the buffer-size used when \fI\*n\fP replies to various control sequences. The default is \*(``1024\*(''. The minimum value is \*(``256\*(''. .TP 8 .B "locale\fP (class\fB Locale\fP)" Specifies how to use \fIluit\fR, an encoding converter between UTF-8 and locale encodings. The resource value (ignoring case) may be: .RS .TP 4 .I true \fI\*N\fR will use the encoding specified by the users' LC_CTYPE locale (i.e., LC_ALL, LC_CTYPE, or LANG variables) as far as possible. This is realized by always enabling UTF-8 mode and invoking \fIluit\fR in non-UTF-8 locales. .TP .I medium \fI\*N\fR will follow users' LC_CTYPE locale only for UTF-8, east Asian, and Thai locales, where the encodings were not supported by conventional 8bit mode with changing fonts. For other locales, \fI\*n\fR will use conventional 8bit mode. .TP .I checkfont If mini-luit is compiled-in, \fI\*n\fR will check if a Unicode font has been specified. If so, it checks if the character encoding for the current locale is POSIX, Latin-1 or Latin-9, uses the appropriate mapping to support those with the Unicode font. For other encodings, \fI\*n\fR assumes that UTF-8 encoding is required. .TP .I false \fI\*N\fR will use conventional 8bit mode or UTF-8 mode according to \fButf8\fR resource or \fB\-u8\fP option. .RE .IP Any other value, e.g., \*(``UTF-8\*('' or \*(``ISO8859-2\*('', is assumed to be an encoding name; \fIluit\fR will be invoked to support the encoding. The actual list of supported encodings depends on \fIluit\fR. The default is \*(``medium\*(''. .IP Regardless of your locale and encoding, you need an ISO-10646-1 font to display the result. Your configuration may not include this font, or locale-support by \fI\*n\fP may not be needed. .IP At startup, \fI\*n\fP uses a mechanism equivalent to the \fBload-vt-fonts(utf8Fonts,\ Utf8Fonts)\fP action to load font name subresources of the VT100 widget. That is, resource patterns such as \*(``\fB*vt100.utf8Fonts.font\fP\*('' will be loaded, and (if this resource is enabled), override the normal fonts. If no subresources are found, the normal fonts such as \*(``\fB*vt100.font\fP\*('', etc., are used. .IP For instance, you could have this in your resource file: .NS *VT100.font: 12x24 *VT100.utf8Fonts.font:9x15 .NE .IP When started with a UTF-8 locale, \fI\*n\fP would use 9x15, but allow you to switch to the 12x24 font using the menu entry \*(``\fBUTF-8 Fonts\fP\*(''. .IP The resource files distributed with \fI\*n\fP use ISO-10646-1 fonts, but do not rely on them unless you are using the locale mechanism. .TP 8 .B "localeFilter\fP (class\fB LocaleFilter\fP)" Specifies the file name for the encoding converter from/to locale encodings and UTF-8 which is used with the \fB\-lc\fR option or \fBlocale\fR resource. The help message shown by \*(``\*n \-help\*('' lists the default value, which depends on your system configuration. .IP If the encoding converter requires command-line parameters, you can add those after the command, e.g., .NS *localeFilter: xterm\-filter \-p .NE .IP Alternatively, you may put those parameter within a shell script to execute the converter, and set this resource to point to the shell script. .IP When using a locale-filter, e.g., with the \fI\-e\fP option, or the shell, \fI\*n\fP first tries passing control via that filter. If it fails, \fI\*n\fP will retry without the locale-filter. \fI\*N\fP warns about the failure before retrying. .TP 8 .B "loginShell\fP (class\fB LoginShell\fP)" Specifies whether or not the shell to be run in the window should be started as a login shell. The default is \*(``false\*(''. .TP 8 .B "logFile\fP (class\fB Logfile\fP)" Specify the name for \fI\*n\fP's log file. If no name is specified, \fI\*n\fP will generate a name when logging is enabled, as described in the \fB\-l\fP option. .TP 8 .B "logInhibit\fP (class\fB LogInhibit\fP)" If \*(``true\*('', prevent the logging feature from being enabled, whether by the command-line option \fB\-l\fP, or the menu entry \fBLog to File\fP. The default is \*(``false\*(''. .TP 8 .B "logging\fP (class\fB Logging\fP)" If \*(``true\*('', (and if \fBlogInhibit\fP is not set) enable the logging feature. This resource is set/updated by the \fB\-l\fP option and the menu entry \fBLog to File\fP. The default is \*(``false\*(''. .TP 8 .B "marginBell\fP (class\fB MarginBell\fP)" Specifies whether or not the bell should be rung when the user types near the right margin. The default is \*(``false\*(''. .TP 8 .B "maxGraphicSize\fP (class\fB MaxGraphicSize\fP)" If \fI\*n\fR is configured to support ReGIS or SIXEL graphics, this resource controls the maximum size of a graph which can be displayed. .IP The default is \*(``1000x1000\*('' (given as \fIwidth\fP by \fIheight\fP). .IP If the resource is \*(``auto\*('' then \fI\*n\fR will use the \fBdecTerminalID\fP resource: .TS l l _ _ r r. \fBResult\fR \fBdecTerminalID\fR 768x400 125 800x460 240 800x460 241 800x480 330 800x480 340 860x750 382 800x480 \fIother\fP .TE .TP 8 .B "metaSendsEscape\fP (class\fB MetaSendsEscape\fP)" Tells \fI\*n\fP what to do with input-characters modified by \fIMeta\fP: .RS .bP If \*(``true\*('', Meta characters (a character combined with the \fIMeta\fP modifier key) are converted into a two-character sequence with the character itself preceded by ESC. This applies as well to function key control sequences, unless \fI\*n\fP sees that \fBMeta\fP is used in your key translations. .bP If \*(``false\*('', Meta characters input from the keyboard are handled according to the \fBeightBitInput\fP resource. .RE .IP The default is \*(``__meta_sends_esc__\*(''. .TP 8 .B "mkSamplePass\fP (class\fB MkSamplePass\fP)" If \fBmkSampleSize\fP is nonzero, and \fBmkWidth\fP (and \fBcjkWidth\fP) are false, on startup \fI\*n\fP compares its built-in tables to the system's wide character width data to decide if it will use the system's data. It tests the first \fBmkSampleSize\fP character values, and allows up to \fBmkSamplePass\fP mismatches before the test fails. The default (for the allowed number of mismatches) is 655 (one percent of the default value for \fBmkSampleSize\fP). .TP 8 .B "mkSampleSize\fP (class\fB MkSampleSize\fP)" With \fBmkSamplePass\fP, this specifies a startup test used for initializing wide character width calculations. The default (number of characters to check) is 65536. .TP 8 .B "mkWidth\fP (class\fB MkWidth\fP)" Specifies whether \fI\*n\fP should use a built-in version of the wide character width calculation. See also the \fBcjkWidth\fP resource which can override this. The default is \*(``false\*(''. .IP Here is a summary of the resources which control the choice of wide character width calculation: .ne 8 .TS l l l _ _ _ l l l. \fIcjkWidth\fR \fImkWidth\fR \fIAction\fP false false use system tables subject to \fBmkSamplePass\fP false true use built-in tables true false use built-in CJK tables true true use built-in CJK tables .TE .IP To disable \fBmkWidth\fP, and use the system's tables, set both \fBmkSampleSize\fP and \fBmkSamplePass\fP to \*(``0\*(''. Doing that may make \fI\*n\fP more consistent with applications running in \fI\*n\fP, but may omit some font glyphs whose width correctly differs from the system's character tables. .TP 8 .B "modifyCursorKeys\fP (class\fB ModifyCursorKeys\fP)" Tells how to handle the special case where Control-, Shift-, Alt- or Meta-modifiers are used to add a parameter to the escape sequence returned by a cursor-key. The default is \*(``2\*('': .RS .TP 5 \-1 disables the feature. .TP 5 0 uses the old/obsolete behavior, i.e., the modifier is the first parameter. .TP 5 1 prefixes modified sequences with CSI. .TP 5 2 forces the modifier to be the second parameter if it would otherwise be the first. .TP 5 3 marks the sequence with a \*(``>\*('' to hint that it is private. .RE .TP 8 .B "modifyFunctionKeys\fP (class\fB ModifyFunctionKeys\fP)" Tells how to handle the special case where Control-, Shift-, Alt- or Meta-modifiers are used to add a parameter to the escape sequence returned by a (numbered) function-key. The default is \*(``2\*(''. The resource values are similar to \fBmodifyCursorKeys\fP: .RS .TP 5 \-1 permits the user to use shift- and control-modifiers to construct function-key strings using the normal encoding scheme. .TP 5 0 uses the old/obsolete behavior, i.e., the modifier is the first parameter. .TP 5 1 prefixes modified sequences with CSI. .TP 5 2 forces the modifier to be the second parameter if it would otherwise be the first. .TP 5 3 marks the sequence with a \*(``>\*('' to hint that it is private. .RE .IP If \fBmodifyFunctionKeys\fP is zero, \fI\*n\fP uses Control- and Shift-modifiers to allow the user to construct numbered function-keys beyond the set provided by the keyboard: .RS .TP 5 Control adds the value given by the \fBctrlFKeys\fP resource. .TP 5 Shift adds twice the value given by the \fBctrlFKeys\fP resource. .TP 5 Control/Shift adds three times the value given by the \fBctrlFKeys\fP resource. .RE .IP .TP 8 .B "modifyKeyboard\fP (class\fB ModifyKeyboard\fP)" Normally \fI\*n\fP makes a special case regarding modifiers (shift, control, etc.) to handle special keyboard layouts (\fBlegacy\fP and \fBvt220\fP). This is done to provide compatible keyboards for DEC VT220 and related terminals that implement user-defined keys (UDK). .IP The bits of the resource value selectively enable modification of the given category when these keyboards are selected. The default is \*(``0\*('': .RS .TP 5 0 The legacy/vt220 keyboards interpret only the Control-modifier when constructing numbered function-keys. Other special keys are not modified. .TP 5 1 allows modification of the numeric keypad .TP 5 2 allows modification of the editing keypad .TP 5 4 allows modification of function-keys, overrides use of Shift-modifier for UDK. .TP 5 8 allows modification of other special keys .RE .TP 8 .B "modifyOtherKeys\fP (class\fB ModifyOtherKeys\fP)" Like \fBmodifyCursorKeys\fP, tells \fI\*n\fP to construct an escape sequence for \fIordinary\fP (i.e., \*(``other\*('') keys (such as \*(``2\*('') when modified by Shift-, Control-, Alt- or Meta-modifiers. This feature does not apply to \fIspecial keys\fP, i.e., cursor-, keypad-, function- or control-keys which are labeled on your keyboard. Those have key symbols which XKB identifies uniquely. .IP For example, this feature does not apply to \fIspecial\fP control-keys (e.g., Escape, Tab, Enter, Backspace) Other control keys (e.g., Control-I, Control-M, Control-H) may send escape sequences when this feature is enabled. .IP The default is \*(``0\*('': .RS .TP 5 0 disables this feature. .TP 5 1 enables this feature for keys except for those with well-known behavior, e.g., Tab, Backarrow and some special control character cases which are built into the X11 library, e.g., Control-Space to make a NUL, or Control-3 to make an Escape character. .IP Except for those special cases built into the X11 library, the Shift- and Control- modifiers are treated normally. The Alt- and Meta- modifiers do not cause \fI\*n\fP to send escape sequences. Those modifier keys are interpreted according to other resources, e.g., the \fBmetaSendsEscape\fP resource. .TP 5 2 enables this feature for keys including the exceptions listed. \fI\*N\fP ignores the special cases built into the X11 library. Any shifted (modified) ordinary key sends an escape sequence. The Alt- and Meta- modifiers cause \fI\*n\fP to send escape sequences. .RE .IP The \fI\*N\fP FAQ has an extended discussion of this feature, with examples: .RS https://invisible\-island.net/xterm/modified\-keys.html .RE .TP 8 .B "multiClickTime\fP (class\fB MultiClickTime\fP)" Specifies the maximum time in milliseconds between multi-click select events. The default is \*(``250\*('' milliseconds. .TP 8 .B "multiScroll\fP (class\fB MultiScroll\fP)" Specifies whether or not scrolling should be done asynchronously. The default is \*(``false\*(''. .TP 8 .B "nMarginBell\fP (class\fB Column\fP)" Specifies the number of characters from the right margin at which the margin bell should be rung, when enabled by the \fBmarginBell\fP resource. The default is \*(``10\*(''. .TP 8 .B "nextEventDelay\fP (class\fB NextEventDelay\fP)" Specifies a delay time in milliseconds before checking for new X events. The default is \*(``1\*(''. .TP 8 .B "numColorRegisters\fP (class\fB NumColorRegisters\fP)" If \fI\*n\fR is configured to support ReGIS or SIXEL graphics, this specifies the number of color-registers which are available. .IP If this resource is not specified, \fI\*n\fR uses a value determined by the \fBdecTerminalID\fP resource: .TS l l _ _ r r. \fBResult\fR \fBdecTerminalID\fR 4 125 4 240 4 241 4 330 16 340 2 382 1024 \fIother\fP .TE .TP 8 .B "numLock\fP (class\fB NumLock\fP)" If \*(``true\*('', \fI\*n\fR checks if NumLock is used as a modifier (see \fBxmodmap\fP(__mansuffix__)). If so, this modifier is used to simplify the logic when implementing special NumLock for the \fBsunKeyboard\fP resource. Also (when \fBsunKeyboard\fP is false), similar logic is used to find the modifier associated with the left and right Alt keys. The default is \*(``true\*(''. .TP 8 .B "oldXtermFKeys\fP (class\fB OldXtermFKeys\fP)" If \*(``true\*('', \fI\*n\fR will use old-style (X11R5) escape sequences for function keys F1 to F4, for compatibility with X Consortium \fI\*n\fR. Otherwise, it uses the VT100 codes for PF1 to PF4. The default is \*(``false\*(''. .IP Setting this resource has the same effect as setting the \fBkeyboardType\fP to \fBlegacy\fP. The \fBkeyboardType\fP resource is the preferred mechanism for selecting this mode. .IP The old-style escape sequences resemble VT220 keys, but appear to have been invented for \fI\*n\fP in X11R4. .TP 8 .B "on2Clicks\fP (class\fB On2Clicks\fP)" .TP .B "on3Clicks\fP (class\fB On3Clicks\fP)" .TP .B "on4Clicks\fP (class\fB On4Clicks\fP)" .TP .B "on5Clicks\fP (class\fB On5Clicks\fP)" Specify selection behavior in response to multiple mouse clicks. A single mouse click is always interpreted as described in the \fBSelection Functions\fP section (see \fBPOINTER USAGE\fP). Multiple mouse clicks (using the button which activates the \fBselect-start\fP action) are interpreted according to the resource values of \fBon2Clicks\fP, etc. The resource value can be one of these: .RS .TP 3 .B word Select a \*(``word\*('' as determined by the \fBcharClass\fP resource. See the \fBCHARACTER CLASSES\fP section. .TP .B line Select a line (counting wrapping). .TP .B group Select a group of adjacent lines (counting wrapping). The selection stops on a blank line, and does not extend outside the current page. .TP .B page Select all visible lines, i.e., the page. .TP .B all .br Select all lines, i.e., including the saved lines. .TP .B regex Select the best match for the POSIX extended regular expression (ERE) which follows in the resource value: .RS .bP \fI\*N\fP matches the regular expression against a byte array for the entire (possibly wrapped) line. That byte array may be UTF-8 or ISO-8859-1, depending on the mode in which \fI\*n\fP is running. .bP \fI\*N\fP steps through each byte-offset in this array, keeping track of the best (longest) match. If more than one match ties for the longest length, the first is used. .IP \fI\*N\fP does this to make it convenient to click anywhere in the area of interest and cause the regular expression to match the entire word, etc. .bP The \*(``^\*('' and \*(``$\*('' anchors in a regular expression denote the ends of the entire line. .bP If the regular expression contains backslashes \*(``\\\*('' those should be escaped \*(``\\\\\*('' because the X libraries interpret backslashes in resource strings. .RE .TP .B none No selection action is associated with this resource. \fI\*N\fP interprets it as the end of the list. For example, you may use it to disable triple (and higher) clicking by setting \fBon3Clicks\fP to \*(``none\*(''. .RE .IP The default values for \fBon2Clicks\fP and \fBon3Clicks\fP are \*(``word\*('' and \*(``line\*('', respectively. There is no default value for \fBon4Clicks\fP or \fBon5Clicks\fP, making those inactive. On startup, \fI\*n\fP determines the maximum number of clicks by the \fBon\fP\fIX\fP\fBClicks\fP resource values which are set. .TP 8 .B "openIm\fP (class\fB OpenIm\fP)" Tells \fI\*n\fP whether to open the input method at startup. The default is \*(``true\*(''. .TP 8 .B "pointerColor\fP (class\fB PointerColor\fP)" Specifies the foreground color of the pointer. The default is \*(``XtDefaultForeground\*(''. .TP 8 .B "pointerColorBackground\fP (class\fB PointerColorBackground\fP)" Specifies the background color of the pointer. The default is \*(``XtDefaultBackground\*(''. .TP 8 .B "pointerMode\fP (class\fB PointerMode\fP)" Specifies when the pointer may be hidden as the user types. It will be redisplayed if the user moves the mouse, or clicks one of its buttons. .RS .TP 3 0 never .TP 3 1 the application running in \fI\*n\fP has not activated mouse mode. This is the default. .TP 3 2 always. .RE .TP 8 .B "pointerShape\fP (class\fB Cursor\fP)" Specifies the name of the shape of the pointer. The default is \*(``xterm\*(''. .TP 8 .B "popOnBell\fP (class\fB PopOnBell\fP)" Specifies whether the window would be raised when Control-G is received. The default is \*(``false\*(''. .IP If the window is iconified, this has no effect. However, the \fBzIconBeep\fP resource provides you with the ability to see which iconified windows have sounded a bell. .TP 8 .B "precompose\fP (class\fB Precompose\fP)" Tells \fI\*n\fP whether to precompose UTF-8 data into Normalization Form C, which combines commonly-used accents onto base characters. If it does not do this, accents are left as separate characters. The default is \*(``true\*(''. .TP 8 .B "preeditType\fP (class\fB PreeditType\fP)" Tells \fI\*n\fP which types of preedit (preconversion) string to display. The default is \*(``OverTheSpot,Root\*(''. .TP 8 .B "printAttributes\fP (class\fB PrintAttributes\fP)" Specifies whether to print graphic attributes along with the text. A real DEC VT\fIxxx\fP terminal will print the underline, highlighting codes but your printer may not handle these. .RS .bP \*(``0\*('' disables the attributes. .bP \*(``1\*('' prints the normal set of attributes (bold, underline, inverse and blink) as VT100-style control sequences. .bP \*(``2\*('' prints ANSI color attributes as well. .RE .IP The default is \*(``1\*(''. .TP 8 .B "printFileImmediate\fP (class \fBPrintFileImmediate\fP)" When the \fBprint-immediate\fP action is invoked, \fI\*n\fP prints the screen contents directly to a file. Set this resource to the prefix of the filename (a timestamp will be appended to the actual name). .IP The default is an empty string, i.e., \*(``\*('', However, when the \fBprint-immediate\fP action is invoked, if the string is empty, then \*(``__default_class__\*('' is used. .TP 8 .B "printFileOnXError\fP (class \fBPrintFileOnXError\fP)" If \fI\*n\fP exits with an X error, e.g., your connection is broken when the server crashes, it can be told to write the contents of the screen to a file. To enable the feature, set this resource to the prefix of the filename (a timestamp will be appended to the actual name). .IP The default is an empty string, i.e., \*(``\*('', which disables this feature. However, when the \fBprint-on-error\fP action is invoked, if the string is empty, then \*(``XTermError\*('' is used. .IP These error codes are handled: ERROR_XERROR, ERROR_XIOERROR and ERROR_ICEERROR. .TP 8 .B "printModeImmediate\fP (class \fBPrintModeImmediate\fP)" When the \fBprint-immediate\fP action is invoked, \fI\*n\fP prints the screen contents directly to a file. You can use the \fBprintModeImmediate\fP resource to tell it to use escape sequences to reconstruct the video attributes and colors. This uses the same values as the \fBprintAttributes\fP resource. The default is \*(``0\*(''. .TP 8 .B "printModeOnXError\fP (class \fBPrintModeOnXError\fP)" \fI\*N\fP implements the \fBprintFileOnXError\fP feature using the printer feature, although the output is written directly to a file. You can use the \fBprintModeOnXError\fP resource to tell it to use escape sequences to reconstruct the video attributes and colors. This uses the same values as the \fBprintAttributes\fP resource. The default is \*(``0\*(''. .TP 8 .B "printOptsImmediate\fP (class \fBPrintOptsImmediate\fP)" Specify the range of text which is printed to a file when the \fBprint-immediate\fP action is invoked. .RS .bP If zero (0), then this selects the current (visible screen) plus the saved lines, except if the alternate screen is being used. In that case, only the alternate screen is selected. .bP If nonzero, the bits of this resource value (checked in descending order) select the range: .RS .TP 3 8 selects the saved lines. .TP 3 4 selects the alternate screen. .TP 3 2 selects the normal screen. .TP 3 1 selects the current screen, which can be either the normal or alternate screen. .RE .RE .IP The default is \*(``9\*('', which selects the current visible screen plus saved lines, with no special case for the alternated screen. .TP 8 .B "printOptsOnXError\fP (class \fBPrintOptsOnXError\fP)" Specify the range of text which is printed to a file when the \fBprint-on-error\fP action is invoked. The resource value is interpreted the same as in \fBprintOptsImmediate\fP. .IP The default is \*(``9\*('', which selects the current visible screen plus saved lines, with no special case for the alternated screen. .TP 8 .B "printerAutoClose\fP (class\fB PrinterAutoClose\fP)" If \*(``true\*('', \fI\*n\fR will close the printer (a pipe) when the application switches the printer offline with a Media Copy command. The default is \*(``false\*(''. .TP 8 .B "printerCommand\fP (class\fB PrinterCommand\fP)" Specifies a shell command to which \fI\*n\fP will open a pipe when the first MC (Media Copy) command is initiated. The default is an empty string, i.e., \*(``\*(''. If the resource value is given as an empty string, the printer is disabled. .TP 8 .B "printerControlMode\fP (class\fB PrinterControlMode\fP)" Specifies the printer control mode. A \*(``1\*('' selects autoprint mode, which causes \fI\*n\fP to print a line from the screen when .RS .bP you move the cursor off that line with a line feed, form feed or vertical tab character, or .bP an autowrap occurs. .RE .IP Autoprint mode is overridden by printer controller mode (a \*(``2\*(''), which causes all of the output to be directed to the printer. The default is \*(``0\*(''. .TP 8 .B "printerExtent\fP (class\fB PrinterExtent\fP)" Controls whether a print page function will print the entire page (true), or only the portion within the scrolling margins (false). The default is \*(``false\*(''. .TP 8 .B "printerFormFeed\fP (class\fB PrinterFormFeed\fP)" Controls whether a form feed is sent to the printer at the end of a print page function. The default is \*(``false\*(''. .TP 8 .B "printerNewLine\fP (class\fB PrinterNewLine\fP)" Controls whether a newline is sent to the printer at the end of a print page function. The default is \*(``true\*(''. .TP 8 .B "privateColorRegisters\fP (class\fB PrivateColorRegisters\fP)" If \fI\*n\fR is configured to support ReGIS or SIXEL graphics, this controls whether \fI\*n\fR allocates separate color registers for each sixel device control string, e.g., for DECGCI. If not true, color registers are allocated only once, when the terminal is reset, and color changes in any graphic affect all graphics. The default is \*(``true\*(''. .TP 8 .B "quietGrab\fP (class\fB QuietGrab\fP)" Controls whether the cursor is repainted when \fINotifyGrab\fP and \fINotifyUngrab\fP event types are received during change of focus. The default is \*(``false\*(''. .TP 8 .B "regisDefaultFont\fP (class\fB RegisDefaultFont\fP)" If \fI\*n\fR is configured to support ReGIS graphics, this resource tells \fI\*n\fR which font to use if the ReGIS data does not specify one. No default value is specified; \fI\*n\fR accepts a TrueType font specification as in the \fBfaceName\fP resource. .IP If no value is specified, \fI\*n\fR draws a bitmap indicating a missing character. .TP 8 .B "regisScreenSize\fP (class\fB RegisScreenSize\fP)" If \fI\*n\fR is configured to support ReGIS graphics, this resource tells \fI\*n\fR the default size (in pixels) for these graphics, which also sets the default coordinate space to [0,0] (upper-left) and [\fIwidth\fP,\fIheight\fP] (lower-right). .IP The application using ReGIS may use the \*(``A\*('' option of the \*(``S\*('' command to adjust the coordinate space or change the addressable portion of the screen. .IP The default is \*(``1000x1000\*('' (given as \fIwidth\fP by \fIheight\fP). .IP \fI\*N\fR accepts a special resource value \*(``auto\*('', which tells \fI\*n\fR to use the \fBdecTerminalID\fP resource to set the default size based on the hardware terminal's limits. Those limits are the same as for the \fBmaxGraphicSize\fP resource. .TP 8 .B "renderFont\fP (class\fB RenderFont\fP)" If \fI\*n\fR is built with the Xft library, this controls whether the \fBfaceName\fR resource is used. The default is \*(``default\*(''. .IP The resource values are strings, evaluated as booleans after startup. .RS .TP 5 false .br disable the feature and use the normal (bitmap) font. .TP 5 true .br startup using the TrueType font specified by the \fBfaceName\fP and \fBfaceSize\fP resource settings. If there is no value for \fBfaceName\fP, disable the feature and use the normal (bitmap) font. .IP After startup, you can still switch to/from the bitmap font using the \*(``TrueType Fonts\*('' menu entry. .TP 5 default .br Enable the \*(``TrueType Fonts\*('' menu entry to allow runtime switching to/from TrueType fonts. The initial font used depends upon whether the \fBfaceName\fP resource is set: .RS .bP If the \fBfaceName\fP resource is not set, start by using the normal (bitmap) font. \fI\*N\fP has a separate compiled-in value for \fBfaceName\fP for this special case. That is normally \*(``mono\*(''. .bP If the \fBfaceName\fP resource is set, then start by using the TrueType font rather than the bitmap font. .RE .RE .TP 8 .B "resizeGravity\fP (class\fB ResizeGravity\fP)" Affects the behavior when the window is resized to be taller or shorter. \fBNorthWest\fP specifies that the top line of text on the screen stay fixed. If the window is made shorter, lines are dropped from the bottom; if the window is made taller, blank lines are added at the bottom. This is compatible with the behavior in X11R4. \fBSouthWest\fP (the default) specifies that the bottom line of text on the screen stay fixed. If the window is made taller, additional saved lines will be scrolled down onto the screen; if the window is made shorter, lines will be scrolled off the top of the screen, and the top saved lines will be dropped. .TP 8 .B "retryInputMethod\fP (class\fB RetryInputMethod\fP)" Tells \fI\*n\fP how many times to retry, in case the input-method server is not responding. This is a different issue than unsupported preedit type, etc. You may encounter retries if your X configuration (and its libraries) are missing pieces. Setting this resource to zero \*(``0\*('' will cancel the retrying. The default is \*(``3\*(''. .TP 8 .B "reverseVideo\fP (class\fB ReverseVideo\fP)" Specifies whether or not reverse video should be simulated. The default is \*(``false\*(''. .IP There are several aspects to reverse video in \fI\*n\fP: .RS .bP The command-line \fB\-rv\fP option tells the X libraries to reverse the foreground and background colors. \fI\*N\fP's command-line options set resource values. In particular, the X Toolkit sets the \fBreverseVideo\fP resource when the \fB\-rv\fP option is used. .bP If the user has also used command-line options \fB\-fg\fP or \fB\-bg\fP to set the foreground and background colors, \fI\*n\fP does not see these options directly. Instead, it examines the resource values to reconstruct the command-line options, and determine which of the colors is the user's intended foreground, etc. Their actual values are irrelevant to the reverse video function; some users prefer the X defaults (black text on a white background), others prefer white text on a black background. .bP After startup, the user can toggle the \*(``Enable Reverse Video\*('' menu entry. This exchanges the current foreground and background colors of the VT100 widget, and repaints the screen. Because of the X resource hierarchy, the \fBreverseVideo\fP resource applies to more than the VT100 widget. .RE .IP Programs running in an \fI\*n\fP can also use control sequences to enable the VT100 reverse video mode. These are independent of the \fBreverseVideo\fP resource and the menu entry. \fI\*N\fP exchanges the current foreground and background colors when drawing text affected by these control sequences. .IP Other control sequences can alter the foreground and background colors which are used: .RS .bP Programs can also use the ANSI color control sequences to set the foreground and background colors. .bP Extensions to the ANSI color controls (such as 16-, 88- or 256-colors) are treated similarly to the ANSI control. .bP Using other control sequences (the \*(``\fIdynamic colors\fR\*('' feature), a program can change the foreground and background colors. .RE .TP 8 .B "reverseWrap\fP (class\fB ReverseWrap\fP)" Specifies whether or not reverse-wraparound should be enabled. This corresponds to \fI\*n\fP's private mode 45. The default is \*(``false\*(''. .TP 8 .B "rightScrollBar\fP (class\fB RightScrollBar\fP)" Specifies whether or not the scrollbar should be displayed on the right rather than the left. The default is \*(``false\*(''. .TP 8 .B "saveLines\fP (class\fB SaveLines\fP)" Specifies the number of lines to save beyond the top of the screen when a scrollbar is turned on. The default is \*(``1024\*(''. .TP 8 .B "scrollBar\fP (class\fB ScrollBar\fP)" Specifies whether or not the scrollbar should be displayed. The default is \*(``false\*(''. .TP 8 .B "scrollBarBorder\fP (class\fB ScrollBarBorder\fP)" Specifies the width of the scrollbar border. Note that this is drawn to overlap the border of the \fI\*n\fP window. Modifying the scrollbar's border affects only the line between the VT100 widget and the scrollbar. The default value is 1. .TP 8 .B "scrollKey\fP (class\fB ScrollCond\fP)" Specifies whether or not pressing a key should automatically cause the scrollbar to go to the bottom of the scrolling region. This corresponds to \fI\*n\fP's private mode 1011. The default is \*(``false\*(''. .TP 8 .B "scrollLines\fP (class\fB ScrollLines\fP)" Specifies the number of lines that the \fBscroll-back\fP and \fBscroll-forw\fP actions should use as a default. The default value is 1. .TP 8 .B "scrollTtyOutput\fP (class\fB ScrollCond\fP)" Specifies whether or not output to the terminal should automatically cause the scrollbar to go to the bottom of the scrolling region. The default is \*(``true\*(''. .TP .B "selectToClipboard\fP (class\fB SelectToClipboard\fP)" Tells \fI\*n\fP whether to use the \fBPRIMARY\fP or \fBCLIPBOARD\fP for \fBSELECT\fP tokens in the selection mechanism. The \fBset-select\fP action can change this at runtime, allowing the user to work with programs that handle only one of these mechanisms. The default is \*(``false\*('', which tells it to use \fBPRIMARY\fP. .TP 8 .B "shiftFonts\fP (class\fB ShiftFonts\fP)" Specifies whether to enable the actions \fBlarger-vt-font()\fP and \fBsmaller-vt-font()\fP, which are normally bound to the shifted KP_Add and KP_Subtract. The default is \*(``true\*(''. .TP 8 .B "showBlinkAsBold\fP (class\fB ShowBlinkAsBold\fP)" Tells \fI\*n\fP whether to display text with blink-attribute the same as bold. If \fI\*n\fP has not been configured to support blinking text, the default is \*(``true\*('', which corresponds to older versions of \fI\*n\fP, otherwise the default is \*(``false\*(''. .TP 8 .B "showMissingGlyphs\fP (class\fB ShowMissingGlyphs\fP)" Tells \fI\*n\fP whether to display a box outlining places where a character has been used that the font does not represent. The default is \*(``false\*(''. .TP 8 .B "showWrapMarks\fP (class\fB ShowWrapMarks\fP)" For debugging \fI\*n\fP and applications that may manipulate the wrapped-line flag by writing text at the right margin, show a mark on the right inner-border of the window. The mark shows which lines have the flag set. .TP 8 .B "signalInhibit\fP (class\fB SignalInhibit\fP)" Specifies whether or not the entries in the \fBMain Options\fP menu for sending signals to \fI\*n\fP should be disallowed. The default is \*(``false\*(''. .TP 8 .B "sixelScrolling\fP (class\fB SixelScrolling\fP)" If \fI\*n\fR is configured to support SIXEL graphics, this resource tells it whether to scroll up one line at a time when sixels would be written past the bottom line on the window. The default is \*(``false\*(''. .TP 8 .B "sixelScrollsRight\fP (class\fB SixelScrollsRight\fP)" If \fI\*n\fR is configured to support SIXEL graphics, this resource tells it whether to scroll to the right as needed to keep the current position visible rather than truncate the plot on the on the right. The default is \*(``false\*(''. .TP 8 .B "tekGeometry\fP (class\fB Geometry\fP)" Specifies the preferred size and position of the Tektronix window. There is no default for this resource. .TP 8 .B "tekInhibit\fP (class\fB TekInhibit\fP)" Specifies whether or not the escape sequence to enter Tektronix mode should be ignored. The default is \*(``false\*(''. .TP 8 .B "tekSmall\fP (class\fB TekSmall\fP)" Specifies whether or not the Tektronix mode window should start in its smallest size if no explicit geometry is given. This is useful when running \fI\*n\fP on displays with small screens. The default is \*(``false\*(''. .TP 8 .B "tekStartup\fP (class\fB TekStartup\fP)" Specifies whether or not \fI\*n\fP should start up in Tektronix mode. The default is \*(``false\*(''. .TP 8 .B "tiXtraScroll\fP (class\fB TiXtraScroll\fP)" Specifies whether \fI\*n\fP should scroll to a new page when processing the \fIti\fP termcap entry, i.e., the private modes 47, 1047 or 1049. This is only in effect if \fBtiteInhibit\fP is \*(``true\*('', because the intent of this option is to provide a picture of the full-screen application's display on the scrollback without wiping out the text that would be shown before the application was initialized. The default for this resource is \*(``false\*(''. .TP 8 .B "titeInhibit\fP (class\fB TiteInhibit\fP)" Originally specified whether or not \fI\*n\fP should remove \fIti\fP and \fIte\fP termcap entries (used to switch between alternate screens on startup of many screen-oriented programs) from the TERMCAP string. .IP TERMCAP is used rarely now, but \fI\*n\fP supports the feature on modern systems: .RS .bP If set, \fI\*n\fP also ignores the escape sequence to switch to the alternate screen. .bP \fI\*N\fP supports terminfo in a different way, supporting composite control sequences (also known as private modes) 1047, 1048 and 1049 which have the same effect as the original 47 control sequence. .RE .IP The default for this resource is \*(``false\*(''. .TP 8 .B "titleModes\fP (class\fB TitleModes\fP)" Tells \fI\*n\fP whether to accept or return window- and icon-labels in ISO-8859-1 (the default) or UTF-8. Either can be encoded in hexadecimal: .RS .bP UTF-8 titles require special treatment, because they may contain bytes which can be mistaken for control characters. Hexadecimal-encoding is supported to eliminate that possibility. .bP As an alternative, you could use the \fBallowC1Printable\fP resource, which suppresses \fI\*n\fP's parsing of the relevant control characters (and as a result, treats those bytes as data). .RE .IP The default for this resource is \*(``0\*(''. .IP Each bit (bit \*(``0\*('' is 1, bit \*(``1\*('' is 2, etc.) corresponds to one of the parameters set by the title modes control sequence: .RS .TP 5 0 Set window/icon labels using hexadecimal .TP 5 1 Query window/icon labels using hexadecimal .TP 5 2 Set window/icon labels using UTF-8 (gives the same effect as the \fButf8Title\fP resource). .TP 5 3 Query window/icon labels using UTF-8 .RE .TP 8 .B "translations\fP (class\fB Translations\fP)" Specifies the key and button bindings for menus, selections, \*(``programmed strings\*('', etc. The \fBtranslations\fP resource, which provides much of \fI\*n\fP's configurability, is a feature of the X Toolkit Intrinsics library (Xt). See the \fBActions\fP section. .TP 8 .B "trimSelection\fP (class\fB TrimSelection\fP)" If you set \fBhighlightSelection\fP, you can see the text which is selected, including any trailing spaces. Clearing the screen (or a line) resets it to a state containing no spaces. Some lines may contain trailing spaces when an application writes them to the screen. However, you may not wish to paste lines with trailing spaces. If this resource is true, \fI\*n\fP will trim trailing spaces from text which is selected. It does not affect spaces which result in a wrapped line, nor will it trim the trailing newline from your selection. The default is \*(``false\*(''. .TP 8 .B "underLine\fP (class\fB UnderLine\fP)" This specifies whether or not text with the underline attribute should be underlined. It may be desirable to disable underlining when color is being used for the underline attribute. The default is \*(``true\*(''. .TP 8 .B "useBorderClipping\fP (class\fB UseBorderClipping\fP)" Tell \fI\*n\fP whether to apply clipping when \fBuseClipping\fP is false. Unlike \fBuseClipping\fP, this simply limits text to keep it within the window borders, e.g., as a refinement to the \fBscaleHeight\fP workaround. The default is \*(``false\*(''. .TP 8 .B "useClipping\fP (class\fB UseClipping\fP)" Tell \fI\*n\fP whether to use clipping to keep from producing dots outside the text drawing area. Originally used to work around for overstriking effects, this is also needed to work with some incorrectly-sized fonts. The default is \*(``true\*(''. .TP 8 .B "utf8\fP (class\fB Utf8\fP)" This specifies whether \fI\*n\fP will run in UTF-8 mode. If you set this resource, \fI\*n\fP also sets the \fBwideChars\fP resource as a side-effect. The resource can be set via the menu entry \*(``UTF-8 Encoding\*(''. The default is \*(``default\*(''. .IP \fI\*N\fP accepts either a keyword (ignoring case) or the number shown in parentheses: .RS .TP 3 false (0) UTF-8 mode is initially off. The command-line option \fB+u8\fP sets the resource to this value. Escape sequences for turning UTF-8 mode on/off are allowed. .TP true (1) UTF-8 mode is initially on. Escape sequences for turning UTF-8 mode on/off are allowed. .TP always (2) The command-line option \fB\-u8\fP sets the resource to this value. Escape sequences for turning UTF-8 mode on/off are ignored. .TP default (3) This is the default value of the resource. It is changed during initialization depending on whether the \fBlocale\fP resource was set, to false (0) or always (2). See the \fBlocale\fR resource for additional discussion of non-UTF-8 locales. .RE .IP If you want to set the value of \fButf8\fP, it should be in this range. Other nonzero values are treated the same as \*(``1\*('', i.e., UTF-8 mode is initially on, and escape sequences for turning UTF-8 mode on/off are allowed. .TP 8 .B "utf8Fonts\fP (class\fB Utf8Fonts\fP)" See the discussion of the \fBlocale\fP resource. This specifies whether \fI\*n\fP will use UTF-8 fonts specified via resource patterns such as \*(``\fB*vt100.utf8Fonts.font\fP\*('' or normal (ISO-8859-1) fonts via patterns such as \*(``\fB*vt100.font\fP\*(''. The resource can be set via the menu entry \*(``\fBUTF-8 Fonts\fP\*(''. The default is \*(``default\*(''. .IP \fI\*N\fP accepts either a keyword (ignoring case) or the number shown in parentheses: .RS .TP false (0) Use the ISO-8859-1 fonts. The menu entry is enabled, allowing the choice of fonts to be changed at runtime. .TP true (1) Use the UTF-8 fonts. The menu entry is enabled, allowing the choice of fonts to be changed at runtime. .TP always (2) Always use the UTF-8 fonts. This also disables the menu entry. .TP default (3) At startup, the resource is set to true or false, according to the effective value of the \fButf8\fP resource. .RE .TP 8 .B "utf8Latin1\fP (class\fB Utf8Latin1\fP)" If true, allow an ISO-8859-1 \fInormal\fP font to be combined with an ISO-10646-1 font if the latter is given via the \fB\-fw\fP option or its corresponding resource value. The default is \*(``false\*(''. .TP 8 .B "utf8SelectTypes\fP (class\fB Utf8SelectTypes\fP)" Override \fI\*n\fP's default selection target list (see \fBSELECT/PASTE\fP) for selections in wide-character (UTF-8) mode. The default is an empty string, i.e., \*(``\*('', which does not override anything. .TP 8 .B "utf8Title\fP (class\fB Utf8Title\fP)" Applications can set \fI\*n\fP's title by writing a control sequence. Normally this control sequence follows the VT220 convention, which encodes the string in ISO-8859-1 and allows for an 8-bit string terminator. If \fI\*n\fP is started in a UTF-8 locale, it translates the ISO-8859-1 string to UTF-8 to work with the X libraries which assume the string is UTF-8. .IP However, some users may wish to write a title string encoded in UTF-8. The window manager is responsible for drawing window titles. Some window managers (not all) support UTF-8 encoding of window titles. Set this resource to \*(``true\*('' to also set UTF-8 encoded title strings using the EWMH properties. .IP This feature is available as a menu entry, since it is related to the particular applications you are running within \fI\*n\fP. You can also use a control sequence (see the discussion of \*(``Title Modes\*('' in \fI\*N Control Sequences\fP), to set an equivalent flag (which can also be set using the \fBtitleModes\fP resource). .IP \fI\*N\fP accepts either a keyword (ignoring case) or the number shown in parentheses: .RS .TP false (0) Set only ISO-8859-1 title strings, e.g., using the ICCCM \fBWM_NAME\fP STRING property. The menu entry is enabled, allowing the choice of title-strings to be changed at runtime. .TP true (1) Set both the EWMH (UTF-8 strings) and the ICCCM \fBWM_NAME\fP, etc. The menu entry is enabled, allowing the choice to be changed at runtime. .TP always (2) Always set both the EWMH (UTF-8 strings) and the ICCCM \fBWM_NAME\fP, etc. This also disables the menu entry. .TP default (3) At startup, the resource is set to true or false, according to the effective value of the \fButf8\fP resource. .RE .IP The default is \*(``default\*(''. .TP 8 .B "veryBoldColors\fP (class\fB VeryBoldColors\fP)" Specifies whether to combine video attributes with colors specified by \fBcolorBD\fR, \fBcolorBL\fR, \fBcolorIT\fR, \fBcolorRV\fR, and \fBcolorUL\fR. The resource value is the sum of values for each attribute: .RS 10 .nf 1 for reverse, 2 for underline, 4 for bold, 8 for blink, and 512 for italic .fi .RE .IP The default is \*(``0\*(''. .TP 8 .B "visualBell\fP (class\fB VisualBell\fP)" Specifies whether or not a visible bell (i.e., flashing) should be used instead of an audible bell when Control-G is received. The default is \*(``false\*('', which tells \fI\*n\fP to use an audible bell. .TP 8 .B "visualBellDelay\fP (class\fB VisualBellDelay\fP)" Number of milliseconds to delay when displaying a visual bell. Default is 100. If set to zero, no visual bell is displayed. This is useful for very slow displays, e.g., an LCD display on a laptop. .TP 8 .B "visualBellLine\fP (class\fB VisualBellLine\fP)" Specifies whether to flash only the current line when displaying a visual bell rather than flashing the entire screen: The default is \*(``false\*('', which tells \fI\*n\fP to flash the entire screen. .TP 8 .B "vt100Graphics\fP (class\fB VT100Graphics\fP)" This specifies whether \fI\*n\fP will interpret VT100 graphic character escape sequences while in UTF-8 mode. The default is \*(``true\*('', to provide support for various legacy applications. .TP 8 .B "wideBoldFont\fP (class\fB WideBoldFont\fP)" This option specifies the font to be used for displaying bold wide text. By default, it will attempt to use a font twice as wide as the font that will be used to draw bold text. If no double-width font is found, it will improvise, by stretching the bold font. .TP 8 .B "wideChars\fP (class\fB WideChars\fP)" Specifies if \fI\*n\fP should respond to control sequences that process 16-bit characters. The default is \*(``false\*(''. .TP 8 .B "wideFont\fP (class\fB WideFont\fP)" This option specifies the font to be used for displaying wide text. By default, it will attempt to use a font twice as wide as the font that will be used to draw normal text. If no double-width font is found, it will improvise, by stretching the normal font. .TP 8 .B "ximFont\fP (class\fB XimFont\fP)" This option specifies the font to be used for displaying the preedit string in the \*(``OverTheSpot\*('' input method. .IP In \*(``OverTheSpot\*('' preedit type, the preedit (preconversion) string is displayed at the position of the cursor. It is the XIM server's responsibility to display the preedit string. The XIM client must inform the XIM server of the cursor position. For best results, the preedit string must be displayed with a proper font. Therefore, \fI\*n\fP informs the XIM server of the proper font. The font is be supplied by a "fontset", whose default value is \*(``*\*(''. This matches every font, the X library automatically chooses fonts with proper charsets. The \fBximFont\fP resource is provided to override this default font setting. .\" .SS Tek4014 Widget Resources .PP The following resources are specified as part of the \fItek4014\fP widget (class \fITek4014\fP). These are specified by patterns such as \*(``\fB__default_class__.tek4014.\fP\fINAME\fP\*('': .TP 8 .B "font2\fP (class\fB Font\fP)" Specifies font number 2 to use in the Tektronix window. .TP 8 .B "font3\fP (class\fB Font\fP)" Specifies font number 3 to use in the Tektronix window. .TP 8 .B "fontLarge\fP (class\fB Font\fP)" Specifies the large font to use in the Tektronix window. .TP 8 .B "fontSmall\fP (class\fB Font\fP)" Specifies the small font to use in the Tektronix window. .TP 8 .B "ginTerminator\fP (class\fB GinTerminator\fP)" Specifies what character(s) should follow a GIN report or status report. The possibilities are \*(``none\*('', which sends no terminating characters, \*(``CRonly\*('', which sends CR, and \*(``CR&EOT\*('', which sends both CR and EOT. The default is \*(``none\*(''. .TP 8 .B "height\fP (class\fB Height\fP)" Specifies the height of the Tektronix window in pixels. .TP 8 .B "initialFont\fP (class\fB InitialFont\fP)" Specifies which of the four Tektronix fonts to use initially. Values are the same as for the \fBset-tek-text\fP action. The default is \*(``large\*(''. .TP 8 .B "width\fP (class\fB Width\fP)" Specifies the width of the Tektronix window in pixels. .\" .SS Menu Resources .PP The resources that may be specified for the various menus are described in the documentation for the Athena \fBSimpleMenu\fP widget. The name and classes of the entries in each of the menus are listed below. Resources named \*(``\fBline\fR\fIN\fR\*('' where \fIN\fR is a number are separators with class \fBSmeLine\fR. .PP As with all X resource-based widgets, the labels mentioned are customary defaults for the application. . .PP The \fBMain Options\fP menu (widget name \fImainMenu\fP) has the following entries: .TP 8 .B "toolbar\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-toolbar(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "securekbd\fP (class\fB SmeBSB\fP)" This entry invokes the \fBsecure()\fP action. .TP 8 .B "allowsends\fP (class\fB SmeBSB\fP)" This entry invokes the \fBallow-send-events(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "redraw\fP (class\fB SmeBSB\fP)" This entry invokes the \fBredraw()\fP action. .TP 8 .B "logging\fP (class\fB SmeBSB\fP)" This entry invokes the \fBlogging(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "print-immediate\fP (class\fB SmeBSB\fP)" This entry invokes the \fBprint-immediate()\fP action. .TP 8 .B "print-on-error\fP (class\fB SmeBSB\fP)" This entry invokes the \fBprint-on-error()\fP action. .TP 8 .B "print\fP (class\fB SmeBSB\fP)" This entry invokes the \fBprint()\fP action. .TP 8 .B "print-redir\fP (class\fB SmeBSB\fP)" This entry invokes the \fBprint-redir()\fP action. .TP 8 .B "dump-html\fP (class\fB SmeBSB\fP)" This entry invokes the \fBdump-html()\fP action. .TP 8 .B "dump-svg\fP (class\fB SmeBSB\fP)" This entry invokes the \fBdump-svg()\fP action. .TP 8 .B "8-bit-control\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-8-bit-control(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "backarrow\ key\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-backarrow(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "num-lock\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-num-lock(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "alt-esc\fP (class\fB SmeBSB\fP)" This entry invokes the \fBalt-sends-escape(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "meta-esc\fP (class\fB SmeBSB\fP)" This entry invokes the \fBmeta-sends-escape(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "delete-is-del\fP (class\fB SmeBSB\fP)" This entry invokes the \fBdelete-is-del(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "oldFunctionKeys\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-old-function-keys(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "hpFunctionKeys\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-hp-function-keys(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "scoFunctionKeys\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-sco-function-keys(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "sunFunctionKeys\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-sun-function-keys(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "sunKeyboard\fP (class\fB SmeBSB\fP)" This entry invokes the \fBsunKeyboard(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "suspend\fP (class\fB SmeBSB\fP)" This entry invokes the \fBsend-signal(\fP\fItstp\fP\fB)\fP action on systems that support job control. .TP 8 .B "continue\fP (class\fB SmeBSB\fP)" This entry invokes the \fBsend-signal(\fP\fIcont\fP\fB)\fP action on systems that support job control. .TP 8 .B "interrupt\fP (class\fB SmeBSB\fP)" This entry invokes the \fBsend-signal(\fP\fIint\fP\fB)\fP action. .TP 8 .B "hangup\fP (class\fB SmeBSB\fP)" This entry invokes the \fBsend-signal(\fP\fIhup\fP\fB)\fP action. .TP 8 .B "terminate\fP (class\fB SmeBSB\fP)" This entry invokes the \fBsend-signal(\fP\fIterm\fP\fB)\fP action. .TP 8 .B "kill\fP (class\fB SmeBSB\fP)" This entry invokes the \fBsend-signal(\fP\fIkill\fP\fB)\fP action. .TP 8 .B "quit\fP (class\fB SmeBSB\fP)" This entry invokes the \fBquit()\fP action. . .PP The \fBVT Options\fP menu (widget name \fIvtMenu\fP) has the following entries: .TP 8 .B "scrollbar\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-scrollbar(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "jumpscroll\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-jumpscroll(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "reversevideo\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-reverse-video(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "autowrap\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-autowrap(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "reversewrap\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-reversewrap(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "autolinefeed\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-autolinefeed(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "appcursor\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-appcursor(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "appkeypad\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-appkeypad(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "scrollkey\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-scroll-on-key(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "scrollttyoutput\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-scroll-on-tty-output(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "allow132\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-allow132(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "cursesemul\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-cursesemul(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "keepSelection\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-keep-selection(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "selectToClipboard\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-keep-clipboard(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "visualbell\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-visual-bell(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "bellIsUrgent\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-bellIsUrgent(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "poponbell\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-pop-on-bell(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "cursorblink\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-cursorblink(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "titeInhibit\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-titeInhibit(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "activeicon\fP (class\fB SmeBSB\fP)" This entry toggles active icons on and off if this feature was compiled into \fI\*n\fP. It is enabled only if \fI\*n\fP was started with the command line option +ai or the \fBactiveIcon\fP resource is set to \*(``true\*(''. .TP 8 .B "softreset\fP (class\fB SmeBSB\fP)" This entry invokes the \fBsoft-reset()\fP action. .TP 8 .B "hardreset\fP (class\fB SmeBSB\fP)" This entry invokes the \fBhard-reset()\fP action. .TP 8 .B "clearsavedlines\fP (class\fB SmeBSB\fP)" This entry invokes the \fBclear-saved-lines()\fP action. .TP 8 .B "tekshow\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-visibility(\fP\fItek,toggle\fP\fB)\fP action. .TP 8 .B "tekmode\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-terminal-type(\fP\fItek\fP\fB)\fP action. .TP 8 .B "vthide\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-visibility(\fP\fIvt,off\fP\fB)\fP action. .TP 8 .B "altscreen\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-altscreen(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "sixelScrolling\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-sixel-scrolling(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "privateColorRegisters\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-private-colors(\fP\fItoggle\fP\fB)\fP action. . .PP The \fBVT Fonts\fP menu (widget name \fIfontMenu\fP) has the following entries: .TP 8 .B "fontdefault\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-vt-font(\fP\fId\fP\fB)\fP action, setting the font using the \fBfont\fP (default) resource, e.g., \*(``Default\*('' in the menu. .TP 8 .B "font1\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-vt-font(\fP\fI1\fP\fB)\fP action, setting the font using the \fBfont1\fP resource, e.g., \*(``Unreadable\*('' in the menu. .TP 8 .B "font2\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-vt-font(\fP\fI2\fP\fB)\fP action, setting the font using the \fBfont2\fP resource, e.g., \*(``Tiny\*('' in the menu. .TP 8 .B "font3\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-vt-font(\fP\fI3\fP\fB)\fP action, setting the font using the \fBfont3\fP resource, e.g., \*(``Small\*('' in the menu. .TP 8 .B "font4\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-vt-font(\fP\fI4\fP\fB)\fP action, letting the font using the \fBfont4\fP resource, e.g., \*(``Medium\*('' in the menu. .TP 8 .B "font5\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-vt-font(\fP\fI5\fP\fB)\fP action, letting the font using the \fBfont5\fP resource, e.g., \*(``Large\*('' in the menu. .TP 8 .B "font6\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-vt-font(\fP\fI6\fP\fB)\fP action, letting the font using the \fBfont6\fP resource, e.g., \*(``Huge\*('' in the menu. .TP 8 .B "fontescape\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-vt-font(\fP\fIe\fP\fB)\fP action. .TP 8 .B "fontsel\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-vt-font(\fP\fIs\fP\fB)\fP action. .TP 8 .B "allow-bold-fonts\fP (class\fB SmeBSB\fP)" This entry invokes the \fBallow-bold-fonts(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "font-linedrawing\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-font-linedrawing(\fP\fIs\fP\fB)\fP action. .TP 8 .B "font-packed\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-font-packed(\fP\fIs\fP\fB)\fP action. .TP 8 .B "font-doublesize\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-font-doublesize(\fP\fIs\fP\fB)\fP action. .TP 8 .B "render-font\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-render-font(\fP\fIs\fP\fB)\fP action. .TP 8 .B "utf8-fonts\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-utf8-fonts(\fP\fIs\fP\fB)\fP action. .TP 8 .B "utf8-mode\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-utf8-mode(\fP\fIs\fP\fB)\fP action. .TP 8 .B "utf8-title\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-utf8-title(\fP\fIs\fP\fB)\fP action. .TP 8 .B "allow-color-ops\fP (class\fB SmeBSB\fP)" This entry invokes the \fBallow-color-ops(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "allow-font-ops\fP (class\fB SmeBSB\fP)" This entry invokes the \fBallow-fonts-ops(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "allow-tcap-ops\fP (class\fB SmeBSB\fP)" This entry invokes the \fBallow-tcap-ops(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "allow-title-ops\fP (class\fB SmeBSB\fP)" This entry invokes the \fBallow-title-ops(\fP\fItoggle\fP\fB)\fP action. .TP 8 .B "allow-window-ops\fP (class\fB SmeBSB\fP)" This entry invokes the \fBallow-window-ops(\fP\fItoggle\fP\fB)\fP action. . .PP The \fBTek Options\fP menu (widget name \fItekMenu\fP) has the following entries: .TP 8 .B "tektextlarge\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-tek-text(\fP\fIlarge\fP\fB)\fP action. .TP 8 .B "tektext2\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-tek-text(\fP\fI2\fP\fB)\fP action. .TP 8 .B "tektext3\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-tek-text(\fP\fI3\fP\fB)\fP action. .TP 8 .B "tektextsmall\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-tek-text(\fP\fIsmall\fP\fB)\fP action. .TP 8 .B "tekpage\fP (class\fB SmeBSB\fP)" This entry invokes the \fBtek-page()\fP action. .TP 8 .B "tekreset\fP (class\fB SmeBSB\fP)" This entry invokes the \fBtek-reset()\fP action. .TP 8 .B "tekcopy\fP (class\fB SmeBSB\fP)" This entry invokes the \fBtek-copy()\fP action. .TP 8 .B "vtshow\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-visibility(\fP\fIvt,toggle\fP\fB)\fP action. .TP 8 .B "vtmode\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-terminal-type(\fP\fIvt\fP\fB)\fP action. .TP 8 .B "tekhide\fP (class\fB SmeBSB\fP)" This entry invokes the \fBset-visibility(\fP\fItek,toggle\fP\fB)\fP action. .\" .SS Scrollbar Resources .PP The following resources are useful when specified for the Athena Scrollbar widget: .TP 8 .B "thickness\fP (class\fB Thickness\fP)" Specifies the width in pixels of the scrollbar. .TP 8 .B "background\fP (class\fB Background\fP)" Specifies the color to use for the background of the scrollbar. .TP 8 .B "foreground\fP (class\fB Foreground\fP)" Specifies the color to use for the foreground of the scrollbar. The \*(``thumb\*('' of the scrollbar is a simple checkerboard pattern alternating pixels for foreground and background color. . . .SH "POINTER USAGE" . .PP Once the VT\fIxxx\fP window is created, \fI\*n\fP allows you to select text and copy it within the same or other windows using the \fIpointer\fP or the keyboard. . .PP A \*(``pointer\*('' could be a mouse, touchpad or similar device. X applications generally do not care, since they see only \fIbutton events\fP which have .bP position and .bP button up/down state .PP \fI\*N\fP can see these events as long as it has \fIfocus\fP. .PP The keyboard also supplies events, but it is less flexible than the pointer for selecting/copying text. .PP \fIEvents\fP are applied to \fIactions\fP using the \fBtranslations\fP resource. See \fBActions\fP for a complete list, and \fBDefault Key Bindings\fP for the built-in set of \fBtranslations\fP resources. . .SS "Selection Functions" .PP The selection functions are invoked when the pointer buttons are used with no modifiers, and when they are used with the \*(``shift\*('' key. The assignment of the functions described below to keys and buttons may be changed through the resource database; see \fBActions\fP below. . .TP 5 Pointer button one (usually left) is used to save text into the cut buffer: .NS ~Meta :\fBselect\-start\fP() .NE .IP Move the cursor to beginning of the text, and then hold the button down while moving the cursor to the end of the region and releasing the button. The selected text is highlighted and is saved in the global \fIcut buffer\fP and made the selection when the button is released: .NS :\fBselect\-end\fP(\fBSELECT\fP, \fBCUT_BUFFER0\fP) \en .NE .IP Normally (but see the discussion of \fBon2Clicks\fP, etc): .RS .bP Double-clicking selects by words. .bP Triple-clicking selects by lines. .bP Quadruple-clicking goes back to characters, etc. .RE .IP Multiple-click is determined by the time from button up to button down, so you can change the selection unit in the middle of a selection. Logical words and lines selected by double- or triple-clicking may wrap across more than one screen line if lines were wrapped by \fI\*n\fP itself rather than by the application running in the window. If the key/button bindings specify that an X selection is to be made, \fI\*n\fP will leave the selected text highlighted for as long as it is the selection owner. . .TP 5 Pointer button two (usually middle) \*(``types\*('' (\fIpastes\fP) the text from the given selection, if any, otherwise from the cut buffer, inserting it as keyboard input: .NS ~Ctrl ~Meta :\fB\fBinsert\-selection\fP\fP(\fBSELECT\fP, \fBCUT_BUFFER0\fP) .NE . .TP 5 Pointer button three (usually right) \fIextends\fP the current selection. .NS ~Ctrl ~Meta :\fB\fBstart\-extend\fP\fP() .NE .IP (Without loss of generality, you can swap \*(``right\*('' and \*(``left\*('' everywhere in the rest of this paragraph.) If pressed while closer to the right edge of the selection than the left, it extends/contracts the right edge of the selection. If you contract the selection past the left edge of the selection, \fI\*n\fP assumes you really meant the left edge, restores the original selection, then extends/contracts the left edge of the selection. Extension starts in the selection unit mode that the last selection or extension was performed in; you can multiple-click to cycle through them. . .PP By cutting and pasting pieces of text without trailing new lines, you can take text from several places in different windows and form a command to the shell, for example, or take output from a program and insert it into your favorite editor. Since cut buffers are globally shared among different applications, you may regard each as a \*(``file\*('' whose contents you know. The terminal emulator and other text programs should be treating it as if it were a text file, i.e., the text is delimited by new lines. . .SS "Scrolling" .PP The scroll region displays the position and amount of text currently showing in the window (highlighted) relative to the amount of text actually saved. As more text is saved (up to the maximum), the size of the highlighted area decreases. . .PP Clicking button one with the pointer in the scroll region moves the adjacent line to the top of the display window. . .PP Clicking button three moves the top line of the display window down to the pointer position. . .PP Clicking button two moves the display to a position in the saved text that corresponds to the pointer's position in the scrollbar. . .SS "Tektronix Pointer" .PP Unlike the VT\fIxxx\fP window, the Tektronix window does not allow the copying of text. It does allow Tektronix GIN mode, and in this mode the cursor will change from an arrow to a cross. Pressing any key will send that key and the current coordinate of the cross cursor. Pressing button one, two, or three will return the letters \*(``l\*('', \*(``m\*('', and \*(``r\*('', respectively. If the \*(``shift\*('' key is pressed when a pointer button is pressed, the corresponding upper case letter is sent. To distinguish a pointer button from a key, the high bit of the character is set (but this is bit is normally stripped unless the terminal mode is RAW; see .IR tty (4) for details). . . .SH SELECT/PASTE X clients provide select and paste support by responding to requests conveyed by the X server. The X server holds data in \*(``atoms\*('' which correspond to the different types of selection (\fBPRIMARY\fP, \fBSECONDARY\fP, \fBCLIPBOARD\fP) as well as the similar cut buffer mechanism (\fBCUT_BUFFER0\fP to \fBCUT_BUFFER7\fP). Those are documented in the ICCCM. .PP The ICCCM deals with the underlying mechanism for select/paste. It does not mention \fIhighlighting\fP. The \fIselection\fP is not the same as \fIhighlighting\fP. \fI\*N\fP (like many applications) uses highlighting to show you the currently selected text. An X application may \fIown\fP a selection, which allows it to be the source of data copied using a given selection atom \fI\*N\fP may continue owning a selection after it stops highlighting (see \fBkeepSelection\fP). .SS PRIMARY When configured to use the primary selection (the default), \fI\*n\fP can provide the selection data in ways which help to retain character encoding information as it is pasted. .PP The \fBPRIMARY\fP token is a standard X feature, documented in the ICCCM (\fIInter-Client Communication Conventions Manual\fR), which states .RS 3 .PP The selection named by the atom \fBPRIMARY\fP is used for all commands that take only a single argument and is the principal means of communication between clients that use the selection mechanism. .RE .PP A user \*(``selects\*('' text on \fI\*n\fP, which highlights the selected text. A subsequent \*(``paste\*('' to another client forwards a request to the client owning the selection. If \fI\*n\fP owns the primary selection, it makes the data available in the form of one or more \*(``selection targets\*(''. If it does not own the primary selection, e.g., if it has released it or another client has asserted ownership, it relies on cut-buffers to pass the data. But cut-buffers handle only ISO-8859-1 data (officially \- some clients ignore the rules). . .SS CLIPBOARD .PP When configured to use the clipboard (using the \fBselectToClipboard\fP resource), the problem with persistence of ownership is bypassed. Otherwise, there is no difference regarding the data which can be passed via selection. .PP The \fBselectToClipboard\fP resource is a compromise, allowing \fBCLIPBOARD\fP to be treated almost like \fBPRIMARY\fP, unlike the ICCCM, which describes \fBCLIPBOARD\fP in different terms than \fBPRIMARY\fP or \fBSECONDARY\fP. Its lengthy explanation begins with the essential points: .RS 3 .PP The selection named by the atom CLIPBOARD is used to hold data that is being transferred between clients, that is, data that usually is being cut and then pasted or copied and then pasted. Whenever a client wants to transfer data to the clipboard: .bP It should assert ownership of the CLIPBOARD. .bP If it succeeds in acquiring ownership, it should be prepared to respond to a request for the contents of the CLIPBOARD in the usual way (retaining the data to be able to return it). The request may be generated by the clipboard client described below. .RE .SS SELECT .PP However, many applications use \fBCLIPBOARD\fP in imitation of other windowing systems. The \fBselectToClipboard\fP resource (and corresponding menu entry \fBSelect to Clipboard\fP) introduce the \fBSELECT\fP token (known only to \fI\*n\fP) which chooses between the \fBPRIMARY\fP and \fBCLIPBOARD\fP tokens. .PP Without using this feature, one can use workarounds such as the \fIxclip\fP program to show the contents of the X clipboard within an \fI\*n\fP window. .SS SECONDARY .PP This is used less often than \fBPRIMARY\fP or \fBCLIPBOARD\fP. According to the ICCCM, it is used .bP As the second argument to commands taking two arguments (for example, \*(``exchange primary and secondary selections\*('') .bP As a means of obtaining data when there is a primary selection and the user does not want to disturb it . .SS Selection Targets The different types of data which are passed depend on what the receiving client asks for. These are termed \fIselection targets\fP. .PP When asking for the selection data, \fI\*n\fP tries the following types in this order: .RS 5 .TP 5 UTF8_STRING This is an XFree86 extension, which denotes that the data is encoded in UTF-8. When \fI\*n\fP is built with wide-character support, it both accepts and provides this type. .TP 5 TEXT the text is in the encoding which corresponds to your current locale. .TP 5 .\" see xc/doc/specs/CTEXT/ctext.tbl.ms .\" (it says the data is stored as a type of ISO 2022) COMPOUND_TEXT this is a format for multiple character set data, such as multi-lingual text. It can store UTF-8 data as a special case. .TP 5 STRING This is Latin 1 (ISO-8859-1) data. .RE .PP The middle two (TEXT and COMPOUND_TEXT) are added if \fI\*n\fP is configured with the \fBi18nSelections\fP resource set to \*(``true\*(''. .PP UTF8_STRING is preferred (therefore first in the list) since \fI\*n\fP stores text as Unicode data when running in wide-character mode, and no translation is needed. On the other hand, TEXT and COMPOUND_TEXT may require translation. If the translation is incomplete, they will insert X's \*(``defaultString\*('' whose value cannot be set, and may simply be empty. \fI\*N\fP's \fBdefaultString\fP resource specifies the string to use for incomplete translations of the UTF8_STRING. .PP You can alter the types which \fI\*n\fP tries using the \fBeightBitSelectTypes\fP or \fButf8SelectTypes\fP resources. For instance, you might have some specific locale setting which does not use UTF-8 encoding. The resource value is a comma-separated list of the selection targets, which consist of the names shown. You can use the special name I18N to denote the optional inclusion of TEXT and COMPOUND_TEXT. The names are matched ignoring case, and can be abbreviated. The default list can be expressed in several ways, e.g., .sp .RS .nf UTF8_STRING,I18N,STRING utf8,i18n,string u,i,s .fi .RE . .SS Mouse Protocol .PP Applications can send escape sequences to \fI\*n\fP to cause it to send escape sequences back to the computer when you press a pointer button, or even (depending on which escape sequence) send escape sequences back to the computer as you move the pointer. .PP These escape sequences and the responses, called the \fImouse protocol\fP, are documented in \fIXTerm Control Sequences\fP. They do not appear in the \fIactions\fP invoked by the \fBtranslations\fP resource because the resource does not change while you run \fI\*n\fP, whereas applications can change the mouse prototol (i.e., enable, disable, use different modes). .PP However, the mouse protocol is interpreted within the \fIactions\fP that are usually associated with the pointer buttons. \fI\*N\fP ignores the mouse protocol in the \fBinsert-selection\fP action if the shift-key is pressed at the same time. It also modifies a few other actions if the shift-key is pressed, e.g., suppressing the response with the pointer position, though not eliminating changes to the selected text. . .SH MENUS . .PP \fI\*N\fP has four menus, named .IR mainMenu , .IR vtMenu , .IR fontMenu , and .IR tekMenu . Each menu pops up under the correct combinations of key and button presses. Each menu is divided into sections, separated by a horizontal line. Some menu entries correspond to modes that can be altered. A check mark appears next to a mode that is currently active. Selecting one of these modes toggles its state. Other menu entries are commands; selecting one of these performs the indicated function. .PP All of the menu entries correspond to X actions. In the list below, the menu label is shown followed by the action's name in parenthesis. . .\" ************************************************************************ .SS "Main Options" .PP The \fI\*n\fP \fImainMenu\fP pops up when the \*(``control\*('' key and pointer button one are pressed in a window. This menu contains items that apply to both the VT\fIxxx\fP and Tektronix windows. There are several sections: .TP Commands for managing X events: .RS .TP .B Toolbar\fP (resource \fBtoolbar\fP) Clicking on the \*(``Toolbar\*('' menu entry hides the toolbar if it is visible, and shows it if it is not. .TP .B Secure Keyboard\fP (resource \fBsecurekbd\fP) The \fBSecure Keyboard\fP mode is helpful when typing in passwords or other sensitive data in an unsecure environment (see \fBSECURITY\fP below, but read the limitations carefully). .TP .B Allow SendEvents\fP (resource \fBallowsends\fP) Specifies whether or not synthetic key and button events generated using the X protocol SendEvent request should be interpreted or discarded. This corresponds to the \fBallowSendEvents\fP resource. .TP .B Redraw Window\fP (resource \fBredraw\fP) Forces the X display to repaint; useful in some environments. .RE .TP Commands for capturing output: .RS .TP .B Log to File\fP (resource \fBlogging\fP) Captures text sent to the screen in a log file, as in the \fB\-l\fP logging option. .TP .B Print-All Immediately\fP (resource \fBprint-immediate\fP) Invokes the \fBprint-immediate\fP action, sending the text of the current window directly to a file, as specified by the \fBprintFileImmediate\fP, \fBprintModeImmediate\fP and \fBprintOptsImmediate\fP resources. .TP .B Print-All on Error\fP (resource \fBprint-on-error\fP) Invokes the \fBprint-on-error\fP action, which toggles a flag telling \fI\*n\fP that if it exits with an X error, to send the text of the current window directly to a file, as specified by the \fBprintFileOnXError\fP, \fBprintModeOnXError\fP and \fBprintOptsOnXError\fP resources. .TP .B Print Window\fP (resource \fBprint\fP) Sends the text of the current window to the program given in the \fBprinterCommand\fP resource. .TP .B Redirect to Printer\fP (resource \fBprint-redir\fP) This sets the \fBprinterControlMode\fR to 0 or 2. You can use this to turn the printer on as if an application had sent the appropriate control sequence. It is also useful for switching the printer off if an application turns it on without resetting the print control mode. .TP .B XHTML Screen Dump\fP (resource \fBdump-html\fP) Available only when compiled with screen dump support. Invokes the \fBdump-html\fP action. This creates an XHTML file matching the contents of the current screen, including the border, internal border, colors and most attributes: bold, italic, underline, faint, strikeout, reverse; blink is rendered as white-on-red; double underline is rendered the same as underline since there is no portable equivalent in CSS 2.2. .IP The font is whatever your browser uses for preformatted (
    )
    elements.
    The XHTML file references a cascading style sheet (CSS)
    named \*(``\fBxterm.css\fP\*('' that you can create to select a font or
    override properties.
    .RS
    .LP
    The following CSS selectors are used with
    the expected default behavior in the XHTML file:
    .sp
    \fI.ul\fP for underline,
    .br
    \fI.bd\fP for bold,
    .br
    \fI.it\fP for italic,
    .br
    \fI.st\fP for strikeout,
    .br
    \fI.lu\fP for strikeout combined with underline.
    .LP
    In addition you may use
    .sp
    \fI.ev\fP to affect even numbered lines and
    .br
    \fI.od\fP to affect odd numbered lines.
    .RE
    .IP
    Attributes faint, reverse and blink are implemented as \fIstyle\fP attributes
    setting color properties.
    All colors are specified as RGB percentages
    in order to support displays with 10 bits per RGB.
    .IP
    The name of the file will be
    .NS
    \fBxterm.\fIyyyy\fB\.\fIMM\fB\.\fIdd\fB.\fIhh\fB.\fImm\fB.\fIss\fR\.xhtml
    .NE
    .IP
    where
    .IR yyyy ,
    .IR MM ,
    .IR dd ,
    .IR hh ,
    .I mm
    and
    .I ss
    are the year, month, day, hour, minute and second
    when the screen dump was performed
    (the file is created in the directory
    \fI\*n\fP is started in, or the home directory for a login \fI\*n\fP).
    .IP
    The \fBdump-html\fP action can also be triggered using the Media Copy
    control sequence CSI 1 0 i, for example from a shell script with
    .NS
    printf \*(AQ\\033[10i\*(AQ
    .NE
    .sp
    Only the UTF-8 encoding is supported.
    .TP
    .B SVG Screen Dump\fP (resource \fBdump-svg\fP)
    Available only when compiled with screen dump support.
    Invokes the \fBdump-svg\fP action.
    This creates a Scalable Vector Graphics (SVG) file matching
    the contents of the current screen, including the border,
    internal border, colors and most attributes: bold, italic,
    underline, double underline, faint, strikeout, reverse;
    blink is rendered as white-on-red.
    The font is whatever your renderer uses for the \fImonospace\fP font-family.
    All colors are specified as RGB percentages
    in order to support displays with 10 bits per RGB.
    .IP
    The name of the file will be
    .NS
    \fBxterm.\fIyyyy\fB\.\fIMM\fB\.\fIdd\fB.\fIhh\fB.\fImm\fB.\fIss\fR\.svg
    .NE
    .IP
    where
    .IR yyyy ,
    .IR MM ,
    .IR dd ,
    .IR hh ,
    .I mm
    and
    .I ss
    are the year, month, day, hour, minute and second
    when the screen dump was performed
    (the file is created in the directory
    \fI\*n\fP is started in, or the home directory for a login \fI\*n\fP).
    .IP
    The \fBdump-svg\fP action can also be triggered using the Media Copy
    control sequence CSI 1 1 i, for example from a shell script with
    .NS
    printf \*(AQ\\033[11i\*(AQ
    .NE
    .sp
    Only the UTF-8 encoding is supported.
    .RE
    .TP
    Modes for setting keyboard style:
    .RS
    .TP
    .B 8-Bit Controls\fP (resource \fB8-bit-control\fP)
    Enabled for VT220 emulation, this controls whether \fI\*n\fP will send
    8-bit control sequences rather than using 7-bit (ASCII) controls,
    e.g., sending a byte in the range 128\(en159 rather than the escape character
    followed by a second byte.
    \fI\*N\fP always interprets both 8-bit and 7-bit control sequences
    (see \fI\*N Control Sequences\fP).
    This corresponds to the \fBeightBitControl\fP resource.
    .TP
    .B Backarrow Key (BS/DEL)\fP (resource \fBbackarrow\ key\fP)
    Modifies the behavior of the backarrow key, making it transmit
    either a backspace (8)
    or delete (127) character.
    This corresponds to the \fBbackarrowKey\fP resource.
    .TP
    .B Alt/NumLock Modifiers\fP (resource \fBnum-lock\fP)
    Controls the treatment of Alt- and NumLock-key modifiers.
    This corresponds to the \fBnumLock\fP resource.
    .TP
    .B Meta Sends Escape\fP (resource \fBmeta-esc\fP)
    Controls whether \fIMeta\fP keys are converted into a two-character
    sequence with the character itself preceded by ESC.
    This corresponds to the \fBmetaSendsEscape\fP resource.
    .TP
    .B Delete is DEL\fP (resource \fBdelete-is-del\fP)
    Controls whether the Delete key on the editing keypad should send DEL (127)
    or the VT220-style Remove escape sequence.
    This corresponds to the \fBdeleteIsDEL\fP resource.
    .TP
    .B Old Function-Keys\fP (resource \fBoldFunctionKeys\fP)
    .TP
    .B HP Function-Keys\fP (resource \fBhpFunctionKeys\fP)
    .TP
    .B SCO Function-Keys\fP (resource \fBscoFunctionKeys\fP)
    .TP
    .B Sun Function-Keys\fP (resource \fBsunFunctionKeys\fP)
    .TP
    .B VT220 Keyboard\fP (resource \fBsunKeyboard\fP)
    These act as a radio-button, selecting one style for the keyboard layout.
    The layout corresponds to more than one resource setting:
    \fBsunKeyboard\fP,
    \fBsunFunctionKeys\fP,
    \fBscoFunctionKeys\fP and
    \fBhpFunctionKeys\fP.
    .RE
    .TP
    Commands for process signalling:
    .RS
    .TP
    .B Send STOP Signal\fP (resource \fBsuspend\fP)
    .TP
    .B Send CONT Signal\fP (resource \fBcontinue\fP)
    .TP
    .B Send INT Signal\fP (resource \fBinterrupt\fP)
    .TP
    .B Send HUP Signal\fP (resource \fBhangup\fP)
    .TP
    .B Send TERM Signal\fP (resource \fBterminate\fP)
    .TP
    .B Send KILL Signal\fP (resource \fBkill\fP)
    These send the SIGTSTP, SIGCONT, SIGINT, SIGHUP, SIGTERM and SIGKILL
    signals respectively, to
    the process group of the process running under \fI\*n\fP (usually the shell).
    The \fBSIGCONT\fP
    function is especially useful if the user has accidentally typed CTRL-Z,
    suspending the process.
    .TP
    .B Quit\fP (resource \fBquit\fP)
    Stop processing X events except to support the \fB-hold\fP option,
    and then send a SIGHUP signal to
    the process group of the process running under \fI\*n\fP (usually the shell).
    .RE
    .PP
    .
    .\" ************************************************************************
    .SS "VT Options"
    .PP
    The \fI\*n\fP \fIvtMenu\fP
    sets various modes in the VT\fIxxx\fP emulation, and is popped up when the
    \*(``control\*('' key and pointer button two
    are pressed in the VT\fIxxx\fP window.
    .TP
    VT\fIxxx\fP Modes:
    .RS
    .
    .TP
    .B Enable Scrollbar\fP (resource \fBscrollbar\fP)
    Enable (or disable) the scrollbar.
    This corresponds to the \fB\-sb\fP option and the \fBscrollBar\fP resource.
    .
    .TP
    .B Enable Jump Scroll\fP (resource \fBjumpscroll\fP)
    Enable (or disable) jump scrolling.
    This corresponds to the \fB\-j\fP option and the \fBjumpScroll\fP resource.
    .
    .TP
    .B Enable Reverse Video\fP (resource \fBreversevideo\fP)
    Enable (or disable) reverse-video.
    This corresponds to the \fB\-rv\fP option and the \fBreverseVideo\fP resource.
    .
    .TP
    .B Enable Auto Wraparound\fP (resource \fBautowrap\fP)
    Enable (or disable) auto-wraparound.
    This corresponds to the \fB\-aw\fP option and the \fBautoWrap\fP resource.
    .
    .TP
    .B Enable Reverse Wraparound\fP (resource \fBreversewrap\fP)
    Enable (or disable) reverse wraparound.
    This corresponds to the \fB\-rw\fP option and the \fBreverseWrap\fP resource.
    .
    .TP
    .B Enable Auto Linefeed\fP (resource \fBautolinefeed\fP)
    Enable (or disable) auto-linefeed.
    This is the VT102 NEL function,
    which causes the emulator to emit a line feed after each carriage return.
    There is no corresponding command-line option or resource setting.
    .
    .TP
    .B Enable Application Cursor Keys\fP (resource \fBappcursor\fP)
    Enable (or disable) application cursor keys.
    This corresponds to the \fBappcursorDefault\fP resource.
    There is no corresponding command-line option.
    .
    .TP
    .B Enable Application Keypad\fP (resource \fBappkeypad\fP)
    Enable (or disable) application keypad keys.
    This corresponds to the \fBappkeypadDefault\fP resource.
    There is no corresponding command-line option.
    .
    .TP
    .B Scroll to Bottom on Key Press\fP (resource \fBscrollkey\fP)
    Enable (or disable) scrolling to the bottom of the scrolling region
    on a keypress.
    This corresponds to the \fB\-sk\fP option and the \fBscrollKey\fP resource.
    .IP
    As a special case, the XON / XOFF keys (control/S and control/Q) are ignored.
    .
    .TP
    .B Scroll to Bottom on Tty Output\fP (resource \fBscrollttyoutput\fP)
    Enable (or disable) scrolling to the bottom of the scrolling region on
    output to the terminal.
    This corresponds to the \fB\-si\fP option and
    the \fBscrollTtyOutput\fP resource.
    .
    .TP
    .B Allow 80/132 Column Switching\fP (resource \fBallow132\fP)
    Enable (or disable) switching between 80 and 132 columns.
    This corresponds to the \fB\-132\fP option and the \fBc132\fP resource.
    .
    .TP
    .B Keep Selection\fP (resource \fBkeepSelection\fP)
    Tell \fI\*n\fP whether to disown the selection when it stops highlighting it,
    e.g., when an application modifies the display so that it no longer matches
    the text which has been highlighted.
    As long as \fI\*n\fP continues to own the selection for a given atom,
    it can provide the corresponding text to other clients which request
    the selection using that atom.
    .IP
    This corresponds to the \fBkeepSelection\fP resource.
    There is no corresponding command-line option.
    .IP
    Telling \fI\*n\fP to not disown the selection
    does not prevent other applications from taking ownership of the selection.
    When that happens, \fI\*n\fP receives notification that this has happened,
    and removes its highlighting.
    .IP
    See \fBSELECT/PASTE\fP for more information.
    .
    .TP
    .B Select to Clipboard\fP (resource \fBselectToClipboard\fP)
    Tell \fI\*n\fP whether to use the \fBPRIMARY\fP or \fBCLIPBOARD\fP
    for \fBSELECT\fP tokens in the \fBtranslations\fP resource which
    maps keyboard and mouse actions to select/paste actions.
    .IP
    This corresponds to the \fBselectToClipboard\fP resource.
    There is no corresponding command-line option.
    .IP
    The \fBkeepSelection\fP resource setting applies
    to \fBCLIPBOARD\fP selections just as it does for \fBPRIMARY\fP selections.
    However some window managers treat the clipboard specially.
    For instance, XQuartz's synchronization between the OSX \fIpasteboard\fP
    and the X11 \fIclipboard\fP causes applications
    to lose the selection ownership
    for that atom when a selection is copied to the clipboard.
    .IP
    See \fBSELECT/PASTE\fP for more information.
    .
    .TP
    .B Enable Visual Bell\fP (resource \fBvisualbell\fP)
    Enable (or disable) visible bell (i.e., flashing) instead of an audible bell.
    This corresponds to the \fB\-vb\fP option and the \fBvisualBell\fP resource.
    .
    .TP
    .B Enable Bell Urgency\fP (resource \fBbellIsUrgent\fP)
    Enable (or disable) Urgency window manager hint when Control-G is received.
    This corresponds to the \fBbellIsUrgent\fP resource.
    .
    .TP
    .B Enable Pop on Bell\fP (resource \fBpoponbell\fP)
    Enable (or disable) raising of the window when Control-G is received.
    This corresponds to the \fB\-pop\fP option and the \fBpopOnBell\fP resource.
    .
    .TP
    .B Enable Blinking Cursor\fP (resource \fBcursorblink\fP)
    Enable (or disable) the blinking-cursor feature.
    This corresponds to the \fB\-bc\fP option and the \fBcursorBlink\fP resource.
    There are also escape sequences
    (see \fI\*N Control Sequences\fP):
    .RS
    .bP
    If the \fBcursorBlinkXOR\fP resource is set,
    the menu entry and the escape sequence states will be XOR'd:
    if both are enabled, the cursor will not blink,
    if only one is enabled, the cursor will blink.
    .bP
    If the \fBcursorBlinkXOR\fP is not set;
    if either the menu entry or the escape sequence states are set,
    the cursor will blink.
    .RE
    .IP
    In either case, the checkbox for the menu shows the state of the
    \fBcursorBlink\fP resource,
    which may not correspond to what the cursor is actually doing.
    .
    .TP
    .B Enable Alternate Screen Switching\fP (resource \fBtiteInhibit\fP)
    Enable (or disable) switching between the normal and alternate screens.
    This corresponds to the \fBtiteInhibit\fP resource.
    There is no corresponding command-line option.
    .
    .TP
    .B Enable Active Icon\fP (resource \fBactiveicon\fP)
    Enable (or disable) the active-icon feature.
    This corresponds to the \fB\-ai\fP option and the \fBactiveIcon\fP resource.
    .
    .TP
    .B Sixel Scrolling\fP (resource \fBsixelScrolling\fP)
    When enabled,
    sixel graphics are positioned at the current text cursor location, scroll
    the image vertically if larger than the screen, and leave the text cursor
    at the start of the next complete line after the image when returning to text
    mode (this is the default).
    When disabled,
    sixel graphics are positioned at the upper left of the screen, are
    cropped to fit the screen, and do not affect the text cursor location.
    This corresponds to the \fBsixelScrolling\fP resource.
    There is no corresponding command-line option.
    .
    .TP
    .B Private Color Registers\fP (resource \fBprivateColorRegisters\fP)
    If \fI\*n\fR is configured to support ReGIS graphics,
    this controls whether a private color palette can be used.
    .IP
    When enabled,
    each graphic image uses a separate set of color registers, so that it
    essentially has a private palette (this is the default).
    If it is not set,
    all graphics images share a common set of registers which is how sixel and
    ReGIS graphics worked on actual hardware.
    The default is likely a more
    useful mode on modern TrueColor hardware.
    .IP
    This corresponds to the \fBprivateColorRegisters\fP resource.
    There is no corresponding command-line option.
    .RE
    .
    .TP
    VT\fIxxx\fP Commands:
    .RS
    .TP
    .B Do Soft Reset\fP (resource \fBsoftreset\fP)
    Reset scroll regions.
    This can be convenient when some program has left the scroll regions
    set incorrectly (often a problem when using VMS or TOPS-20).
    This corresponds to the VT220 DECSTR control sequence.
    .
    .TP
    .B Do Full Reset\fP (resource \fBhardreset\fP)
    The full reset entry will clear the screen, reset tabs to every
    eight columns, and reset the terminal modes (such as wrap and smooth scroll)
    to their initial states just after
    \fI\*n\fP has finished processing the command line options.
    This corresponds to the VT102 RIS control sequence,
    with a few obvious differences.
    For example, your session is not disconnected as a real VT102 would do.
    .
    .TP
    .B Reset and Clear Saved Lines\fP (resource \fBclearsavedlines\fP)
    Perform a full reset,
    and also clear the saved lines.
    .RE
    .
    .TP
    Commands for setting the current screen:
    .RS
    .
    .TP
    .B Show Tek Window\fP (resource \fBtekshow\fP)
    When enabled,
    pops the Tektronix 4014 window up (makes it visible).
    When disabled,
    hides the Tektronix 4014 window.
    .
    .TP
    .B Switch to Tek Mode\fP (resource \fBtekmode\fP)
    When enabled,
    pops the Tektronix 4014 window up if it is not already visible,
    and switches the input stream to that window.
    When disabled,
    hides the Tektronix 4014 window and
    switches input back to the VT\fIxxx\fP window.
    .
    .TP
    .B Hide VT Window\fP (resource \fBvthide\fP)
    When enabled,
    hides the VT\fIxxx\fP window,
    shows the Tektronix 4014 window if
    it was not already visible
    and switches the input stream to that window.
    When disabled,
    shows the VT\fIxxx\fP window,
    and switches the input stream to that window.
    .
    .TP
    .B Show Alternate Screen\fP (resource \fBaltscreen\fP)
    When enabled,
    shows the alternate screen.
    When disabled,
    shows the normal screen.
    Note that the normal screen may have saved lines;
    the alternate screen does not.
    .RE
    .PP
    .
    .SS "VT Fonts"
    .PP
    The \fI\*n\fP \fIfontMenu\fP pops up when
    the \*(``control\*('' key and pointer button three are pressed in a window.
    It sets the font used in the VT\fIxxx\fP window,
    or modifies the way the font is specified or displayed.
    There are several sections.
    .PP
    The first section allows you to select the font from a set of alternatives:
    .RS
    .TP
    .B Default\fP (resource \fBfontdefault\fP)
    Set the font to the default, i.e., that given by the \fB*VT100.font\fP resource.
    .TP
    .B Unreadable\fP (resource \fBfont1\fP)
    Set the font to that given by the \fB*VT100.font1\fP resource.
    .TP
    .B Tiny\fP (resource \fBfont2\fP)
    Set the font to that given by the \fB*VT100.font2\fP resource.
    .TP
    .B Small\fP (resource \fBfont3\fP)
    Set the font to that given by the \fB*VT100.font3\fP resource.
    .TP
    .B Medium\fP (resource \fBfont4\fP)
    Set the font to that given by the \fB*VT100.font4\fP resource.
    .TP
    .B Large\fP (resource \fBfont5\fP)
    Set the font to that given by the \fB*VT100.font5\fP resource.
    .TP
    .B Huge\fP (resource \fBfont6\fP)
    Set the font to that given by the \fB*VT100.font6\fP resource.
    .TP
    .B Escape Sequence\fP (resource \fBfontescape\fP)
    This allows you to set the font last specified by the Set
    Font escape sequence (see \fI\*N Control Sequences\fP).
    .TP
    .B Selection\fP (resource \fBfontsel\fP)
    This allows you to set the font specified
    the current selection as a font name (if the \fBPRIMARY\fP selection is owned).
    .RE
    .PP
    The second section allows you to modify the way it is displayed:
    .RS
    .TP
    .B Bold Fonts\fP (resource \fBallow-bold-fonts\fP)
    This is normally checked (enabled).
    When unchecked, \fI\*n\fP will not use bold fonts.
    The setting corresponds to the \fBallowBoldFonts\fP resource.
    .TP
    .B Line-Drawing Characters\fP (resource \fBfont-linedrawing\fP)
    When set, tells \fI\*n\fP to draw its own line-drawing characters.
    Otherwise it relies on the font containing these.
    Compare to the \fBforceBoxChars\fP resource.
    .TP
    .B Packed Font\fP (resource \fBfont-packed\fP)
    When set, tells \fI\*n\fP to use the minimum glyph-width from a font
    when displaying characters.
    Use the maximum width (unchecked) to help display proportional fonts.
    Compare to the \fBforcePackedFont\fP resource.
    .TP
    .B Doublesized Characters\fP (resource \fBfont-doublesize\fP)
    When set, \fI\*n\fP may ask the font server to produce scaled versions
    of the normal font, for VT102 double-size characters.
    .RE
    .PP
    The third section allows you to modify the way it is specified:
    .RS
    .TP
    .B TrueType Fonts\fP (resource \fBrender-font\fP)
    If the \fBrenderFont\fP and corresponding resources were set,
    this is a further control whether \fI\*n\fP will actually use the
    Xft library calls to obtain a font.
    .TP
    .B UTF-8 Encoding\fP (resource \fButf8-mode\fP)
    This controls whether \fI\*n\fP uses UTF-8 encoding of input/output.
    It is useful for temporarily switching \fI\*n\fP to display
    text from an application which does not follow the locale settings.
    It corresponds to the \fButf8\fP resource.
    .TP
    .B UTF-8 Fonts\fP (resource \fButf8-fonts\fP)
    This controls whether \fI\*n\fP uses UTF-8 fonts for display.
    It is useful for temporarily switching \fI\*n\fP to display
    text from an application which does not follow the locale settings.
    It combines the \fButf8\fP and \fButf8Fonts\fP resources,
    subject to the \fBlocale\fP resource.
    .TP
    .B UTF-8 Titles\fP (resource \fButf8-title\fP)
    This controls whether \fI\*n\fP accepts UTF-8 encoding for
    title control sequences.
    It corresponds to the \fButf8Fonts\fP resource.
    .IP
    Initially the checkmark is set according to both the \fButf8\fP
    and \fButf8Fonts\fP resource values.
    If the latter is set to \*(``always\*('', the checkmark is disabled.
    Likewise, if there are no fonts given in the \fButf8Fonts\fP
    subresources, then the checkmark also is disabled.
    .IP
    The standard \fB__default_class__\fP app-defaults file defines
    both sets of fonts,
    while the \fBU__default_class__\fP app-defaults file defines only one set.
    Assuming the standard app-defaults files,
    this command will launch \fI\*n\fP able to switch between UTF-8
    and ISO-8859-1 encoded fonts:
    .NS
    u\*n \-class __default_class__
    .NE
    .RE
    .PP
    The fourth section allows you to enable or disable special operations
    which can be controlled by writing escape sequences to the terminal.
    These are disabled if the SendEvents feature is enabled:
    .RS
    .TP
    .B Allow Color Ops\fP (resource \fBallow-font-ops\fP)
    This corresponds to the \fBallowColorOps\fP resource.
    Enable or disable control sequences that set/query the colors.
    .TP
    .B Allow Font Ops\fP (resource \fBallow-font-ops\fP)
    This corresponds to the \fBallowFontOps\fP resource.
    Enable or disable control sequences that set/query the font.
    .TP
    .B Allow Mouse Ops\fP (resource \fBallow-mouse-ops\fP)
    Enable or disable control sequences that cause the terminal to
    send escape sequences on pointer-clicks and movement.
    This corresponds to the \fBallowMouseOps\fP resource.
    .TP
    .B Allow Tcap Ops\fP (resource \fBallow-tcap-ops\fP)
    Enable or disable control sequences that query the terminal's
    notion of its function-key strings, as termcap or terminfo capabilities.
    This corresponds to the \fBallowTcapOps\fP resource.
    .TP
    .B Allow Title Ops\fP (resource \fBallow-title-ops\fP)
    Enable or disable control sequences that modify the window title or icon name.
    This corresponds to the \fBallowTitleOps\fP resource.
    .TP
    .B Allow Window Ops\fP (resource \fBallow-window-ops\fP)
    Enable or disable extended window control sequences (as used in dtterm).
    This corresponds to the \fBallowWindowOps\fP resource.
    .RE
    .
    .SS "Tek Options"
    .PP
    The \fI\*n\fP \fItekMenu\fP sets various modes in the Tektronix emulation,
    and is popped up when the
    \*(``control\*('' key and pointer button two
    are pressed in the Tektronix window.
    The current font size is checked in the modes section of the menu.
    .RS
    .TP
    .B Large Characters\fP (resource \fBtektextlarge\fP)
    .TP
    .B \ Size Characters\fP (resource \fBtektext2\fP)
    .TP
    .B \ Size Characters\fP (resource \fBtektext3\fP)
    .TP
    .B Small Characters\fP (resource \fBtektextsmall\fP)
    .RE
    .PP
    Commands:
    .RS
    .TP
    .B PAGE\fP (resource \fBtekpage\fP)
    Simulates the Tektronix \*(``PAGE\*('' button by
    .RS
    .bP
    clearing the window,
    .bP
    cancelling the graphics input-mode, and
    .bP
    moving the cursor to the \fIhome\fP position.
    .RE
    .TP
    .B RESET\fP (resource \fBtekreset\fP)
    Unlike the similarly-named Tektronix \*(``RESET\*('' button,
    this does everything that \fBPAGE\fP does
    as well as resetting the line-type and font-size to their default values.
    .TP
    .B COPY\fP (resource \fBtekcopy\fP)
    Simulates the Tektronix \*(``COPY\*('' button
    (which makes a hard-copy of the screen)
    by writing the information to a text file.
    .RE
    .PP
    Windows:
    .RS
    .TP
    .B Show VT Window\fP (resource \fBvtshow\fP)
    .TP
    .B Switch to VT Mode\fP (resource \fBvtmode\fP)
    .TP
    .B Hide Tek Window\fP (resource \fBtekhide\fP)
    .RE
    .
    .
    .SH SECURITY
    .
    .PP
    X environments differ in their security consciousness.
    .bP
    Most servers,
    run under \fIxdm\fP,
    are capable of using a \*(``magic cookie\*('' authorization
    scheme that can provide a reasonable level of security for many people.
    If your server is only using a host-based mechanism to control access to
    the server (see \fBxhost(__mansuffix__)\fP),
    then if you enable access for a host and
    other users are also permitted to run clients on that same host,
    it is possible that someone can run an application which uses the
    basic services of the X protocol to snoop on your activities,
    potentially capturing a transcript of everything you type at the keyboard.
    .bP
    Any process which has access to your X display can manipulate it
    in ways that you might not anticipate,
    even redirecting your keyboard to itself
    and sending events to your application's windows.
    This is true even with the \*(``magic cookie\*('' authorization scheme.
    While the \fBallowSendEvents\fP provides some protection against
    rogue applications tampering with your programs,
    guarding against a snooper is harder.
    .
    .bP
    The X input extension for instance allows an application to bypass
    all of the other (limited) authorization and security features,
    including the GrabKeyboard protocol.
    .
    .bP
    The possibility of an application spying on your keystrokes
    is of particular concern when you want to type in a password
    or other sensitive data.
    The best solution to this problem is to use a better
    authorization mechanism than is provided by X.
    .PP
    Subject to all of these caveats,
    a simple mechanism exists for protecting keyboard input in \fI\*n\fP.
    .
    .PP
    The \fI\*n\fP menu (see \fBMENUS\fP above) contains a \fBSecure Keyboard\fP
    entry which, when enabled,
    attempts to ensure that all keyboard input is directed
    \fIonly\fP to \fI\*n\fP (using the GrabKeyboard protocol request).
    When an application prompts you for a password
    (or other sensitive data), you can enable \fBSecure Keyboard\fP using the
    menu, type in the data, and then disable \fBSecure Keyboard\fP using
    the menu again.
    .bP
    This ensures that you know which window is accepting your keystrokes.
    .bP
    It cannot ensure that there are no processes which have access to your
    X display that might be observing the keystrokes as well.
    .
    .PP
    Only one X client at a time can grab the keyboard,
    so when you attempt to enable \fBSecure Keyboard\fP it may fail.
    In this case, the bell will sound.
    If the \fBSecure Keyboard\fP succeeds,
    the foreground and background colors will be exchanged (as if you
    selected the \fBEnable Reverse Video\fP entry in the \fBModes\fP menu);
    they will be exchanged again when you exit secure mode.
    If the colors
    do \fInot\fP switch, then
    you should be \fIvery\fP suspicious that you are being spoofed.
    If the application you are running displays a prompt before asking for
    the password, it is safest to enter secure mode \fIbefore\fP the
    prompt gets displayed, and to make sure that the prompt gets displayed
    correctly (in the new colors), to minimize the probability of
    spoofing.
    You can also bring up the menu again and make sure that a check
    mark appears next to the entry.
    .
    .PP
    \fBSecure Keyboard\fP mode will be disabled automatically if your \fI\*n\fP
    window becomes iconified (or otherwise unmapped), or if you start up
    a reparenting window manager (that places a title bar or other decoration
    around the window) while in \fBSecure Keyboard\fP mode.
    (This is a
    feature of the X protocol not easily overcome.)  When this happens,
    the foreground and background colors will be switched back and the bell
    will sound in warning.
    .
    .
    .SH "CHARACTER CLASSES"
    Clicking the left pointer button twice in rapid succession
    (double-clicking) causes all characters of the same class
    (e.g., letters, white space, punctuation) to be selected as a \*(``word\*(''.
    Since different people have different preferences for what should
    be selected (for example, should filenames be selected as a whole or only
    the separate subnames), the default mapping can be overridden through the use
    of the \fBcharClass\fP (class \fICharClass\fP) resource.
    .
    .PP
    This resource is a
    series of comma-separated
    \fIrange\fP:\fIvalue\fP pairs.
    .bP
    The
    \fIrange\fP is either a single number or \fIlow\fP-\fIhigh\fP in the range of 0
    to 65535, corresponding to the code for the character or characters to be
    set.
    .bP
    The \fIvalue\fP is arbitrary.
    For example, the default table uses the
    character number of the first character occurring in the set.
    When not in
    UTF-8 mode, only the first 256 entries of this table will be used.
    .
    .PP
    The default table starts as follows \-
    .NS
    static int charClass[256] = {
    /\(** NUL  SOH  STX  ETX  EOT  ENQ  ACK  BEL */
        32,   1,   1,   1,   1,   1,   1,   1,
    /\(**  BS   HT   NL   VT   NP   CR   SO   SI */
         1,  32,   1,   1,   1,   1,   1,   1,
    /\(** DLE  DC1  DC2  DC3  DC4  NAK  SYN  ETB */
         1,   1,   1,   1,   1,   1,   1,   1,
    /\(** CAN   EM  SUB  ESC   FS   GS   RS   US */
         1,   1,   1,   1,   1,   1,   1,   1,
    /\(**  SP    !    "    #    $    %    &    \*(AQ */
    .\"   " <- for emacs autocolor to work well :-)
        32,  33,  34,  35,  36,  37,  38,  39,
    /\(**   (    )    *    +    ,    \-    .    / */
        40,  41,  42,  43,  44,  45,  46,  47,
    /\(**   0    1    2    3    4    5    6    7 */
        48,  48,  48,  48,  48,  48,  48,  48,
    /\(**   8    9    :    ;    <    =    >    ? */
        48,  48,  58,  59,  60,  61,  62,  63,
    /\(**   @    A    B    C    D    E    F    G */
        64,  48,  48,  48,  48,  48,  48,  48,
    /\(**   H    I    J    K    L    M    N    O */
        48,  48,  48,  48,  48,  48,  48,  48,
    /\(**   P    Q    R    S    T    U    V    W */
        48,  48,  48,  48,  48,  48,  48,  48,
    /\(**   X    Y    Z    [    \\    ]    ^    _ */
        48,  48,  48,  91,  92,  93,  94,  48,
    /\(**   `    a    b    c    d    e    f    g */
        96,  48,  48,  48,  48,  48,  48,  48,
    /\(**   h    i    j    k    l    m    n    o */
        48,  48,  48,  48,  48,  48,  48,  48,
    /\(**   p    q    r    s    t    u    v    w */
        48,  48,  48,  48,  48,  48,  48,  48,
    /\(**   x    y    z    {    |    }    ~  DEL */
        48,  48,  48, 123, 124, 125, 126,   1,
    /\(** x80  x81  x82  x83  IND  NEL  SSA  ESA */
         1,   1,   1,   1,   1,   1,   1,   1,
    /\(** HTS  HTJ  VTS  PLD  PLU   RI  SS2  SS3 */
         1,   1,   1,   1,   1,   1,   1,   1,
    /\(** DCS  PU1  PU2  STS  CCH   MW  SPA  EPA */
         1,   1,   1,   1,   1,   1,   1,   1,
    /\(** x98  x99  x9A  CSI   ST  OSC   PM  APC */
         1,   1,   1,   1,   1,   1,   1,   1,
    /\(**   \-    i   c/    L   ox   Y\-    |   So */
       160, 161, 162, 163, 164, 165, 166, 167,
    /\(**  ..   c0   ip   <<    _        R0    \- */
       168, 169, 170, 171, 172, 173, 174, 175,
    /\(**   o   +\-    2    3    \*(AQ    u   q|    . */
       176, 177, 178, 179, 180, 181, 182, 183,
    /\(**   ,    1    2   >>  1/4  1/2  3/4    ? */
       184, 185, 186, 187, 188, 189, 190, 191,
    /\(**  A`   A\*(AQ   A^   A~   A:   Ao   AE   C, */
        48,  48,  48,  48,  48,  48,  48,  48,
    /\(**  E`   E\*(AQ   E^   E:   I`   I\*(AQ   I^   I: */
        48,  48,  48,  48,  48,  48,  48,  48,
    /\(**  D\-   N~   O`   O\*(AQ   O^   O~   O:    X */
        48,  48,  48,  48,  48,  48,  48, 215,
    /\(**  O/   U`   U\*(AQ   U^   U:   Y\*(AQ    P    B */
        48,  48,  48,  48,  48,  48,  48,  48,
    /\(**  a`   a\*(AQ   a^   a~   a:   ao   ae   c, */
        48,  48,  48,  48,  48,  48,  48,  48,
    /\(**  e`   e\*(AQ   e^   e:   i`   i\*(AQ   i^   i: */
        48,  48,  48,  48,  48,  48,  48,  48,
    /\(**   d   n~   o`   o\*(AQ   o^   o~   o:   \-: */
        48,  48,  48,  48,  48,  48,  48, 247,
    /\(**  o/   u`   u\*(AQ   u^   u:   y\*(AQ    P   y: */
        48,  48,  48,  48,  48,  48,  48,  48};
    .NE
    .IP
    For example, the string \*(``33:48,37:48,45\-47:48,38:48\*('' indicates that the
    exclamation mark, percent sign, dash, period, slash, and ampersand characters
    should be treated the same way as characters and numbers.
    This is useful
    for cutting and pasting electronic mailing addresses and filenames.
    .
    .
    .SH KEY BINDINGS
    .PP
    It is possible to rebind keys (or sequences of keys) to arbitrary strings
    for input, by changing the \fBtranslations\fP resources
    for the vt100 or tek4014 widgets.
    Changing the \fBtranslations\fP resource
    for events other than key and button events is not expected,
    and will cause unpredictable behavior.
    .SS Actions
    The following
    actions are provided for use within the \fIvt100\fP or \fItek4014\fP
    \fBtranslations\fP resources:
    .TP 8
    .B "allow-bold-fonts(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBallowBoldFonts\fP resource
    and is also invoked by the \fBallow-bold-fonts\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "allow-color-ops(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBallowColorOps\fP resource and is also
    invoked by the \fBallow-color-ops\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "allow-font-ops(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBallowFontOps\fP resource and is also
    invoked by the \fBallow-font-ops\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "allow-mouse-ops(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBallowMousepOps\fP resource
    and is also invoked by the \fBallow-mouse-ops\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "allow-send-events(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBallowSendEvents\fP resource
    and is also invoked by the \fBallowsends\fP entry in \fImainMenu\fP.
    .TP 8
    .B "allow-tcap-ops(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBallowTcapOps\fP resource
    and is also invoked by the \fBallow-tcap-ops\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "allow-title-ops(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBallowTitleOps\fP resource
    and is also invoked by the \fBallow-title-ops\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "allow-window-ops(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBallowWindowOps\fP resource
    and is also invoked by the \fBallow-window-ops\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "alt-sends-escape()"
    This action toggles the state of the \fBaltSendsEscape\fP resource.
    .TP 8
    .B "bell([\fIpercent\fP])"
    This action rings the keyboard bell at the specified percentage
    above or below the base volume.
    .TP 8
    .B "clear-saved-lines()"
    This action does \fBhard-reset()\fP and also clears the history
    of lines saved off the top of the screen.
    It is also invoked from the \fBclearsavedlines\fP entry in \fIvtMenu\fP.
    The effect is identical to a hardware reset (RIS) control sequence.
    .TP 8
    .B "copy-selection(\fIdestname\fP [, \&...\&])"
    This action puts the currently selected text into all of the selections or
    cutbuffers specified by \fIdestname\fP.
    Unlike \fBselect-end\fP, it does not send a mouse position or otherwise
    modify the internal selection state.
    .TP 8
    .B "create-menu(\fIm/v/f/t\fP)"
    This action creates one of the menus used by \fI\*n\fP,
    if it has not been previously created.
    The parameter values are the menu names:
    \fImainMenu\fP, \fIvtMenu\fP, \fIfontMenu\fP, \fItekMenu\fP, respectively.
    .TP 8
    .B "dabbrev-expand()"
    Expands the word before cursor by searching in the preceding text on the
    screen and in the scrollback buffer for words starting with that
    abbreviation.
    Repeating \fBdabbrev-expand()\fP several times in sequence searches for an
    alternative expansion by looking farther back.
    Lack of more matches is signaled by a bell.
    Attempts to expand an empty word
    (i.e., when cursor is preceded by a space) yield successively all previous
    words.
    Consecutive identical expansions are ignored.
    The word here is defined as a sequence of non-whitespace characters.
    This feature partially emulates the behavior
    of \*(``dynamic abbreviation\*('' expansion in Emacs (bound there to M\-/).
    Here is a resource setting for \fI\*n\fP which will do the same thing:
    .NS
    *VT100*translations:    #override \\n\\\&
            Meta  /:\fBdabbrev\-expand\fP()
    .NE
    .TP 8
    .B "deiconify()"
    Changes the window state back to normal, if it was iconified.
    .TP 8
    .B "delete-is-del()"
    This action toggles the state of the \fBdeleteIsDEL\fP resource.
    .TP 8
    .B "dired-button()"
    Handles a button event (other than press and release)
    by echoing the event's position
    (i.e., character line and column) in the following format:
    .NS
    ^X ESC G  
    .NE
    .TP 8
    .B "dump-html()"
    Invokes the \fBXHTML Screen Dump\fP feature.
    .TP 8
    .B "dump-svg()"
    Invokes the \fBSVG Screen Dump\fP feature.
    .TP 8
    .B "exec-formatted(\fIformat\fP, \fIsourcename\fP [, \&...\&])"
    Execute an external command,
    using the current selection for part of the command's parameters.
    The first parameter, \fIformat\fP gives the basic command.
    Succeeding parameters specify the selection source as in \fBinsert-selection\fP.
    .IP
    The \fIformat\fP parameter allows these substitutions:
    .RS
    .TP 5
    %%
    inserts a "%".
    .TP 5
    %P
    the screen-position at the beginning of the highlighted region,
    as a semicolon-separated pair of integers using the
    values that the CUP control sequence would use.
    .TP 5
    %p
    the screen-position after the beginning of the highlighted region,
    using the same convention as \*(``%P\*(''.
    .TP 5
    %S
    the length of the string that \*(``%s\*('' would insert.
    .TP 5
    %s
    the content of the selection, unmodified.
    .TP 5
    %T
    the length of the string that \*(``%t\*('' would insert.
    .TP 5
    %t
    the selection, trimmed of leading/trailing whitespace.
    Embedded spaces (and newlines) are copied as is.
    .TP 5
    %R
    the length of the string that \*(``%r\*('' would insert.
    .TP 5
    %r
    the selection, trimmed of trailing whitespace.
    .TP 5
    %V
    the video attributes at the beginning of the highlighted region,
    as a semicolon-separated list of integers using the
    values that the SGR control sequence would use.
    .TP 5
    %v
    the video attributes after the end of the highlighted region,
    using the same convention as \*(``%V\*(''.
    .RE
    .IP
    After constructing the command-string,
    \fI\*n\fP forks a subprocess and executes the command,
    which completes independently of \fI\*n\fP.
    .IP
    For example, this translation would invoke a new \fI\*n\fP process
    to view a file whose name is selected while holding the shift key down.
    The new process is started when the mouse button is released:
    .NS
    *VT100*translations: #override Shift \\\&
        :\fBexec\-formatted\fP("xterm \-e view \*(AQ%t\*(AQ", \fBSELECT\fP)
    .NE
    .TP 8
    .B "exec-selectable(\fIformat\fP, \fIonClicks\fP)"
    Execute an external command,
    using data copied from the screen for part of the command's parameters.
    The first parameter, \fIformat\fP gives
    the basic command as in \fBexec-formatted\fP.
    The second parameter specifies the method for copying
    the data as in the \fBon2Clicks\fP resource.
    .TP 8
    .B "fullscreen(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBfullscreen\fP resource.
    .TP 8
    .B "iconify()"
    Iconifies the window.
    .TP 8
    .B "hard-reset()"
    This action resets the scrolling region, tabs, window size, and cursor keys
    and clears the screen.
    It is also invoked from the \fBhardreset\fP
    entry in \fIvtMenu\fP.
    .TP 8
    .B "ignore()"
    This action ignores the event but checks for special pointer position
    escape sequences.
    .TP 8
    .B "insert()"
    This action inserts the character or string associated with
    the key that was pressed.
    .TP 8
    .B "insert-eight-bit()"
    This action inserts an eight-bit (Meta) version of the character or string
    associated with the key that was pressed.
    Only single-byte values are treated specially.
    The exact action depends on the value of
    the \fBaltSendsEscape\fP and
    the \fBmetaSendsEscape\fP and
    the \fBeightBitInput\fP resources.
    The \fBmetaSendsEscape\fP resource is tested first.
    See the \fBeightBitInput\fP resource for a full discussion.
    .IP
    The term \*(``eight-bit\*('' is misleading:
    \fI\*n\fP checks if the key is in the range 128 to 255
    (the eighth bit is set).
    If the value is in that range,
    depending on the resource values,
    \fI\*n\fP may then do one of the following:
    .RS
    .bP
    add 128 to the value, setting its eighth bit,
    .bP
    send an ESC byte before the key, or
    .bP
    send the key unaltered.
    .RE
    .TP 8
    .B "insert-formatted(\fIformat\fP, \fIsourcename\fP [, \&...\&])"
    Insert the current selection or data related to it, formatted.
    The first parameter, \fIformat\fP gives the template for the data
    as in \fBexec-formatted\fP.
    Succeeding parameters specify the selection source as in \fBinsert-selection\fP.
    .TP 8
    .B "insert-selectable(\fIformat\fP, \fIonClicks\fP)"
    Insert data copied from the screen, formatted.
    The first parameter, \fIformat\fP gives the template for the data
    as in \fBexec-formatted\fP.
    The second parameter specifies the method for copying
    the data as in the \fBon2Clicks\fP resource.
    .TP 8
    .B "insert-selection(\fIsourcename\fP [, \&...\&])"
    This action inserts the string found in the selection or cutbuffer indicated
    by \fIsourcename\fP.
    Sources are checked in the order given (case is
    significant) until one is found.
    Commonly-used selections include:
    \fBPRIMARY\fP, \fBSECONDARY\fP, and \fBCLIPBOARD\fP.
    Cut buffers are
    typically named \fBCUT_BUFFER0\fP through \fBCUT_BUFFER7\fP.
    .TP 8
    .B "insert-seven-bit()"
    This action is a synonym for \fBinsert()\fP.
    The term \*(``seven-bit\*('' is misleading:
    it only implies that \fI\*n\fP does not try to add 128 to the key's value
    as in \fBinsert-eight-bit()\fP.
    .TP 8
    .B "interpret(\fIcontrol-sequence\fP)"
    Interpret the given control sequence locally, i.e., without passing it to
    the host.
    This works by inserting the control sequence at the front
    of the input buffer.
    Use \*(``\\\*('' to escape octal digits in the string.
    Xt does not allow you to put a null character
    (i.e., \*(``\\000\*('') in the string.
    .TP 8
    .B "keymap(\fIname\fP)"
    This action dynamically defines a new translation table whose resource
    name is \fIname\fP with the suffix \*(``\fIKeymap\fP\*(''
    (i.e., \fIname\fP\fBKeymap\fP, where case is significant).
    The name \fINone\fP restores the original translation table.
    .TP 8
    .B "larger-vt-font()"
    Set the font to the next larger one, based on the font dimensions.
    See also \fBset-vt-font()\fP.
    .TP 8
    .B "load-vt-fonts(\fIname\fP[,\fIclass\fP])"
    Load fontnames from the given subresource name and class.
    That is, load the \*(``*VT100.\fIname\fP.font\*('',
    resource as \*(``*VT100.font\*('' etc.
    If no name is given, the original set of fontnames is restored.
    .IP
    Unlike \fBset-vt-font()\fR, this does not affect the escape- and select-fonts,
    since those are not based on resource values.
    It does affect the fonts loosely organized under the \*(``Default\*('' menu
    entry, including \fBfont\fP, \fBboldFont\fP, \fBwideFont\fP
    and \fBwideBoldFont\fP.
    .TP 8
    .B "maximize()"
    Resizes the window to fill the screen.
    .TP 8
    .B "meta-sends-escape()"
    This action toggles the state of the \fBmetaSendsEscape\fP resource.
    .TP 8
    .B "popup-menu(\fImenuname\fP)"
    This action displays the specified popup menu.
    Valid names (case is
    significant) include:  \fImainMenu\fP, \fIvtMenu\fP, \fIfontMenu\fP,
    and \fItekMenu\fP.
    .TP 8
    .B "print(\fIprinter-flags\fP)"
    This action prints the window.
    It is also invoked by the \fBprint\fP entry in \fImainMenu\fP.
    .IP
    The action accepts optional parameters, which temporarily override
    resource settings.
    The parameter values are matched ignoring case:
    .RS
    .TP 5
    noFormFeed
    no form feed will be sent at the end of the last line printed
    (i.e., \fBprinterFormFeed\fP is \*(``false\*('').
    .TP 5
    FormFeed
    a form feed will be sent at the end of the last line printed
    (i.e., \fBprinterFormFeed\fP is \*(``true\*('').
    .TP 5
    noNewLine
    no newline will be sent at the end of the last line printed,
    and wrapped lines will be combined into long lines
    (i.e., \fBprinterNewLine\fP is \*(``false\*('').
    .TP 5
    NewLine
    a newline will be sent at the end of the last line printed,
    and each line will be limited (by adding a newline) to the screen width
    (i.e., \fBprinterNewLine\fP is \*(``true\*('').
    .TP 5
    noAttrs
    the page is printed without attributes
    (i.e., \fBprintAttributes\fP is \*(``0\*('').
    .TP 5
    monoAttrs
    the page is printed with monochrome (vt220) attributes
    (i.e., \fBprintAttributes\fP is \*(``1\*('').
    .TP 5
    colorAttrs
    the page is printed with ANSI color attributes
    (i.e., \fBprintAttributes\fP is \*(``2\*('').
    .RE
    .TP 8
    .B "print-everything(\fIprinter-flags\fP)"
    This action sends the entire text history, in addition to the text
    currently visible, to the program given in the \fBprinterCommand\fP resource.
    It allows the same optional parameters as the \fBprint\fP action.
    With a suitable printer command, the action can be used to load the text
    history in an editor.
    .TP 8
    .B "print-immediate()"
    Sends the text of the current window directly to a file,
    as specified by the
    \fBprintFileImmediate\fP,
    \fBprintModeImmediate\fP and
    \fBprintOptsImmediate\fP
    resources.
    .TP 8
    .B "print-on-error()"
    Toggles a flag telling \fI\*n\fP that if it exits with an X error,
    to send the text of the current window directly to a file,
    as specified by the
    \fBprintFileOnXError\fP,
    \fBprintModeOnXError\fP and
    \fBprintOptsOnXError\fP
    resources.
    .TP 8
    .B "print-redir()"
    This action toggles the \fBprinterControlMode\fR between 0 and 2.
    The corresponding popup menu entry is useful for switching the printer
    off if you happen to change your mind after deciding to print random
    binary files on the terminal.
    .TP 8
    .B "quit()"
    .br
    This action sends a SIGHUP to the subprogram and exits.
    It is also invoked
    by the \fBquit\fP entry in \fImainMenu\fP.
    .TP 8
    .B "readline-button()"
    Supports the optional readline feature by echoing repeated cursor forward
    or backward control sequences on button release event,
    to request that the host application update its notion of the cursor's
    position to match the button event.
    .TP 8
    .B "redraw()"
    This action redraws the window.
    It is also invoked by the \fBredraw\fP entry in \fImainMenu\fP.
    .TP 8
    .B "restore()"
    Restores the window to the size before it was last maximized.
    .TP 8
    .B "scroll-back(\fIcount\fP [,\fIunits\fP [,\fImouse\fP] ])"
    This action scrolls the text window backward so that text that had previously
    scrolled off the top of the screen is now visible.
    .IP
    The \fIcount\fP argument
    indicates the number of \fIunits\fP (which may be \fIpage\fP, \fIhalfpage\fP,
    \fIpixel\fP, or \fIline\fP) by which to scroll.
    If no \fIcount\fP parameter is given, \fI\*n\fP uses the number of lines
    given by the \fBscrollLines\fP resource.
    .IP
    An adjustment can be specified for the \fIpage\fP or \fIhalfpage\fP units
    by appending a \*(``+\*('' or \*(``\-\*(''
    sign followed by a number,
    e.g., \fIpage\-2\fP to specify 2 lines less than a page.
    .IP
    If the second parameter is omitted \*(``lines\*('' is used.
    .IP
    If the third parameter \fImouse\fP is given, the action is ignored when
    mouse reporting is enabled.
    .TP 8
    .B "scroll-forw(\fIcount\fP [,\fIunits\fP [,\fImouse\fP] ])"
    This action is similar to \fBscroll-back\fP except that it scrolls
    in the other direction.
    .TP 8
    .B "secure()"
    This action toggles the \fISecure Keyboard\fP mode
    (see \fBSECURITY\fP), and is invoked from the \fBsecurekbd\fP
    entry in \fImainMenu\fP.
    .TP 8
    .B "scroll-lock(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles internal state which tells
    \fI\*n\fP whether Scroll Lock is active,
    subject to the \fBallowScrollLock\fP resource.
    .TP 8
    .B "scroll-to(\fIcount\fP)"
    Scroll to the given line relative to the beginning of the saved-lines.
    For instance, \*(``\fBscroll-to(0)\fP\*('' would scroll to the beginning.
    Two special nonnumeric parameters are recognized:
    .RS
    .TP 8
    .B scroll-to(begin)
    Scroll to the beginning of the saved lines.
    .TP 8
    .B scroll-to(end)
    Scroll to the end of the saved lines, i.e., to the currently active page.
    .RE
    .TP 8
    .B "select-cursor-end(\fIdestname\fP [, \&...\&])"
    This action is similar to \fBselect-end\fP except that it should be used
    with \fBselect-cursor-start\fP.
    .TP 8
    .B "select-cursor-extend()"
    This action is similar to \fBselect-extend\fP except that it should be used
    with \fBselect-cursor-start\fP.
    .TP 8
    .B "select-cursor-start()"
    This action is similar to \fBselect-start\fP except that it begins the
    selection at the current text cursor position.
    .TP 8
    .B "select-end(\fIdestname\fP [, \&...\&])"
    This action puts the currently selected text into all of the selections or
    cutbuffers specified by \fIdestname\fP.
    It also sends a mouse position and updates the internal selection state
    to reflect the end of the selection process.
    .TP 8
    .B "select-extend()"
    This action tracks the pointer and extends the selection.
    It should only be bound to Motion events.
    .TP 8
    .B "select-set()"
    This action stores text that corresponds to the current selection,
    without affecting the selection mode.
    .TP 8
    .B "select-start()"
    This action begins text selection at the current pointer location.
    See
    the section on \fBPOINTER USAGE\fP for information on making selections.
    .TP 8
    .B "send-signal(\fIsigname\fP)"
    This action sends the signal named by \fIsigname\fP
    to the \fI\*n\fP subprocess (the shell or program specified with
    the \fI\-e\fP command line option).
    It is also invoked by the
    \fBsuspend\fP,
    \fBcontinue\fP,
    \fBinterrupt\fP,
    \fBhangup\fP,
    \fBterminate\fP,
    and
    \fBkill\fP
    entries in \fImainMenu\fP.
    Allowable signal names are (case is
    not significant):
    \fItstp\fP (if supported by the operating system), \fIsuspend\fP (same
    as \fItstp\fP), \fIcont\fP
    (if supported by the operating system), \fIint\fP, \fIhup\fP, \fIterm\fP,
    \fIquit\fP,
    \fIalrm\fP, \fIalarm\fP (same as \fIalrm\fP) and \fIkill\fP.
    .TP 8
    .B "set-8-bit-control(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBeightBitControl\fP resource.
    It is also invoked from the \fB8-bit-control\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-allow132(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBc132\fP resource.
    It is also invoked from the \fBallow132\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-altscreen(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles between the alternate and current screens.
    .TP 8
    .B "set-appcursor(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the handling Application Cursor Key mode
    and is also invoked by the \fBappcursor\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-appkeypad(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the handling of Application Keypad mode
    and is also invoked by the \fBappkeypad\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-autolinefeed(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles automatic insertion of line feeds.
    It is also invoked by the \fBautolinefeed\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-autowrap(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles automatic wrapping of long lines.
    It is also invoked by the \fBautowrap\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-backarrow(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBbackarrowKey\fP resource.
    It is also invoked from the \fBbackarrow key\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-bellIsUrgent(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBbellIsUrgent\fP resource.
    It is also invoked by the \fBbellIsUrgent\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-cursorblink(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBcursorBlink\fP resource.
    It is also invoked from the \fBcursorblink\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-cursesemul(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBcurses\fP resource.
    It is also invoked from the \fBcursesemul\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-font-doublesize(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBfontDoublesize\fP resource.
    It is also invoked by the \fBfont-doublesize\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "set-hp-function-keys(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBhpFunctionKeys\fP resource.
    It is also invoked by the \fBhpFunctionKeys\fP entry in \fImainMenu\fP.
    .TP 8
    .B "set-jumpscroll(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBjumpscroll\fP resource.
    It is also invoked by the \fBjumpscroll\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-font-linedrawing(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fI\*n\fR's state regarding whether
    the current font has line-drawing characters and whether it should draw them
    directly.
    It is also invoked by the \fBfont-linedrawing\fP entry in \fIfontMenu\fP.
    .\" .\" not implemented
    .\" .TP 8
    .\" .B "set-font-loading(\fIon/off/toggle\fP)"
    .\" This action sets, unsets or toggles the TBD resource
    .\" which controls the ability to load VT220 soft fonts.
    .\" It is also invoked by the \fBfont-loadable\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "set-font-packed(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBforcePackedFont\fR resource
    which controls use of the font's minimum or maximum glyph width.
    It is also invoked by the \fBfont-packed\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "set-keep-clipboard(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBkeepClipboard\fP resource.
    .TP 8
    .B "set-keep-selection(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBkeepSelection\fP resource.
    It is also invoked by the \fBkeepSelection\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-logging(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the state of the logging option.
    .TP 8
    .B "set-old-function-keys(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the state of legacy function keys.
    It is also invoked by the \fBoldFunctionKeys\fP entry in \fImainMenu\fP.
    .TP 8
    .B "set-marginbell(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBmarginBell\fP resource.
    .TP 8
    .B "set-num-lock(\fIon/off/toggle\fP)"
    This action toggles the state of the \fBnumLock\fP resource.
    .TP 8
    .B "set-pop-on-bell(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBpopOnBell\fP resource.
    It is also invoked by the \fBpoponbell\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-private-colors(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBprivateColorRegisters\fP resource.
    .TP 8
    .B "set-render-font(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBrenderFont\fP resource.
    It is also invoked by the \fBrender-font\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "set-reverse-video(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBreverseVideo\fP resource.
    It is also invoked by the \fBreversevideo\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-reversewrap(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBreverseWrap\fP resource.
    It is also invoked by the \fBreversewrap\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-scroll-on-key(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBscrollKey\fP resource.
    It is also invoked from the \fBscrollkey\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-scroll-on-tty-output(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBscrollTtyOutput\fP resource.
    It is also invoked from the \fBscrollttyoutput\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-scrollbar(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBscrollbar\fP resource.
    It is also invoked by the \fBscrollbar\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-sco-function-keys(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBscoFunctionKeys\fP resource.
    It is also invoked by the \fBscoFunctionKeys\fP entry in \fImainMenu\fP.
    .TP 8
    .B "set-select(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBselectToClipboard\fP resource.
    It is also invoked by the \fBselectToClipboard\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-sixel-scrolling(\fIon/off/toggle\fP)"
    This action toggles between inline (sixel scrolling) and absolute positioning.
    It can also be controlled via DEC private mode 80 (DECSDM) or from
    the \fBsixelScrolling\fP entry in the \fIbtMenu\fP.
    .TP 8
    .B "set-sun-function-keys(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBsunFunctionKeys\fP resource.
    It is also invoked by the \fBsunFunctionKeys\fP entry in \fImainMenu\fP.
    .TP 8
    .B "set-sun-keyboard(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBsunKeyboard\fP resource.
    It is also invoked by the \fBsunKeyboard\fP entry in \fImainMenu\fP.
    .TP 8
    .B "set-tek-text(\fIlarge/2/3/small\fP)"
    This action sets the font used in the Tektronix window to the value of the
    selected resource according to the argument.
    The argument can be either a keyword or single-letter alias,
    as shown in parentheses:
    .RS
    .TP 5
    large (l)
    Use resource \fBfontLarge\fP, same as menu entry \fBtektextlarge\fP.
    .TP 5
    two (2)
    Use resource \fBfont2\fP, same as menu entry \fBtektext2\fP.
    .TP 5
    three (3)
    Use resource \fBfont3\fP, same as menu entry \fBtektext3\fP.
    .TP 5
    small (s)
    Use resource \fBfontSmall\fP, same as menu entry \fBtektextsmall\fP.
    .RE
    .TP 8
    .B "set-terminal-type(\fItype\fP)"
    This action directs output to either the \fIvt\fP or \fItek\fP windows,
    according to the \fItype\fP string.
    It is also invoked by the
    \fBtekmode\fP entry in \fIvtMenu\fP and the \fBvtmode\fP entry in
    \fItekMenu\fP.
    .TP 8
    .B "set-titeInhibit(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBtiteInhibit\fP resource,
    which controls switching between the alternate and current screens.
    .TP 8
    .B "set-toolbar(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the toolbar feature.
    It is also invoked by the \fBtoolbar\fP entry in \fImainMenu\fP.
    .TP 8
    .B "set-utf8-fonts(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fButf8Fonts\fP resource.
    It is also invoked by the \fButf8-fonts\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "set-utf8-mode(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fButf8\fP resource.
    It is also invoked by the \fButf8-mode\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "set-utf8-title(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fButf8Title\fP resource.
    It is also invoked by the \fButf8-title\fP entry in \fIfontMenu\fP.
    .TP 8
    .B "set-visibility(\fIvt/tek\fP,\fIon/off/toggle\fP)"
    This action sets, unsets or toggles whether or not
    the \fIvt\fP or \fItek\fP windows are visible.
    It is also invoked from the \fBtekshow\fP and \fBvthide\fP entries
    in \fIvtMenu\fP and the \fBvtshow\fP and \fBtekhide\fP entries in
    \fItekMenu\fP.
    .TP 8
    .B "set-visual-bell(\fIon/off/toggle\fP)"
    This action sets, unsets or toggles the \fBvisualBell\fP resource.
    It is also invoked by the \fBvisualbell\fP entry in \fIvtMenu\fP.
    .TP 8
    .B "set-vt-font(\fId/1/2/3/4/5/6/e/s\fP [,\fInormalfont\fP [, \fIboldfont\fP]])"
    This action sets the font or fonts currently being used
    in the VT\fIxxx\fP window.
    The first argument is a single character that specifies the font to be used:
    .RS 8
    .HP
    \fId\fP or \fID\fP indicate the default font (the font initially
    used when
    \fI\*n\fP was started),
    .HP
    \fI1\fP through \fI6\fP indicate the fonts
    specified by the \fBfont1\fP through \fBfont6\fP resources,
    .HP
    \fIe\fP or \fIE\fP
    indicate the normal and bold fonts that have been set through escape codes
    (or specified as the second and third action arguments, respectively), and
    .HP
    \fIs\fP or \fIS\fP indicate the font selection (as made by programs such as
    \fBxfontsel(__mansuffix__)\fP) indicated by the second action argument.
    .RE
    .IP
    If \fI\*n\fR is configured to support wide characters, an
    additional two optional parameters are recognized for the \fIe\fP argument:
    wide font and wide bold font.
    .TP 8
    .B "smaller-vt-font()"
    Set the font to the next smaller one, based on the font dimensions.
    See also \fBset-vt-font()\fP.
    .TP 8
    .B "soft-reset()"
    This action resets the scrolling region.
    It is also invoked from the \fBsoftreset\fP entry in \fIvtMenu\fP.
    The effect is identical to a soft reset (DECSTR) control sequence.
    .TP 8
    .B "spawn-new-terminal(\fIparams\fP)"
    Spawn a new \fI\*n\fP process.
    This is available on systems which have a modern version of the
    process filesystem, e.g., \*(``/proc\*('', which \fI\*n\fP can read.
    .IP
    Use the \*(``cwd\*('' process entry, e.g., /proc/12345/cwd to obtain the
    working directory of the process which is running in the current \fI\*n\fP.
    .IP
    On systems which have the \*(``exe\*('' process entry, e.g., /proc/12345/exe,
    use this to obtain the actual executable.
    Otherwise, use the \fB$PATH\fP variable to find \fI\*n\fP.
    .IP
    If parameters are given in the action,
    pass them to the new \fI\*n\fP process.
    .TP 8
    .B "start-extend()"
    This action is similar to \fBselect-start\fP except that the
    selection is extended to the current pointer location.
    .TP 8
    .B "start-cursor-extend()"
    This action is similar to \fBselect-extend\fP except that the
    selection is extended to the current text cursor position.
    .TP 8
    .B "string(\fIstring\fP)"
    This action inserts the specified text string as if it had been typed.
    Quotation is necessary if the string contains whitespace or
    non-alphanumeric characters.
    If the string argument begins with the
    characters \*(``0x\*('', it is interpreted
    as a hex character constant.
    .TP 8
    .B "tek-copy()"
    This action copies the escape codes used to generate the current window
    contents to a file in the current directory beginning with the name COPY.
    It is also invoked from the \fBtekcopy\fP entry in \fItekMenu\fP.
    .TP 8
    .B "tek-page()"
    This action clears the Tektronix window.
    It is also invoked by the \fBtekpage\fP entry in \fItekMenu\fP.
    .TP 8
    .B "tek-reset()"
    This action resets the Tektronix window.
    It is also invoked by the \fBtekreset\fP entry in \fItekMenu\fP.
    .TP 8
    .B "vi-button()"
    Handles a button event (other than press and release)
    by echoing a control sequence computed from the event's line number
    in the screen relative to the current line:
    .NS
    ESC ^P
    .NE
    .IP
    or
    .NS
    ESC ^N
    .NE
    .IP
    according to whether the event is before, or after the current line,
    respectively.
    The ^N (or ^P) is repeated once for each line that the event differs
    from the current line.
    The control sequence is omitted altogether if the button event is on the
    current line.
    .TP 8
    .B "visual-bell()"
    This action flashes the window quickly.
    .
    .PP
    The Tektronix window also has the following action:
    .TP 8
    .B "gin-press(\fIl/L/m/M/r/R\fP)"
    This action sends the indicated graphics input code.
    .
    .SS Default Key Bindings
    .PP
    The default bindings in the VT\fIxxx\fP window use the \fBSELECT\fP token,
    which is set by the \fBselectToClipboard\fP resource.
    These are for the \fIvt100\fP widget:
    .NS
              Shift  Prior:\fBscroll\-back\fP(1,halfpage) \\n\\\&
               Shift  Next:\fBscroll\-forw\fP(1,halfpage) \\n\\\&
             Shift  Select:\fBselect\-cursor\-start\fP() \\\&
                                     \fBselect\-cursor\-end\fP(\fBSELECT\fP, \fBCUT_BUFFER0\fP) \\n\\\&
             Shift  Insert:\fBinsert\-selection\fP(\fBSELECT\fP, \fBCUT_BUFFER0\fP) \\n\\\&
                     Alt Return:\fBfullscreen\fP() \\n\\\&
             Scroll_Lock:\fBscroll\-lock\fP() \\n\\\&
        Shift~Ctrl  KP_Add:\fBlarger\-vt\-font\fP() \\n\\\&
        Shift Ctrl  KP_Add:\fBsmaller\-vt\-font\fP() \\n\\\&
        Shift  KP_Subtract:\fBsmaller\-vt\-font\fP() \\n\\\&
                    ~Meta :\fBinsert\-seven\-bit\fP() \\n\\\&
                     Meta :\fBinsert\-eight\-bit\fP() \\n\\\&
                    !Ctrl :\fBpopup\-menu\fP(mainMenu) \\n\\\&
               !Lock Ctrl :\fBpopup\-menu\fP(mainMenu) \\n\\\&
     !Lock Ctrl @Num_Lock :\fBpopup\-menu\fP(mainMenu) \\n\\\&
         ! @Num_Lock Ctrl :\fBpopup\-menu\fP(mainMenu) \\n\\\&
                    ~Meta :\fBselect\-start\fP() \\n\\\&
                  ~Meta :\fBselect\-extend\fP() \\n\\\&
                    !Ctrl :\fBpopup\-menu\fP(vtMenu) \\n\\\&
               !Lock Ctrl :\fBpopup\-menu\fP(vtMenu) \\n\\\&
     !Lock Ctrl @Num_Lock :\fBpopup\-menu\fP(vtMenu) \\n\\\&
         ! @Num_Lock Ctrl :\fBpopup\-menu\fP(vtMenu) \\n\\\&
              ~Ctrl ~Meta :\fBignore\fP() \\n\\\&
                     Meta :\fBclear\-saved\-lines\fP() \\n\\\&
                ~Ctrl ~Meta :\fBinsert\-selection\fP(\fBSELECT\fP, \fBCUT_BUFFER0\fP) \\n\\\&
                    !Ctrl :\fBpopup\-menu\fP(fontMenu) \\n\\\&
               !Lock Ctrl :\fBpopup\-menu\fP(fontMenu) \\n\\\&
     !Lock Ctrl @Num_Lock :\fBpopup\-menu\fP(fontMenu) \\n\\\&
         ! @Num_Lock Ctrl :\fBpopup\-menu\fP(fontMenu) \\n\\\&
              ~Ctrl ~Meta :\fBstart\-extend\fP() \\n\\\&
                  ~Meta :\fBselect\-extend\fP() \\n\\\&
                     Ctrl :\fBscroll\-back\fP(1,halfpage,m) \\n\\\&
                Lock Ctrl :\fBscroll\-back\fP(1,halfpage,m) \\n\\\&
      Lock @Num_Lock Ctrl :\fBscroll\-back\fP(1,halfpage,m) \\n\\\&
           @Num_Lock Ctrl :\fBscroll\-back\fP(1,halfpage,m) \\n\\\&
                          :\fBscroll\-back\fP(5,line,m)     \\n\\\&
                     Ctrl :\fBscroll\-forw\fP(1,halfpage,m) \\n\\\&
                Lock Ctrl :\fBscroll\-forw\fP(1,halfpage,m) \\n\\\&
      Lock @Num_Lock Ctrl :\fBscroll\-forw\fP(1,halfpage,m) \\n\\\&
           @Num_Lock Ctrl :\fBscroll\-forw\fP(1,halfpage,m) \\n\\\&
                          :\fBscroll\-forw\fP(5,line,m)     \\n\\\&
                             :\fBselect\-end\fP(\fBSELECT\fP, \fBCUT_BUFFER0\fP) \\n\\\&
                           :\fBignore\fP()
    .NE
    .PP
    The default bindings in the Tektronix window are analogous but less extensive.
    These are for the \fItek4014\fP widget:
    .NS
                     ~Meta: \fBinsert\-seven\-bit\fP() \\n\\\&
                      Meta: \fBinsert\-eight\-bit\fP() \\n\\\&
                    !Ctrl : \fBpopup\-menu\fP(mainMenu) \\n\\\&
               !Lock Ctrl : \fBpopup\-menu\fP(mainMenu) \\n\\\&
     !Lock Ctrl @Num_Lock : \fBpopup\-menu\fP(mainMenu) \\n\\\&
          !Ctrl @Num_Lock : \fBpopup\-menu\fP(mainMenu) \\n\\\&
                    !Ctrl : \fBpopup\-menu\fP(tekMenu) \\n\\\&
               !Lock Ctrl : \fBpopup\-menu\fP(tekMenu) \\n\\\&
     !Lock Ctrl @Num_Lock : \fBpopup\-menu\fP(tekMenu) \\n\\\&
          !Ctrl @Num_Lock : \fBpopup\-menu\fP(tekMenu) \\n\\\&
               Shift ~Meta: \fBgin\-press\fP(L) \\n\\\&
                     ~Meta: \fBgin\-press\fP(l) \\n\\\&
               Shift ~Meta: \fBgin\-press\fP(M) \\n\\\&
                     ~Meta: \fBgin\-press\fP(m) \\n\\\&
               Shift ~Meta: \fBgin\-press\fP(R) \\n\\\&
                     ~Meta: \fBgin\-press\fP(r)
    .NE
    .SS Custom Key Bindings
    .PP
    You can modify the \fBtranslations\fP resource by overriding parts
    of it, or merging your resources with it.
    .PP
    Here is an example which uses shifted select/paste to copy to the clipboard,
    and unshifted select/paste for the primary selection.
    In each case, a (different) cut buffer is
    also a target or source of the select/paste operation.
    It is important to remember however,
    that cut buffers store data in ISO-8859-1 encoding,
    while selections can store data in a variety of formats and encodings.
    While \fI\*n\fP owns the selection, it highlights it.
    When it loses the selection, it removes the corresponding highlight.
    But you can still paste from the corresponding cut buffer.
    .NS
    *VT100*translations:    #override \\n\\\&
       ~Shift~Ctrl: \fBinsert\-selection\fP(\fBPRIMARY\fP, \fBCUT_BUFFER0\fP) \\n\\\&
        Shift~Ctrl: \fBinsert\-selection\fP(\fBCLIPBOARD\fP, \fBCUT_BUFFER1\fP) \\n\\\&
       ~Shift      : \fBselect\-end\fP(\fBPRIMARY\fP, \fBCUT_BUFFER0\fP) \\n\\\&
        Shift      : \fBselect\-end\fP(\fBCLIPBOARD\fP, \fBCUT_BUFFER1\fP)
    .NE
    .PP
    In the example, the class name \fBVT100\fP is used rather than the widget name.
    These are different; a class name could apply to more than one widget.
    A leading \*(``*\*('' is used because the widget hierarchy above the
    \fIvt100\fP widget depends on
    whether the toolbar support is compiled into \fI\*n\fP.
    .PP
    Most of the predefined translations are related to the mouse,
    with a few that use some of the special keys on the keyboard.
    Applications use special keys (function-keys, cursor-keys, keypad-keys)
    with modifiers (shift, control, alt).
    If \fI\*n\fP defines a translation for a given combination of
    special key and modifier, that makes it unavailable for use
    by applications within the terminal.
    For instance, one might extend the use of \fIPage Up\fP and \fIPage Down\fP
    keys seen here:
    .NS
        Shift  Prior : \fBscroll\-back\fP(1,halfpage) \\n\\\&
        Shift  Next  : \fBscroll\-forw\fP(1,halfpage) \\n\\\&
    .NE
    .PP
    to the \fIHome\fP and \fIEnd\fP keys:
    .NS
        Shift  Home : \fBscroll\-to\fP(begin) \\n\\\&
        Shift  End  : \fBscroll\-to\fP(end)
    .NE
    .PP
    but then shift\-\fIHome\fP and shift\-\fIEnd\fP would then
    be unavailable to applications.
    .PP
    Not everyone finds the three-button mouse bindings easy to use.
    In a wheel mouse, the middle button might be the wheel.
    As an alternative, you could add a binding using shifted keys:
    .NS
    *VT100*translations:      #override \\n\\\&
        Shift Home:    \fBcopy\-selection\fP(\fBSELECT\fP) \\n\\\&
        Shift Insert:  \fBcopy\-selection\fP(\fBSELECT\fP) \\n\\\&
        Ctrl Shift C:  \fBcopy\-selection\fP(\fBSELECT\fP) \\n\\\&
        Ctrl Shift V:  \fBinsert\-selection\fP(\fBSELECT\fP)
    .NE
    .PP
    You would still use the left- and right-mouse buttons (typically 1 and 3)
    for beginning and extending selections.
    .PP
    Besides mouse problems, there are also keyboards with inconvenient layouts.
    Some lack a numeric keypad, making it hard to use the shifted keypad plus
    and minus bindings for switching between font sizes.
    You can work around that by assigning the actions to more readily accessed
    keys:
    .NS
    *VT100*translations:      #override \\n\\\&
        Ctrl  +:       \fBlarger\-vt\-font\fP() \\n\\\&
        Ctrl  \-:       \fBsmaller\-vt\-font\fP()
    .NE
    .PP
    The keymap feature allows you to switch between sets of translations.
    The sample below shows
    how the \fBkeymap()\fP action may be used to add special
    keys for entering commonly-typed words:
    .NS
    *VT100.Translations: #override F13: keymap(dbx)
    *VT100.dbxKeymap.translations: \\\&
            F14:       \fBkeymap\fP(None) \\n\\\&
            F17:       \fBstring\fP("next") \\n\\\&
                            \fBstring\fP(0x0d) \\n\\\&
            F18:       \fBstring\fP("step") \\n\\\&
                            \fBstring\fP(0x0d) \\n\\\&
            F19:       \fBstring\fP("continue") \\n\\\&
                            \fBstring\fP(0x0d) \\n\\\&
            F20:       \fBstring\fP("print ") \\n\\\&
                            \fBinsert\-selection\fP(\fBPRIMARY\fP, \fBCUT_BUFFER0\fP)
    .NE
    .SS Default Scrollbar Bindings
    .PP
    Key bindings are normally associated with the \fIvt100\fP or \fItek4014\fP
    widgets which act as terminal emulators.
    \fI\*N\fP's scrollbar (and toolbar if it is configured) are separate widgets.
    Because all of these use the X Toolkit,
    they have corresponding \fBtranslations\fP resources.
    Those resources are distinct,
    and match different patterns, e.g., the differences in widget-name and
    number of levels of widgets which they may contain.
    .PP
    The \fIscrollbar\fP widget is a child of the \fIvt100\fP widget.
    It is positioned on top of the \fIvt100\fP widget.
    Toggling the scrollbar on and off causes the \fIvt100\fP widget to resize.
    .PP
    The default bindings for the scrollbar widget use only mouse-button events:
    .NS
       : StartScroll(Forward) \\n\\\&
       : StartScroll(Forward) \\n\\\&
       : StartScroll(Continuous) MoveThumb() NotifyThumb() \\n\\\&
       : StartScroll(Backward) \\n\\\&
       : StartScroll(Backward) \\n\\\&
       : MoveThumb() NotifyThumb() \\n\\\&
       :    NotifyScroll(Proportional) EndScroll()
    .NE
    .PP
    Events which the \fIscrollbar\fP widget does not recognize at all are lost.
    .PP
    However, at startup, \fI\*n\fP augments these translations with the default
    translations used for the \fIvt100\fP widget,
    together with the resource \*(``actions\*('' which those translations use.
    Because the \fIscrollbar\fP (or \fImenubar\fP) widgets do not recognize these
    actions (but because it has a corresponding translation),
    they are passed on to the \fIvt100\fP widget.
    .PP
    This augmenting of the scrollbar's translations has a few limitations:
    .bP
    \fI\*N\fP knows what the default translations are,
    but there is no suitable library interface for determining what
    customizations a user may have added to the \fIvt100\fP widget.
    All that \fI\*n\fP can do is augment the \fIscrollbar\fP widget to
    give it the same starting point for further customization by the user.
    .bP
    Events in the gap between the widgets may be lost.
    .bP
    Compose sequences begun in one widget cannot be completed in the other,
    because the input methods for each widget do not share context information.
    .PP
    Most customizations of the scrollbar translations do not concern key bindings.
    Rather, users are generally more interested in changing the bindings of the
    mouse buttons.
    For example, some people prefer using the left pointer button
    for dragging the scrollbar thumb.
    That can be set up by altering the translations resource, e.g.,
    .NS
    *VT100.scrollbar.translations:  #override \\n\\\&
       :     StartScroll(Forward) \\n\\\&
       :     StartScroll(Continuous) MoveThumb() NotifyThumb() \\n\\\&
       :     StartScroll(Backward) \\n\\\&
       :   MoveThumb() NotifyThumb() \\n\\\&
       :        NotifyScroll(Proportional) EndScroll()
    .NE
    .SH "CONTROL SEQUENCES AND KEYBOARD"
    Applications can send sequences of characters to the terminal to change its
    behavior.
    Often they are referred to as
    \*(``ANSI escape sequences\*('' or just plain
    \*(``escape sequences\*('' but both terms are misleading:
    .bP
    ANSI x3.64 (obsolete) which was replaced by ISO 6429 (ECMA-48) gave rules
    for the \fIformat\fP of these sequences of characters.
    .bP
    While the original VT100 was claimed to be ANSI-compatible (against x3.64),
    there is no freely available version of the ANSI standard to show where
    the VT100 differs.
    Most of the documents which mention the ANSI standard have
    additions not found in the original (such as those
    based on \fBansi.sys\fP).
    So this discussion focuses on the ISO standards.
    .bP
    The standard describes only sequences sent from the host to the terminal.
    There is no standard for sequences sent by special keys from the terminal
    to the host.
    By convention (and referring to existing terminals), the format of those
    sequences usually conforms to the host-to-terminal standard.
    .bP
    Some of \fI\*n\fP's sequences do not fit into the standard scheme.
    Technically those are \*(``unspecified\*(''.
    As an example,
    DEC Screen Alignment Test (DECALN) is this three-character sequence:
    .NS
    \fIESC\fP # 8
    .NE
    .PP
    .bP
    Some sequences fit into the standard format,
    but are not listed in the standard.
    These include the sequences used for setting up scrolling margins
    and doing forward/reverse scrolling.
    .bP
    Some of the sequences (in particular, the single-character functions
    such as tab and backspace)
    do not include the \fIescape\fP character.
    .PP
    With all of that in mind, the standard refers to these sequences of
    characters as \*(``control sequences\*(''.
    .PP
    \fI\*N Control Sequences\fP lists the control sequences which
    an application can send \fI\*n\fP to make it perform various operations.
    Most of these operations are standardized, from either the DEC or Tektronix
    terminals, or from more widely used standards such as ISO-6429.
    .PP
    A few examples of usage are given in this section.
    .SS Window and Icon Titles
    .PP
    Some scripts use \fBecho\fP with options \fB\-e\fP and \fB\-n\fP to tell
    the shell to interpret the string \*(``\\e\*('' as
    the \fIescape\fP character and
    to suppress a trailing newline on output.
    Those are not portable, nor recommended.
    Instead, use \fBprintf\fP (POSIX).
    .PP
    For example, to set the \fIwindow title\fP to \*(``Hello world!\*('',
    you could use one of these commands in a script:
    .NS
    printf \*(AQ\\033]2;Hello world!\\033\\\*(AQ
    printf \*(AQ\\033]2;Hello world!\\007\*(AQ
    printf \*(AQ\\033]2;%s\\033\\\*(AQ "Hello world!"
    printf \*(AQ\\033]2;%s\\007\*(AQ "Hello world!"
    .NE
    .PP
    The \fBprintf\fP command interprets the octal value \*(``\\033\*('' for
    \fIescape\fP, and (since it was not given in the format) omits a trailing
    newline from the output.
    .PP
    Some programs (such as \fBscreen\fP(1)) set both window- and icon-titles
    at the same time, using a slightly different control sequence:
    .NS
    printf \*(AQ\\033]0;Hello world!\\033\\\*(AQ
    printf \*(AQ\\033]0;Hello world!\\007\*(AQ
    printf \*(AQ\\033]0;%s\\033\\\*(AQ "Hello world!"
    printf \*(AQ\\033]0;%s\\007\*(AQ "Hello world!"
    .NE
    .PP
    The difference is the \fIparameter\fP \*(``0\*('' in each command.
    Most window managers will honor either window title or icon title.
    Some will make a distinction and allow you to set just the icon title.
    You can tell \fI\*n\fP to ask for this with a different parameter
    in the control sequence:
    .NS
    printf \*(AQ\\033]1;Hello world!\\033\\\*(AQ
    printf \*(AQ\\033]1;Hello world!\\007\*(AQ
    printf \*(AQ\\033]1;%s\\033\\\*(AQ "Hello world!"
    printf \*(AQ\\033]1;%s\\007\*(AQ "Hello world!"
    .NE
    .
    .SS Special Keys
    .PP
    \fI\*N\fP, like any VT100-compatible terminal emulator,
    has two modes for the \fIspecial keys\fP (cursor-keys, numeric keypad,
    and certain function-keys):
    .bP
    \fInormal mode\fP, which makes the special keys transmit
    \*(``useful\*('' sequences such as the control sequence for cursor-up
    when pressing the up-arrow, and
    .bP
    \fIapplication mode\fP,
    which uses a different control sequence that cannot be mistaken for
    the
    \*(``useful\*('' sequences.
    .PP
    The main difference between the two modes is that normal mode sequences
    start with \fICSI\fP (\fIescape\ [\fP) and application mode sequences
    start with \fISS3\fP (\fIescape\ O\fP).
    .PP
    The terminal is initialized into one of these two modes (usually the
    normal mode), based on the terminal description (termcap or terminfo).
    The terminal description also has capabilities (strings) defined for
    the keypad mode used in curses applications.
    .PP
    There is a problem in using the terminal description for applications
    that are not intended to be full-screen curses applications:
    the definitions of special keys are only correct for this keypad mode.
    For example, some shells
    (unlike \fBksh\fP(1), which appears to be hard-coded, not even using termcap)
    allow their users to customize key-bindings,
    assigning shell actions to special keys.
    .bP
    \fBbash\fP(1) allows \fIconstant\fP strings to be assigned
    to functions.
    This is only successful if the terminal is initialized to application
    mode by default,
    because \fBbash\fP lacks flexibility in this area.
    It uses a (less expressive than \fBbash\fP's)
    \fBreadline\fP scripting language for setting up key bindings,
    which relies upon the user to statically enumerate the possible bindings for
    given values of \fB$TERM\fP.
    .bP
    \fBzsh\fP(1) provides an analogous feature,
    but it accepts runtime expressions,
    as well as providing a \fB$terminfo\fP array for scripts.
    In particular, one can use the terminal database,
    transforming when defining a key-binding.
    By transforming the output so that \fICSI\fP and \fISS3\fP are equated,
    \fBzsh\fP can use the terminal database to obtain useful definitions
    for its command-line use regardless of whether the terminal uses
    normal or application mode initially.
    Here is an example:
    .NS
    [[ "$terminfo[kcuu1]" == "^[O"* ]] && \\\&
    bindkey \-M viins "${terminfo[kcuu1]/O/[}" \\\&
    vi\-up\-line\-or\-history
    .NE
    .
    .
    .SS Changing Colors
    .PP
    A few shell programs provide the ability for users to add color and other
    video attributes to the shell prompt strings.
    Users can do this by setting \fB$PS1\fP (the primary prompt string).
    Again, \fBbash\fP and \fBzsh\fP have provided features not found in \fBksh\fP.
    There is a problem, however: the prompt's width on the screen will not
    necessarily be the same as the number of characters.
    Because there is no guidance in the POSIX standard, each shell addresses
    the problem in a different way:
    .bP
    \fBbash\fP treats characters within
    \*(``\\[\*('' and
    \*(``\\]\*(''
    as nonprinting (using no width on the screen).
    .bP
    \fBzsh\fP treats characters within
    \*(``%{\*('' and
    \*(``%}\*(''
    as nonprinting.
    .PP
    In addition to the difference in syntax,
    the shells provide different methods for obtaining useful escape sequences:
    .bP
    As noted in \fBSpecial Keys\fP, \fBzsh\fP initializes the $terminfo array
    with the terminal capabilities.
    .IP
    It also provides a function \fBechoti\fP which works like \fBtput\fP(1)
    to convert a terminal capability with its parameters into a string
    that can be written to the terminal.
    .bP
    Shells lacking a comparable feature (such as \fBbash\fP) can always
    use the program \fBtput\fP to do this transformation.
    .PP
    Hard-coded escape sequences are supported by each shell,
    but are not recommended because those rely upon particular configurations
    and cannot be easily moved between different user environments.
    .
    .
    .SH ENVIRONMENT
    \fI\*N\fP sets several environment variables.
    .SS System Independent
    .PP
    Some variables are used on every system:
    .TP 5
    .B DISPLAY
    is the display name,
    pointing to the X server (see \fIDISPLAY NAMES\fP in X(__miscmansuffix__)).
    .TP 5
    .B TERM
    .br
    is set according to the terminfo (or termcap) entry which it is using as
    a reference.
    .IP
    On some systems, you may encounter situations where the shell which you
    use and \fI\*n\fP are built using libraries with different terminal databases.
    In that situation, \fI\*n\fP may choose a terminal description not known
    to the shell.
    .TP 5
    .B WINDOWID
    is set to the X window id number of the \fI\*n\fP window.
    .TP 5
    .B XTERM_FILTER
    is set if a locale-filter is used.
    The value is the pathname of the filter.
    .TP 5
    .B XTERM_LOCALE
    shows the locale which was used by \fI\*n\fP on startup.
    Some shell initialization scripts may set a different locale.
    .TP 5
    .B XTERM_SHELL
    is set to the pathname of the program which is invoked.
    Usually that is a shell program, e.g., \fI/bin/sh\fP.
    Since it is not necessarily a shell program however,
    it is distinct from \*(``SHELL\*(''.
    .TP 5
    .B XTERM_VERSION
    is set to the string displayed by the \fB\-version\fP option.
    That is normally an identifier for the X Window libraries used to
    build \fI\*n\fP, followed by
    \fI\*n\fP's patch number in parenthesis.
    The patch number is also part of the response to a Secondary Device Attributes
    (DA) control sequence (see \fIXterm Control Sequences\fP).
    .
    .SS System Dependent
    .
    .PP
    Depending on your system configuration, \fI\*n\fP may also set the
    following:
    .TP 5
    .B COLUMNS
    the width of the \fI\*n\fP in characters (cf: \*(``stty columns\*('').
    .IP
    When this variable is set, \fIcurses\fP applications (and most
    terminal programs) will assume that the terminal has this many columns.
    .IP
    \fI\*N\fP would do this for systems which have no ability
    to tell the size of the terminal.
    Those are very rare, none newer than the mid 1990s when SVR4 became prevalent.
    .TP 5
    .B HOME
    .br
    when \fI\*n\fP is configured (at build-time) to update utmp.
    .TP 5
    .B LINES
    the height of the \fI\*n\fP in characters (cf: \*(``stty rows\*('').
    .IP
    When this variable is set, \fIcurses\fP applications (and most
    terminal programs) will assume that the terminal has this many lines (rows).
    .IP
    \fI\*N\fP would do this for systems which have no ability
    to tell the size of the terminal.
    Those are very rare, none newer than the mid 1990s when SVR4 became prevalent.
    .TP 5
    .B LOGNAME
    when \fI\*n\fP is configured (at build-time) to update utmp.
    .IP
    Your configuration may have set \fBLOGNAME\fP; \fI\*n\fP does not modify that.
    If it is unset, \fI\*n\fP will use \fBUSER\fP if it is set.
    Finally, if neither is set, \fI\*n\fP will use the \fBgetlogin\fP(3) function.
    .TP 5
    .B SHELL
    when \fI\*n\fP is configured (at build-time) to update utmp.
    It is also set if you provide a valid shell name as the optional parameter.
    .IP
    \fI\*N\fP sets this to an absolute pathname.
    If you have set the variable to a relative pathname,
    \fI\*n\fP may set it to a different shell pathname.
    .IP
    If you have set this to an pathname which does not correspond to a valid
    shell, \fI\*n\fP may unset it, to avoid confusion.
    .TP 5
    .B TERMCAP
    the contents of the termcap entry corresponding to \fB$TERM\fP,
    with lines and columns values substituted
    for the actual size window you have created.
    .IP
    This feature is, like \fBLINES\fP and \fBCOLUMNS\fP, used rarely.
    It addresses the same limitation of a few older systems
    by providing a way for \fItermcap\fP-based applications to get the initial
    screen size.
    .TP 5
    .B TERMINFO
    may be defined to a nonstandard location using the configure script.
    .\"
    .
    .
    .SH WINDOW PROPERTIES
    .PP
    In the output from \fBxprop\fP(1), there are several properties.
    .SS Properties set by X Toolkit
    .TP 5
    .B WM_CLASS
    This shows the \fIinstance name\fP and the X resource \fIclass\fP,
    passed to X Toolkit during initialization of \fI\*n\fP,
    e.g.,
    .NS
    WM_CLASS(STRING) = "xterm", "UXTerm"
    .NE
    .TP 5
    .B WM_CLIENT_LEADER
    This shows the window-id which \fI\*n\fP provides
    with an environment variable (\fBWINDOWID\fP),
    e.g.,
    .NS
    WM_CLIENT_LEADER(WINDOW): window id # 0x800023
    .NE
    .TP 5
    .B WM_COMMAND
    This shows the command-line arguments for \fI\*n\fP
    which are passed to X Toolkit during initialization, e.g.,
    .NS
    WM_COMMAND(STRING) = { "xterm", "-class", "UXTerm", "-title", "uxterm", "-u8" }
    .NE
    .TP 5
    .B WM_ICON_NAME
    This holds the icon title,
    which different window managers handle in various ways.
    It is set via the \fBiconName\fP resource.
    Applications can change this using control sequences.
    .TP 5
    .B WM_LOCALE_NAME
    This shows the result from the \fBsetlocale\fP(3) function
    for the \fILC_CTYPE\fP category,
    e.g.,
    .NS
    WM_LOCALE_NAME(STRING) = "en_US.UTF-8"
    .NE
    .TP 5
    .B WM_NAME
    This holds the window title, normally at the top of \fI\*n\fP's window.
    It is set via the \fBtitle\fP resource.
    Applications can change this using control sequences.
    .SS Properties set by Xterm
    X Toolkit does not manage EWMH properties.
    \*N does this directly.
    .TP 5
    .B _NET_WM_ICON_NAME
    stores the icon name.
    .TP 5
    .B _NET_WM_NAME
    stores the title string.
    .TP 5
    .B _NET_WM_PID
    stores the process identifier for \fI\*n\fP's display.
    .SS Properties used by Xterm
    .TP 5
    .B _NET_SUPPORTED
    \*N checks this property on the \fIsupporting window\fP
    to decide if the window manager supports
    specific maximizing styles.
    That may include other window manager hints;
    \fI\*n\fP uses the X library calls to manage those.
    .TP 5
    .B _NET_SUPPORTING_WM_CHECK
    \*N checks this to ensure that it will only update the EWMH
    properties for a window manager which claims EWMH compliance.
    .TP 5
    .B _NET_WM_STATE
    This tells \fI\*n\fP whether its window has been maximized by the window manager,
    and if so, what type of maximizing:
    .RS
    .TP 5
    .B _NET_WM_STATE_FULLSCREEN
    .TP 5
    .B _NET_WM_STATE_MAXIMIZED_HORZ
    .TP 5
    .B _NET_WM_STATE_MAXIMIZED_VERT
    .RE
    .PP
    .
    .
    .SH FILES
    The actual pathnames given may differ on your system.
    .TP 5
    \fI/etc/shells\fP
    contains a list of valid shell programs,
    used by \fI\*n\fP to decide if the \*(``SHELL\*('' environment
    variable should be set for the process started by \fI\*n\fP.
    .IP
    On systems which have the \fIgetusershell\fP function,
    \fI\*n\fP will use that function rather than directly reading the file,
    since the file may not be present if the system uses default settings.
    .TP 5
    \fI/etc/utmp\fP
    the system log file, which records user logins.
    .TP 5
    \fI/etc/wtmp\fP
    the system log file, which records user logins and logouts.
    .TP 5
    .I __apploaddir__/__default_class__
    the \fI\*n\fP default application resources.
    .TP 5
    .I __apploaddir__/__default_class__\-color
    the \fI\*n\fP color application resources.
    If your display supports color, use this
    .NS
    *customization: \-color
    .NE
    .IP
    in your \&.Xdefaults file to
    automatically use this resource file rather than
    .IR __apploaddir__/__default_class__ .
    If you do not do this,
    \fI\*n\fP uses its compiled-in default resource settings for colors.
    .TP 5
    .I __pixmapsdir__
    the directory in which \fI\*n\fP's pixmap icon files are installed.
    .
    .
    .SH ERROR MESSAGES
    Most of the fatal error messages from \fI\*n\fP use the following format:
    .NS
    \*n: Error \fIXXX\fP, errno \fIYYY\fP: \fIZZZ\fR
    .NE
    .PP
    The \fIXXX\fP codes (which are used by \fI\*n\fP as its exit-code)
    are listed below, with a brief explanation.
    .TP 5
    1
    is used for miscellaneous errors, usually accompanied by a specific message,
    .TP
    11
    ERROR_FIONBIO
    .br
    main: ioctl() failed on FIONBIO
    .TP
    12
    ERROR_F_GETFL
    .br
    main: ioctl() failed on F_GETFL
    .TP
    13
    ERROR_F_SETFL
    .br
    main: ioctl() failed on F_SETFL
    .TP
    14
    ERROR_OPDEVTTY
    .br
    spawn: open() failed on /dev/tty
    .TP
    15
    ERROR_TIOCGETP
    .br
    spawn: ioctl() failed on TIOCGETP
    .TP
    17
    ERROR_PTSNAME
    .br
    spawn: ptsname() failed
    .TP
    18
    ERROR_OPPTSNAME
    .br
    spawn: open() failed on ptsname
    .TP
    19
    ERROR_PTEM
    .br
    spawn: ioctl() failed on I_PUSH/"ptem"
    .TP
    20
    ERROR_CONSEM
    .br
    spawn: ioctl() failed on I_PUSH/"consem"
    .TP
    21
    ERROR_LDTERM
    .br
    spawn: ioctl() failed on I_PUSH/"ldterm"
    .TP
    22
    ERROR_TTCOMPAT
    .br
    spawn: ioctl() failed on I_PUSH/"ttcompat"
    .TP
    23
    ERROR_TIOCSETP
    .br
    spawn: ioctl() failed on TIOCSETP
    .TP
    24
    ERROR_TIOCSETC
    .br
    spawn: ioctl() failed on TIOCSETC
    .TP
    25
    ERROR_TIOCSETD
    .br
    spawn: ioctl() failed on TIOCSETD
    .TP
    26
    ERROR_TIOCSLTC
    .br
    spawn: ioctl() failed on TIOCSLTC
    .TP
    27
    ERROR_TIOCLSET
    .br
    spawn: ioctl() failed on TIOCLSET
    .TP
    28
    ERROR_INIGROUPS
    .br
    spawn: initgroups() failed
    .TP
    29
    ERROR_FORK
    .br
    spawn: fork() failed
    .TP
    30
    ERROR_EXEC
    .br
    spawn: exec() failed
    .TP
    32
    ERROR_PTYS
    .br
    get_pty: not enough ptys
    .TP
    34
    ERROR_PTY_EXEC
    .br
    waiting for initial map
    .TP
    35
    ERROR_SETUID
    .br
    spawn: setuid() failed
    .TP
    36
    ERROR_INIT
    .br
    spawn: can't initialize window
    .TP
    46
    ERROR_TIOCKSET
    .br
    spawn: ioctl() failed on TIOCKSET
    .TP
    47
    ERROR_TIOCKSETC
    .br
    spawn: ioctl() failed on TIOCKSETC
    .TP
    49
    ERROR_LUMALLOC
    .br
    luit: command-line malloc failed
    .TP
    50
    ERROR_SELECT
    .br
    in_put: select() failed
    .TP
    54
    ERROR_VINIT
    .br
    VTInit: can't initialize window
    .TP
    57
    ERROR_KMMALLOC1
    .br
    HandleKeymapChange: malloc failed
    .TP
    60
    ERROR_TSELECT
    .br
    Tinput: select() failed
    .TP
    64
    ERROR_TINIT
    .br
    TekInit: can't initialize window
    .TP
    71
    ERROR_BMALLOC2
    .br
    SaltTextAway: malloc() failed
    .TP
    80
    ERROR_LOGEXEC
    .br
    StartLog: exec() failed
    .TP
    83
    ERROR_XERROR
    .br
    xerror: XError event
    .TP
    84
    ERROR_XIOERROR
    .br
    xioerror: X I/O error
    .TP
    85
    ERROR_ICEERROR
    .br
    ICE I/O error
    .TP
    90
    ERROR_SCALLOC
    .br
    Alloc: calloc() failed on base
    .TP
    91
    ERROR_SCALLOC2
    .br
    Alloc: calloc() failed on rows
    .TP
    102
    ERROR_SAVE_PTR
    .br
    ScrnPointers: malloc/realloc() failed
    .
    .
    .SH BUGS
    .
    .PP
    Large pastes do not work on some systems.
    This is not a bug in
    \fI\*n\fP; it is a bug in the pseudo terminal driver of those
    systems.
    \fI\*N\fP feeds large pastes to the pty only as fast as the pty
    will accept data, but some pty drivers do not return enough information
    to know if the write has succeeded.
    .
    .PP
    When connected to an input method, it is possible for \fI\*n\fP to hang
    if the XIM server is suspended or killed.
    .
    .PP
    Many of the options are not resettable after \fI\*n\fP starts.
    .
    .PP
    This program still needs to be rewritten.
    It should be split into very
    modular sections, with the various emulators being completely separate
    widgets that do not know about each other.
    Ideally, you'd like to be able to
    pick and choose emulator widgets and stick them into a single control widget.
    .
    .PP
    There needs to be a dialog box to allow entry of the Tek COPY file name.
    .
    .
    .SH "SEE ALSO"
    .na
    resize(__mansuffix__),
    luit(__mansuffix__),
    u\*n(__mansuffix__),
    X(__miscmansuffix__),
    pty(4),
    tty(4)
    .ad
    .PP
    \fIXterm Control Sequences\fP
    (this is the file ctlseqs.ms).
    .RS 4n
    .sp
    https://invisible\-island.net/xterm/xterm.html
    .br
    https://invisible\-island.net/xterm/manpage/xterm.html
    .br
    https://invisible\-island.net/xterm/ctlseqs/ctlseqs.html
    .br
    https://invisible\-island.net/xterm/xterm.faq.html
    .br
    https://invisible\-island.net/xterm/xterm.log.html
    .RE
    .PP
    \fIX Toolkit Intrinsics \(en C Language Interface\fP (Xt),
    .br
    Joel McCormack, Paul Asente, Ralph R. Swick (1994),
    .br
    Thomas E. Dickey (2019).
    .PP
    \fIInter-Client Communication Conventions Manual\fR (ICCCM),
    .br
    David Rosenthal and
    Stuart W. Marks (version 2.0, 1994).
    .PP
    \fIExtended Window Manager Hints\fP (EWMH),
    .br
    X Desktop Group (version 1.3, 2005).
    .PP
    EWMH uses \fIUTF8_STRING\fP pervasively without defining it,
    but does mention the ICCCM.
    Version 2.0 of the ICCCM does not address UTF-8.
    That is an extension added in XFree86.
    .bP
    Markus Kuhn summarized this in
    \fIUTF-8 and Unicode FAQ for Unix/Linux\fP (2001),
    in the section \*(``Is X11 ready for Unicode?\*(''
    .IP
    https://www.cl.cam.ac.uk/~mgk25/unicode.html
    .bP
    Juliusz Chroboczek proposed the UTF8_STRING selection atom in 1999/2000,
    which became part of the ICCCM in XFree86.
    .IP
    https://www.irif.fr/~jch/software/UTF8_STRING/
    .IP
    An Xorg developer removed that part of the documentation in 2004
    when incorporating other work from XFree86 into Xorg.
    The feature is still supported in Xorg, though undocumented as of 2019.
    .
    .SH AUTHORS
    Far too many people.
    .PP
    These contributed to the X Consortium:
    Loretta Guarino Reid (DEC-UEG-WSL),
    Joel McCormack (DEC-UEG-WSL), Terry Weissman (DEC-UEG-WSL),
    Edward Moy (Berkeley), Ralph R.\& Swick (MIT-Athena),
    Mark Vandevoorde (MIT-Athena), Bob McNamara (DEC-MAD),
    Jim Gettys (MIT-Athena), Bob Scheifler (MIT X Consortium), Doug Mink (SAO),
    Steve Pitschke (Stellar), Ron Newman (MIT-Athena), Jim Fulton (MIT X
    Consortium), Dave Serisky (HP), Jonathan Kamens (MIT-Athena).
    .PP
    Beginning with XFree86, there were far more identifiable contributors.
    The \fITHANKS\fP file in \fI\*n\fP's source lists 211 at the end of 2018.
    Keep in mind these:
    Jason Bacon,
    Jens Schweikhardt,
    Ross Combs,
    Stephen P.\& Wall,
    David Wexelblat, and
    Thomas Dickey (invisible-island.net).
    xterm-353/error.h0000644000175100001440000001200612033423457012550 0ustar  tomusers/* $XTermId: error.h,v 1.26 2012/10/05 00:17:51 tom Exp $ */
    
    /*
     * Copyright 1997-2011,2012 by Thomas E. Dickey
     *
     *                         All Rights Reserved
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     *
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * Except as contained in this notice, the name(s) of the above copyright
     * holders shall not be used in advertising or otherwise to promote the
     * sale, use or other dealings in this Software without prior written
     * authorization.
     *
     * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
     *
     *                         All Rights Reserved
     *
     * Permission to use, copy, modify, and distribute this software and its
     * documentation for any purpose and without fee is hereby granted,
     * provided that the above copyright notice appear in all copies and that
     * both that copyright notice and this permission notice appear in
     * supporting documentation, and that the name of Digital Equipment
     * Corporation not be used in advertising or publicity pertaining to
     * distribution of the software without specific, written prior permission.
     *
     *
     * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     * SOFTWARE.
     */
    
    /* @(#)error.h	X10/6.6	11/6/86 */
    
    /* main.c */
    #define	ERROR_FIONBIO	11	/* main: ioctl() failed on FIONBIO */
    #define	ERROR_F_GETFL	12	/* main: ioctl() failed on F_GETFL */
    #define	ERROR_F_SETFL	13	/* main: ioctl() failed on F_SETFL */
    #define	ERROR_OPDEVTTY	14	/* spawn: open() failed on /dev/tty */
    #define	ERROR_TIOCGETP	15	/* spawn: ioctl() failed on TIOCGETP */
    #define ERROR_PTSNAME   17	/* spawn: ptsname() failed */
    #define ERROR_OPPTSNAME 18	/* spawn: open() failed on ptsname */
    #define ERROR_PTEM      19	/* spawn: ioctl() failed on I_PUSH/"ptem" */
    #define ERROR_CONSEM    20	/* spawn: ioctl() failed on I_PUSH/"consem" */
    #define ERROR_LDTERM    21	/* spawn: ioctl() failed on I_PUSH/"ldterm" */
    #define ERROR_TTCOMPAT  22	/* spawn: ioctl() failed on I_PUSH/"ttcompat" */
    #define	ERROR_TIOCSETP	23	/* spawn: ioctl() failed on TIOCSETP */
    #define	ERROR_TIOCSETC	24	/* spawn: ioctl() failed on TIOCSETC */
    #define	ERROR_TIOCSETD	25	/* spawn: ioctl() failed on TIOCSETD */
    #define	ERROR_TIOCSLTC	26	/* spawn: ioctl() failed on TIOCSLTC */
    #define	ERROR_TIOCLSET	27	/* spawn: ioctl() failed on TIOCLSET */
    #define	ERROR_INIGROUPS 28	/* spawn: initgroups() failed */
    #define	ERROR_FORK	29	/* spawn: fork() failed */
    #define	ERROR_EXEC	30	/* spawn: exec() failed */
    #define	ERROR_PTYS	32	/* get_pty: not enough ptys */
    #define ERROR_PTY_EXEC	34	/* waiting for initial map */
    #define	ERROR_SETUID	35	/* spawn: setuid() failed */
    #define	ERROR_INIT	36	/* spawn: can't initialize window */
    #define	ERROR_TIOCKSET	46	/* spawn: ioctl() failed on TIOCKSET */
    #define	ERROR_TIOCKSETC	47	/* spawn: ioctl() failed on TIOCKSETC */
    #define	ERROR_LUMALLOC  49	/* luit: command-line malloc failed */
    
    /* charproc.c */
    #define	ERROR_SELECT	50	/* in_put: select() failed */
    #define	ERROR_VINIT	54	/* VTInit: can't initialize window */
    #define	ERROR_KMMALLOC1 57	/* HandleKeymapChange: malloc failed */
    
    /* Tekproc.c */
    #define	ERROR_TSELECT	60	/* Tinput: select() failed */
    #define	ERROR_TINIT	64	/* TekInit: can't initialize window */
    
    /* button.c */
    #define	ERROR_BMALLOC2	71	/* SaltTextAway: malloc() failed */
    
    /* misc.c */
    #define	ERROR_LOGEXEC	80	/* StartLog: exec() failed */
    #define	ERROR_XERROR	83	/* xerror: XError event */
    #define	ERROR_XIOERROR	84	/* xioerror: X I/O error */
    #define	ERROR_ICEERROR	85	/* ice_error: ICE I/O error */
    
    /* screen.c */
    #define	ERROR_SCALLOC	90	/* Alloc: calloc() failed on base */
    #define	ERROR_SCALLOC2	91	/* Alloc: calloc() failed on rows */
    #define	ERROR_SAVE_PTR	102	/* ScrnPointers: malloc/realloc() failed */
    xterm-353/button.c0000644000175100001440000043307713506234333012743 0ustar  tomusers/* $XTermId: button.c,v 1.575 2019/06/30 22:34:03 tom Exp $ */
    
    /*
     * Copyright 1999-2018,2019 by Thomas E. Dickey
     *
     *                         All Rights Reserved
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     *
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * Except as contained in this notice, the name(s) of the above copyright
     * holders shall not be used in advertising or otherwise to promote the
     * sale, use or other dealings in this Software without prior written
     * authorization.
     *
     *
     * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
     *
     *                         All Rights Reserved
     *
     * Permission to use, copy, modify, and distribute this software and its
     * documentation for any purpose and without fee is hereby granted,
     * provided that the above copyright notice appear in all copies and that
     * both that copyright notice and this permission notice appear in
     * supporting documentation, and that the name of Digital Equipment
     * Corporation not be used in advertising or publicity pertaining to
     * distribution of the software without specific, written prior permission.
     *
     *
     * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     * SOFTWARE.
     */
    
    /*
    button.c	Handles button events in the terminal emulator.
    		does cut/paste operations, change modes via menu,
    		passes button events through to some applications.
    				J. Gettys.
    */
    
    #include 
    
    #include 
    #include 
    #include 
    
    #include 
    #include 
    #include 
    
    #include 
    #include 
    
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #if OPT_SELECT_REGEX
    #ifdef HAVE_PCRE2POSIX_H
    #include 
    #else
    #ifdef HAVE_PCREPOSIX_H
    #include 
    #else /* POSIX regex.h */
    #include 
    #include 
    #endif
    #endif
    #endif
    
    #define PRIMARY_NAME    "PRIMARY"
    #define CLIPBOARD_NAME  "CLIPBOARD"
    #define SECONDARY_NAME  "SECONDARY"
    
    #define AtomToSelection(d,n) \
    		 (((n) == XA_CLIPBOARD(d)) \
    		  ? CLIPBOARD_CODE \
    		  : (((n) == XA_SECONDARY) \
    		     ? SECONDARY_CODE \
    		     : PRIMARY_CODE))
    
    #define isSelectionCode(n) ((n) >= PRIMARY_CODE)
    #define CutBufferToCode(n) ((n) +  MAX_SELECTION_CODES)
    #define okSelectionCode(n) (isSelectionCode(n) ? (n) : PRIMARY_CODE)
    
    #if OPT_WIDE_CHARS
    #include 
    #include 
    #else
    #define CharacterClass(value) \
    	charClass[(value) & (int)((sizeof(charClass)/sizeof(charClass[0]))-1)]
    #endif
    
        /*
         * We'll generally map rows to indices when doing selection.
         * Simplify that with a macro.
         *
         * Note that ROW2INX() is safe to use with auto increment/decrement for
         * the row expression since that is evaluated once.
         */
    #define GET_LINEDATA(screen, row) \
    	getLineData(screen, ROW2INX(screen, row))
    
        /*
         * We reserve shift modifier for cut/paste operations.
         *
         * In principle we can pass through control and meta modifiers, but in
         * practice, the popup menu uses control, and the window manager is likely
         * to use meta, so those events usually are not delivered to
         * SendMousePosition.
         */
    #define OurModifiers (ShiftMask)
    #define AllModifiers (ShiftMask | LockMask | ControlMask | Mod1Mask | \
    		      Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
    
    #define BtnModifiers(event) (event->state & OurModifiers)
    #define KeyModifiers(event) (event->xbutton.state & OurModifiers)
    
    #define IsBtnEvent(event) ((event)->type == ButtonPress || (event)->type == ButtonRelease)
    #define IsKeyEvent(event) ((event)->type == KeyPress    || (event)->type == KeyRelease)
    
    #define KeyState(x) (((int) ((x) & (ShiftMask|ControlMask))) \
    			  + (((x) & Mod1Mask) ? 2 : 0))
        /* adds together the bits:
           shift key -> 1
           meta key  -> 2
           control key -> 4 */
    
    #define	Coordinate(s,c)	((c)->row * MaxCols(s) + (c)->col)
    
    static const CELL zeroCELL =
    {0, 0};
    
    #if OPT_DEC_LOCATOR
    static Bool SendLocatorPosition(XtermWidget xw, XButtonEvent *event);
    static void CheckLocatorPosition(XtermWidget xw, XButtonEvent *event);
    #endif /* OPT_DEC_LOCATOR */
    
    /* Multi-click handling */
    #if OPT_READLINE
    static Time lastButtonDownTime = 0;
    static int ExtendingSelection = 0;
    static Time lastButton3UpTime = 0;
    static Time lastButton3DoubleDownTime = 0;
    static CELL lastButton3;	/* At the release time */
    #endif /* OPT_READLINE */
    
    static Char *SaveText(TScreen *screen, int row, int scol, int ecol,
    		      Char *lp, int *eol);
    static int Length(TScreen *screen, int row, int scol, int ecol);
    static void ComputeSelect(XtermWidget xw, CELL *startc, CELL *endc, Bool extend);
    static void EditorButton(XtermWidget xw, XButtonEvent *event);
    static void EndExtend(XtermWidget w, XEvent *event, String *params, Cardinal
    		      num_params, Bool use_cursor_loc);
    static void ExtendExtend(XtermWidget xw, const CELL *cell);
    static void PointToCELL(TScreen *screen, int y, int x, CELL *cell);
    static void ReHiliteText(XtermWidget xw, CELL *first, CELL *last);
    static void SaltTextAway(XtermWidget xw, int which, CELL *cellc, CELL *cell);
    static void SelectSet(XtermWidget xw, XEvent *event, String *params, Cardinal num_params);
    static void SelectionReceived PROTO_XT_SEL_CB_ARGS;
    static void StartSelect(XtermWidget xw, const CELL *cell);
    static void TrackDown(XtermWidget xw, XButtonEvent *event);
    static void TrackText(XtermWidget xw, const CELL *first, const CELL *last);
    static void UnHiliteText(XtermWidget xw);
    static void _OwnSelection(XtermWidget xw, String *selections, Cardinal count);
    static void do_select_end(XtermWidget xw, XEvent *event, String *params,
    			  Cardinal *num_params, Bool use_cursor_loc);
    
    #define MOUSE_LIMIT (255 - 32)
    
    /* Send SET_EXT_SIZE_MOUSE to enable offsets up to EXT_MOUSE_LIMIT */
    #define EXT_MOUSE_LIMIT (2047 - 32)
    #define EXT_MOUSE_START (127 - 32)
    
    static int
    MouseLimit(TScreen *screen)
    {
        int mouse_limit;
    
        switch (screen->extend_coords) {
        default:
    	mouse_limit = MOUSE_LIMIT;
    	break;
        case SET_EXT_MODE_MOUSE:
    	mouse_limit = EXT_MOUSE_LIMIT;
    	break;
        case SET_SGR_EXT_MODE_MOUSE:
        case SET_URXVT_EXT_MODE_MOUSE:
    	mouse_limit = -1;
    	break;
        }
        return mouse_limit;
    }
    
    static unsigned
    EmitMousePosition(TScreen *screen, Char line[], unsigned count, int value)
    {
        int mouse_limit = MouseLimit(screen);
    
        /*
         * Add pointer position to key sequence
         *
         * In extended mode we encode large positions as two-byte UTF-8.
         *
         * NOTE: historically, it was possible to emit 256, which became
         * zero by truncation to 8 bits. While this was arguably a bug,
         * it's also somewhat useful as a past-end marker. We preserve
         * this behavior for both normal and extended mouse modes.
         */
        switch (screen->extend_coords) {
        default:
    	if (value == mouse_limit) {
    	    line[count++] = CharOf(0);
    	} else {
    	    line[count++] = CharOf(' ' + value + 1);
    	}
    	break;
        case SET_EXT_MODE_MOUSE:
    	if (value == mouse_limit) {
    	    line[count++] = CharOf(0);
    	} else if (value < EXT_MOUSE_START) {
    	    line[count++] = CharOf(' ' + value + 1);
    	} else {
    	    value += ' ' + 1;
    	    line[count++] = CharOf(0xC0 + (value >> 6));
    	    line[count++] = CharOf(0x80 + (value & 0x3F));
    	}
    	break;
        case SET_SGR_EXT_MODE_MOUSE:
    	/* FALLTHRU */
        case SET_URXVT_EXT_MODE_MOUSE:
    	count += (unsigned) sprintf((char *) line + count, "%d", value + 1);
    	break;
        }
        return count;
    }
    
    static unsigned
    EmitMousePositionSeparator(TScreen *screen, Char line[], unsigned count)
    {
        switch (screen->extend_coords) {
        case SET_SGR_EXT_MODE_MOUSE:
        case SET_URXVT_EXT_MODE_MOUSE:
    	line[count++] = ';';
    	break;
        }
        return count;
    }
    
    Bool
    SendMousePosition(XtermWidget xw, XEvent *event)
    {
        XButtonEvent *my_event = (XButtonEvent *) event;
        Bool result = False;
    
        switch (okSendMousePos(xw)) {
        case MOUSE_OFF:
    	/* If send_mouse_pos mode isn't on, we shouldn't be here */
    	break;
    
        case BTN_EVENT_MOUSE:
        case ANY_EVENT_MOUSE:
    	if (KeyModifiers(event) == 0) {
    	    /* xterm extension for motion reporting. June 1998 */
    	    /* EditorButton() will distinguish between the modes */
    	    switch (event->type) {
    	    case MotionNotify:
    		my_event->button = 0;
    		/* FALLTHRU */
    	    case ButtonPress:
    		/* FALLTHRU */
    	    case ButtonRelease:
    		EditorButton(xw, my_event);
    		result = True;
    		break;
    	    }
    	}
    	break;
    
        case X10_MOUSE:		/* X10 compatibility sequences */
    	if (IsBtnEvent(event)) {
    	    if (BtnModifiers(my_event) == 0) {
    		if (my_event->type == ButtonPress)
    		    EditorButton(xw, my_event);
    		result = True;
    	    }
    	}
    	break;
    
        case VT200_HIGHLIGHT_MOUSE:	/* DEC vt200 hilite tracking */
    	if (IsBtnEvent(event)) {
    	    if (my_event->type == ButtonPress &&
    		BtnModifiers(my_event) == 0 &&
    		my_event->button == Button1) {
    		TrackDown(xw, my_event);
    		result = True;
    	    } else if (BtnModifiers(my_event) == 0) {
    		EditorButton(xw, my_event);
    		result = True;
    	    }
    	}
    	break;
    
        case VT200_MOUSE:		/* DEC vt200 compatible */
    	if (IsBtnEvent(event)) {
    	    if (BtnModifiers(my_event) == 0) {
    		EditorButton(xw, my_event);
    		result = True;
    	    }
    	}
    	break;
    
        case DEC_LOCATOR:
    #if OPT_DEC_LOCATOR
    	if (IsBtnEvent(event) || event->type == MotionNotify) {
    	    result = SendLocatorPosition(xw, my_event);
    	}
    #endif /* OPT_DEC_LOCATOR */
    	break;
        }
        return result;
    }
    
    #if OPT_DEC_LOCATOR
    
    #define	LocatorCoords( row, col, x, y, oor )			\
        if( screen->locator_pixels ) {				\
    	(oor)=False; (row) = (y)+1; (col) = (x)+1;		\
    	/* Limit to screen dimensions */			\
    	if ((row) < 1) (row) = 1,(oor)=True;			\
    	else if ((row) > screen->border*2+Height(screen))	\
    	    (row) = screen->border*2+Height(screen),(oor)=True;	\
    	if ((col) < 1) (col) = 1,(oor)=True;			\
    	else if ((col) > OriginX(screen)*2+Width(screen))	\
    	    (col) = OriginX(screen)*2+Width(screen),(oor)=True;	\
        } else {							\
    	(oor)=False;						\
    	/* Compute character position of mouse pointer */	\
    	(row) = ((y) - screen->border) / FontHeight(screen);	\
    	(col) = ((x) - OriginX(screen)) / FontWidth(screen);	\
    	/* Limit to screen dimensions */			\
    	if ((row) < 0) (row) = 0,(oor)=True;			\
    	else if ((row) > screen->max_row)			\
    	    (row) = screen->max_row,(oor)=True;			\
    	if ((col) < 0) (col) = 0,(oor)=True;			\
    	else if ((col) > screen->max_col)			\
    	    (col) = screen->max_col,(oor)=True;			\
    	(row)++; (col)++;					\
        }
    
    static Bool
    SendLocatorPosition(XtermWidget xw, XButtonEvent *event)
    {
        ANSI reply;
        TScreen *screen = TScreenOf(xw);
        int row, col;
        Bool oor;
        int button;
        unsigned state;
    
        /* Make sure the event is an appropriate type */
        if ((!IsBtnEvent(event) &&
    	 !screen->loc_filter) ||
    	(BtnModifiers(event) != 0))
    	return (False);
    
        if ((event->type == ButtonPress &&
    	 !(screen->locator_events & LOC_BTNS_DN)) ||
    	(event->type == ButtonRelease &&
    	 !(screen->locator_events & LOC_BTNS_UP)))
    	return (True);
    
        if (event->type == MotionNotify) {
    	CheckLocatorPosition(xw, event);
    	return (True);
        }
    
        /* get button # */
        button = (int) event->button - 1;
    
        LocatorCoords(row, col, event->x, event->y, oor);
    
        /*
         * DECterm mouse:
         *
         * ESCAPE '[' event ; mask ; row ; column '&' 'w'
         */
        memset(&reply, 0, sizeof(reply));
        reply.a_type = ANSI_CSI;
    
        if (oor) {
    	reply.a_nparam = 1;
    	reply.a_param[0] = 0;	/* Event - 0 = locator unavailable */
    	reply.a_inters = '&';
    	reply.a_final = 'w';
    	unparseseq(xw, &reply);
    
    	if (screen->locator_reset) {
    	    MotionOff(screen, xw);
    	    screen->send_mouse_pos = MOUSE_OFF;
    	}
    	return (True);
        }
    
        /*
         * event:
         *        1       no buttons
         *        2       left button down
         *        3       left button up
         *        4       middle button down
         *        5       middle button up
         *        6       right button down
         *        7       right button up
         *        8       M4 down
         *        9       M4 up
         */
        reply.a_nparam = 4;
        switch (event->type) {
        case ButtonPress:
    	reply.a_param[0] = (ParmType) (2 + (button << 1));
    	break;
        case ButtonRelease:
    	reply.a_param[0] = (ParmType) (3 + (button << 1));
    	break;
        default:
    	return (True);
        }
        /*
         * mask:
         * bit7   bit6   bit5   bit4   bit3     bit2       bit1         bit0
         *                             M4 down  left down  middle down  right down
         *
         * Notice that Button1 (left) and Button3 (right) are swapped in the mask.
         * Also, mask should be the state after the button press/release,
         * X provides the state not including the button press/release.
         */
        state = (event->state
    	     & (Button1Mask | Button2Mask | Button3Mask | Button4Mask)) >> 8;
        /* update mask to "after" state */
        state ^= ((unsigned) (1 << button));
        /* swap Button1 & Button3 */
        state = ((state & (unsigned) ~(4 | 1))
    	     | ((state & 1) ? 4 : 0)
    	     | ((state & 4) ? 1 : 0));
    
        reply.a_param[1] = (ParmType) state;
        reply.a_param[2] = (ParmType) row;
        reply.a_param[3] = (ParmType) col;
        reply.a_inters = '&';
        reply.a_final = 'w';
    
        unparseseq(xw, &reply);
    
        if (screen->locator_reset) {
    	MotionOff(screen, xw);
    	screen->send_mouse_pos = MOUSE_OFF;
        }
    
        /*
         * DECterm turns the Locator off if a button is pressed while a filter
         * rectangle is active.  This might be a bug, but I don't know, so I'll
         * emulate it anyway.
         */
        if (screen->loc_filter) {
    	screen->send_mouse_pos = MOUSE_OFF;
    	screen->loc_filter = False;
    	screen->locator_events = 0;
    	MotionOff(screen, xw);
        }
    
        return (True);
    }
    
    /*
     * mask:
     * bit 7   bit 6   bit 5   bit 4   bit 3   bit 2       bit 1         bit 0
     *                                 M4 down left down   middle down   right down
     *
     * Button1 (left) and Button3 (right) are swapped in the mask relative to X.
     */
    #define	ButtonState(state, mask)	\
    { int stemp = (int) (((mask) & (Button1Mask | Button2Mask | Button3Mask | Button4Mask)) >> 8);	\
      /* swap Button1 & Button3 */								\
      (state) = (stemp & ~(4|1)) | ((stemp & 1) ? 4 : 0) | ((stemp & 4) ? 1 : 0);			\
    }
    
    void
    GetLocatorPosition(XtermWidget xw)
    {
        ANSI reply;
        TScreen *screen = TScreenOf(xw);
        Window root, child;
        int rx, ry, x, y;
        unsigned int mask;
        int row = 0, col = 0;
        Bool oor = False;
        Bool ret = False;
        int state;
    
        /*
         * DECterm turns the Locator off if the position is requested while a
         * filter rectangle is active.  This might be a bug, but I don't know, so
         * I'll emulate it anyways.
         */
        if (screen->loc_filter) {
    	screen->send_mouse_pos = MOUSE_OFF;
    	screen->loc_filter = False;
    	screen->locator_events = 0;
    	MotionOff(screen, xw);
        }
    
        memset(&reply, 0, sizeof(reply));
        reply.a_type = ANSI_CSI;
    
        if (okSendMousePos(xw) == DEC_LOCATOR) {
    	ret = XQueryPointer(screen->display, VWindow(screen), &root,
    			    &child, &rx, &ry, &x, &y, &mask);
    	if (ret) {
    	    LocatorCoords(row, col, x, y, oor);
    	}
        }
        if (ret == False || oor) {
    	reply.a_nparam = 1;
    	reply.a_param[0] = 0;	/* Event - 0 = locator unavailable */
    	reply.a_inters = '&';
    	reply.a_final = 'w';
    	unparseseq(xw, &reply);
    
    	if (screen->locator_reset) {
    	    MotionOff(screen, xw);
    	    screen->send_mouse_pos = MOUSE_OFF;
    	}
    	return;
        }
    
        ButtonState(state, mask);
    
        reply.a_nparam = 4;
        reply.a_param[0] = 1;	/* Event - 1 = response to locator request */
        reply.a_param[1] = (ParmType) state;
        reply.a_param[2] = (ParmType) row;
        reply.a_param[3] = (ParmType) col;
        reply.a_inters = '&';
        reply.a_final = 'w';
        unparseseq(xw, &reply);
    
        if (screen->locator_reset) {
    	MotionOff(screen, xw);
    	screen->send_mouse_pos = MOUSE_OFF;
        }
    }
    
    void
    InitLocatorFilter(XtermWidget xw)
    {
        ANSI reply;
        TScreen *screen = TScreenOf(xw);
        Window root, child;
        int rx, ry, x, y;
        unsigned int mask;
        int row = 0, col = 0;
        Bool oor = 0;
        Bool ret;
    
        ret = XQueryPointer(screen->display, VWindow(screen),
    			&root, &child, &rx, &ry, &x, &y, &mask);
        if (ret) {
    	LocatorCoords(row, col, x, y, oor);
        }
        if (ret == False || oor) {
    	/* Locator is unavailable */
    
    	if (screen->loc_filter_top != LOC_FILTER_POS ||
    	    screen->loc_filter_left != LOC_FILTER_POS ||
    	    screen->loc_filter_bottom != LOC_FILTER_POS ||
    	    screen->loc_filter_right != LOC_FILTER_POS) {
    	    /*
    	     * If any explicit coordinates were received,
    	     * report immediately with no coordinates.
    	     */
    	    memset(&reply, 0, sizeof(reply));
    	    reply.a_type = ANSI_CSI;
    	    reply.a_nparam = 1;
    	    reply.a_param[0] = 0;	/* Event - 0 = locator unavailable */
    	    reply.a_inters = '&';
    	    reply.a_final = 'w';
    	    unparseseq(xw, &reply);
    
    	    if (screen->locator_reset) {
    		MotionOff(screen, xw);
    		screen->send_mouse_pos = MOUSE_OFF;
    	    }
    	} else {
    	    /*
    	     * No explicit coordinates were received, and the pointer is
    	     * unavailable.  Report when the pointer re-enters the window.
    	     */
    	    screen->loc_filter = True;
    	    MotionOn(screen, xw);
    	}
    	return;
        }
    
        /*
         * Adjust rectangle coordinates:
         *  1. Replace "LOC_FILTER_POS" with current coordinates
         *  2. Limit coordinates to screen size
         *  3. make sure top and left are less than bottom and right, resp.
         */
        if (screen->locator_pixels) {
    	rx = OriginX(screen) * 2 + Width(screen);
    	ry = screen->border * 2 + Height(screen);
        } else {
    	rx = screen->max_col;
    	ry = screen->max_row;
        }
    
    #define	Adjust( coord, def, max )				\
    	if( (coord) == LOC_FILTER_POS )	(coord) = (def);	\
    	else if ((coord) < 1)		(coord) = 1;		\
    	else if ((coord) > (max))	(coord) = (max)
    
        Adjust(screen->loc_filter_top, row, ry);
        Adjust(screen->loc_filter_left, col, rx);
        Adjust(screen->loc_filter_bottom, row, ry);
        Adjust(screen->loc_filter_right, col, rx);
    
        if (screen->loc_filter_top > screen->loc_filter_bottom) {
    	ry = screen->loc_filter_top;
    	screen->loc_filter_top = screen->loc_filter_bottom;
    	screen->loc_filter_bottom = ry;
        }
    
        if (screen->loc_filter_left > screen->loc_filter_right) {
    	rx = screen->loc_filter_left;
    	screen->loc_filter_left = screen->loc_filter_right;
    	screen->loc_filter_right = rx;
        }
    
        if ((col < screen->loc_filter_left) ||
    	(col > screen->loc_filter_right) ||
    	(row < screen->loc_filter_top) ||
    	(row > screen->loc_filter_bottom)) {
    	int state;
    
    	/* Pointer is already outside the rectangle - report immediately */
    	ButtonState(state, mask);
    
    	memset(&reply, 0, sizeof(reply));
    	reply.a_type = ANSI_CSI;
    	reply.a_nparam = 4;
    	reply.a_param[0] = 10;	/* Event - 10 = locator outside filter */
    	reply.a_param[1] = (ParmType) state;
    	reply.a_param[2] = (ParmType) row;
    	reply.a_param[3] = (ParmType) col;
    	reply.a_inters = '&';
    	reply.a_final = 'w';
    	unparseseq(xw, &reply);
    
    	if (screen->locator_reset) {
    	    MotionOff(screen, xw);
    	    screen->send_mouse_pos = MOUSE_OFF;
    	}
    	return;
        }
    
        /*
         * Rectangle is set up.  Allow pointer tracking
         * to detect if the mouse leaves the rectangle.
         */
        screen->loc_filter = True;
        MotionOn(screen, xw);
    }
    
    static void
    CheckLocatorPosition(XtermWidget xw, XButtonEvent *event)
    {
        ANSI reply;
        TScreen *screen = TScreenOf(xw);
        int row, col;
        Bool oor;
    
        LocatorCoords(row, col, event->x, event->y, oor);
    
        /*
         * Send report if the pointer left the filter rectangle, if
         * the pointer left the window, or if the filter rectangle
         * had no coordinates and the pointer re-entered the window.
         */
        if (oor || (screen->loc_filter_top == LOC_FILTER_POS) ||
    	(col < screen->loc_filter_left) ||
    	(col > screen->loc_filter_right) ||
    	(row < screen->loc_filter_top) ||
    	(row > screen->loc_filter_bottom)) {
    	/* Filter triggered - disable it */
    	screen->loc_filter = False;
    	MotionOff(screen, xw);
    
    	memset(&reply, 0, sizeof(reply));
    	reply.a_type = ANSI_CSI;
    	if (oor) {
    	    reply.a_nparam = 1;
    	    reply.a_param[0] = 0;	/* Event - 0 = locator unavailable */
    	} else {
    	    int state;
    
    	    ButtonState(state, event->state);
    
    	    reply.a_nparam = 4;
    	    reply.a_param[0] = 10;	/* Event - 10 = locator outside filter */
    	    reply.a_param[1] = (ParmType) state;
    	    reply.a_param[2] = (ParmType) row;
    	    reply.a_param[3] = (ParmType) col;
    	}
    
    	reply.a_inters = '&';
    	reply.a_final = 'w';
    	unparseseq(xw, &reply);
    
    	if (screen->locator_reset) {
    	    MotionOff(screen, xw);
    	    screen->send_mouse_pos = MOUSE_OFF;
    	}
        }
    }
    #endif /* OPT_DEC_LOCATOR */
    
    #if OPT_READLINE
    static int
    isClick1_clean(XtermWidget xw, XButtonEvent *event)
    {
        TScreen *screen = TScreenOf(xw);
        int delta;
    
        if (!IsBtnEvent(event)
        /* Disable on Shift-Click-1, including the application-mouse modes */
    	|| (BtnModifiers(event) & ShiftMask)
    	|| (okSendMousePos(xw) != MOUSE_OFF)	/* Kinda duplicate... */
    	||ExtendingSelection)	/* Was moved */
    	return 0;
    
        if (event->type != ButtonRelease)
    	return 0;
    
        if (lastButtonDownTime == (Time) 0) {
    	/* first time or once in a blue moon */
    	delta = screen->multiClickTime + 1;
        } else if (event->time > lastButtonDownTime) {
    	/* most of the time */
    	delta = (int) (event->time - lastButtonDownTime);
        } else {
    	/* time has rolled over since lastButtonUpTime */
    	delta = (int) ((((Time) ~ 0) - lastButtonDownTime) + event->time);
        }
    
        return delta <= screen->multiClickTime;
    }
    
    static int
    isDoubleClick3(TScreen *screen, XButtonEvent *event)
    {
        int delta;
    
        if (event->type != ButtonRelease
    	|| (BtnModifiers(event) & ShiftMask)
    	|| event->button != Button3) {
    	lastButton3UpTime = 0;	/* Disable the cached info */
    	return 0;
        }
        /* Process Btn3Release. */
        if (lastButton3DoubleDownTime == (Time) 0) {
    	/* No previous click or once in a blue moon */
    	delta = screen->multiClickTime + 1;
        } else if (event->time > lastButton3DoubleDownTime) {
    	/* most of the time */
    	delta = (int) (event->time - lastButton3DoubleDownTime);
        } else {
    	/* time has rolled over since lastButton3DoubleDownTime */
    	delta = (int) ((((Time) ~ 0) - lastButton3DoubleDownTime) + event->time);
        }
        if (delta <= screen->multiClickTime) {
    	/* Double click */
    	CELL cell;
    
    	/* Cannot check ExtendingSelection, since mouse-3 always sets it */
    	PointToCELL(screen, event->y, event->x, &cell);
    	if (isSameCELL(&cell, &lastButton3)) {
    	    lastButton3DoubleDownTime = 0;	/* Disable the third click */
    	    return 1;
    	}
        }
        /* Not a double click, memorize for future check. */
        lastButton3UpTime = event->time;
        PointToCELL(screen, event->y, event->x, &lastButton3);
        return 0;
    }
    
    static int
    CheckSecondPress3(TScreen *screen, XEvent *event)
    {
        int delta;
    
        if (event->type != ButtonPress
    	|| (KeyModifiers(event) & ShiftMask)
    	|| event->xbutton.button != Button3) {
    	lastButton3DoubleDownTime = 0;	/* Disable the cached info */
    	return 0;
        }
        /* Process Btn3Press. */
        if (lastButton3UpTime == (Time) 0) {
    	/* No previous click or once in a blue moon */
    	delta = screen->multiClickTime + 1;
        } else if (event->xbutton.time > lastButton3UpTime) {
    	/* most of the time */
    	delta = (int) (event->xbutton.time - lastButton3UpTime);
        } else {
    	/* time has rolled over since lastButton3UpTime */
    	delta = (int) ((((Time) ~ 0) - lastButton3UpTime) + event->xbutton.time);
        }
        if (delta <= screen->multiClickTime) {
    	CELL cell;
    
    	PointToCELL(screen, event->xbutton.y, event->xbutton.x, &cell);
    	if (isSameCELL(&cell, &lastButton3)) {
    	    /* A candidate for a double-click */
    	    lastButton3DoubleDownTime = event->xbutton.time;
    	    PointToCELL(screen, event->xbutton.y, event->xbutton.x, &lastButton3);
    	    return 1;
    	}
    	lastButton3UpTime = 0;	/* Disable the info about the previous click */
        }
        /* Either too long, or moved, disable. */
        lastButton3DoubleDownTime = 0;
        return 0;
    }
    
    static int
    rowOnCurrentLine(TScreen *screen,
    		 int line,
    		 int *deltap)	/* must be XButtonEvent */
    {
        int result = 1;
    
        *deltap = 0;
    
        if (line != screen->cur_row) {
    	int l1, l2;
    
    	if (line < screen->cur_row)
    	    l1 = line, l2 = screen->cur_row;
    	else
    	    l2 = line, l1 = screen->cur_row;
    	l1--;
    	while (++l1 < l2) {
    	    LineData *ld = GET_LINEDATA(screen, l1);
    	    if (!LineTstWrapped(ld)) {
    		result = 0;
    		break;
    	    }
    	}
    	if (result) {
    	    /* Everything is on one "wrapped line" now */
    	    *deltap = line - screen->cur_row;
    	}
        }
        return result;
    }
    
    static int
    eventRow(TScreen *screen, XEvent *event)	/* must be XButtonEvent */
    {
        return (event->xbutton.y - screen->border) / FontHeight(screen);
    }
    
    static int
    eventColBetween(TScreen *screen, XEvent *event)		/* must be XButtonEvent */
    {
        /* Correct by half a width - we are acting on a boundary, not on a cell. */
        return ((event->xbutton.x - OriginX(screen) + (FontWidth(screen) - 1) / 2)
    	    / FontWidth(screen));
    }
    
    static int
    ReadLineMovePoint(TScreen *screen, int col, int ldelta)
    {
        Char line[6];
        unsigned count = 0;
    
        col += ldelta * MaxCols(screen) - screen->cur_col;
        if (col == 0)
    	return 0;
        if (screen->control_eight_bits) {
    	line[count++] = ANSI_CSI;
        } else {
    	line[count++] = ANSI_ESC;
    	line[count++] = '[';	/* XXX maybe sometimes O is better? */
        }
        line[count] = CharOf(col > 0 ? 'C' : 'D');
        if (col < 0)
    	col = -col;
        while (col--)
    	v_write(screen->respond, line, 3);
        return 1;
    }
    
    static int
    ReadLineDelete(TScreen *screen, CELL *cell1, CELL *cell2)
    {
        int del;
    
        del = (cell2->col - cell1->col) + ((cell2->row - cell1->row) * MaxCols(screen));
        if (del <= 0)		/* Just in case... */
    	return 0;
        while (del--)
    	v_write(screen->respond, (const Char *) "\177", 1);
        return 1;
    }
    
    static void
    readlineExtend(XtermWidget xw, XEvent *event)
    {
        TScreen *screen = TScreenOf(xw);
        int ldelta1, ldelta2;
    
        if (IsBtnEvent(event)) {
    	XButtonEvent *my_event = (XButtonEvent *) event;
    	if (isClick1_clean(xw, my_event)
    	    && SCREEN_FLAG(screen, click1_moves)
    	    && rowOnCurrentLine(screen, eventRow(screen, event), &ldelta1)) {
    	    ReadLineMovePoint(screen, eventColBetween(screen, event), ldelta1);
    	}
    	if (isDoubleClick3(screen, my_event)
    	    && SCREEN_FLAG(screen, dclick3_deletes)
    	    && rowOnCurrentLine(screen, screen->startSel.row, &ldelta1)
    	    && rowOnCurrentLine(screen, screen->endSel.row, &ldelta2)) {
    	    ReadLineMovePoint(screen, screen->endSel.col, ldelta2);
    	    ReadLineDelete(screen, &screen->startSel, &(screen->endSel));
    	}
        }
    }
    #endif /* OPT_READLINE */
    
    /* ^XM-G */
    void
    DiredButton(Widget w,
    	    XEvent *event,	/* must be XButtonEvent */
    	    String *params GCC_UNUSED,	/* selections */
    	    Cardinal *num_params GCC_UNUSED)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TScreen *screen = TScreenOf(xw);
    
    	if (IsBtnEvent(event)
    	    && (event->xbutton.y >= screen->border)
    	    && (event->xbutton.x >= OriginX(screen))) {
    	    Char Line[6];
    	    unsigned line, col;
    
    	    line = (unsigned) ((event->xbutton.y - screen->border)
    			       / FontHeight(screen));
    	    col = (unsigned) ((event->xbutton.x - OriginX(screen))
    			      / FontWidth(screen));
    	    Line[0] = CONTROL('X');
    	    Line[1] = ANSI_ESC;
    	    Line[2] = 'G';
    	    Line[3] = CharOf(' ' + col);
    	    Line[4] = CharOf(' ' + line);
    	    v_write(screen->respond, Line, 5);
    	}
        }
    }
    
    #if OPT_READLINE
    void
    ReadLineButton(Widget w,
    	       XEvent *event,	/* must be XButtonEvent */
    	       String *params GCC_UNUSED,	/* selections */
    	       Cardinal *num_params GCC_UNUSED)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TScreen *screen = TScreenOf(xw);
    	Char Line[6];
    	int line, col, ldelta = 0;
    
    	if (!IsBtnEvent(event)
    	    || (okSendMousePos(xw) != MOUSE_OFF) || ExtendingSelection)
    	    goto finish;
    	if (event->type == ButtonRelease) {
    	    int delta;
    
    	    if (lastButtonDownTime == (Time) 0) {
    		/* first time and once in a blue moon */
    		delta = screen->multiClickTime + 1;
    	    } else if (event->xbutton.time > lastButtonDownTime) {
    		/* most of the time */
    		delta = (int) (event->xbutton.time - lastButtonDownTime);
    	    } else {
    		/* time has rolled over since lastButtonUpTime */
    		delta = (int) ((((Time) ~ 0) - lastButtonDownTime) + event->xbutton.time);
    	    }
    	    if (delta > screen->multiClickTime)
    		goto finish;	/* All this work for this... */
    	}
    	line = (event->xbutton.y - screen->border) / FontHeight(screen);
    	if (!rowOnCurrentLine(screen, line, &ldelta))
    	    goto finish;
    	/* Correct by half a width - we are acting on a boundary, not on a cell. */
    	col = (event->xbutton.x - OriginX(screen) + (FontWidth(screen) - 1)
    	       / 2)
    	    / FontWidth(screen) - screen->cur_col + ldelta * MaxCols(screen);
    	if (col == 0)
    	    goto finish;
    	Line[0] = ANSI_ESC;
    	/* XXX: sometimes it is better to send '['? */
    	Line[1] = 'O';
    	Line[2] = CharOf(col > 0 ? 'C' : 'D');
    	if (col < 0)
    	    col = -col;
    	while (col--)
    	    v_write(screen->respond, Line, 3);
          finish:
    	if (event->type == ButtonRelease)
    	    do_select_end(xw, event, params, num_params, False);
        }
    }
    #endif /* OPT_READLINE */
    
    /* repeats n or p */
    void
    ViButton(Widget w,
    	 XEvent *event,		/* must be XButtonEvent */
    	 String *params GCC_UNUSED,	/* selections */
    	 Cardinal *num_params GCC_UNUSED)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TScreen *screen = TScreenOf(xw);
    	int pty = screen->respond;
    
    	if (IsBtnEvent(event)) {
    	    int line;
    
    	    line = screen->cur_row -
    		((event->xbutton.y - screen->border) / FontHeight(screen));
    
    	    if (line != 0) {
    		Char Line[6];
    
    		Line[0] = ANSI_ESC;	/* force an exit from insert-mode */
    		v_write(pty, Line, 1);
    
    		if (line < 0) {
    		    line = -line;
    		    Line[0] = CONTROL('n');
    		} else {
    		    Line[0] = CONTROL('p');
    		}
    		while (--line >= 0)
    		    v_write(pty, Line, 1);
    	    }
    	}
        }
    }
    
    /*
     * This function handles button-motion events
     */
    /*ARGSUSED*/
    void
    HandleSelectExtend(Widget w,
    		   XEvent *event,	/* must be XMotionEvent */
    		   String *params GCC_UNUSED,
    		   Cardinal *num_params GCC_UNUSED)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TScreen *screen = TScreenOf(xw);
    	CELL cell;
    
    	TRACE_EVENT("HandleSelectExtend", event, params, num_params);
    
    	screen->selection_time = event->xmotion.time;
    	switch (screen->eventMode) {
    	    /* If not in one of the DEC mouse-reporting modes */
    	case LEFTEXTENSION:
    	case RIGHTEXTENSION:
    	    PointToCELL(screen, event->xmotion.y, event->xmotion.x, &cell);
    	    ExtendExtend(xw, &cell);
    	    break;
    
    	    /* If in motion reporting mode, send mouse position to
    	       character process as a key sequence \E[M... */
    	case NORMAL:
    	    /* will get here if send_mouse_pos != MOUSE_OFF */
    	    if (okSendMousePos(xw) == BTN_EVENT_MOUSE
    		|| okSendMousePos(xw) == ANY_EVENT_MOUSE) {
    		(void) SendMousePosition(xw, event);
    	    }
    	    break;
    	}
        }
    }
    
    void
    HandleKeyboardSelectExtend(Widget w,
    			   XEvent *event GCC_UNUSED,	/* must be XButtonEvent */
    			   String *params GCC_UNUSED,
    			   Cardinal *num_params GCC_UNUSED)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TScreen *screen = TScreenOf(xw);
    
    	TRACE_EVENT("HandleKeyboardSelectExtend", event, params, num_params);
    	ExtendExtend(xw, &screen->cursorp);
        }
    }
    
    static void
    do_select_end(XtermWidget xw,
    	      XEvent *event,	/* must be XButtonEvent */
    	      String *params,	/* selections */
    	      Cardinal *num_params,
    	      Bool use_cursor_loc)
    {
        TScreen *screen = TScreenOf(xw);
    
        screen->selection_time = event->xbutton.time;
    
        TRACE(("do_select_end %s @%ld\n",
    	   visibleEventMode(screen->eventMode),
    	   screen->selection_time));
    
        switch (screen->eventMode) {
        case NORMAL:
    	(void) SendMousePosition(xw, event);
    	break;
        case LEFTEXTENSION:
        case RIGHTEXTENSION:
    	EndExtend(xw, event, params, *num_params, use_cursor_loc);
    #if OPT_READLINE
    	readlineExtend(xw, event);
    #endif /* OPT_READLINE */
    	break;
        }
    }
    
    void
    HandleSelectEnd(Widget w,
    		XEvent *event,	/* must be XButtonEvent */
    		String *params,	/* selections */
    		Cardinal *num_params)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TRACE(("HandleSelectEnd\n"));
    	do_select_end(xw, event, params, num_params, False);
        }
    }
    
    void
    HandleKeyboardSelectEnd(Widget w,
    			XEvent *event,	/* must be XButtonEvent */
    			String *params,		/* selections */
    			Cardinal *num_params)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TRACE(("HandleKeyboardSelectEnd\n"));
    	do_select_end(xw, event, params, num_params, True);
        }
    }
    
    /*
     * Copy the selection data to the given target(s).
     */
    void
    HandleCopySelection(Widget w,
    		    XEvent *event,
    		    String *params,	/* list of targets */
    		    Cardinal *num_params)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TRACE_EVENT("HandleCopySelection", event, params, num_params);
    	SelectSet(xw, event, params, *num_params);
        }
    }
    
    struct _SelectionList {
        String *params;
        Cardinal count;
        Atom *targets;
        Time time;
    };
    
    static unsigned
    DECtoASCII(unsigned ch)
    {
        if (xtermIsDecGraphic(ch)) {
    	ch = CharOf("###########+++++##-##++++|######"[ch]);
    	/*           01234567890123456789012345678901 */
        }
        return ch;
    }
    
    #if OPT_WIDE_CHARS
    static Cardinal
    addXtermChar(Char **buffer, Cardinal *used, Cardinal offset, unsigned value)
    {
        if (offset + 1 >= *used) {
    	*used = 1 + (2 * (offset + 1));
    	allocXtermChars(buffer, *used);
        }
        (*buffer)[offset++] = (Char) value;
        return offset;
    }
    #define AddChar(buffer, used, offset, value) \
    	offset = addXtermChar(buffer, used, offset, (unsigned) value)
    
    /*
     * Convert a UTF-8 string to Latin-1, replacing non Latin-1 characters by `#',
     * or ASCII/Latin-1 equivalents for special cases.
     */
    static Char *
    UTF8toLatin1(TScreen *screen, Char *s, unsigned long len, unsigned long *result)
    {
        static Char *buffer;
        static Cardinal used;
    
        Cardinal offset = 0;
    
        if (len != 0) {
    	PtyData data;
    
    	fakePtyData(&data, s, s + len);
    	while (decodeUtf8(screen, &data)) {
    	    Bool fails = False;
    	    Bool extra = False;
    	    IChar value;
    	    skipPtyData(&data, value);
    	    if (value == UCS_REPL) {
    		fails = True;
    	    } else if (value < 256) {
    		AddChar(&buffer, &used, offset, CharOf(value));
    	    } else {
    		unsigned eqv = ucs2dec(screen, value);
    		if (xtermIsDecGraphic(eqv)) {
    		    AddChar(&buffer, &used, offset, DECtoASCII(eqv));
    		} else {
    		    eqv = AsciiEquivs(value);
    		    if (eqv == value) {
    			fails = True;
    		    } else {
    			AddChar(&buffer, &used, offset, eqv);
    		    }
    		    if (isWide((wchar_t) value))
    			extra = True;
    		}
    	    }
    
    	    /*
    	     * If we're not able to plug in a single-byte result, insert the
    	     * defaultString (which normally is a single "#", but could be
    	     * whatever the user wants).
    	     */
    	    if (fails) {
    		const Char *p;
    
    		for (p = (const Char *) screen->default_string; *p != '\0'; ++p) {
    		    AddChar(&buffer, &used, offset, *p);
    		}
    	    }
    	    if (extra)
    		AddChar(&buffer, &used, offset, ' ');
    	}
    	AddChar(&buffer, &used, offset, '\0');
    	*result = (unsigned long) (offset - 1);
        } else {
    	*result = 0;
        }
        return buffer;
    }
    
    int
    xtermUtf8ToTextList(XtermWidget xw,
    		    XTextProperty * text_prop,
    		    char ***text_list,
    		    int *text_list_count)
    {
        TScreen *screen = TScreenOf(xw);
        Display *dpy = screen->display;
        int rc = -1;
    
        if (text_prop->format == 8
    	&& (rc = Xutf8TextPropertyToTextList(dpy, text_prop,
    					     text_list,
    					     text_list_count)) >= 0) {
    	if (*text_list != NULL && *text_list_count != 0) {
    	    int i;
    	    Char *data;
    	    char **new_text_list, *tmp;
    	    unsigned long size, new_size;
    
    	    TRACE(("xtermUtf8ToTextList size %d\n", *text_list_count));
    
    	    /*
    	     * XLib StringList actually uses only two pointers, one for the
    	     * list itself, and one for the data.  Pointer to the data is the
    	     * first element of the list, the rest (if any) list elements point
    	     * to the same memory block as the first element
    	     */
    	    new_size = 0;
    	    for (i = 0; i < *text_list_count; ++i) {
    		data = (Char *) (*text_list)[i];
    		size = strlen((*text_list)[i]) + 1;
    		(void) UTF8toLatin1(screen, data, size, &size);
    		new_size += size + 1;
    	    }
    	    new_text_list = TypeXtMallocN(char *, *text_list_count);
    	    new_text_list[0] = tmp = XtMalloc((Cardinal) new_size);
    	    for (i = 0; i < (*text_list_count); ++i) {
    		data = (Char *) (*text_list)[i];
    		size = strlen((*text_list)[i]) + 1;
    		if ((data = UTF8toLatin1(screen, data, size, &size)) != 0) {
    		    memcpy(tmp, data, size + 1);
    		    new_text_list[i] = tmp;
    		    tmp += size + 1;
    		}
    	    }
    	    XFreeStringList((*text_list));
    	    *text_list = new_text_list;
    	} else {
    	    rc = -1;
    	}
        }
        return rc;
    }
    #endif /* OPT_WIDE_CHARS */
    
    static char *
    parseItem(char *value, char *nextc)
    {
        char *nextp = value;
        while (*nextp != '\0' && *nextp != ',') {
    	*nextp = x_toupper(*nextp);
    	++nextp;
        }
        *nextc = *nextp;
        *nextp = '\0';
    
        return nextp;
    }
    
    /*
     * All of the wanted strings are unique in the first character, so we can
     * use simple abbreviations.
     */
    static Bool
    sameItem(const char *actual, const char *wanted)
    {
        Bool result = False;
        size_t have = strlen(actual);
        size_t need = strlen(wanted);
    
        if (have != 0 && have <= need) {
    	if (!strncmp(actual, wanted, have)) {
    	    TRACE(("...matched \"%s\"\n", wanted));
    	    result = True;
    	}
        }
    
        return result;
    }
    
    /*
     * Handle the eightBitSelectTypes or utf8SelectTypes resource values.
     */
    static Bool
    overrideTargets(Widget w, String value, Atom **resultp)
    {
        Bool override = False;
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TScreen *screen = TScreenOf(xw);
    
    	if (!IsEmpty(value)) {
    	    char *copied = x_strdup(value);
    	    if (copied != 0) {
    		Atom *result = 0;
    		Cardinal count = 1;
    		int n;
    
    		TRACE(("decoding SelectTypes \"%s\"\n", value));
    		for (n = 0; copied[n] != '\0'; ++n) {
    		    if (copied[n] == ',')
    			++count;
    		}
    		result = TypeXtMallocN(Atom, (2 * count) + 1);
    		if (result == NULL) {
    		    TRACE(("Couldn't allocate selection types\n"));
    		} else {
    		    char nextc = '?';
    		    char *listp = (char *) copied;
    		    count = 0;
    		    do {
    			char *nextp = parseItem(listp, &nextc);
    			char *item = x_strtrim(listp);
    			size_t len = (item ? strlen(item) : 0);
    
    			if (len == 0) {
    			    /* EMPTY */ ;
    			}
    #if OPT_WIDE_CHARS
    			else if (sameItem(item, "UTF8")) {
    			    result[count++] = XA_UTF8_STRING(XtDisplay(w));
    			}
    #endif
    			else if (sameItem(item, "I18N")) {
    			    if (screen->i18nSelections) {
    				result[count++] = XA_TEXT(XtDisplay(w));
    				result[count++] = XA_COMPOUND_TEXT(XtDisplay(w));
    			    }
    			} else if (sameItem(item, "TEXT")) {
    			    result[count++] = XA_TEXT(XtDisplay(w));
    			} else if (sameItem(item, "COMPOUND_TEXT")) {
    			    result[count++] = XA_COMPOUND_TEXT(XtDisplay(w));
    			} else if (sameItem(item, "STRING")) {
    			    result[count++] = XA_STRING;
    			}
    			*nextp++ = nextc;
    			listp = nextp;
    			free(item);
    		    } while (nextc != '\0');
    		    if (count) {
    			result[count] = None;
    			override = True;
    			*resultp = result;
    		    } else {
    			XtFree((char *) result);
    		    }
    		}
    		free(copied);
    	    } else {
    		TRACE(("Couldn't allocate copy of selection types\n"));
    	    }
    	}
        }
        return override;
    }
    
    #if OPT_WIDE_CHARS
    static Atom *
    allocUtf8Targets(Widget w, TScreen *screen)
    {
        Atom **resultp = &(screen->selection_targets_utf8);
    
        if (*resultp == 0) {
    	Atom *result;
    
    	if (!overrideTargets(w, screen->utf8_select_types, &result)) {
    	    result = TypeXtMallocN(Atom, 5);
    	    if (result == NULL) {
    		TRACE(("Couldn't allocate utf-8 selection targets\n"));
    	    } else {
    		int n = 0;
    
    		if (XSupportsLocale()) {
    		    result[n++] = XA_UTF8_STRING(XtDisplay(w));
    #ifdef X_HAVE_UTF8_STRING
    		    if (screen->i18nSelections) {
    			result[n++] = XA_TEXT(XtDisplay(w));
    			result[n++] = XA_COMPOUND_TEXT(XtDisplay(w));
    		    }
    #endif
    		}
    		result[n++] = XA_STRING;
    		result[n] = None;
    	    }
    	}
    
    	*resultp = result;
        }
    
        return *resultp;
    }
    #endif
    
    static Atom *
    alloc8bitTargets(Widget w, TScreen *screen)
    {
        Atom **resultp = &(screen->selection_targets_8bit);
    
        if (*resultp == 0) {
    	Atom *result = 0;
    
    	if (!overrideTargets(w, screen->eightbit_select_types, &result)) {
    	    result = TypeXtMallocN(Atom, 5);
    	    if (result == NULL) {
    		TRACE(("Couldn't allocate 8bit selection targets\n"));
    	    } else {
    		int n = 0;
    
    		if (XSupportsLocale()) {
    #ifdef X_HAVE_UTF8_STRING
    		    result[n++] = XA_UTF8_STRING(XtDisplay(w));
    #endif
    		    if (screen->i18nSelections) {
    			result[n++] = XA_TEXT(XtDisplay(w));
    			result[n++] = XA_COMPOUND_TEXT(XtDisplay(w));
    		    }
    		}
    		result[n++] = XA_STRING;
    		result[n] = None;
    	    }
    	}
    
    	*resultp = result;
        }
    
        return *resultp;
    }
    
    static Atom *
    _SelectionTargets(Widget w)
    {
        Atom *result;
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) == 0) {
    	result = NULL;
        } else {
    	TScreen *screen = TScreenOf(xw);
    
    #if OPT_WIDE_CHARS
    	if (screen->wide_chars) {
    	    result = allocUtf8Targets(w, screen);
    	} else
    #endif
    	{
    	    /* not screen->wide_chars */
    	    result = alloc8bitTargets(w, screen);
    	}
        }
    
        return result;
    }
    
    #define isSELECT(value) (!strcmp(value, "SELECT"))
    
    static int
    DefaultSelection(TScreen *screen)
    {
        return (screen->selectToClipboard ? 1 : 0);
    }
    
    static int
    TargetToSelection(TScreen *screen, String name)
    {
        int result = -1;
        int cutb;
    
        if (isSELECT(name)) {
    	result = DefaultSelection(screen);
        } else if (!strcmp(name, PRIMARY_NAME)) {
    	result = PRIMARY_CODE;
        } else if (!strcmp(name, CLIPBOARD_NAME)) {
    	result = CLIPBOARD_CODE;
        } else if (!strcmp(name, SECONDARY_NAME)) {
    	result = SECONDARY_CODE;
        } else if (sscanf(name, "CUT_BUFFER%d", &cutb) == 1) {
    	if (cutb >= 0 && cutb < MAX_CUT_BUFFER) {
    	    result = CutBufferToCode(cutb);
    	} else {
    	    xtermWarning("unexpected cut-buffer code: %d\n", cutb);
    	}
        } else {
    	xtermWarning("unexpected selection target: %s\n", name);
        }
        TRACE2(("TargetToSelection(%s) ->%d\n", name, result));
        return result;
    }
    
    static void
    UnmapSelections(XtermWidget xw)
    {
        TScreen *screen = TScreenOf(xw);
        Cardinal n;
    
        if (screen->mappedSelect) {
    	for (n = 0; screen->mappedSelect[n] != 0; ++n)
    	    free((void *) screen->mappedSelect[n]);
    	free(screen->mappedSelect);
    	screen->mappedSelect = 0;
        }
    }
    
    /*
     * xterm generally uses the primary selection.  Some applications prefer
     * (or are limited to) the clipboard.  Since the translations resource is
     * complicated, users seldom change the way it affects selection.  But it
     * is simple to remap the choice between primary and clipboard before the
     * call to XmuInternStrings().
     */
    static String *
    MapSelections(XtermWidget xw, String *params, Cardinal num_params)
    {
        String *result = params;
    
        if (params != 0 && num_params > 0) {
    	Cardinal j;
    	Boolean map = False;
    
    	for (j = 0; j < num_params; ++j) {
    	    TRACE(("param[%d]:%s\n", j, params[j]));
    	    if (isSELECT(params[j])) {
    		map = True;
    		break;
    	    }
    	}
    	if (map) {
    	    TScreen *screen = TScreenOf(xw);
    	    const char *mapTo = (screen->selectToClipboard
    				 ? CLIPBOARD_NAME
    				 : PRIMARY_NAME);
    
    	    UnmapSelections(xw);
    	    if ((result = TypeMallocN(String, num_params + 1)) != 0) {
    		result[num_params] = 0;
    		for (j = 0; j < num_params; ++j) {
    		    result[j] = x_strdup((isSELECT(params[j])
    					  ? mapTo
    					  : params[j]));
    		    if (result[j] == 0) {
    			UnmapSelections(xw);
    			while (j != 0) {
    			    free((void *) result[--j]);
    			}
    			free(result);
    			result = 0;
    			break;
    		    }
    		}
    		screen->mappedSelect = result;
    	    }
    	}
        }
        return result;
    }
    
    /*
     * Lookup the cut-buffer number, which will be in the range 0-7.
     * If it is not a cut-buffer, it is a type of selection, e.g., primary.
     */
    static int
    CutBuffer(Atom code)
    {
        int cutbuffer;
        switch ((unsigned) code) {
        case XA_CUT_BUFFER0:
    	cutbuffer = 0;
    	break;
        case XA_CUT_BUFFER1:
    	cutbuffer = 1;
    	break;
        case XA_CUT_BUFFER2:
    	cutbuffer = 2;
    	break;
        case XA_CUT_BUFFER3:
    	cutbuffer = 3;
    	break;
        case XA_CUT_BUFFER4:
    	cutbuffer = 4;
    	break;
        case XA_CUT_BUFFER5:
    	cutbuffer = 5;
    	break;
        case XA_CUT_BUFFER6:
    	cutbuffer = 6;
    	break;
        case XA_CUT_BUFFER7:
    	cutbuffer = 7;
    	break;
        default:
    	cutbuffer = -1;
    	break;
        }
        TRACE2(("CutBuffer(%d) = %d\n", (int) code, cutbuffer));
        return cutbuffer;
    }
    
    #if OPT_PASTE64
    static void
    FinishPaste64(XtermWidget xw)
    {
        TScreen *screen = TScreenOf(xw);
    
        TRACE(("FinishPaste64(%d)\n", screen->base64_paste));
        if (screen->base64_paste) {
    	screen->base64_paste = 0;
    	unparseputc1(xw, screen->base64_final);
    	unparse_end(xw);
        }
    }
    #endif
    
    #if !OPT_PASTE64
    static
    #endif
    void
    xtermGetSelection(Widget w,
    		  Time ev_time,
    		  String *params,	/* selections in precedence order */
    		  Cardinal num_params,
    		  Atom *targets)
    {
        Atom selection;
        int cutbuffer;
        Atom target;
    
        XtermWidget xw;
    
        if (num_params == 0)
    	return;
        if ((xw = getXtermWidget(w)) == 0)
    	return;
    
        TRACE(("xtermGetSelection num_params %d @%ld\n", num_params, ev_time));
        params = MapSelections(xw, params, num_params);
    
        XmuInternStrings(XtDisplay(w), params, (Cardinal) 1, &selection);
        cutbuffer = CutBuffer(selection);
    
        TRACE(("Cutbuffer: %d, target: %s\n", cutbuffer,
    	   (targets
    	    ? visibleSelectionTarget(XtDisplay(w), targets[0])
    	    : "None")));
    
        if (cutbuffer >= 0) {
    	int inbytes;
    	unsigned long nbytes;
    	int fmt8 = 8;
    	Atom type = XA_STRING;
    	char *line;
    
    	/* 'line' is freed in SelectionReceived */
    	line = XFetchBuffer(XtDisplay(w), &inbytes, cutbuffer);
    	nbytes = (unsigned long) inbytes;
    
    	if (nbytes > 0) {
    	    SelectionReceived(w, NULL, &selection, &type, (XtPointer) line,
    			      &nbytes, &fmt8);
    	} else if (num_params > 1) {
    	    xtermGetSelection(w, ev_time, params + 1, num_params - 1, NULL);
    	}
    #if OPT_PASTE64
    	else {
    	    FinishPaste64(xw);
    	}
    #endif
        } else {
    
    	if (targets == NULL || targets[0] == None) {
    	    targets = _SelectionTargets(w);
    	}
    
    	if (targets != 0) {
    	    struct _SelectionList *list;
    
    	    target = targets[0];
    
    	    if (targets[1] == None) {	/* last target in list */
    		params++;
    		num_params--;
    		targets = _SelectionTargets(w);
    	    } else {
    		targets = &(targets[1]);
    	    }
    
    	    if (num_params) {
    		/* 'list' is freed in SelectionReceived */
    		list = TypeXtMalloc(struct _SelectionList);
    		if (list != 0) {
    		    list->params = params;
    		    list->count = num_params;
    		    list->targets = targets;
    		    list->time = ev_time;
    		}
    	    } else {
    		list = NULL;
    	    }
    
    	    XtGetSelectionValue(w, selection,
    				target,
    				SelectionReceived,
    				(XtPointer) list, ev_time);
    	}
        }
    }
    
    #if OPT_TRACE && OPT_WIDE_CHARS
    static void
    GettingSelection(Display *dpy, Atom type, Char *line, unsigned long len)
    {
        Char *cp;
        const char *name = TraceAtomName(dpy, type);
    
        TRACE(("Getting %s (type=%ld, length=%ld)\n", name, (long int) type, len));
        for (cp = line; cp < line + len; cp++) {
    	TRACE(("[%d:%lu]", (int) (cp + 1 - line), len));
    	if (isprint(*cp)) {
    	    TRACE(("%c\n", *cp));
    	} else {
    	    TRACE(("\\x%02x\n", *cp));
    	}
        }
    }
    #else
    #define GettingSelection(dpy,type,line,len)	/* nothing */
    #endif
    
    #ifdef VMS
    #  define tty_vwrite(pty,lag,l)		tt_write(lag,l)
    #else /* !( VMS ) */
    #  define tty_vwrite(pty,lag,l)		v_write(pty,lag,l)
    #endif /* defined VMS */
    
    #if OPT_PASTE64
    /* Return base64 code character given 6-bit number */
    static const char base64_code[] = "\
    ABCDEFGHIJKLMNOPQRSTUVWXYZ\
    abcdefghijklmnopqrstuvwxyz\
    0123456789+/";
    static void
    base64_flush(TScreen *screen)
    {
        Char x;
    
        TRACE(("base64_flush count %d, pad %d (%d)\n",
    	   screen->base64_count,
    	   screen->base64_pad,
    	   screen->base64_pad & 3));
    
        switch (screen->base64_count) {
        case 0:
    	break;
        case 2:
    	x = CharOf(base64_code[screen->base64_accu << 4]);
    	tty_vwrite(screen->respond, &x, 1);
    	break;
        case 4:
    	x = CharOf(base64_code[screen->base64_accu << 2]);
    	tty_vwrite(screen->respond, &x, 1);
    	break;
        }
        if (screen->base64_pad & 3) {
    	tty_vwrite(screen->respond,
    		   (const Char *) "===",
    		   (unsigned) (3 - (screen->base64_pad & 3)));
        }
        screen->base64_count = 0;
        screen->base64_accu = 0;
        screen->base64_pad = 0;
    }
    #endif /* OPT_PASTE64 */
    
    /*
     * Translate ISO-8859-1 or UTF-8 data to NRCS.
     */
    static void
    ToNational(XtermWidget xw, Char *buffer, unsigned *length)
    {
        TScreen *screen = TScreenOf(xw);
        DECNRCM_codes gsetL = screen->gsets[screen->curgl];
        DECNRCM_codes gsetR = screen->gsets[screen->curgr];
    
    #if OPT_WIDE_CHARS
        if ((screen->utf8_nrc_mode | screen->utf8_mode) != uFalse) {
    	Char *p;
    	PtyData *data = TypeXtMallocX(PtyData, *length);
    
    	memset(data, 0, sizeof(*data));
    	data->next = data->buffer;
    	data->last = data->buffer + *length;
    	memcpy(data->buffer, buffer, (size_t) *length);
    	p = buffer;
    	while (data->next < data->last) {
    	    unsigned chr, out, gl, gr;
    
    	    if (!decodeUtf8(screen, data)) {
    		data->utf_size = 1;
    		data->utf_data = data->next[0];
    	    }
    	    data->next += data->utf_size;
    	    chr = data->utf_data;
    	    out = chr;
    	    if ((gl = xtermCharSetIn(xw, chr, gsetL)) != chr) {
    		out = gl;
    	    } else if ((gr = xtermCharSetIn(xw, chr, gsetR)) != chr) {
    		out = gr;
    	    }
    	    *p++ = (Char) ((out < 256) ? out : ' ');
    	}
    	*length = (unsigned) (p - buffer);
    	free(data);
        } else
    #endif
        {
    	Char *p;
    
    	for (p = buffer; (int) (p - buffer) < (int) *length; ++p) {
    	    unsigned gl, gr;
    	    unsigned chr = *p;
    	    unsigned out = chr;
    	    if ((gl = xtermCharSetIn(xw, chr, gsetL)) != chr) {
    		out = gl;
    	    } else if ((gr = xtermCharSetIn(xw, chr, gsetR)) != chr) {
    		out = gr;
    	    }
    	    *p = (Char) out;
    	}
        }
    }
    
    static void
    _qWriteSelectionData(XtermWidget xw, Char *lag, unsigned length)
    {
        TScreen *screen = TScreenOf(xw);
    
        /*
         * If we are pasting into a window which is using NRCS, we want to map
         * the text from the normal encoding (ISO-8859-1 or UTF-8) into the coding
         * that an application would use to write characters with NRCS.
         *
         * TODO: handle conversion from UTF-8, and adjust length.  This can be done
         * in the same buffer because the target is always 8-bit.
         */
        if ((xw->flags & NATIONAL) && (length != 0)) {
    	ToNational(xw, lag, &length);
        }
    #if OPT_PASTE64
        if (screen->base64_paste) {
    	/* Send data as base64 */
    	Char *p = lag;
    	Char buf[64];
    	unsigned x = 0;
    
    	TRACE(("convert to base64 %d:%s\n", length, visibleChars(p, length)));
    
    	/*
    	 * Handle the case where the selection is from _this_ xterm, which
    	 * puts part of the reply in the buffer before the selection callback
    	 * happens.
    	 */
    	if (screen->base64_paste && screen->unparse_len) {
    	    unparse_end(xw);
    	}
    	while (length--) {
    	    switch (screen->base64_count) {
    	    case 0:
    		buf[x++] = CharOf(base64_code[*p >> 2]);
    		screen->base64_accu = (unsigned) (*p & 0x3);
    		screen->base64_count = 2;
    		++p;
    		break;
    	    case 2:
    		buf[x++] = CharOf(base64_code[(screen->base64_accu << 4) +
    					      (*p >> 4)]);
    		screen->base64_accu = (unsigned) (*p & 0xF);
    		screen->base64_count = 4;
    		++p;
    		break;
    	    case 4:
    		buf[x++] = CharOf(base64_code[(screen->base64_accu << 2) +
    					      (*p >> 6)]);
    		buf[x++] = CharOf(base64_code[*p & 0x3F]);
    		screen->base64_accu = 0;
    		screen->base64_count = 0;
    		++p;
    		break;
    	    }
    	    if (x >= 63) {
    		/* Write 63 or 64 characters */
    		screen->base64_pad += x;
    		TRACE(("writing base64 interim %s\n", visibleChars(buf, x)));
    		tty_vwrite(screen->respond, buf, x);
    		x = 0;
    	    }
    	}
    	if (x != 0) {
    	    screen->base64_pad += x;
    	    TRACE(("writing base64 finish %s\n", visibleChars(buf, x)));
    	    tty_vwrite(screen->respond, buf, x);
    	}
        } else
    #endif /* OPT_PASTE64 */
    #if OPT_READLINE
        if (SCREEN_FLAG(screen, paste_quotes)) {
    	while (length--) {
    	    tty_vwrite(screen->respond, (const Char *) "\026", 1);	/* Control-V */
    	    tty_vwrite(screen->respond, lag++, 1);
    	}
        } else
    #endif
        {
    	TRACE(("writing base64 padding %s\n", visibleChars(lag, length)));
    	tty_vwrite(screen->respond, lag, length);
        }
    }
    
    static void
    _WriteSelectionData(XtermWidget xw, Char *line, size_t length)
    {
        /* Write data to pty a line at a time. */
        /* Doing this one line at a time may no longer be necessary
           because v_write has been re-written. */
    
    #if OPT_PASTE64
        TScreen *screen = TScreenOf(xw);
    #endif
        Char *lag, *end;
    
        /* in the VMS version, if tt_pasting isn't set to True then qio
           reads aren't blocked and an infinite loop is entered, where the
           pasted text shows up as new input, goes in again, shows up
           again, ad nauseum. */
    #ifdef VMS
        tt_pasting = True;
    #endif
    
        end = &line[length];
        lag = line;
    
    #if OPT_PASTE64
        if (screen->base64_paste) {
    	_qWriteSelectionData(xw, lag, (unsigned) (end - lag));
    	base64_flush(screen);
        } else
    #endif
        {
    	if (!SCREEN_FLAG(screen, paste_literal_nl)) {
    	    Char *cp;
    	    for (cp = line; cp != end; cp++) {
    		if (*cp == '\n') {
    		    *cp = '\r';
    		    _qWriteSelectionData(xw, lag, (unsigned) (cp - lag + 1));
    		    lag = cp + 1;
    		}
    	    }
    	}
    
    	if (lag != end) {
    	    _qWriteSelectionData(xw, lag, (unsigned) (end - lag));
    	}
        }
    #ifdef VMS
        tt_pasting = False;
        tt_start_read();		/* reenable reads or a character may be lost */
    #endif
    }
    
    #if OPT_PASTE64 || OPT_READLINE
    static void
    _WriteKey(TScreen *screen, const Char *in)
    {
        Char line[16];
        unsigned count = 0;
        size_t length = strlen((const char *) in);
    
        if (screen->control_eight_bits) {
    	line[count++] = ANSI_CSI;
        } else {
    	line[count++] = ANSI_ESC;
    	line[count++] = '[';
        }
        while (length--)
    	line[count++] = *in++;
        line[count++] = '~';
        tty_vwrite(screen->respond, line, count);
    }
    #endif /* OPT_READLINE */
    
    /*
     * Unless enabled by the user, strip control characters other than formatting.
     */
    static size_t
    removeControls(XtermWidget xw, char *value)
    {
        TScreen *screen = TScreenOf(xw);
        size_t dst = 0;
    
        if (screen->allowPasteControls) {
    	dst = strlen(value);
        } else {
    	size_t src = 0;
    	while ((value[dst] = value[src]) != '\0') {
    	    int ch = CharOf(value[src++]);
    
    #define ReplacePaste(n) \
    	    if (screen->disallow_paste_controls[n]) \
    		value[dst] = ' '
    
    	    if (ch < 32) {
    		ReplacePaste(epC0);
    		switch (ch) {
    		case ANSI_BS:
    		    ReplacePaste(epBS);
    		    break;
    		case ANSI_CR:
    		    ReplacePaste(epCR);
    		    break;
    		case ANSI_ESC:
    		    ReplacePaste(epESC);
    		    break;
    		case ANSI_FF:
    		    ReplacePaste(epFF);
    		    break;
    		case ANSI_HT:
    		    ReplacePaste(epHT);
    		    break;
    		case ANSI_LF:
    		    ReplacePaste(epNL);
    		    break;
    		default:
    		    continue;
    		}
    		++dst;
    	    } else if (ch == ANSI_DEL) {
    		ReplacePaste(epDEL);
    		++dst;
    	    }
    #if OPT_WIDE_CHARS
    	    else if (screen->utf8_inparse || screen->utf8_nrc_mode)
    		++dst;
    #endif
    #if OPT_C1_PRINT || OPT_WIDE_CHARS
    	    else if (screen->c1_printable)
    		++dst;
    #endif
    	    else if (ch >= 128 && ch < 160)
    		continue;
    	    else
    		++dst;
    	}
        }
        return dst;
    }
    
    #if OPT_SELECTION_OPS
    static void
    beginInternalSelect(XtermWidget xw)
    {
        TScreen *screen = TScreenOf(xw);
        InternalSelect *mydata = &(screen->internal_select);
    
        (void) mydata;
        /* override flags so that SelectionReceived only updates a buffer */
    #if OPT_PASTE64
        mydata->base64_paste = screen->base64_paste;
        screen->base64_paste = 0;
    #endif
    #if OPT_PASTE64 || OPT_READLINE
        mydata->paste_brackets = screen->paste_brackets;
        SCREEN_FLAG_unset(screen, paste_brackets);
    #endif
    }
    
    static void
    finishInternalSelect(XtermWidget xw)
    {
        TScreen *screen = TScreenOf(xw);
        InternalSelect *mydata = &(screen->internal_select);
    
        (void) mydata;
    #if OPT_PASTE64
        screen->base64_paste = mydata->base64_paste;
    #endif
    #if OPT_PASTE64 || OPT_READLINE
        screen->paste_brackets = mydata->paste_brackets;
    #endif
    }
    
    #else
    #define finishInternalSelect(xw)	/* nothing */
    #endif /* OPT_SELECTION_OPS */
    
    /* SelectionReceived: stuff received selection text into pty */
    
    /* ARGSUSED */
    static void
    SelectionReceived(Widget w,
    		  XtPointer client_data,
    		  Atom *selection GCC_UNUSED,
    		  Atom *type,
    		  XtPointer value,
    		  unsigned long *length,
    		  int *format)
    {
        char **text_list = NULL;
        int text_list_count = 0;
        XTextProperty text_prop;
        TScreen *screen;
        Display *dpy;
    #if OPT_TRACE && OPT_WIDE_CHARS
        Char *line = (Char *) value;
    #endif
    
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) == 0)
    	return;
    
        screen = TScreenOf(xw);
        dpy = XtDisplay(w);
    
        if (*type == 0		/*XT_CONVERT_FAIL */
    	|| *length == 0
    	|| value == NULL) {
    	TRACE(("...no data to convert\n"));
    	goto fail;
        }
    
        text_prop.value = (unsigned char *) value;
        text_prop.encoding = *type;
        text_prop.format = *format;
        text_prop.nitems = *length;
    
        TRACE(("SelectionReceived %s %s format %d, nitems %ld\n",
    	   TraceAtomName(screen->display, *selection),
    	   visibleSelectionTarget(dpy, text_prop.encoding),
    	   text_prop.format,
    	   text_prop.nitems));
    
    #if OPT_WIDE_CHARS
        if (XSupportsLocale() && screen->wide_chars) {
    	if (*type == XA_UTF8_STRING(dpy) ||
    	    *type == XA_STRING ||
    	    *type == XA_COMPOUND_TEXT(dpy)) {
    	    GettingSelection(dpy, *type, line, *length);
    	    if (Xutf8TextPropertyToTextList(dpy, &text_prop,
    					    &text_list,
    					    &text_list_count) < 0) {
    		TRACE(("default Xutf8 Conversion failed\n"));
    		text_list = NULL;
    	    }
    	}
        } else
    #endif /* OPT_WIDE_CHARS */
        {
    	/* Convert the selection to locale's multibyte encoding. */
    
    	if (*type == XA_UTF8_STRING(dpy) ||
    	    *type == XA_STRING ||
    	    *type == XA_COMPOUND_TEXT(dpy)) {
    	    Status rc;
    
    	    GettingSelection(dpy, *type, line, *length);
    
    #if OPT_WIDE_CHARS
    	    if (*type == XA_UTF8_STRING(dpy) &&
    		!(screen->wide_chars || screen->c1_printable)) {
    		rc = xtermUtf8ToTextList(xw, &text_prop,
    					 &text_list, &text_list_count);
    	    } else
    #endif
    	    if (*type == XA_STRING && (!XSupportsLocale() || screen->brokenSelections)) {
    		rc = XTextPropertyToStringList(&text_prop,
    					       &text_list, &text_list_count);
    	    } else {
    		rc = XmbTextPropertyToTextList(dpy, &text_prop,
    					       &text_list,
    					       &text_list_count);
    	    }
    	    if (rc < 0) {
    		TRACE(("Conversion failed\n"));
    		text_list = NULL;
    	    }
    	}
        }
    
        if (text_list != NULL && text_list_count != 0) {
    	int i;
    
    #if OPT_PASTE64
    	if (screen->base64_paste) {
    	    /* EMPTY */ ;
    	} else
    #endif
    #if OPT_PASTE64 || OPT_READLINE
    	if (SCREEN_FLAG(screen, paste_brackets) && !screen->selectToBuffer) {
    	    _WriteKey(screen, (const Char *) "200");
    	}
    #endif
    	for (i = 0; i < text_list_count; i++) {
    	    size_t len = removeControls(xw, text_list[i]);
    
    	    if (screen->selectToBuffer) {
    		InternalSelect *mydata = &(screen->internal_select);
    		if (!mydata->done) {
    		    size_t have = (mydata->buffer
    				   ? strlen(mydata->buffer)
    				   : 0);
    		    size_t need = have + len + 1;
    		    char *buffer = realloc(mydata->buffer, need);
    
    		    if (buffer != 0) {
    			strcpy(buffer + have, text_list[i]);
    			mydata->buffer = buffer;
    		    }
    		    TRACE(("FormatSelect %d.%d .. %d.%d %s\n",
    			   screen->startSel.row,
    			   screen->startSel.col,
    			   screen->endSel.row,
    			   screen->endSel.col,
    			   mydata->buffer));
    		    mydata->format_select(w, mydata->format, mydata->buffer,
    					  &(screen->startSel),
    					  &(screen->endSel));
    		    mydata->done = True;
    		}
    
    	    } else {
    		_WriteSelectionData(xw, (Char *) text_list[i], len);
    	    }
    	}
    #if OPT_PASTE64
    	if (screen->base64_paste) {
    	    FinishPaste64(xw);
    	} else
    #endif
    #if OPT_PASTE64 || OPT_READLINE
    	if (SCREEN_FLAG(screen, paste_brackets) && !screen->selectToBuffer) {
    	    _WriteKey(screen, (const Char *) "201");
    	}
    #endif
    	if (screen->selectToBuffer) {
    	    InternalSelect *mydata = &(screen->internal_select);
    	    finishInternalSelect(xw);
    	    if (mydata->done) {
    		free(mydata->format);
    		free(mydata->buffer);
    		memset(mydata, 0, sizeof(*mydata));
    	    }
    	    screen->selectToBuffer = False;
    	}
    	XFreeStringList(text_list);
        } else {
    	TRACE(("...empty text-list\n"));
    	goto fail;
        }
    
        XtFree((char *) client_data);
        XtFree((char *) value);
    
        return;
    
      fail:
        if (client_data != 0) {
    	struct _SelectionList *list = (struct _SelectionList *) client_data;
    
    	TRACE(("SelectionReceived ->xtermGetSelection\n"));
    	xtermGetSelection(w, list->time,
    			  list->params, list->count, list->targets);
    	XtFree((char *) client_data);
    #if OPT_PASTE64
        } else {
    	FinishPaste64(xw);
    #endif
        }
        return;
    }
    
    void
    HandleInsertSelection(Widget w,
    		      XEvent *event,	/* assumed to be XButtonEvent* */
    		      String *params,	/* selections in precedence order */
    		      Cardinal *num_params)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TRACE_EVENT("HandleInsertSelection", event, params, num_params);
    	if (!SendMousePosition(xw, event)) {
    #if OPT_READLINE
    	    int ldelta;
    	    TScreen *screen = TScreenOf(xw);
    	    if (IsBtnEvent(event)
    	    /* Disable on Shift-mouse, including the application-mouse modes */
    		&& !(KeyModifiers(event) & ShiftMask)
    		&& (okSendMousePos(xw) == MOUSE_OFF)
    		&& SCREEN_FLAG(screen, paste_moves)
    		&& rowOnCurrentLine(screen, eventRow(screen, event), &ldelta))
    		ReadLineMovePoint(screen, eventColBetween(screen, event), ldelta);
    #endif /* OPT_READLINE */
    
    	    xtermGetSelection(w, event->xbutton.time, params, *num_params, NULL);
    	}
        }
    }
    
    static SelectUnit
    EvalSelectUnit(XtermWidget xw,
    	       Time buttonDownTime,
    	       SelectUnit defaultUnit,
    	       unsigned int button)
    {
        TScreen *screen = TScreenOf(xw);
        SelectUnit result;
        int delta;
    
        if (button != screen->lastButton) {
    	delta = screen->multiClickTime + 1;
        } else if (screen->lastButtonUpTime == (Time) 0) {
    	/* first time and once in a blue moon */
    	delta = screen->multiClickTime + 1;
        } else if (buttonDownTime > screen->lastButtonUpTime) {
    	/* most of the time */
    	delta = (int) (buttonDownTime - screen->lastButtonUpTime);
        } else {
    	/* time has rolled over since lastButtonUpTime */
    	delta = (int) ((((Time) ~ 0) - screen->lastButtonUpTime) + buttonDownTime);
        }
    
        if (delta > screen->multiClickTime) {
    	screen->numberOfClicks = 1;
    	result = defaultUnit;
        } else {
    	result = screen->selectMap[screen->numberOfClicks % screen->maxClicks];
    	screen->numberOfClicks += 1;
        }
        TRACE(("EvalSelectUnit(%d) = %d\n", screen->numberOfClicks, result));
        return result;
    }
    
    static void
    do_select_start(XtermWidget xw,
    		XEvent *event,	/* must be XButtonEvent* */
    		CELL *cell)
    {
        TScreen *screen = TScreenOf(xw);
    
        if (SendMousePosition(xw, event))
    	return;
        screen->selectUnit = EvalSelectUnit(xw,
    					event->xbutton.time,
    					Select_CHAR,
    					event->xbutton.button);
        screen->replyToEmacs = False;
    
    #if OPT_READLINE
        lastButtonDownTime = event->xbutton.time;
    #endif
    
        StartSelect(xw, cell);
    }
    
    /* ARGSUSED */
    void
    HandleSelectStart(Widget w,
    		  XEvent *event,	/* must be XButtonEvent* */
    		  String *params GCC_UNUSED,
    		  Cardinal *num_params GCC_UNUSED)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TScreen *screen = TScreenOf(xw);
    	CELL cell;
    
    	TRACE_EVENT("HandleSelectStart", event, params, num_params);
    	screen->firstValidRow = 0;
    	screen->lastValidRow = screen->max_row;
    	PointToCELL(screen, event->xbutton.y, event->xbutton.x, &cell);
    
    #if OPT_READLINE
    	ExtendingSelection = 0;
    #endif
    
    	do_select_start(xw, event, &cell);
        }
    }
    
    /* ARGSUSED */
    void
    HandleKeyboardSelectStart(Widget w,
    			  XEvent *event,	/* must be XButtonEvent* */
    			  String *params GCC_UNUSED,
    			  Cardinal *num_params GCC_UNUSED)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TScreen *screen = TScreenOf(xw);
    
    	TRACE_EVENT("HandleKeyboardSelectStart", event, params, num_params);
    	do_select_start(xw, event, &screen->cursorp);
        }
    }
    
    static void
    TrackDown(XtermWidget xw, XButtonEvent *event)
    {
        TScreen *screen = TScreenOf(xw);
        CELL cell;
    
        screen->selectUnit = EvalSelectUnit(xw,
    					event->time,
    					Select_CHAR,
    					event->button);
        if (screen->numberOfClicks > 1) {
    	PointToCELL(screen, event->y, event->x, &cell);
    	screen->replyToEmacs = True;
    	StartSelect(xw, &cell);
        } else {
    	screen->waitingForTrackInfo = True;
    	EditorButton(xw, event);
        }
    }
    
    #define boundsCheck(x)	if (x < 0) \
    			    x = 0; \
    			else if (x >= screen->max_row) \
    			    x = screen->max_row
    
    void
    TrackMouse(XtermWidget xw,
    	   int func,
    	   CELL *start,
    	   int firstrow,
    	   int lastrow)
    {
        TScreen *screen = TScreenOf(xw);
    
        if (screen->waitingForTrackInfo) {	/* if Timed, ignore */
    	screen->waitingForTrackInfo = False;
    
    	if (func != 0) {
    	    CELL first = *start;
    
    	    boundsCheck(first.row);
    	    boundsCheck(firstrow);
    	    boundsCheck(lastrow);
    	    screen->firstValidRow = firstrow;
    	    screen->lastValidRow = lastrow;
    	    screen->replyToEmacs = True;
    	    StartSelect(xw, &first);
    	}
        }
    }
    
    static void
    StartSelect(XtermWidget xw, const CELL *cell)
    {
        TScreen *screen = TScreenOf(xw);
    
        TRACE(("StartSelect row=%d, col=%d\n", cell->row, cell->col));
        if (screen->cursor_state)
    	HideCursor();
        if (screen->numberOfClicks == 1) {
    	/* set start of selection */
    	screen->rawPos = *cell;
        }
        /* else use old values in rawPos */
        screen->saveStartR = screen->startExt = screen->rawPos;
        screen->saveEndR = screen->endExt = screen->rawPos;
        if (Coordinate(screen, cell) < Coordinate(screen, &(screen->rawPos))) {
    	screen->eventMode = LEFTEXTENSION;
    	screen->startExt = *cell;
        } else {
    	screen->eventMode = RIGHTEXTENSION;
    	screen->endExt = *cell;
        }
        ComputeSelect(xw, &(screen->startExt), &(screen->endExt), False);
    }
    
    static void
    EndExtend(XtermWidget xw,
    	  XEvent *event,	/* must be XButtonEvent */
    	  String *params,	/* selections */
    	  Cardinal num_params,
    	  Bool use_cursor_loc)
    {
        CELL cell;
        TScreen *screen = TScreenOf(xw);
    
        TRACE_EVENT("EndExtend", event, params, &num_params);
        if (use_cursor_loc) {
    	cell = screen->cursorp;
        } else {
    	PointToCELL(screen, event->xbutton.y, event->xbutton.x, &cell);
        }
        ExtendExtend(xw, &cell);
    
        screen->lastButtonUpTime = event->xbutton.time;
        screen->lastButton = event->xbutton.button;
    
        if (!isSameCELL(&(screen->startSel), &(screen->endSel))) {
    	if (screen->replyToEmacs) {
    	    Char line[64];
    	    unsigned count = 0;
    
    	    if (screen->control_eight_bits) {
    		line[count++] = ANSI_CSI;
    	    } else {
    		line[count++] = ANSI_ESC;
    		line[count++] = '[';
    	    }
    	    if (isSameCELL(&(screen->rawPos), &(screen->startSel))
    		&& isSameCELL(&cell, &(screen->endSel))) {
    		/* Use short-form emacs select */
    
    		switch (screen->extend_coords) {
    		case 0:
    		case SET_EXT_MODE_MOUSE:
    		    line[count++] = 't';
    		    break;
    		case SET_SGR_EXT_MODE_MOUSE:
    		    line[count++] = '<';
    		    break;
    		}
    
    		count = EmitMousePosition(screen, line, count, screen->endSel.col);
    		count = EmitMousePositionSeparator(screen, line, count);
    		count = EmitMousePosition(screen, line, count, screen->endSel.row);
    
    		switch (screen->extend_coords) {
    		case SET_SGR_EXT_MODE_MOUSE:
    		case SET_URXVT_EXT_MODE_MOUSE:
    		    line[count++] = 't';
    		    break;
    		}
    	    } else {
    		/* long-form, specify everything */
    
    		switch (screen->extend_coords) {
    		case 0:
    		case SET_EXT_MODE_MOUSE:
    		    line[count++] = 'T';
    		    break;
    		case SET_SGR_EXT_MODE_MOUSE:
    		    line[count++] = '<';
    		    break;
    		}
    
    		count = EmitMousePosition(screen, line, count, screen->startSel.col);
    		count = EmitMousePositionSeparator(screen, line, count);
    		count = EmitMousePosition(screen, line, count, screen->startSel.row);
    		count = EmitMousePositionSeparator(screen, line, count);
    		count = EmitMousePosition(screen, line, count, screen->endSel.col);
    		count = EmitMousePositionSeparator(screen, line, count);
    		count = EmitMousePosition(screen, line, count, screen->endSel.row);
    		count = EmitMousePositionSeparator(screen, line, count);
    		count = EmitMousePosition(screen, line, count, cell.col);
    		count = EmitMousePositionSeparator(screen, line, count);
    		count = EmitMousePosition(screen, line, count, cell.row);
    
    		switch (screen->extend_coords) {
    		case SET_SGR_EXT_MODE_MOUSE:
    		case SET_URXVT_EXT_MODE_MOUSE:
    		    line[count++] = 'T';
    		    break;
    		}
    	    }
    	    v_write(screen->respond, line, count);
    	    UnHiliteText(xw);
    	}
        }
        SelectSet(xw, event, params, num_params);
        screen->eventMode = NORMAL;
    }
    
    void
    HandleSelectSet(Widget w,
    		XEvent *event,
    		String *params,
    		Cardinal *num_params)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TRACE_EVENT("HandleSelectSet", event, params, num_params);
    	SelectSet(xw, event, params, *num_params);
        }
    }
    
    /* ARGSUSED */
    static void
    SelectSet(XtermWidget xw,
    	  XEvent *event GCC_UNUSED,
    	  String *params,
    	  Cardinal num_params)
    {
        TScreen *screen = TScreenOf(xw);
    
        TRACE(("SelectSet\n"));
        /* Only do select stuff if non-null select */
        if (!isSameCELL(&(screen->startSel), &(screen->endSel))) {
    	Cardinal n;
    	for (n = 0; n < num_params; ++n) {
    	    SaltTextAway(xw,
    			 TargetToSelection(screen, params[n]),
    			 &(screen->startSel), &(screen->endSel));
    	}
    	_OwnSelection(xw, params, num_params);
        } else {
    	ScrnDisownSelection(xw);
        }
    }
    
    #define Abs(x)		((x) < 0 ? -(x) : (x))
    
    /* ARGSUSED */
    static void
    do_start_extend(XtermWidget xw,
    		XEvent *event,	/* must be XButtonEvent* */
    		String *params GCC_UNUSED,
    		Cardinal *num_params GCC_UNUSED,
    		Bool use_cursor_loc)
    {
        TScreen *screen = TScreenOf(xw);
        int coord;
        CELL cell;
    
        if (SendMousePosition(xw, event))
    	return;
    
        screen->firstValidRow = 0;
        screen->lastValidRow = screen->max_row;
    #if OPT_READLINE
        if ((KeyModifiers(event) & ShiftMask)
    	|| event->xbutton.button != Button3
    	|| !(SCREEN_FLAG(screen, dclick3_deletes)))
    #endif
    	screen->selectUnit = EvalSelectUnit(xw,
    					    event->xbutton.time,
    					    screen->selectUnit,
    					    event->xbutton.button);
        screen->replyToEmacs = False;
    
    #if OPT_READLINE
        CheckSecondPress3(screen, event);
    #endif
    
        if (screen->numberOfClicks == 1
    	|| (SCREEN_FLAG(screen, dclick3_deletes)	/* Dclick special */
    	    &&!(KeyModifiers(event) & ShiftMask))) {
    	/* Save existing selection so we can reestablish it if the guy
    	   extends past the other end of the selection */
    	screen->saveStartR = screen->startExt = screen->startRaw;
    	screen->saveEndR = screen->endExt = screen->endRaw;
        } else {
    	/* He just needed the selection mode changed, use old values. */
    	screen->startExt = screen->startRaw = screen->saveStartR;
    	screen->endExt = screen->endRaw = screen->saveEndR;
        }
        if (use_cursor_loc) {
    	cell = screen->cursorp;
        } else {
    	PointToCELL(screen, event->xbutton.y, event->xbutton.x, &cell);
        }
        coord = Coordinate(screen, &cell);
    
        if (Abs(coord - Coordinate(screen, &(screen->startSel)))
    	< Abs(coord - Coordinate(screen, &(screen->endSel)))
    	|| coord < Coordinate(screen, &(screen->startSel))) {
    	/* point is close to left side of selection */
    	screen->eventMode = LEFTEXTENSION;
    	screen->startExt = cell;
        } else {
    	/* point is close to left side of selection */
    	screen->eventMode = RIGHTEXTENSION;
    	screen->endExt = cell;
        }
        ComputeSelect(xw, &(screen->startExt), &(screen->endExt), True);
    
    #if OPT_READLINE
        if (!isSameCELL(&(screen->startSel), &(screen->endSel)))
    	ExtendingSelection = 1;
    #endif
    }
    
    static void
    ExtendExtend(XtermWidget xw, const CELL *cell)
    {
        TScreen *screen = TScreenOf(xw);
        int coord = Coordinate(screen, cell);
    
        TRACE(("ExtendExtend row=%d, col=%d\n", cell->row, cell->col));
        if (screen->eventMode == LEFTEXTENSION
    	&& ((coord + (screen->selectUnit != Select_CHAR))
    	    > Coordinate(screen, &(screen->endSel)))) {
    	/* Whoops, he's changed his mind.  Do RIGHTEXTENSION */
    	screen->eventMode = RIGHTEXTENSION;
    	screen->startExt = screen->saveStartR;
        } else if (screen->eventMode == RIGHTEXTENSION
    	       && coord < Coordinate(screen, &(screen->startSel))) {
    	/* Whoops, he's changed his mind.  Do LEFTEXTENSION */
    	screen->eventMode = LEFTEXTENSION;
    	screen->endExt = screen->saveEndR;
        }
        if (screen->eventMode == LEFTEXTENSION) {
    	screen->startExt = *cell;
        } else {
    	screen->endExt = *cell;
        }
        ComputeSelect(xw, &(screen->startExt), &(screen->endExt), False);
    
    #if OPT_READLINE
        if (!isSameCELL(&(screen->startSel), &(screen->endSel)))
    	ExtendingSelection = 1;
    #endif
    }
    
    void
    HandleStartExtend(Widget w,
    		  XEvent *event,	/* must be XButtonEvent* */
    		  String *params,	/* unused */
    		  Cardinal *num_params)		/* unused */
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TRACE_EVENT("HandleStartExtend", event, params, num_params);
    	do_start_extend(xw, event, params, num_params, False);
        }
    }
    
    void
    HandleKeyboardStartExtend(Widget w,
    			  XEvent *event,	/* must be XButtonEvent* */
    			  String *params,	/* unused */
    			  Cardinal *num_params)		/* unused */
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TRACE_EVENT("HandleKeyboardStartExtend", event, params, num_params);
    	do_start_extend(xw, event, params, num_params, True);
        }
    }
    
    void
    ScrollSelection(TScreen *screen, int amount, Bool always)
    {
        int minrow = INX2ROW(screen, -screen->savedlines);
        int maxrow = INX2ROW(screen, screen->max_row);
        int maxcol = screen->max_col;
    
    #define scroll_update_one(cell) \
    	(cell)->row += amount; \
    	if ((cell)->row < minrow) { \
    	    (cell)->row = minrow; \
    	    (cell)->col = 0; \
    	} \
    	if ((cell)->row > maxrow) { \
    	    (cell)->row = maxrow; \
    	    (cell)->col = maxcol; \
    	}
    
        scroll_update_one(&(screen->startRaw));
        scroll_update_one(&(screen->endRaw));
        scroll_update_one(&(screen->startSel));
        scroll_update_one(&(screen->endSel));
    
        scroll_update_one(&(screen->rawPos));
    
        /*
         * If we are told to scroll the selection but it lies outside the scrolling
         * margins, then that could cause the selection to move (bad).  It is not
         * simple to fix, because this function is called both for the scrollbar
         * actions as well as application scrolling.  The 'always' flag is set in
         * the former case.  The rest of the logic handles the latter.
         */
        if (ScrnHaveSelection(screen)) {
    	int adjust;
    
    	adjust = ROW2INX(screen, screen->startH.row);
    	if (always
    	    || !ScrnHaveRowMargins(screen)
    	    || ScrnIsRowInMargins(screen, adjust)) {
    	    scroll_update_one(&screen->startH);
    	}
    	adjust = ROW2INX(screen, screen->endH.row);
    	if (always
    	    || !ScrnHaveRowMargins(screen)
    	    || ScrnIsRowInMargins(screen, adjust)) {
    	    scroll_update_one(&screen->endH);
    	}
        }
    
        screen->startHCoord = Coordinate(screen, &screen->startH);
        screen->endHCoord = Coordinate(screen, &screen->endH);
    }
    
    /*ARGSUSED*/
    void
    ResizeSelection(TScreen *screen GCC_UNUSED, int rows, int cols)
    {
        rows--;			/* decr to get 0-max */
        cols--;
    
        if (screen->startRaw.row > rows)
    	screen->startRaw.row = rows;
        if (screen->startSel.row > rows)
    	screen->startSel.row = rows;
        if (screen->endRaw.row > rows)
    	screen->endRaw.row = rows;
        if (screen->endSel.row > rows)
    	screen->endSel.row = rows;
        if (screen->rawPos.row > rows)
    	screen->rawPos.row = rows;
    
        if (screen->startRaw.col > cols)
    	screen->startRaw.col = cols;
        if (screen->startSel.col > cols)
    	screen->startSel.col = cols;
        if (screen->endRaw.col > cols)
    	screen->endRaw.col = cols;
        if (screen->endSel.col > cols)
    	screen->endSel.col = cols;
        if (screen->rawPos.col > cols)
    	screen->rawPos.col = cols;
    }
    
    #if OPT_WIDE_CHARS
    #define isWideCell(row, col) isWideFrg((int)XTERM_CELL(row, col))
    #endif
    
    static void
    PointToCELL(TScreen *screen,
    	    int y,
    	    int x,
    	    CELL *cell)
    /* Convert pixel coordinates to character coordinates.
       Rows are clipped between firstValidRow and lastValidRow.
       Columns are clipped between to be 0 or greater, but are not clipped to some
           maximum value. */
    {
        cell->row = (y - screen->border) / FontHeight(screen);
        if (cell->row < screen->firstValidRow)
    	cell->row = screen->firstValidRow;
        else if (cell->row > screen->lastValidRow)
    	cell->row = screen->lastValidRow;
        cell->col = (x - OriginX(screen)) / FontWidth(screen);
        if (cell->col < 0)
    	cell->col = 0;
        else if (cell->col > MaxCols(screen)) {
    	cell->col = MaxCols(screen);
        }
    #if OPT_WIDE_CHARS
        /*
         * If we got a click on the right half of a doublewidth character,
         * pretend it happened on the left half.
         */
        if (cell->col > 0
    	&& isWideCell(cell->row, cell->col - 1)
    	&& (XTERM_CELL(cell->row, cell->col) == HIDDEN_CHAR)) {
    	cell->col -= 1;
        }
    #endif
    }
    
    /*
     * Find the last column at which text was drawn on the given row.
     */
    static int
    LastTextCol(TScreen *screen, CLineData *ld, int row)
    {
        int i = -1;
    
        if (ld != 0) {
    	if (okScrnRow(screen, row)) {
    	    const IAttr *ch;
    	    for (i = screen->max_col,
    		 ch = ld->attribs + i;
    		 i >= 0 && !(*ch & CHARDRAWN);
    		 ch--, i--) {
    		;
    	    }
    #if OPT_DEC_CHRSET
    	    if (CSET_DOUBLE(GetLineDblCS(ld))) {
    		i *= 2;
    	    }
    #endif
    	}
        }
        return (i);
    }
    
    #if !OPT_WIDE_CHARS
    /*
    ** double click table for cut and paste in 8 bits
    **
    ** This table is divided in four parts :
    **
    **	- control characters	[0,0x1f] U [0x80,0x9f]
    **	- separators		[0x20,0x3f] U [0xa0,0xb9]
    **	- binding characters	[0x40,0x7f] U [0xc0,0xff]
    **	- exceptions
    */
    /* *INDENT-OFF* */
    static int charClass[256] =
    {
    /* NUL  SOH  STX  ETX  EOT  ENQ  ACK  BEL */
        32,  1,    1,   1,   1,   1,   1,   1,
    /*  BS   HT   NL   VT   FF   CR   SO   SI */
         1,  32,   1,   1,   1,   1,   1,   1,
    /* DLE  DC1  DC2  DC3  DC4  NAK  SYN  ETB */
         1,   1,   1,   1,   1,   1,   1,   1,
    /* CAN   EM  SUB  ESC   FS   GS   RS   US */
         1,   1,   1,   1,   1,   1,   1,   1,
    /*  SP    !    "    #    $    %    &    ' */
        32,  33,  34,  35,  36,  37,  38,  39,
    /*   (    )    *    +    ,    -    .    / */
        40,  41,  42,  43,  44,  45,  46,  47,
    /*   0    1    2    3    4    5    6    7 */
        48,  48,  48,  48,  48,  48,  48,  48,
    /*   8    9    :    ;    <    =    >    ? */
        48,  48,  58,  59,  60,  61,  62,  63,
    /*   @    A    B    C    D    E    F    G */
        64,  48,  48,  48,  48,  48,  48,  48,
    /*   H    I    J    K    L    M    N    O */
        48,  48,  48,  48,  48,  48,  48,  48,
    /*   P    Q    R    S    T    U    V    W */
        48,  48,  48,  48,  48,  48,  48,  48,
    /*   X    Y    Z    [    \    ]    ^    _ */
        48,  48,  48,  91,  92,  93,  94,  48,
    /*   `    a    b    c    d    e    f    g */
        96,  48,  48,  48,  48,  48,  48,  48,
    /*   h    i    j    k    l    m    n    o */
        48,  48,  48,  48,  48,  48,  48,  48,
    /*   p    q    r    s    t    u    v    w */
        48,  48,  48,  48,  48,  48,  48,  48,
    /*   x    y    z    {    |    }    ~  DEL */
        48,  48,  48, 123, 124, 125, 126,   1,
    /* x80  x81  x82  x83  IND  NEL  SSA  ESA */
        1,    1,   1,   1,   1,   1,   1,   1,
    /* HTS  HTJ  VTS  PLD  PLU   RI  SS2  SS3 */
        1,    1,   1,   1,   1,   1,   1,   1,
    /* DCS  PU1  PU2  STS  CCH   MW  SPA  EPA */
        1,    1,   1,   1,   1,   1,   1,   1,
    /* x98  x99  x9A  CSI   ST  OSC   PM  APC */
        1,    1,   1,   1,   1,   1,   1,   1,
    /*   -    i   c/    L   ox   Y-    |   So */
        160, 161, 162, 163, 164, 165, 166, 167,
    /*  ..   c0   ip   <<    _        R0    - */
        168, 169, 170, 171, 172, 173, 174, 175,
    /*   o   +-    2    3    '    u   q|    . */
        176, 177, 178, 179, 180, 181, 182, 183,
    /*   ,    1    2   >>  1/4  1/2  3/4    ? */
        184, 185, 186, 187, 188, 189, 190, 191,
    /*  A`   A'   A^   A~   A:   Ao   AE   C, */
         48,  48,  48,  48,  48,  48,  48,  48,
    /*  E`   E'   E^   E:   I`   I'   I^   I: */
         48,  48,  48,  48,  48,  48,  48,  48,
    /*  D-   N~   O`   O'   O^   O~   O:    X */
         48,  48,  48,  48,  48,  48,  48, 215,
    /*  O/   U`   U'   U^   U:   Y'    P    B */
         48,  48,  48,  48,  48,  48,  48,  48,
    /*  a`   a'   a^   a~   a:   ao   ae   c, */
         48,  48,  48,  48,  48,  48,  48,  48,
    /*  e`   e'   e^   e:    i`  i'   i^   i: */
         48,  48,  48,  48,  48,  48,  48,  48,
    /*   d   n~   o`   o'   o^   o~   o:   -: */
         48,  48,  48,  48,  48,  48,  48, 247,
    /*  o/   u`   u'   u^   u:   y'    P   y: */
         48,  48,  48,  48,  48,  48,  48,  48};
    /* *INDENT-ON* */
    
    int
    SetCharacterClassRange(int low,	/* in range of [0..255] */
    		       int high,
    		       int value)	/* arbitrary */
    {
    
        if (low < 0 || high > 255 || high < low)
    	return (-1);
    
        for (; low <= high; low++)
    	charClass[low] = value;
    
        return (0);
    }
    #endif
    
    static int
    class_of(LineData *ld, CELL *cell)
    {
        CELL temp = *cell;
        int result = 0;
    
    #if OPT_DEC_CHRSET
        if (CSET_DOUBLE(GetLineDblCS(ld))) {
    	temp.col /= 2;
        }
    #endif
        if (temp.col < (int) ld->lineSize)
    	result = CharacterClass((int) (ld->charData[temp.col]));
        return result;
    }
    
    #if OPT_WIDE_CHARS
    #define CClassSelects(name, cclass) \
    	 (CClassOf(name) == cclass \
    	 || XTERM_CELL(screen->name.row, screen->name.col) == HIDDEN_CHAR)
    #else
    #define CClassSelects(name, cclass) \
    	 (class_of(ld.name, &((screen->name))) == cclass)
    #endif
    
    #define CClassOf(name) class_of(ld.name, &((screen->name)))
    
    #if OPT_REPORT_CCLASS
    static int
    show_cclass_range(int lo, int hi)
    {
        int cclass = CharacterClass(lo);
        int ident = (cclass == lo);
        int more = 0;
        if (ident) {
    	int ch;
    	for (ch = lo + 1; ch <= hi; ch++) {
    	    if (CharacterClass(ch) != ch) {
    		ident = 0;
    		break;
    	    }
    	}
    	if (ident && (hi < 255)) {
    	    ch = hi + 1;
    	    if (CharacterClass(ch) == ch) {
    		if (ch >= 255 || CharacterClass(ch + 1) != ch) {
    		    more = 1;
    		}
    	    }
    	}
        }
        if (!more) {
    	if (lo == hi) {
    	    printf("\t%d", lo);
    	} else {
    	    printf("\t%d-%d", lo, hi);
    	}
    	if (!ident)
    	    printf(":%d", cclass);
    	if (hi < 255)
    	    printf(", \\");
    	printf("\n");
        }
        return !more;
    }
    
    void
    report_char_class(XtermWidget xw)
    {
        /* simple table, to match documentation */
        static const char charnames[] =
        "NUL\0" "SOH\0" "STX\0" "ETX\0" "EOT\0" "ENQ\0" "ACK\0" "BEL\0"
        " BS\0" " HT\0" " NL\0" " VT\0" " NP\0" " CR\0" " SO\0" " SI\0"
        "DLE\0" "DC1\0" "DC2\0" "DC3\0" "DC4\0" "NAK\0" "SYN\0" "ETB\0"
        "CAN\0" " EM\0" "SUB\0" "ESC\0" " FS\0" " GS\0" " RS\0" " US\0"
        " SP\0" "  !\0" "  \"\0" "  #\0" "  $\0" "  %\0" "  &\0" "  '\0"
        "  (\0" "  )\0" "  *\0" "  +\0" "  ,\0" "  -\0" "  .\0" "  /\0"
        "  0\0" "  1\0" "  2\0" "  3\0" "  4\0" "  5\0" "  6\0" "  7\0"
        "  8\0" "  9\0" "  :\0" "  ;\0" "  <\0" "  =\0" "  >\0" "  ?\0"
        "  @\0" "  A\0" "  B\0" "  C\0" "  D\0" "  E\0" "  F\0" "  G\0"
        "  H\0" "  I\0" "  J\0" "  K\0" "  L\0" "  M\0" "  N\0" "  O\0"
        "  P\0" "  Q\0" "  R\0" "  S\0" "  T\0" "  U\0" "  V\0" "  W\0"
        "  X\0" "  Y\0" "  Z\0" "  [\0" "  \\\0" "  ]\0" "  ^\0" "  _\0"
        "  `\0" "  a\0" "  b\0" "  c\0" "  d\0" "  e\0" "  f\0" "  g\0"
        "  h\0" "  i\0" "  j\0" "  k\0" "  l\0" "  m\0" "  n\0" "  o\0"
        "  p\0" "  q\0" "  r\0" "  s\0" "  t\0" "  u\0" "  v\0" "  w\0"
        "  x\0" "  y\0" "  z\0" "  {\0" "  |\0" "  }\0" "  ~\0" "DEL\0"
        "x80\0" "x81\0" "x82\0" "x83\0" "IND\0" "NEL\0" "SSA\0" "ESA\0"
        "HTS\0" "HTJ\0" "VTS\0" "PLD\0" "PLU\0" " RI\0" "SS2\0" "SS3\0"
        "DCS\0" "PU1\0" "PU2\0" "STS\0" "CCH\0" " MW\0" "SPA\0" "EPA\0"
        "x98\0" "x99\0" "x9A\0" "CSI\0" " ST\0" "OSC\0" " PM\0" "APC\0"
        "  -\0" "  i\0" " c/\0" "  L\0" " ox\0" " Y-\0" "  |\0" " So\0"
        " ..\0" " c0\0" " ip\0" " <<\0" "  _\0" "   \0" " R0\0" "  -\0"
        "  o\0" " +-\0" "  2\0" "  3\0" "  '\0" "  u\0" " q|\0" "  .\0"
        "  ,\0" "  1\0" "  2\0" " >>\0" "1/4\0" "1/2\0" "3/4\0" "  ?\0"
        " A`\0" " A'\0" " A^\0" " A~\0" " A:\0" " Ao\0" " AE\0" " C,\0"
        " E`\0" " E'\0" " E^\0" " E:\0" " I`\0" " I'\0" " I^\0" " I:\0"
        " D-\0" " N~\0" " O`\0" " O'\0" " O^\0" " O~\0" " O:\0" "  X\0"
        " O/\0" " U`\0" " U'\0" " U^\0" " U:\0" " Y'\0" "  P\0" "  B\0"
        " a`\0" " a'\0" " a^\0" " a~\0" " a:\0" " ao\0" " ae\0" " c,\0"
        " e`\0" " e'\0" " e^\0" " e:\0" " i`\0" " i'\0" " i^\0" " i:\0"
        "  d\0" " n~\0" " o`\0" " o'\0" " o^\0" " o~\0" " o:\0" " -:\0"
        " o/\0" " u`\0" " u'\0" " u^\0" " u:\0" " y'\0" "  P\0" " y:\0";
        int ch, dh;
        int class_p;
    
        (void) xw;
    
        printf("static int charClass[256] = {\n");
        for (ch = 0; ch < 256; ++ch) {
    	const char *s = charnames + (ch * 4);
    	if ((ch & 7) == 0)
    	    printf("/*");
    	printf(" %s ", s);
    	if (((ch + 1) & 7) == 0) {
    	    printf("*/\n  ");
    	    for (dh = ch - 7; dh <= ch; ++dh) {
    		printf(" %3d%s", CharacterClass(dh), dh == 255 ? "};" : ",");
    	    }
    	    printf("\n");
    	}
        }
    
        /* print the table as if it were the charClass resource */
        printf("\n");
        printf("The table is equivalent to this \"charClass\" resource:\n");
        class_p = CharacterClass(dh = 0);
        for (ch = 0; ch < 256; ++ch) {
    	int class_c = CharacterClass(ch);
    	if (class_c != class_p) {
    	    if (show_cclass_range(dh, ch - 1)) {
    		dh = ch;
    		class_p = class_c;
    	    }
    	}
        }
        if (dh < 255) {
    	show_cclass_range(dh, 255);
        }
    
        if_OPT_WIDE_CHARS(TScreenOf(xw), {
    	/* if this is a wide-character configuration, print all intervals */
    	report_wide_char_class();
        });
    }
    #endif
    
    /*
     * If the given column is past the end of text on the given row, bump to the
     * beginning of the next line.
     */
    static Boolean
    okPosition(TScreen *screen,
    	   LineData **ld,
    	   CELL *cell)
    {
        Boolean result = True;
    
        if (cell->row > screen->max_row) {
    	result = False;
        } else if (cell->col > (LastTextCol(screen, *ld, cell->row) + 1)) {
    	if (cell->row < screen->max_row) {
    	    cell->col = 0;
    	    *ld = GET_LINEDATA(screen, ++cell->row);
    	    result = False;
    	}
        }
        return result;
    }
    
    static void
    trimLastLine(TScreen *screen,
    	     LineData **ld,
    	     CELL *last)
    {
        if (screen->cutNewline && last->row < screen->max_row) {
    	last->col = 0;
    	*ld = GET_LINEDATA(screen, ++last->row);
        } else {
    	last->col = LastTextCol(screen, *ld, last->row) + 1;
        }
    }
    
    #if OPT_SELECT_REGEX
    /*
     * Returns the first row of a wrapped line.
     */
    static int
    firstRowOfLine(TScreen *screen, int row, Bool visible)
    {
        LineData *ld = 0;
        int limit = visible ? 0 : -screen->savedlines;
    
        while (row > limit &&
    	   (ld = GET_LINEDATA(screen, row - 1)) != 0 &&
    	   LineTstWrapped(ld)) {
    	--row;
        }
        return row;
    }
    
    /*
     * Returns the last row of a wrapped line.
     */
    static int
    lastRowOfLine(TScreen *screen, int row)
    {
        LineData *ld;
    
        while (row < screen->max_row &&
    	   (ld = GET_LINEDATA(screen, row)) != 0 &&
    	   LineTstWrapped(ld)) {
    	++row;
        }
        return row;
    }
    
    /*
     * Returns the number of cells on the range of rows.
     */
    static unsigned
    lengthOfLines(TScreen *screen, int firstRow, int lastRow)
    {
        unsigned length = 0;
        int n;
    
        for (n = firstRow; n <= lastRow; ++n) {
    	LineData *ld = GET_LINEDATA(screen, n);
    	int value = LastTextCol(screen, ld, n);
    	if (value >= 0)
    	    length += (unsigned) (value + 1);
        }
        return length;
    }
    
    /*
     * Make a copy of the wrapped-line which corresponds to the given row as a
     * string of bytes.  Construct an index for the columns from the beginning of
     * the line.
     */
    static char *
    make_indexed_text(TScreen *screen, int row, unsigned length, int *indexed)
    {
        Char *result = 0;
        size_t need = (length + 1);
    
        /*
         * Get a quick upper bound to the number of bytes needed, if the whole
         * string were UTF-8.
         */
        if_OPT_WIDE_CHARS(screen, {
    	need *= ((screen->lineExtra + 1) * 6);
        });
    
        if ((result = TypeCallocN(Char, need + 1)) != 0) {
    	LineData *ld = GET_LINEDATA(screen, row);
    	unsigned used = 0;
    	Char *last = result;
    
    	do {
    	    int col = 0;
    	    int limit = LastTextCol(screen, ld, row);
    
    	    while (col <= limit) {
    		Char *next = last;
    		unsigned data = ld->charData[col];
    
    		assert(col < (int) ld->lineSize);
    		/* some internal points may not be drawn */
    		if (data == 0)
    		    data = ' ';
    
    		if_WIDE_OR_NARROW(screen, {
    		    next = convertToUTF8(last, data);
    		}
    		, {
    		    *next++ = CharOf(data);
    		});
    
    		if_OPT_WIDE_CHARS(screen, {
    		    size_t off;
    		    for_each_combData(off, ld) {
    			data = ld->combData[off][col];
    			if (data == 0)
    			    break;
    			next = convertToUTF8(next, data);
    		    }
    		});
    
    		indexed[used] = (int) (last - result);
    		*next = 0;
    		/* TRACE(("index[%d.%d] %d:%s\n", row, used, indexed[used], last)); */
    		last = next;
    		++used;
    		++col;
    		indexed[used] = (int) (next - result);
    	    }
    	} while (used < length &&
    		 LineTstWrapped(ld) &&
    		 (ld = GET_LINEDATA(screen, ++row)) != 0 &&
    		 row < screen->max_row);
        }
        /* TRACE(("result:%s\n", result)); */
        return (char *) result;
    }
    
    /*
     * Find the column given an offset into the character string by using the
     * index constructed in make_indexed_text().
     */
    static int
    indexToCol(int *indexed, int len, int off)
    {
        int col = 0;
        while (indexed[col] < len) {
    	if (indexed[col] >= off)
    	    break;
    	++col;
        }
        return col;
    }
    
    /*
     * Given a row number, and a column offset from that (which may be wrapped),
     * set the cell to the actual row/column values.
     */
    static void
    columnToCell(TScreen *screen, int row, int col, CELL *cell)
    {
        while (row < screen->max_row) {
    	CLineData *ld = GET_LINEDATA(screen, row);
    	int last = LastTextCol(screen, ld, row);
    
    	/* TRACE(("last(%d) = %d, have %d\n", row, last, col)); */
    	if (col <= last) {
    	    break;
    	}
    	/*
    	 * Stop if the current row does not wrap (does not continue the current
    	 * line).
    	 */
    	if (!LineTstWrapped(ld)) {
    	    col = last + 1;
    	    break;
    	}
    	col -= (last + 1);
    	++row;
        }
        if (col < 0)
    	col = 0;
        cell->row = row;
        cell->col = col;
    }
    
    /*
     * Given a cell, find the corresponding column offset.
     */
    static int
    cellToColumn(TScreen *screen, CELL *cell)
    {
        CLineData *ld = 0;
        int col = cell->col;
        int row = firstRowOfLine(screen, cell->row, False);
        while (row < cell->row) {
    	ld = GET_LINEDATA(screen, row);
    	col += LastTextCol(screen, ld, row++);
        }
    #if OPT_DEC_CHRSET
        if (ld == 0)
    	ld = GET_LINEDATA(screen, row);
        if (CSET_DOUBLE(GetLineDblCS(ld)))
    	col /= 2;
    #endif
        return col;
    }
    
    static void
    do_select_regex(TScreen *screen, CELL *startc, CELL *endc)
    {
        LineData *ld = GET_LINEDATA(screen, startc->row);
        int inx = ((screen->numberOfClicks - 1) % screen->maxClicks);
        char *expr = screen->selectExpr[inx];
        regex_t preg;
        regmatch_t match;
    
        TRACE(("Select_REGEX[%d]:%s\n", inx, NonNull(expr)));
        if (okPosition(screen, &ld, startc) && expr != 0) {
    	if (regcomp(&preg, expr, REG_EXTENDED) == 0) {
    	    int firstRow = firstRowOfLine(screen, startc->row, True);
    	    int lastRow = lastRowOfLine(screen, firstRow);
    	    unsigned size = lengthOfLines(screen, firstRow, lastRow);
    	    int actual = cellToColumn(screen, startc);
    	    int *indexed;
    
    	    TRACE(("regcomp ok rows %d..%d bytes %d\n",
    		   firstRow, lastRow, size));
    
    	    if ((indexed = TypeCallocN(int, size + 1)) != 0) {
    		char *search;
    		if ((search = make_indexed_text(screen,
    						firstRow,
    						size,
    						indexed)) != 0) {
    		    int len = (int) strlen(search);
    		    int col;
    		    int best_col = -1;
    		    int best_len = -1;
    
    		    startc->row = 0;
    		    startc->col = 0;
    		    endc->row = 0;
    		    endc->col = 0;
    
    		    for (col = 0; indexed[col] < len; ++col) {
    			if (regexec(&preg,
    				    search + indexed[col],
    				    (size_t) 1, &match, 0) == 0) {
    			    int start_inx = (int) (match.rm_so + indexed[col]);
    			    int finis_inx = (int) (match.rm_eo + indexed[col]);
    			    int start_col = indexToCol(indexed, len, start_inx);
    			    int finis_col = indexToCol(indexed, len, finis_inx);
    
    			    if (start_col <= actual &&
    				actual <= finis_col) {
    				int test = finis_col - start_col;
    				if (best_len < test) {
    				    best_len = test;
    				    best_col = start_col;
    				    TRACE(("match column %d len %d\n",
    					   best_col,
    					   best_len));
    				}
    			    }
    			}
    		    }
    		    if (best_col >= 0) {
    			int best_nxt = best_col + best_len;
    			columnToCell(screen, firstRow, best_col, startc);
    			columnToCell(screen, firstRow, best_nxt, endc);
    			TRACE(("search::%s\n", search));
    			TRACE(("indexed:%d..%d -> %d..%d\n",
    			       best_col, best_nxt,
    			       indexed[best_col],
    			       indexed[best_nxt]));
    			TRACE(("matched:%d:%s\n",
    			       indexed[best_nxt] + 1 -
    			       indexed[best_col],
    			       visibleChars((Char *) (search + indexed[best_col]),
    					    (unsigned) (indexed[best_nxt] +
    							1 -
    							indexed[best_col]))));
    		    }
    		    free(search);
    		}
    		free(indexed);
    #if OPT_DEC_CHRSET
    		if ((ld = GET_LINEDATA(screen, startc->row)) != 0) {
    		    if (CSET_DOUBLE(GetLineDblCS(ld)))
    			startc->col *= 2;
    		}
    		if ((ld = GET_LINEDATA(screen, endc->row)) != 0) {
    		    if (CSET_DOUBLE(GetLineDblCS(ld)))
    			endc->col *= 2;
    		}
    #endif
    	    }
    	    regfree(&preg);
    	}
        }
    }
    #endif /* OPT_SELECT_REGEX */
    
    #define InitRow(name) \
    	ld.name = GET_LINEDATA(screen, screen->name.row)
    
    #define NextRow(name) \
    	ld.name = GET_LINEDATA(screen, ++screen->name.row)
    
    #define PrevRow(name) \
    	ld.name = GET_LINEDATA(screen, --screen->name.row)
    
    #define MoreRows(name) \
    	(screen->name.row < screen->max_row)
    
    #define isPrevWrapped(name) \
    	(screen->name.row > 0 \
    	   && (ltmp = GET_LINEDATA(screen, screen->name.row - 1)) != 0 \
    	   && LineTstWrapped(ltmp))
    
    /*
     * sets startSel endSel
     * ensuring that they have legal values
     */
    static void
    ComputeSelect(XtermWidget xw,
    	      CELL *startc,
    	      CELL *endc,
    	      Bool extend)
    {
        TScreen *screen = TScreenOf(xw);
    
        int cclass;
        CELL first = *startc;
        CELL last = *endc;
        Boolean ignored = False;
    
        struct {
    	LineData *startSel;
    	LineData *endSel;
        } ld;
        LineData *ltmp;
    
        TRACE(("ComputeSelect(startRow=%d, startCol=%d, endRow=%d, endCol=%d, %sextend)\n",
    	   first.row, first.col,
    	   last.row, last.col,
    	   extend ? "" : "no"));
    
    #if OPT_WIDE_CHARS
        if (first.col > 1
    	&& isWideCell(first.row, first.col - 1)
    	&& XTERM_CELL(first.row, first.col - 0) == HIDDEN_CHAR) {
    	TRACE(("Adjusting start. Changing downwards from %i.\n", first.col));
    	first.col -= 1;
    	if (last.col == (first.col + 1))
    	    last.col--;
        }
    
        if (last.col > 1
    	&& isWideCell(last.row, last.col - 1)
    	&& XTERM_CELL(last.row, last.col) == HIDDEN_CHAR) {
    	last.col += 1;
        }
    #endif
    
        if (Coordinate(screen, &first) <= Coordinate(screen, &last)) {
    	screen->startSel = screen->startRaw = first;
    	screen->endSel = screen->endRaw = last;
        } else {			/* Swap them */
    	screen->startSel = screen->startRaw = last;
    	screen->endSel = screen->endRaw = first;
        }
    
        InitRow(startSel);
        InitRow(endSel);
    
        switch (screen->selectUnit) {
        case Select_CHAR:
    	(void) okPosition(screen, &(ld.startSel), &(screen->startSel));
    	(void) okPosition(screen, &(ld.endSel), &(screen->endSel));
    	break;
    
        case Select_WORD:
    	TRACE(("Select_WORD\n"));
    	if (okPosition(screen, &(ld.startSel), &(screen->startSel))) {
    	    cclass = CClassOf(startSel);
    	    do {
    		--screen->startSel.col;
    		if (screen->startSel.col < 0
    		    && isPrevWrapped(startSel)) {
    		    PrevRow(startSel);
    		    screen->startSel.col = LastTextCol(screen, ld.startSel, screen->startSel.row);
    		}
    	    } while (screen->startSel.col >= 0
    		     && CClassSelects(startSel, cclass));
    	    ++screen->startSel.col;
    	}
    #if OPT_WIDE_CHARS
    	if (screen->startSel.col
    	    && XTERM_CELL(screen->startSel.row,
    			  screen->startSel.col) == HIDDEN_CHAR)
    	    screen->startSel.col++;
    #endif
    
    	if (okPosition(screen, &(ld.endSel), &(screen->endSel))) {
    	    int length = LastTextCol(screen, ld.endSel, screen->endSel.row);
    	    cclass = CClassOf(endSel);
    	    do {
    		++screen->endSel.col;
    		if (screen->endSel.col > length
    		    && LineTstWrapped(ld.endSel)) {
    		    if (!MoreRows(endSel))
    			break;
    		    screen->endSel.col = 0;
    		    NextRow(endSel);
    		    length = LastTextCol(screen, ld.endSel, screen->endSel.row);
    		}
    	    } while (screen->endSel.col <= length
    		     && CClassSelects(endSel, cclass));
    	    /* Word-select selects if pointing to any char in "word",
    	     * especially note that it includes the last character in a word.
    	     * So we do no --endSel.col and do special eol handling.
    	     */
    	    if (screen->endSel.col > length + 1
    		&& MoreRows(endSel)) {
    		screen->endSel.col = 0;
    		NextRow(endSel);
    	    }
    	}
    #if OPT_WIDE_CHARS
    	if (screen->endSel.col
    	    && XTERM_CELL(screen->endSel.row,
    			  screen->endSel.col) == HIDDEN_CHAR)
    	    screen->endSel.col++;
    #endif
    
    	screen->saveStartW = screen->startSel;
    	break;
    
        case Select_LINE:
    	TRACE(("Select_LINE\n"));
    	while (LineTstWrapped(ld.endSel)
    	       && MoreRows(endSel)) {
    	    NextRow(endSel);
    	}
    	if (screen->cutToBeginningOfLine
    	    || screen->startSel.row < screen->saveStartW.row) {
    	    screen->startSel.col = 0;
    	    while (isPrevWrapped(startSel)) {
    		PrevRow(startSel);
    	    }
    	} else if (!extend) {
    	    if ((first.row < screen->saveStartW.row)
    		|| (isSameRow(&first, &(screen->saveStartW))
    		    && first.col < screen->saveStartW.col)) {
    		screen->startSel.col = 0;
    		while (isPrevWrapped(startSel)) {
    		    PrevRow(startSel);
    		}
    	    } else {
    		screen->startSel = screen->saveStartW;
    	    }
    	}
    	trimLastLine(screen, &(ld.endSel), &(screen->endSel));
    	break;
    
        case Select_GROUP:		/* paragraph */
    	TRACE(("Select_GROUP\n"));
    	if (okPosition(screen, &(ld.startSel), &(screen->startSel))) {
    	    /* scan backward for beginning of group */
    	    while (screen->startSel.row > 0 &&
    		   (LastTextCol(screen, ld.startSel, screen->startSel.row -
    				1) > 0 ||
    		    isPrevWrapped(startSel))) {
    		PrevRow(startSel);
    	    }
    	    screen->startSel.col = 0;
    	    /* scan forward for end of group */
    	    while (MoreRows(endSel) &&
    		   (LastTextCol(screen, ld.endSel, screen->endSel.row + 1) >
    		    0 ||
    		    LineTstWrapped(ld.endSel))) {
    		NextRow(endSel);
    	    }
    	    trimLastLine(screen, &(ld.endSel), &(screen->endSel));
    	}
    	break;
    
        case Select_PAGE:		/* everything one can see */
    	TRACE(("Select_PAGE\n"));
    	screen->startSel.row = 0;
    	screen->startSel.col = 0;
    	screen->endSel.row = MaxRows(screen);
    	screen->endSel.col = 0;
    	break;
    
        case Select_ALL:		/* counts scrollback if in normal screen */
    	TRACE(("Select_ALL\n"));
    	screen->startSel.row = -screen->savedlines;
    	screen->startSel.col = 0;
    	screen->endSel.row = MaxRows(screen);
    	screen->endSel.col = 0;
    	break;
    
    #if OPT_SELECT_REGEX
        case Select_REGEX:
    	do_select_regex(screen, &(screen->startSel), &(screen->endSel));
    	break;
    #endif
    
        case NSELECTUNITS:		/* always ignore */
    	ignored = True;
    	break;
        }
    
        if (!ignored) {
    	/* check boundaries */
    	ScrollSelection(screen, 0, False);
    	TrackText(xw, &(screen->startSel), &(screen->endSel));
        }
    
        return;
    }
    
    /* Guaranteed (first.row, first.col) <= (last.row, last.col) */
    static void
    TrackText(XtermWidget xw,
    	  const CELL *firstp,
    	  const CELL *lastp)
    {
        TScreen *screen = TScreenOf(xw);
        int from, to;
        CELL old_start, old_end;
        CELL first = *firstp;
        CELL last = *lastp;
    
        TRACE(("TrackText(first=%d,%d, last=%d,%d)\n",
    	   first.row, first.col, last.row, last.col));
    
        old_start = screen->startH;
        old_end = screen->endH;
        TRACE(("...previous(first=%d,%d, last=%d,%d)\n",
    	   old_start.row, old_start.col,
    	   old_end.row, old_end.col));
        if (isSameCELL(&first, &old_start) &&
    	isSameCELL(&last, &old_end)) {
    	return;
        }
    
        screen->startH = first;
        screen->endH = last;
        from = Coordinate(screen, &screen->startH);
        to = Coordinate(screen, &screen->endH);
        if (to <= screen->startHCoord || from > screen->endHCoord) {
    	/* No overlap whatsoever between old and new hilite */
    	ReHiliteText(xw, &old_start, &old_end);
    	ReHiliteText(xw, &first, &last);
        } else {
    	if (from < screen->startHCoord) {
    	    /* Extend left end */
    	    ReHiliteText(xw, &first, &old_start);
    	} else if (from > screen->startHCoord) {
    	    /* Shorten left end */
    	    ReHiliteText(xw, &old_start, &first);
    	}
    	if (to > screen->endHCoord) {
    	    /* Extend right end */
    	    ReHiliteText(xw, &old_end, &last);
    	} else if (to < screen->endHCoord) {
    	    /* Shorten right end */
    	    ReHiliteText(xw, &last, &old_end);
    	}
        }
        screen->startHCoord = from;
        screen->endHCoord = to;
    }
    
    static void
    UnHiliteText(XtermWidget xw)
    {
        TrackText(xw, &zeroCELL, &zeroCELL);
    }
    
    /* Guaranteed that (first->row, first->col) <= (last->row, last->col) */
    static void
    ReHiliteText(XtermWidget xw,
    	     CELL *firstp,
    	     CELL *lastp)
    {
        TScreen *screen = TScreenOf(xw);
        CELL first = *firstp;
        CELL last = *lastp;
    
        TRACE(("ReHiliteText from %d.%d to %d.%d\n",
    	   first.row, first.col, last.row, last.col));
    
        if (first.row < 0)
    	first.row = first.col = 0;
        else if (first.row > screen->max_row)
    	return;			/* nothing to do, since last.row >= first.row */
    
        if (last.row < 0)
    	return;			/* nothing to do, since first.row <= last.row */
        else if (last.row > screen->max_row) {
    	last.row = screen->max_row;
    	last.col = MaxCols(screen);
        }
        if (isSameCELL(&first, &last))
    	return;
    
        if (!isSameRow(&first, &last)) {	/* do multiple rows */
    	int i;
    	if ((i = screen->max_col - first.col + 1) > 0) {	/* first row */
    	    ScrnRefresh(xw, first.row, first.col, 1, i, True);
    	}
    	if ((i = last.row - first.row - 1) > 0) {	/* middle rows */
    	    ScrnRefresh(xw, first.row + 1, 0, i, MaxCols(screen), True);
    	}
    	if (last.col > 0 && last.row <= screen->max_row) {	/* last row */
    	    ScrnRefresh(xw, last.row, 0, 1, last.col, True);
    	}
        } else {			/* do single row */
    	ScrnRefresh(xw, first.row, first.col, 1, last.col - first.col, True);
        }
    }
    
    /*
     * Guaranteed that (cellc->row, cellc->col) <= (cell->row, cell->col),
     * and that both points are valid
     * (may have cell->row = screen->max_row+1, cell->col = 0).
     */
    static void
    SaltTextAway(XtermWidget xw,
    	     int which,
    	     CELL *cellc,
    	     CELL *cell)
    {
        TScreen *screen = TScreenOf(xw);
        SelectedCells *scp;
        int i;
        int eol;
        int need = 0;
        Char *line;
        Char *lp;
        CELL first = *cellc;
        CELL last = *cell;
    
        if (which < 0 || which >= MAX_SELECTIONS) {
    	TRACE(("SaltTextAway - which selection?\n"));
    	return;
        }
        scp = &(screen->selected_cells[which]);
    
        TRACE(("SaltTextAway which=%d, first=%d,%d, last=%d,%d\n",
    	   which, first.row, first.col, last.row, last.col));
    
        if (isSameRow(&first, &last) && first.col > last.col) {
    	int tmp;
    	EXCHANGE(first.col, last.col, tmp);
        }
    
        --last.col;
        /* first we need to know how long the string is before we can save it */
    
        if (isSameRow(&last, &first)) {
    	need = Length(screen, first.row, first.col, last.col);
        } else {			/* two cases, cut is on same line, cut spans multiple lines */
    	need += Length(screen, first.row, first.col, screen->max_col) + 1;
    	for (i = first.row + 1; i < last.row; i++)
    	    need += Length(screen, i, 0, screen->max_col) + 1;
    	if (last.col >= 0)
    	    need += Length(screen, last.row, 0, last.col);
        }
    
        /* UTF-8 may require more space */
        if_OPT_WIDE_CHARS(screen, {
    	need *= 4;
        });
    
        /* now get some memory to save it in */
        if (need < 0)
    	return;
    
        if (scp->data_limit <= (unsigned) need) {
    	if ((line = (Char *) malloc((size_t) need + 1)) == 0)
    	    SysError(ERROR_BMALLOC2);
    	free(scp->data_buffer);
    	scp->data_buffer = line;
    	scp->data_limit = (size_t) (need + 1);
        } else {
    	line = scp->data_buffer;
        }
    
        if (line == 0)
    	return;
    
        line[need] = '\0';		/* make sure it is null terminated */
        lp = line;			/* lp points to where to save the text */
        if (isSameRow(&last, &first)) {
    	lp = SaveText(screen, last.row, first.col, last.col, lp, &eol);
        } else {
    	lp = SaveText(screen, first.row, first.col, screen->max_col, lp, &eol);
    	if (eol)
    	    *lp++ = '\n';	/* put in newline at end of line */
    	for (i = first.row + 1; i < last.row; i++) {
    	    lp = SaveText(screen, i, 0, screen->max_col, lp, &eol);
    	    if (eol)
    		*lp++ = '\n';
    	}
    	if (last.col >= 0)
    	    lp = SaveText(screen, last.row, 0, last.col, lp, &eol);
        }
        *lp = '\0';			/* make sure we have end marked */
    
        TRACE(("Salted TEXT:%u:%s\n", (unsigned) (lp - line),
    	   visibleChars(line, (unsigned) (lp - line))));
    
        scp->data_length = (size_t) (lp - line);
    }
    
    #if OPT_PASTE64
    void
    ClearSelectionBuffer(TScreen *screen, String selection)
    {
        int which = TargetToSelection(screen, selection);
        SelectedCells *scp = &(screen->selected_cells[okSelectionCode(which)]);
        if (scp->data_buffer) {
    	free(scp->data_buffer);
    	scp->data_buffer = 0;
    	scp->data_limit = 0;
        }
        scp->data_length = 0;
        screen->base64_count = 0;
    }
    
    static void
    AppendStrToSelectionBuffer(SelectedCells * scp, Char *text, size_t len)
    {
        if (len != 0) {
    	size_t j = (scp->data_length + len);
    	size_t k = j + (j >> 2) + 80;
    	if (j + 1 >= scp->data_limit) {
    	    Char *line;
    	    if (!scp->data_length) {
    		line = (Char *) malloc(k);
    	    } else {
    		line = (Char *) realloc(scp->data_buffer, k);
    	    }
    	    if (line == 0)
    		SysError(ERROR_BMALLOC2);
    	    scp->data_buffer = line;
    	    scp->data_limit = k;
    	}
    	if (scp->data_buffer != 0) {
    	    memcpy(scp->data_buffer + scp->data_length, text, len);
    	    scp->data_length += len;
    	    scp->data_buffer[scp->data_length] = 0;
    	}
        }
    }
    
    void
    AppendToSelectionBuffer(TScreen *screen, unsigned c, String selection)
    {
        int which = TargetToSelection(screen, selection);
        SelectedCells *scp = &(screen->selected_cells[okSelectionCode(which)]);
        unsigned six;
        Char ch;
    
        /* Decode base64 character */
        if (c >= 'A' && c <= 'Z')
    	six = c - 'A';
        else if (c >= 'a' && c <= 'z')
    	six = c - 'a' + 26;
        else if (c >= '0' && c <= '9')
    	six = c - '0' + 52;
        else if (c == '+')
    	six = 62;
        else if (c == '/')
    	six = 63;
        else
    	return;
    
        /* Accumulate bytes */
        switch (screen->base64_count) {
        case 0:
    	screen->base64_accu = six;
    	screen->base64_count = 6;
    	break;
    
        case 2:
    	ch = CharOf((screen->base64_accu << 6) + six);
    	screen->base64_count = 0;
    	AppendStrToSelectionBuffer(scp, &ch, (size_t) 1);
    	break;
    
        case 4:
    	ch = CharOf((screen->base64_accu << 4) + (six >> 2));
    	screen->base64_accu = (six & 0x3);
    	screen->base64_count = 2;
    	AppendStrToSelectionBuffer(scp, &ch, (size_t) 1);
    	break;
    
        case 6:
    	ch = CharOf((screen->base64_accu << 2) + (six >> 4));
    	screen->base64_accu = (six & 0xF);
    	screen->base64_count = 4;
    	AppendStrToSelectionBuffer(scp, &ch, (size_t) 1);
    	break;
        }
    }
    
    void
    CompleteSelection(XtermWidget xw, String *args, Cardinal len)
    {
        TScreen *screen = TScreenOf(xw);
    
        screen->base64_count = 0;
        screen->base64_accu = 0;
        _OwnSelection(xw, args, len);
    }
    #endif /* OPT_PASTE64 */
    
    static Bool
    _ConvertSelectionHelper(Widget w,
    			SelectedCells * scp,
    			Atom *type,
    			XtPointer *value,
    			unsigned long *length,
    			int *format,
    			int (*conversion_function) (Display *,
    						    char **, int,
    						    XICCEncodingStyle,
    						    XTextProperty *),
    			XICCEncodingStyle conversion_style)
    {
        XtermWidget xw;
    
        *value = 0;
        *length = 0;
        *type = 0;
        *format = 0;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	Display *dpy = XtDisplay(w);
    	XTextProperty textprop;
    	int out_n = 0;
    	char *result = 0;
    	char *the_data = (char *) scp->data_buffer;
    	char *the_next;
    	unsigned long remaining = scp->data_length;
    
    	TRACE(("converting %ld:'%s'\n",
    	       (long) scp->data_length,
    	       visibleChars(scp->data_buffer, (unsigned) scp->data_length)));
    	/*
    	 * For most selections, we can convert in one pass.  It is possible
    	 * that some applications contain embedded nulls, e.g., using xterm's
    	 * paste64 feature.  For those cases, we will build up the result in
    	 * parts.
    	 */
    	if (memchr(the_data, 0, scp->data_length) != 0) {
    	    TRACE(("selection contains embedded nulls\n"));
    	    result = calloc(scp->data_length + 1, sizeof(char));
    	}
    
          next_try:
    	memset(&textprop, 0, sizeof(textprop));
    	if (conversion_function(dpy, &the_data, 1,
    				conversion_style,
    				&textprop) >= Success) {
    	    if ((result != 0)
    		&& (textprop.value != 0)
    		&& (textprop.format == 8)) {
    		char *text_values = (char *) textprop.value;
    		unsigned long in_n;
    
    		if (out_n == 0) {
    		    *value = result;
    		    *type = textprop.encoding;
    		    *format = textprop.format;
    		}
    		for (in_n = 0; in_n < textprop.nitems; ++in_n) {
    		    result[out_n++] = text_values[in_n];
    		}
    		*length += textprop.nitems;
    		if ((the_next = memchr(the_data, 0, remaining)) != 0) {
    		    unsigned long this_was = (unsigned long) (the_next - the_data);
    		    this_was++;
    		    the_data += this_was;
    		    remaining -= this_was;
    		    result[out_n++] = 0;
    		    *length += 1;
    		    if (remaining)
    			goto next_try;
    		}
    		return True;
    	    } else {
    		free(result);
    		*value = (XtPointer) textprop.value;
    		*length = textprop.nitems;
    		*type = textprop.encoding;
    		*format = textprop.format;
    		return True;
    	    }
    	}
    	free(result);
        }
        return False;
    }
    
    static Boolean
    SaveConvertedLength(XtPointer *target, unsigned long source)
    {
        Boolean result = False;
    
        *target = XtMalloc(4);
        if (*target != 0) {
    	result = True;
    	if (sizeof(unsigned long) == 4) {
    	    *(unsigned long *) *target = source;
    	} else if (sizeof(unsigned) == 4) {
    	    *(unsigned *) *target = (unsigned) source;
    	} else if (sizeof(unsigned short) == 4) {
    	    *(unsigned short *) *target = (unsigned short) source;
    	} else {
    	    /* FIXME - does this depend on byte-order? */
    	    unsigned long temp = source;
    	    memcpy((char *) *target,
    		   ((char *) &temp) + sizeof(temp) - 4,
    		   (size_t) 4);
    	}
        }
        return result;
    }
    
    #define keepClipboard(d,atom) ((screen->keepClipboard) && \
    	 (atom == XA_CLIPBOARD(d)))
    
    static Boolean
    ConvertSelection(Widget w,
    		 Atom *selection,
    		 Atom *target,
    		 Atom *type,
    		 XtPointer *value,
    		 unsigned long *length,
    		 int *format)
    {
        Display *dpy = XtDisplay(w);
        TScreen *screen;
        SelectedCells *scp;
        Bool result = False;
    
        Char *data;
        unsigned long data_length;
    
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) == 0)
    	return False;
    
        screen = TScreenOf(xw);
    
        TRACE(("ConvertSelection %s -> %s\n",
    	   TraceAtomName(screen->display, *selection),
    	   visibleSelectionTarget(dpy, *target)));
    
        if (keepClipboard(dpy, *selection)) {
    	TRACE(("asked for clipboard\n"));
    	scp = &(screen->clipboard_data);
        } else {
    	TRACE(("asked for selection\n"));
    	scp = &(screen->selected_cells[AtomToSelection(dpy, *selection)]);
        }
    
        data = scp->data_buffer;
        data_length = scp->data_length;
        if (data == NULL) {
    	TRACE(("...no selection-data\n"));
    	return False;
        }
    
        if (*target == XA_TARGETS(dpy)) {
    	Atom *targetP;
    	XPointer std_return = 0;
    	unsigned long std_length;
    
    	if (XmuConvertStandardSelection(w, screen->selection_time, selection,
    					target, type, &std_return,
    					&std_length, format)) {
    	    Atom *my_targets = _SelectionTargets(w);
    	    Atom *allocP;
    	    Atom *std_targets;
    
    	    TRACE(("XmuConvertStandardSelection - success\n"));
    	    std_targets = (Atom *) (void *) (std_return);
    	    *length = std_length + 6;
    
    	    targetP = TypeXtMallocN(Atom, *length);
    	    allocP = targetP;
    
    	    *value = (XtPointer) targetP;
    
    	    if (my_targets != 0) {
    		while (*my_targets != None) {
    		    *targetP++ = *my_targets++;
    		}
    	    }
    	    *targetP++ = XA_LENGTH(dpy);
    	    *targetP++ = XA_LIST_LENGTH(dpy);
    
    	    *length = std_length + (unsigned long) (targetP - allocP);
    
    	    memcpy(targetP, std_targets, sizeof(Atom) * std_length);
    	    XtFree((char *) std_targets);
    	    *type = XA_ATOM;
    	    *format = 32;
    	    result = True;
    	} else {
    	    TRACE(("XmuConvertStandardSelection - failed\n"));
    	}
        }
    #if OPT_WIDE_CHARS
        else if (screen->wide_chars && *target == XA_STRING) {
    	result =
    	    _ConvertSelectionHelper(w, scp,
    				    type, value, length, format,
    				    Xutf8TextListToTextProperty,
    				    XStringStyle);
    	TRACE(("...Xutf8TextListToTextProperty:%d\n", result));
        } else if (screen->wide_chars && *target == XA_UTF8_STRING(dpy)) {
    	result =
    	    _ConvertSelectionHelper(w, scp,
    				    type, value, length, format,
    				    Xutf8TextListToTextProperty,
    				    XUTF8StringStyle);
    	TRACE(("...Xutf8TextListToTextProperty:%d\n", result));
        } else if (screen->wide_chars && *target == XA_TEXT(dpy)) {
    	result =
    	    _ConvertSelectionHelper(w, scp,
    				    type, value, length, format,
    				    Xutf8TextListToTextProperty,
    				    XStdICCTextStyle);
    	TRACE(("...Xutf8TextListToTextProperty:%d\n", result));
        } else if (screen->wide_chars && *target == XA_COMPOUND_TEXT(dpy)) {
    	result =
    	    _ConvertSelectionHelper(w, scp,
    				    type, value, length, format,
    				    Xutf8TextListToTextProperty,
    				    XCompoundTextStyle);
    	TRACE(("...Xutf8TextListToTextProperty:%d\n", result));
        }
    #endif
    
        else if (*target == XA_STRING) {	/* not wide_chars */
    	/* We can only reach this point if the selection requestor
    	   requested STRING before any of TEXT, COMPOUND_TEXT or
    	   UTF8_STRING.  We therefore assume that the requestor is not
    	   properly internationalised, and dump raw eight-bit data
    	   with no conversion into the selection.  Yes, this breaks
    	   the ICCCM in non-Latin-1 locales. */
    	*type = XA_STRING;
    	*value = (XtPointer) data;
    	*length = data_length;
    	*format = 8;
    	result = True;
    	TRACE(("...raw 8-bit data:%d\n", result));
        } else if (*target == XA_TEXT(dpy)) {	/* not wide_chars */
    	result =
    	    _ConvertSelectionHelper(w, scp,
    				    type, value, length, format,
    				    XmbTextListToTextProperty,
    				    XStdICCTextStyle);
    	TRACE(("...XmbTextListToTextProperty(StdICC):%d\n", result));
        } else if (*target == XA_COMPOUND_TEXT(dpy)) {	/* not wide_chars */
    	result =
    	    _ConvertSelectionHelper(w, scp,
    				    type, value, length, format,
    				    XmbTextListToTextProperty,
    				    XCompoundTextStyle);
    	TRACE(("...XmbTextListToTextProperty(Compound):%d\n", result));
        }
    #ifdef X_HAVE_UTF8_STRING
        else if (*target == XA_UTF8_STRING(dpy)) {	/* not wide_chars */
    	result =
    	    _ConvertSelectionHelper(w, scp,
    				    type, value, length, format,
    				    XmbTextListToTextProperty,
    				    XUTF8StringStyle);
    	TRACE(("...XmbTextListToTextProperty(UTF8):%d\n", result));
        }
    #endif
        else if (*target == XA_LIST_LENGTH(dpy)) {
    	result = SaveConvertedLength(value, (unsigned long) 1);
    	*type = XA_INTEGER;
    	*length = 1;
    	*format = 32;
    	TRACE(("...list of values:%d\n", result));
        } else if (*target == XA_LENGTH(dpy)) {
    	/* This value is wrong if we have UTF-8 text */
    	result = SaveConvertedLength(value, scp->data_length);
    	*type = XA_INTEGER;
    	*length = 1;
    	*format = 32;
    	TRACE(("...list of values:%d\n", result));
        } else if (XmuConvertStandardSelection(w,
    					   screen->selection_time, selection,
    					   target, type, (XPointer *) value,
    					   length, format)) {
    	result = True;
    	TRACE(("...XmuConvertStandardSelection:%d\n", result));
        }
    
        /* else */
        return (Boolean) result;
    }
    
    static void
    LoseSelection(Widget w, Atom *selection)
    {
        TScreen *screen;
        Atom *atomP;
        Cardinal i;
    
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) == 0)
    	return;
    
        screen = TScreenOf(xw);
        TRACE(("LoseSelection %s\n", TraceAtomName(screen->display, *selection)));
    
        for (i = 0, atomP = screen->selection_atoms;
    	 i < screen->selection_count; i++, atomP++) {
    	if (*selection == *atomP)
    	    *atomP = (Atom) 0;
    	if (CutBuffer(*atomP) >= 0) {
    	    *atomP = (Atom) 0;
    	}
        }
    
        for (i = screen->selection_count; i; i--) {
    	if (screen->selection_atoms[i - 1] != 0)
    	    break;
        }
        screen->selection_count = i;
    
        for (i = 0, atomP = screen->selection_atoms;
    	 i < screen->selection_count; i++, atomP++) {
    	if (*atomP == (Atom) 0) {
    	    *atomP = screen->selection_atoms[--screen->selection_count];
    	}
        }
    
        if (screen->selection_count == 0)
    	UnHiliteText(xw);
    }
    
    /* ARGSUSED */
    static void
    SelectionDone(Widget w GCC_UNUSED,
    	      Atom *selection GCC_UNUSED,
    	      Atom *target GCC_UNUSED)
    {
        /* empty proc so Intrinsics know we want to keep storage */
        TRACE(("SelectionDone\n"));
    }
    
    static void
    _OwnSelection(XtermWidget xw,
    	      String *selections,
    	      Cardinal count)
    {
        TScreen *screen = TScreenOf(xw);
        Display *dpy = screen->display;
        Atom *atoms = screen->selection_atoms;
        Cardinal i;
        Bool have_selection = False;
        SelectedCells *scp;
    
        if (count == 0)
    	return;
    
        TRACE(("_OwnSelection count %d\n", count));
        selections = MapSelections(xw, selections, count);
    
        if (count > screen->sel_atoms_size) {
    	XtFree((char *) atoms);
    	atoms = TypeXtMallocN(Atom, count);
    	screen->selection_atoms = atoms;
    	screen->sel_atoms_size = count;
        }
        XmuInternStrings(dpy, selections, count, atoms);
        for (i = 0; i < count; i++) {
    	int cutbuffer = CutBuffer(atoms[i]);
    	if (cutbuffer >= 0) {
    	    unsigned long limit =
    	    (unsigned long) (4 * XMaxRequestSize(dpy) - 32);
    	    scp = &(screen->selected_cells[CutBufferToCode(cutbuffer)]);
    	    if (scp->data_length > limit) {
    		TRACE(("selection too big (%lu bytes), not storing in CUT_BUFFER%d\n",
    		       scp->data_length, cutbuffer));
    		xtermWarning("selection too big (%lu bytes), not storing in CUT_BUFFER%d\n",
    			     (unsigned long) scp->data_length, cutbuffer);
    	    } else {
    		/* This used to just use the UTF-8 data, which was totally
    		 * broken as not even the corresponding paste code in xterm
    		 * understood this!  So now it converts to Latin1 first.
    		 *   Robert Brady, 2000-09-05
    		 */
    		unsigned long length = scp->data_length;
    		Char *data = scp->data_buffer;
    		if_OPT_WIDE_CHARS((screen), {
    		    data = UTF8toLatin1(screen, data, length, &length);
    		});
    		TRACE(("XStoreBuffer(%d)\n", cutbuffer));
    		XStoreBuffer(dpy,
    			     (char *) data,
    			     (int) length,
    			     cutbuffer);
    	    }
    	} else {
    	    int which = AtomToSelection(dpy, atoms[i]);
    	    if (keepClipboard(dpy, atoms[i])) {
    		Char *buf;
    		SelectedCells *tcp = &(screen->clipboard_data);
    		TRACE(("saving selection to clipboard buffer\n"));
    		scp = &(screen->selected_cells[CLIPBOARD_CODE]);
    		if ((buf = (Char *) malloc((size_t) scp->data_length)) == 0)
    		    SysError(ERROR_BMALLOC2);
    
    		free(tcp->data_buffer);
    		memcpy(buf, scp->data_buffer, scp->data_length);
    		tcp->data_buffer = buf;
    		tcp->data_limit = scp->data_length;
    		tcp->data_length = scp->data_length;
    	    }
    	    scp = &(screen->selected_cells[which]);
    	    if (scp->data_length == 0) {
    		TRACE(("XtDisownSelection(%s, @%ld)\n",
    		       TraceAtomName(screen->display, atoms[i]),
    		       (long) screen->selection_time));
    		XtDisownSelection((Widget) xw,
    				  atoms[i],
    				  screen->selection_time);
    	    } else if (!screen->replyToEmacs && atoms[i] != 0) {
    		TRACE(("XtOwnSelection(%s, @%ld)\n",
    		       TraceAtomName(screen->display, atoms[i]),
    		       (long) screen->selection_time));
    		have_selection |=
    		    XtOwnSelection((Widget) xw, atoms[i],
    				   screen->selection_time,
    				   ConvertSelection,
    				   LoseSelection,
    				   SelectionDone);
    	    }
    	}
    	TRACE(("... _OwnSelection used length %ld value %s\n",
    	       scp->data_length,
    	       visibleChars(scp->data_buffer,
    			    (unsigned) scp->data_length)));
        }
        if (!screen->replyToEmacs)
    	screen->selection_count = count;
        if (!have_selection)
    	UnHiliteText(xw);
    }
    
    static void
    ResetSelectionState(TScreen *screen)
    {
        screen->selection_count = 0;
        screen->startH = zeroCELL;
        screen->endH = zeroCELL;
    }
    
    void
    DisownSelection(XtermWidget xw)
    {
        TScreen *screen = TScreenOf(xw);
        Atom *atoms = screen->selection_atoms;
        Cardinal count = screen->selection_count;
        Cardinal i;
    
        TRACE(("DisownSelection count %d, start %d.%d, end %d.%d\n",
    	   count,
    	   screen->startH.row,
    	   screen->startH.col,
    	   screen->endH.row,
    	   screen->endH.col));
    
        for (i = 0; i < count; i++) {
    	int cutbuffer = CutBuffer(atoms[i]);
    	if (cutbuffer < 0) {
    	    XtDisownSelection((Widget) xw, atoms[i],
    			      screen->selection_time);
    	}
        }
        /*
         * If none of the callbacks via XtDisownSelection() reset highlighting
         * do it now.
         */
        if (ScrnHaveSelection(screen)) {
    	/* save data which will be reset */
    	CELL first = screen->startH;
    	CELL last = screen->endH;
    
    	ResetSelectionState(screen);
    	ReHiliteText(xw, &first, &last);
        } else {
    	ResetSelectionState(screen);
        }
    }
    
    void
    UnhiliteSelection(XtermWidget xw)
    {
        TScreen *screen = TScreenOf(xw);
    
        if (ScrnHaveSelection(screen)) {
    	CELL first = screen->startH;
    	CELL last = screen->endH;
    
    	screen->startH = zeroCELL;
    	screen->endH = zeroCELL;
    	ReHiliteText(xw, &first, &last);
        }
    }
    
    /* returns number of chars in line from scol to ecol out */
    /* ARGSUSED */
    static int
    Length(TScreen *screen,
           int row,
           int scol,
           int ecol)
    {
        CLineData *ld = GET_LINEDATA(screen, row);
        const int lastcol = LastTextCol(screen, ld, row);
    
        if (ecol > lastcol)
    	ecol = lastcol;
        return (ecol - scol + 1);
    }
    
    /* copies text into line, preallocated */
    static Char *
    SaveText(TScreen *screen,
    	 int row,
    	 int scol,
    	 int ecol,
    	 Char *lp,		/* pointer to where to put the text */
    	 int *eol)
    {
        LineData *ld;
        int i = 0;
        Char *result = lp;
    #if OPT_WIDE_CHARS
        unsigned previous = 0;
    #endif
    
        ld = GET_LINEDATA(screen, row);
        i = Length(screen, row, scol, ecol);
        ecol = scol + i;
    #if OPT_DEC_CHRSET
        if (CSET_DOUBLE(GetLineDblCS(ld))) {
    	scol = (scol + 0) / 2;
    	ecol = (ecol + 1) / 2;
        }
    #endif
        *eol = !LineTstWrapped(ld);
        for (i = scol; i < ecol; i++) {
    	unsigned c;
    	assert(i < (int) ld->lineSize);
    	c = E2A(ld->charData[i]);
    #if OPT_WIDE_CHARS
    	/* We want to strip out every occurrence of HIDDEN_CHAR AFTER a
    	 * wide character.
    	 */
    	if (c == HIDDEN_CHAR) {
    	    if (isWide((int) previous)) {
    		previous = c;
    		/* Combining characters attached to double-width characters
    		   are in memory attached to the HIDDEN_CHAR */
    		if_OPT_WIDE_CHARS(screen, {
    		    if ((screen->utf8_nrc_mode | screen->utf8_mode) != uFalse) {
    			size_t off;
    			for_each_combData(off, ld) {
    			    unsigned ch = ld->combData[off][i];
    			    if (ch == 0)
    				break;
    			    lp = convertToUTF8(lp, ch);
    			}
    		    }
    		});
    		continue;
    	    } else {
    		c = ' ';	/* should not happen, but just in case... */
    	    }
    	}
    	previous = c;
    	if ((screen->utf8_nrc_mode | screen->utf8_mode) != uFalse) {
    	    lp = convertToUTF8(lp, (c != 0) ? c : ' ');
    	    if_OPT_WIDE_CHARS(screen, {
    		size_t off;
    		for_each_combData(off, ld) {
    		    unsigned ch = ld->combData[off][i];
    		    if (ch == 0)
    			break;
    		    lp = convertToUTF8(lp, ch);
    		}
    	    });
    	} else
    #endif
    	{
    	    if (c == 0) {
    		c = E2A(' ');
    	    } else if (c < E2A(' ')) {
    		c = DECtoASCII(c);
    	    } else if (c == 0x7f) {
    		c = 0x5f;
    	    }
    	    *lp++ = CharOf(A2E(c));
    	}
    	if (c != E2A(' '))
    	    result = lp;
        }
    
        /*
         * If requested, trim trailing blanks from selected lines.  Do not do this
         * if the line is wrapped.
         */
        if (!*eol || !screen->trim_selection)
    	result = lp;
    
        return (result);
    }
    
    /* 32 + following 8-bit word:
    
       1:0  Button no: 0, 1, 2.  3=release.
         2  shift
         3  meta
         4  ctrl
         5  set for motion notify
         6  set for wheel (and button 6 and 7)
         7  set for buttons 8 to 11
    */
    
    /* Position: 32 - 255. */
    static int
    BtnCode(XButtonEvent *event, int button)
    {
        int result = (int) (32 + (KeyState(event->state) << 2));
    
        if (event->type == MotionNotify)
    	result += 32;
    
        if (button < 0) {
    	result += 3;
        } else {
    	result += button & 3;
    	if (button & 4)
    	    result += 64;
    	if (button & 8)
    	    result += 128;
        }
        TRACE(("BtnCode button %d, %s state " FMT_MODIFIER_NAMES " ->%#x\n",
    	   button,
    	   visibleEventType(event->type),
    	   ARG_MODIFIER_NAMES(event->state),
    	   result));
        return result;
    }
    
    static unsigned
    EmitButtonCode(XtermWidget xw,
    	       Char *line,
    	       unsigned count,
    	       XButtonEvent *event,
    	       int button)
    {
        TScreen *screen = TScreenOf(xw);
        int value;
    
        if (okSendMousePos(xw) == X10_MOUSE) {
    	value = CharOf(' ' + button);
        } else {
    	value = BtnCode(event, button);
        }
    
        switch (screen->extend_coords) {
        default:
    	line[count++] = CharOf(value);
    	break;
        case SET_SGR_EXT_MODE_MOUSE:
    	value -= 32;		/* encoding starts at zero */
    	/* FALLTHRU */
        case SET_URXVT_EXT_MODE_MOUSE:
    	count += (unsigned) sprintf((char *) line + count, "%d", value);
    	break;
        case SET_EXT_MODE_MOUSE:
    	if (value < 128) {
    	    line[count++] = CharOf(value);
    	} else {
    	    line[count++] = CharOf(0xC0 + (value >> 6));
    	    line[count++] = CharOf(0x80 + (value & 0x3F));
    	}
    	break;
        }
        return count;
    }
    
    static int
    FirstBitN(int bits)
    {
        int result = -1;
        if (bits > 0) {
    	result = 0;
    	while (!(bits & 1)) {
    	    bits /= 2;
    	    ++result;
    	}
        }
        return result;
    }
    
    #define ButtonBit(button) ((button >= 0) ? (1 << (button)) : 0)
    
    #define EMIT_BUTTON(button) EmitButtonCode(xw, line, count, event, button)
    
    static void
    EditorButton(XtermWidget xw, XButtonEvent *event)
    {
        TScreen *screen = TScreenOf(xw);
        int pty = screen->respond;
        int mouse_limit = MouseLimit(screen);
        Char line[32];
        Char final = 'M';
        int row, col;
        int button;
        unsigned count = 0;
        Boolean changed = True;
    
        /* If button event, get button # adjusted for DEC compatibility */
        button = (int) (event->button - 1);
        if (button >= 3)
    	button++;
    
        /* Ignore buttons that cannot be encoded */
        if (screen->send_mouse_pos == X10_MOUSE) {
    	if (button > 3)
    	    return;
        } else if (screen->extend_coords == SET_SGR_EXT_MODE_MOUSE
    	       || screen->extend_coords == SET_URXVT_EXT_MODE_MOUSE) {
    	if (button > 15) {
    	    return;
    	}
        } else {
    	if (button > 11) {
    	    return;
    	}
        }
    
        /* Compute character position of mouse pointer */
        row = (event->y - screen->border) / FontHeight(screen);
        col = (event->x - OriginX(screen)) / FontWidth(screen);
    
        /* Limit to screen dimensions */
        if (row < 0)
    	row = 0;
        else if (row > screen->max_row)
    	row = screen->max_row;
    
        if (col < 0)
    	col = 0;
        else if (col > screen->max_col)
    	col = screen->max_col;
    
        if (mouse_limit > 0) {
    	/* Limit to representable mouse dimensions */
    	if (row > mouse_limit)
    	    row = mouse_limit;
    	if (col > mouse_limit)
    	    col = mouse_limit;
        }
    
        /* Build key sequence starting with \E[M */
        if (screen->control_eight_bits) {
    	line[count++] = ANSI_CSI;
        } else {
    	line[count++] = ANSI_ESC;
    	line[count++] = '[';
        }
        switch (screen->extend_coords) {
        case 0:
        case SET_EXT_MODE_MOUSE:
    #if OPT_SCO_FUNC_KEYS
    	if (xw->keyboard.type == keyboardIsSCO) {
    	    /*
    	     * SCO function key F1 is \E[M, which would conflict with xterm's
    	     * normal kmous.
    	     */
    	    line[count++] = '>';
    	}
    #endif
    	line[count++] = final;
    	break;
        case SET_SGR_EXT_MODE_MOUSE:
    	line[count++] = '<';
    	break;
        }
    
        /* Add event code to key sequence */
        if (okSendMousePos(xw) == X10_MOUSE) {
    	count = EMIT_BUTTON(button);
        } else {
    	/* Button-Motion events */
    	switch (event->type) {
    	case ButtonPress:
    	    screen->mouse_button |= ButtonBit(button);
    	    count = EMIT_BUTTON(button);
    	    break;
    	case ButtonRelease:
    	    /*
    	     * The (vertical) wheel mouse interface generates release-events
    	     * for buttons 4 and 5, coded here as 3 and 4 respectively.
    	     *
    	     * The X10/X11 xterm protocol maps the release for buttons 1..3 to
    	     * a -1, which will * be later mapped into a "0" (some button was
    	     * released),
    	     *
    	     * The SGR (extended) xterm mouse protocol keeps the button number
    	     * and uses a "m" to indicate button release.
    	     *
    	     * The behavior for mice with more buttons is unclear, and may be
    	     * revised -TD
    	     */
    	    screen->mouse_button &= ~ButtonBit(button);
    	    if (button < 3 || button >= 8) {
    		switch (screen->extend_coords) {
    		case SET_SGR_EXT_MODE_MOUSE:
    		    final = 'm';
    		    break;
    		default:
    		    button = -1;
    		    break;
    		}
    	    }
    	    count = EMIT_BUTTON(button);
    	    break;
    	case MotionNotify:
    	    /* BTN_EVENT_MOUSE and ANY_EVENT_MOUSE modes send motion
    	     * events only if character cell has changed.
    	     */
    	    if ((row == screen->mouse_row)
    		&& (col == screen->mouse_col)) {
    		changed = False;
    	    } else {
    		count = EMIT_BUTTON(FirstBitN(screen->mouse_button));
    	    }
    	    break;
    	default:
    	    changed = False;
    	    break;
    	}
        }
    
        if (changed) {
    	screen->mouse_row = row;
    	screen->mouse_col = col;
    
    	TRACE(("mouse at %d,%d button+mask = %#x\n", row, col, line[count - 1]));
    
    	/* Add pointer position to key sequence */
    	count = EmitMousePositionSeparator(screen, line, count);
    	count = EmitMousePosition(screen, line, count, col);
    	count = EmitMousePositionSeparator(screen, line, count);
    	count = EmitMousePosition(screen, line, count, row);
    
    	switch (screen->extend_coords) {
    	case SET_SGR_EXT_MODE_MOUSE:
    	case SET_URXVT_EXT_MODE_MOUSE:
    	    line[count++] = final;
    	    break;
    	}
    
    	/* Transmit key sequence to process running under xterm */
    	v_write(pty, line, count);
        }
        return;
    }
    
    /*
     * Check the current send_mouse_pos against allowed mouse-operations, returning
     * none if it is disallowed.
     */
    XtermMouseModes
    okSendMousePos(XtermWidget xw)
    {
        TScreen *screen = TScreenOf(xw);
        XtermMouseModes result = screen->send_mouse_pos;
    
        switch (result) {
        case MOUSE_OFF:
    	break;
        case X10_MOUSE:
    	if (!AllowMouseOps(xw, emX10))
    	    result = MOUSE_OFF;
    	break;
        case VT200_MOUSE:
    	if (!AllowMouseOps(xw, emVT200Click))
    	    result = MOUSE_OFF;
    	break;
        case VT200_HIGHLIGHT_MOUSE:
    	if (!AllowMouseOps(xw, emVT200Hilite))
    	    result = MOUSE_OFF;
    	break;
        case BTN_EVENT_MOUSE:
    	if (!AllowMouseOps(xw, emAnyButton))
    	    result = MOUSE_OFF;
    	break;
        case ANY_EVENT_MOUSE:
    	if (!AllowMouseOps(xw, emAnyEvent))
    	    result = MOUSE_OFF;
    	break;
        case DEC_LOCATOR:
    	if (!AllowMouseOps(xw, emLocator))
    	    result = MOUSE_OFF;
    	break;
        }
        return result;
    }
    
    #if OPT_FOCUS_EVENT
    /*
     * Check the current send_focus_pos against allowed mouse-operations, returning
     * none if it is disallowed.
     */
    static int
    okSendFocusPos(XtermWidget xw)
    {
        TScreen *screen = TScreenOf(xw);
        int result = screen->send_focus_pos;
    
        if (!AllowMouseOps(xw, emFocusEvent)) {
    	result = False;
        }
        return result;
    }
    
    void
    SendFocusButton(XtermWidget xw, XFocusChangeEvent *event)
    {
        if (okSendFocusPos(xw)) {
    	ANSI reply;
    
    	memset(&reply, 0, sizeof(reply));
    	reply.a_type = ANSI_CSI;
    
    #if OPT_SCO_FUNC_KEYS
    	if (xw->keyboard.type == keyboardIsSCO) {
    	    reply.a_pintro = '>';
    	}
    #endif
    	reply.a_final = CharOf((event->type == FocusIn) ? 'I' : 'O');
    	unparseseq(xw, &reply);
        }
        return;
    }
    #endif /* OPT_FOCUS_EVENT */
    
    #if OPT_SELECTION_OPS
    /*
     * Get the event-time, needed to process selections.
     */
    static Time
    getEventTime(XEvent *event)
    {
        Time result;
    
        if (IsBtnEvent(event)) {
    	result = ((XButtonEvent *) event)->time;
        } else if (IsKeyEvent(event)) {
    	result = ((XKeyEvent *) event)->time;
        } else {
    	result = 0;
        }
    
        return result;
    }
    
    /* obtain the selection string, passing the endpoints to caller's parameters */
    static void
    doSelectionFormat(XtermWidget xw,
    		  Widget w,
    		  XEvent *event,
    		  String *params,
    		  Cardinal *num_params,
    		  FormatSelect format_select)
    {
        TScreen *screen = TScreenOf(xw);
        InternalSelect *mydata = &(screen->internal_select);
    
        memset(mydata, 0, sizeof(*mydata));
        mydata->format = x_strdup(params[0]);
        mydata->format_select = format_select;
    
        screen->selectToBuffer = True;
        beginInternalSelect(xw);
    
        xtermGetSelection(w, getEventTime(event), params + 1, *num_params - 1, NULL);
    
        if (screen->selectToBuffer)
    	finishInternalSelect(xw);
    }
    
    /* obtain data from the screen, passing the endpoints to caller's parameters */
    static char *
    getDataFromScreen(XtermWidget xw, XEvent *event, String method, CELL *start, CELL *finish)
    {
        TScreen *screen = TScreenOf(xw);
    
        CELL save_old_start = screen->startH;
        CELL save_old_end = screen->endH;
    
        CELL save_startSel = screen->startSel;
        CELL save_startRaw = screen->startRaw;
        CELL save_finishSel = screen->endSel;
        CELL save_finishRaw = screen->endRaw;
    
        int save_firstValidRow = screen->firstValidRow;
        int save_lastValidRow = screen->lastValidRow;
    
        const Cardinal noClick = 0;
        int save_numberOfClicks = screen->numberOfClicks;
    
        SelectUnit saveUnits = screen->selectUnit;
        SelectUnit saveMap = screen->selectMap[noClick];
    #if OPT_SELECT_REGEX
        char *saveExpr = screen->selectExpr[noClick];
    #endif
        SelectedCells *scp = &(screen->selected_cells[PRIMARY_CODE]);
        SelectedCells save_selection = *scp;
    
        char *result = 0;
    
        TRACE(("getDataFromScreen %s\n", method));
    
        memset(scp, 0, sizeof(*scp));
    
        screen->numberOfClicks = 1;
        lookupSelectUnit(xw, noClick, method);
        screen->selectUnit = screen->selectMap[noClick];
    
        memset(start, 0, sizeof(*start));
        if (IsBtnEvent(event)) {
    	XButtonEvent *btn_event = (XButtonEvent *) event;
    	CELL cell;
    	screen->firstValidRow = 0;
    	screen->lastValidRow = screen->max_row;
    	PointToCELL(screen, btn_event->y, btn_event->x, &cell);
    	start->row = cell.row;
    	start->col = cell.col;
    	finish->row = cell.row;
    	finish->col = screen->max_col;
        } else {
    	start->row = screen->cur_row;
    	start->col = screen->cur_col;
    	finish->row = screen->cur_row;
    	finish->col = screen->max_col;
        }
    
        ComputeSelect(xw, start, finish, False);
        SaltTextAway(xw,
    		 TargetToSelection(screen, PRIMARY_NAME),
    		 &(screen->startSel), &(screen->endSel));
    
        if (scp->data_limit && scp->data_buffer) {
    	TRACE(("...getDataFromScreen selection-data %.*s\n",
    	       (int) scp->data_limit,
    	       scp->data_buffer));
    	result = malloc(scp->data_limit + 1);
    	if (result) {
    	    memcpy(result, scp->data_buffer, scp->data_limit);
    	    result[scp->data_limit] = 0;
    	}
    	free(scp->data_buffer);
    	scp->data_limit = 0;
        }
    
        TRACE(("...getDataFromScreen restoring previous selection\n"));
    
        screen->startSel = save_startSel;
        screen->startRaw = save_startRaw;
        screen->endSel = save_finishSel;
        screen->endRaw = save_finishRaw;
    
        screen->firstValidRow = save_firstValidRow;
        screen->lastValidRow = save_lastValidRow;
    
        screen->numberOfClicks = save_numberOfClicks;
        screen->selectUnit = saveUnits;
        screen->selectMap[noClick] = saveMap;
    #if OPT_SELECT_REGEX
        screen->selectExpr[noClick] = saveExpr;
    #endif
    
        screen->selected_cells[0] = save_selection;
    
        TrackText(xw, &save_old_start, &save_old_end);
    
        TRACE(("...getDataFromScreen done\n"));
        return result;
    }
    
    /*
     * Split-up the format before substituting data, to avoid quoting issues.
     * The resource mechanism has a limited ability to handle escapes.  We take
     * the result as if it were an sh-type string and parse it into a regular
     * argv array.
     */
    static char **
    tokenizeFormat(String format)
    {
        char **result = 0;
        int argc;
    
        format = x_skip_blanks(format);
        if (*format != '\0') {
    	char *blob = x_strdup(format);
    	int pass;
    
    	for (pass = 0; pass < 2; ++pass) {
    	    int used = 0;
    	    int first = 1;
    	    int escaped = 0;
    	    int squoted = 0;
    	    int dquoted = 0;
    	    int n;
    
    	    argc = 0;
    	    for (n = 0; format[n] != '\0'; ++n) {
    		if (escaped) {
    		    blob[used++] = format[n];
    		    escaped = 0;
    		} else if (format[n] == '"') {
    		    if (!squoted) {
    			if (!dquoted)
    			    blob[used++] = format[n];
    			dquoted = !dquoted;
    		    }
    		} else if (format[n] == '\'') {
    		    if (!dquoted) {
    			if (!squoted)
    			    blob[used++] = format[n];
    			squoted = !squoted;
    		    }
    		} else if (format[n] == '\\') {
    		    blob[used++] = format[n];
    		    escaped = 1;
    		} else {
    		    if (first) {
    			first = 0;
    			if (pass) {
    			    result[argc] = &blob[n];
    			}
    			++argc;
    		    }
    		    if (isspace((Char) format[n])) {
    			first = !isspace((Char) format[n + 1]);
    			if (squoted || dquoted) {
    			    blob[used++] = format[n];
    			} else if (first) {
    			    blob[used++] = '\0';
    			}
    		    } else {
    			blob[used++] = format[n];
    		    }
    		}
    	    }
    	    blob[used] = '\0';
    	    assert(strlen(blob) <= strlen(format));
    	    if (!pass) {
    		result = TypeCallocN(char *, argc + 1);
    		if (result == 0) {
    		    free(blob);
    		    break;
    		}
    	    }
    	}
        }
    #if OPT_TRACE
        if (result) {
    	TRACE(("tokenizeFormat %s\n", format));
    	for (argc = 0; result[argc]; ++argc) {
    	    TRACE(("argv[%d] = %s\n", argc, result[argc]));
    	}
        }
    #endif
    
        return result;
    }
    
    static void
    formatVideoAttrs(XtermWidget xw, char *buffer, CELL *cell)
    {
        TScreen *screen = TScreenOf(xw);
        LineData *ld = GET_LINEDATA(screen, cell->row);
    
        *buffer = '\0';
        if (ld != 0 && cell->col < (int) ld->lineSize) {
    	IAttr attribs = ld->attribs[cell->col];
    	const char *delim = "";
    
    	if (attribs & INVERSE) {
    	    buffer += sprintf(buffer, "7");
    	    delim = ";";
    	}
    	if (attribs & UNDERLINE) {
    	    buffer += sprintf(buffer, "%s4", delim);
    	    delim = ";";
    	}
    	if (attribs & BOLD) {
    	    buffer += sprintf(buffer, "%s1", delim);
    	    delim = ";";
    	}
    	if (attribs & BLINK) {
    	    buffer += sprintf(buffer, "%s5", delim);
    	    delim = ";";
    	}
    #if OPT_ISO_COLORS
    	if (attribs & FG_COLOR) {
    	    Pixel fg = extract_fg(xw, ld->color[cell->col], attribs);
    	    if (fg < 8) {
    		fg += 30;
    	    } else if (fg < 16) {
    		fg += 90;
    	    } else {
    		buffer += sprintf(buffer, "%s38;5", delim);
    		delim = ";";
    	    }
    	    buffer += sprintf(buffer, "%s%lu", delim, fg);
    	    delim = ";";
    	}
    	if (attribs & BG_COLOR) {
    	    Pixel bg = extract_bg(xw, ld->color[cell->col], attribs);
    	    if (bg < 8) {
    		bg += 40;
    	    } else if (bg < 16) {
    		bg += 100;
    	    } else {
    		buffer += sprintf(buffer, "%s48;5", delim);
    		delim = ";";
    	    }
    	    (void) sprintf(buffer, "%s%lu", delim, bg);
    	}
    #endif
        }
    }
    
    static char *
    formatStrlen(char *target, char *source, int freeit)
    {
        if (source != 0) {
    	sprintf(target, "%u", (unsigned) strlen(source));
    	if (freeit) {
    	    free(source);
    	}
        } else {
    	strcpy(target, "0");
        }
        return target;
    }
    
    /* substitute data into format, reallocating the result */
    static char *
    expandFormat(XtermWidget xw,
    	     const char *format,
    	     char *data,
    	     CELL *start,
    	     CELL *finish)
    {
        char *result = 0;
        if (!IsEmpty(format)) {
    	static char empty[1];
    	int pass;
    	int n;
    	char numbers[80];
    
    	if (data == 0)
    	    data = empty;
    
    	for (pass = 0; pass < 2; ++pass) {
    	    size_t need = 0;
    
    	    for (n = 0; format[n] != '\0'; ++n) {
    
    		if (format[n] == '%') {
    		    char *value = 0;
    
    		    switch (format[++n]) {
    		    case '%':
    			if (pass) {
    			    result[need] = format[n];
    			}
    			++need;
    			break;
    		    case 'P':
    			sprintf(numbers, "%d;%d",
    				TScreenOf(xw)->topline + start->row + 1,
    				start->col + 1);
    			value = numbers;
    			break;
    		    case 'p':
    			sprintf(numbers, "%d;%d",
    				TScreenOf(xw)->topline + finish->row + 1,
    				finish->col + 1);
    			value = numbers;
    			break;
    		    case 'R':
    			value = formatStrlen(numbers, x_strrtrim(data), 1);
    			break;
    		    case 'r':
    			value = x_strrtrim(data);
    			break;
    		    case 'S':
    			value = formatStrlen(numbers, data, 0);
    			break;
    		    case 's':
    			value = data;
    			break;
    		    case 'T':
    			value = formatStrlen(numbers, x_strtrim(data), 1);
    			break;
    		    case 't':
    			value = x_strtrim(data);
    			break;
    		    case 'V':
    			formatVideoAttrs(xw, numbers, start);
    			value = numbers;
    			break;
    		    case 'v':
    			formatVideoAttrs(xw, numbers, finish);
    			value = numbers;
    			break;
    		    default:
    			if (pass) {
    			    result[need] = format[n];
    			}
    			--n;
    			++need;
    			break;
    		    }
    		    if (value != 0) {
    			if (pass) {
    			    strcpy(result + need, value);
    			}
    			need += strlen(value);
    			if (value != numbers && value != data) {
    			    free(value);
    			}
    		    }
    		} else {
    		    if (pass) {
    			result[need] = format[n];
    		    }
    		    ++need;
    		}
    	    }
    	    if (pass) {
    		result[need] = '\0';
    	    } else {
    		++need;
    		result = malloc(need);
    		if (result == 0) {
    		    break;
    		}
    	    }
    	}
        }
        TRACE(("expandFormat(%s) = %s\n", NonNull(format), NonNull(result)));
        return result;
    }
    
    /* execute the command after forking.  The main process frees its data */
    static void
    executeCommand(pid_t pid, char **argv)
    {
        (void) pid;
        if (argv != 0 && argv[0] != 0) {
    	char *child_cwd = ProcGetCWD(pid);
    
    	if (fork() == 0) {
    	    if (child_cwd) {
    		IGNORE_RC(chdir(child_cwd));	/* We don't care if this fails */
    	    }
    	    execvp(argv[0], argv);
    	    exit(EXIT_FAILURE);
    	}
    	free(child_cwd);
        }
    }
    
    static void
    freeArgv(char *blob, char **argv)
    {
        if (blob) {
    	free(blob);
    	if (argv) {
    	    int n;
    	    for (n = 0; argv[n]; ++n)
    		free(argv[n]);
    	    free(argv);
    	}
        }
    }
    
    static void
    reallyExecFormatted(Widget w, char *format, char *data, CELL *start, CELL *finish)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	char **argv;
    
    	if ((argv = tokenizeFormat(format)) != 0) {
    	    char *blob = argv[0];
    	    int argc;
    
    	    for (argc = 0; argv[argc] != 0; ++argc) {
    		argv[argc] = expandFormat(xw, argv[argc], data, start, finish);
    	    }
    	    executeCommand(TScreenOf(xw)->pid, argv);
    	    freeArgv(blob, argv);
    	}
        }
    }
    
    void
    HandleExecFormatted(Widget w,
    		    XEvent *event,
    		    String *params,	/* selections */
    		    Cardinal *num_params)
    {
        XtermWidget xw;
    
        TRACE_EVENT("HandleExecFormatted", event, params, num_params);
        if ((xw = getXtermWidget(w)) != 0 &&
    	(*num_params > 1)) {
    	doSelectionFormat(xw, w, event, params, num_params, reallyExecFormatted);
        }
    }
    
    void
    HandleExecSelectable(Widget w,
    		     XEvent *event,
    		     String *params,	/* selections */
    		     Cardinal *num_params)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TRACE_EVENT("HandleExecSelectable", event, params, num_params);
    
    	if (*num_params == 2) {
    	    CELL start, finish;
    	    char *data;
    	    char **argv;
    
    	    data = getDataFromScreen(xw, event, params[1], &start, &finish);
    	    if (data != 0) {
    		if ((argv = tokenizeFormat(params[0])) != 0) {
    		    char *blob = argv[0];
    		    int argc;
    
    		    for (argc = 0; argv[argc] != 0; ++argc) {
    			argv[argc] = expandFormat(xw, argv[argc], data,
    						  &start, &finish);
    		    }
    		    executeCommand(TScreenOf(xw)->pid, argv);
    		    freeArgv(blob, argv);
    		}
    		free(data);
    	    }
    	}
        }
    }
    
    static void
    reallyInsertFormatted(Widget w, char *format, char *data, CELL *start, CELL *finish)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	char *exps;
    
    	if ((exps = expandFormat(xw, format, data, start, finish)) != 0) {
    	    unparseputs(xw, exps);
    	    unparse_end(xw);
    	    free(exps);
    	}
        }
    }
    
    void
    HandleInsertFormatted(Widget w,
    		      XEvent *event,
    		      String *params,	/* selections */
    		      Cardinal *num_params)
    {
        XtermWidget xw;
    
        TRACE_EVENT("HandleInsertFormatted", event, params, num_params);
        if ((xw = getXtermWidget(w)) != 0 &&
    	(*num_params > 1)) {
    	doSelectionFormat(xw, w, event, params, num_params, reallyInsertFormatted);
        }
    }
    
    void
    HandleInsertSelectable(Widget w,
    		       XEvent *event,
    		       String *params,	/* selections */
    		       Cardinal *num_params)
    {
        XtermWidget xw;
    
        if ((xw = getXtermWidget(w)) != 0) {
    	TRACE_EVENT("HandleInsertSelectable", event, params, num_params);
    
    	if (*num_params == 2) {
    	    CELL start, finish;
    	    char *data;
    	    char *temp = x_strdup(params[0]);
    
    	    data = getDataFromScreen(xw, event, params[1], &start, &finish);
    	    if (data != 0) {
    		char *exps = expandFormat(xw, temp, data, &start, &finish);
    		if (exps != 0) {
    		    unparseputs(xw, exps);
    		    unparse_end(xw);
    		    free(exps);
    		}
    		free(data);
    	    }
    	    free(temp);
    	}
        }
    }
    #endif /* OPT_SELECTION_OPS */
    xterm-353/graphics.h0000644000175100001440000001510512722612275013225 0ustar  tomusers/* $XTermId: graphics.h,v 1.23 2016/05/29 16:11:41 tom Exp $ */
    
    /*
     * Copyright 2013-2015,2016 by Ross Combs
     * Copyright 2013-2015,2016 by Thomas E. Dickey
     *
     *                         All Rights Reserved
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     *
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * Except as contained in this notice, the name(s) of the above copyright
     * holders shall not be used in advertising or otherwise to promote the
     * sale, use or other dealings in this Software without prior written
     * authorization.
     */
    
    #ifndef included_graphics_h
    #define included_graphics_h
    /* *INDENT-OFF* */
    
    #include 
    
    #if OPT_GRAPHICS
    
    #define CHANNEL_MAX 100
    
    typedef struct {
        short r, g, b;
    } ColorRegister;
    
    typedef unsigned short RegisterNum;
    
    #define MAX_COLOR_REGISTERS 1024U
    #define COLOR_HOLE ((RegisterNum)MAX_COLOR_REGISTERS)
    
    #define MAX_GRAPHICS 16U
    
    typedef struct {
        RegisterNum *pixels;
        ColorRegister *private_color_registers;
        ColorRegister *color_registers;
        char color_registers_used[MAX_COLOR_REGISTERS];
        XtermWidget xw;
        int max_width;              /* largest image which can be stored */
        int max_height;             /* largest image which can be stored */
        unsigned valid_registers;   /* for wrap-around behavior */
        int actual_width;           /* size of image before scaling */
        int actual_height;          /* size of image before scaling */
        int private_colors;         /* if not using the shared color registers */
        int charrow;                /* upper left starting point in characters */
        int charcol;                /* upper left starting point in characters */
        int pixw;                   /* width of graphic pixels in screen pixels */
        int pixh;                   /* height of graphic pixels in screen pixels */
        int bufferid;               /* which screen buffer the graphic is associated with */
        unsigned type;              /* type of graphic 0==sixel, 1...NUM_REGIS_PAGES==ReGIS page */
        unsigned id;                /* sequential id used for preserving layering */
        int valid;                  /* if the graphic has been initialized */
        int dirty;                  /* if the graphic needs to be redrawn */
        int hidden;                 /* if the graphic should not be displayed */
    } Graphic;
    
    extern Graphic *get_new_graphic(XtermWidget /* xw */, int /* charrow */, int /* charcol */, unsigned /* type */);
    extern Graphic *get_new_or_matching_graphic(XtermWidget /* xw */, int /* charrow */, int /* charcol */, int /* actual_width */, int /* actual_height */, unsigned /* type */);
    extern RegisterNum read_pixel(Graphic */* graphic */, int /* x */, int /* y */);
    extern void draw_solid_pixel(Graphic */* graphic */, int /* x */, int /* y */, unsigned /* color */);
    extern void draw_solid_rectangle(Graphic */* graphic */, int /* x1 */, int /* y1 */, int /* x2 */, int /* y2 */, unsigned /* color */);
    extern void draw_solid_line(Graphic */* graphic */, int /* x1 */, int /* y1 */, int /* x2 */, int /* y2 */, unsigned /* color */);
    extern void copy_overlapping_area(Graphic */* graphic */, int /* src_x */, int /* src_y */, int /* dst_x */, int /* dst_y */, unsigned /* w */, unsigned /* h */, unsigned /* default_color */);
    extern void hls2rgb(int /* h */, int /* l */, int /* s */, short */* r */, short */* g */, short */* b */);
    extern void dump_graphic(Graphic const */* graphic */);
    extern unsigned get_color_register_count(TScreen const */* screen */);
    extern void update_color_register(Graphic */* graphic */, unsigned /* color */, int /* r */, int /* g */, int /* b */);
    extern RegisterNum find_color_register(ColorRegister const */* color_registers */, int /* r */, int /* g */, int /* b */);
    extern void chararea_clear_displayed_graphics(TScreen const */* screen */, int /* leftcol */, int /* toprow */, int /* ncols */, int /* nrows */);
    extern void pixelarea_clear_displayed_graphics(TScreen const */* screen */, int /* winx */, int /* winy */, int /* w */, int /* h */);
    extern void refresh_displayed_graphics(XtermWidget /* xw */, int /* leftcol */, int /* toprow */, int /* ncols */, int /* nrows */);
    extern void refresh_modified_displayed_graphics(XtermWidget /* xw */);
    extern void reset_displayed_graphics(TScreen const */* screen */);
    extern void scroll_displayed_graphics(XtermWidget /* xw */, int /* rows */);
    
    #ifdef NO_LEAKS
    extern void noleaks_graphics(void);
    #endif
    
    #else
    
    #define get_new_graphic(xw, charrow, charcol, type) /* nothing */
    #define get_new_or_matching_graphic(xw, charrow, charcol, actual_width, actual_height, type) /* nothing */
    #define read_pixel(graphic, x, y) /* nothing */
    #define draw_solid_pixel(graphic, x, y, color) /* nothing */
    #define draw_solid_rectangle(graphic, x1, y1, x2, y2, color) /* nothing */
    #define draw_solid_line(graphic, x1, y1, x2, y2, color) /* nothing */
    #define copy_overlapping_area(graphic, src_x, src_y, dst_x, dst_y, w, h, default_color) /* nothing */
    #define hls2rgb(h, l, s, r, g, b) /* nothing */
    #define dump_graphic(graphic) /* nothing */
    #define get_color_register_count(screen) /* nothing */
    #define update_color_register(graphic, color, r, g, b) /* nothing */
    #define find_color_register(color_registers, r, g, b) /* nothing */
    #define chararea_clear_displayed_graphics(screen, leftcol, toprow, ncols, nrows) /* nothing */
    #define pixelarea_clear_displayed_graphics(screen, winx, winy, w, h) /* nothing */
    #define refresh_displayed_graphics(xw, leftcol, toprow, ncols, nrows) /* nothing */
    #define refresh_modified_displayed_graphics(xw) /* nothing */
    #define reset_displayed_graphics(screen) /* nothing */
    #define scroll_displayed_graphics(xw, rows) /* nothing */
    
    #endif
    
    /* *INDENT-ON* */
    
    #endif /* included_graphics_h */
    xterm-353/Makefile.in0000644000175100001440000004774313477423526013345 0ustar  tomusers## $XTermId: Makefile.in,v 1.246 2019/06/10 09:48:06 tom Exp $
    # -----------------------------------------------------------------------------
    # this file is part of xterm
    #
    # Copyright 1997-2018,2019 by Thomas E. Dickey
    #
    #                         All Rights Reserved
    #
    # Permission is hereby granted, free of charge, to any person obtaining a
    # copy of this software and associated documentation files (the
    # "Software"), to deal in the Software without restriction, including
    # without limitation the rights to use, copy, modify, merge, publish,
    # distribute, sublicense, and/or sell copies of the Software, and to
    # permit persons to whom the Software is furnished to do so, subject to
    # the following conditions:
    #
    # The above copyright notice and this permission notice shall be included
    # in all copies or substantial portions of the Software.
    #
    # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
    # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    #
    # Except as contained in this notice, the name(s) of the above copyright
    # holders shall not be used in advertising or otherwise to promote the
    # sale, use or other dealings in this Software without prior written
    # authorization.
    # -----------------------------------------------------------------------------
    
    SHELL		= /bin/sh
    
    #### Start of system configuration section. ####
    
    srcdir		= @srcdir@
    VPATH  		= @srcdir@
    
    x		= @EXEEXT@
    o		= .@OBJEXT@
    
    CC		= @CC@
    CPP		= @CPP@
    AWK		= @AWK@
    LINK		= $(CC) $(CFLAGS)
    
    CTAGS		= @CTAGS@
    ETAGS		= @ETAGS@
    
    LN_S		= @LN_S@
    RM              = rm -f
    LINT		= @LINT@
    LINT_OPTS	= @LINT_OPTS@
    
    INSTALL		= @INSTALL@
    INSTALL_PROGRAM	= @INSTALL_PROGRAM@
    INSTALL_SCRIPT	= @INSTALL_SCRIPT@
    INSTALL_DATA	= @INSTALL_DATA@
    transform	= @program_transform_name@
    
    EXTRA_CFLAGS	= @EXTRA_CFLAGS@
    EXTRA_CPPFLAGS	= @EXTRA_CPPFLAGS@
    EXTRA_LOADFLAGS	= @IMAKE_LOADFLAGS@
    
    CPPFLAGS	= -I. -I$(srcdir) -DHAVE_CONFIG_H @CPPFLAGS@ -DDEFCLASS=\"@APP_CLASS@\" $(EXTRA_CPPFLAGS)
    CFLAGS		= @CFLAGS@ $(EXTRA_CFLAGS)
    LDFLAGS		= @LDFLAGS@ @EXTRA_LDFLAGS@
    LIBS		= @LIBS@
    
    prefix		= @prefix@
    exec_prefix	= @exec_prefix@
    datarootdir	= @datarootdir@
    datadir		= @datadir@
    
    manext		= 1
    bindir		= @bindir@
    libdir		= @libdir@
    mandir		= @mandir@/man$(manext)
    appsdir		= @APPSDIR@
    icondir		= @ICONDIR@
    pixmapdir	= @PIXMAPDIR@
    
    #### End of system configuration section. ####
    
    ICON_NAME	= @ICON_NAME@
    ICON_SYMLINK	= @ICON_SYMLINK@
    
    DESTDIR		=
    BINDIR		= $(DESTDIR)$(bindir)
    LIBDIR		= $(DESTDIR)$(libdir)
    MANDIR		= $(DESTDIR)$(mandir)
    APPSDIR		= $(DESTDIR)$(appsdir)
    
    @no_icondir@ICONDIR		= $(DESTDIR)$(icondir)
    @no_pixmapdir@PIXMAPDIR	= $(DESTDIR)$(pixmapdir)
    
    INSTALL_DIRS    = $(BINDIR) $(APPSDIR) $(ICONDIR) $(PIXMAPDIR) $(MANDIR)
    
    CLASS		= @APP_CLASS@
    EXTRAHDR	= @EXTRAHDRS@
    EXTRASRC	= @EXTRASRCS@
    EXTRAOBJ	= @EXTRAOBJS@
    
    AUTO_SOURCE	= \
    		builtin_icons.h \
    		VTparse.cin \
    		Tekparse.cin \
    		VTparse.hin \
    		Tekparse.hin
    
              SRCS1 = button.c cachedGCs.c charproc.c charsets.c cursor.c \
    	  	  data.c doublechr.c fontutils.c input.c \
    		  linedata.c main.c menu.c misc.c \
    		  print.c ptydata.c scrollback.c \
    		  screen.c scrollbar.c tabs.c util.c version.c xstrings.c \
    		  xtermcap.c VTPrsTbl.c $(EXTRASRC)
              OBJS1 = button$o cachedGCs$o charproc$o charsets$o cursor$o \
    	  	  data$o doublechr$o fontutils$o input$o \
    		  linedata$o main$o menu$o misc$o \
    		  print$o ptydata$o scrollback$o \
    		  screen$o scrollbar$o tabs$o util$o version$o xstrings$o \
    		  xtermcap$o VTPrsTbl$o $(EXTRAOBJ)
              SRCS2 = resize.c version.c xstrings.c
              OBJS2 = resize$o version$o xstrings$o
               SRCS = $(SRCS1) $(SRCS2)
               OBJS = $(OBJS1) $(OBJS2)
               HDRS = VTparse.h data.h error.h fontutils.h main.h menu.h \
                      ptyx.h version.h xstrings.h xterm.h xtermcap.h $(EXTRAHDR)
           PROGRAMS = xterm$x resize$x
      TEST_PROGRAMS = test_wcwidth$x
    
    all :	$(PROGRAMS)
    ################################################################################
    .SUFFIXES : .i .def .cin .hin .$(manext) .ms .man .txt @MAN2HTML_NOTE@ .html @GROFF_NOTE@ .ps .pdf
    
    .c$o :
    	@RULE_CC@
    	@ECHO_CC@$(CC) $(CPPFLAGS) $(CFLAGS) -c $(srcdir)/$*.c
    
    .c.i :
    	@RULE_CC@
    	@ECHO_CC@$(CPP) -C $(CPPFLAGS) $*.c >$@
    
    .def.cin :
    	@echo "making $@ from $<"
    	@$(AWK) 'BEGIN{printf "/* vile:cmode */\n";}/^CASE_/{printf "{ %d, \"%s\" },\n", n++, $$1; }' < $< >$@
    
    .def.hin :
    	@echo "making $@ from $<"
    	@$(AWK) 'BEGIN{printf "/* vile:cmode */\n";}/^CASE_/{printf "#define %s %d\n", $$1, n++}' < $< >$@
    
    .man.$(manext) :
    	$(SHELL) ./minstall "$(INSTALL_DATA)" $< $@ $(appsdir) $(CLASS) $* $* $(pixmapdir)
    
    @NROFF_NOTE@.$(manext).txt :
    @NROFF_NOTE@	$(SHELL) -c "tbl $*.$(manext) | nroff -man | col -bx" >$@
    @NROFF_NOTE@
    @NROFF_NOTE@.ms.txt :
    @NROFF_NOTE@	$(SHELL) -c "tbl $*.$(manext) | nroff -ms | col -bx" >$@
    @NROFF_NOTE@
    
    @MAN2HTML_NOTE@.$(manext).html :
    @MAN2HTML_NOTE@	./@MAN2HTML_TEMP@ $* $(manext) man >$@
    @MAN2HTML_NOTE@
    @GROFF_NOTE@.$(manext).ps :
    @GROFF_NOTE@	$(SHELL) -c "tbl $*.$(manext) | groff -man" >$@
    @GROFF_NOTE@
    @GROFF_NOTE@.$(manext).txt :
    @GROFF_NOTE@	GROFF_NO_SGR=stupid $(SHELL) -c "tbl $*.$(manext) | groff -Tascii -man | col -bx" >$@
    @GROFF_NOTE@
    @MAN2HTML_NOTE@.ms.html :
    @MAN2HTML_NOTE@	./@MAN2HTML_TEMP@ $* ms ms >$@
    @MAN2HTML_NOTE@
    @GROFF_NOTE@.ms.ps :
    @GROFF_NOTE@	$(SHELL) -c "tbl $< | groff -ms" >$@
    @GROFF_NOTE@
    @GROFF_NOTE@.ms.txt :
    @GROFF_NOTE@	GROFF_NO_SGR=stupid $(SHELL) -c "tbl $< | groff -Tascii -ms | col -bx" >$@
    @GROFF_NOTE@
    @GROFF_NOTE@.ps.pdf :
    @GROFF_NOTE@	ps2pdf $*.ps
    ################################################################################
    
    VTPARSE_H = VTparse.h VTparse.hin
    TEKPARSE_H = Tekparse.h Tekparse.hin
    
    main$o : main.h
    misc$o : version.h
    
    $(OBJS1) : xterm.h ptyx.h xtermcfg.h
    main$o resize$o screen$o : xterm_io.h
    
    xterm$x : $(OBJS1)
    	@ECHO_LD@$(SHELL) $(srcdir)/plink.sh $(LINK) $(LDFLAGS) -o $@ $(OBJS1) $(LIBS) $(EXTRA_LOADFLAGS)
    
    resize$x : $(OBJS2)
    	@ECHO_LD@$(SHELL) $(srcdir)/plink.sh $(LINK) $(LDFLAGS) -o $@ $(OBJS2) $(LIBS)
    
    256colres.h :
    	-$(RM) $@
    	perl $(srcdir)/256colres.pl > $@
    
    88colres.h :
    	-$(RM) $@
    	perl $(srcdir)/88colres.pl > $@
    
    charproc$o : $(VTPARSE_H) main.h @CHARPROC_DEPS@
    graphics_regis$o : $(VTPARSE_H) 
    graphics_sixel$o : $(VTPARSE_H) 
    misc$o : $(VTPARSE_H) 
    VTPrsTbl$o : $(VTPARSE_H) 
    
    TekPrsTbl$o : $(TEKPARSE_H)
    Tekproc$o : $(TEKPARSE_H)
    
    misc$o : builtin_icons.h
    
    trace$o : VTparse.cin Tekparse.cin
    
    # do this to quiet gcc -Wcast-qual warnings 
    builtin_icons.h :
    	@echo "#if OPT_BUILTIN_XPMS" >$@
    	@echo "#include " >>$@
    	@echo "#include " >>$@
    	@echo "#include " >>$@
    	@echo "#include " >>$@
    	@echo "#else" >>$@
    	@sed -e 's/static char \* /static const char * /' $(srcdir)/icons/mini.xterm_48x48.xpm >>$@
    	@echo "#endif" >>$@
    	@echo "made $@"
    
    ################################################################################
    test_wcwidth$x : wcwidth.c
    	$(CC) -o $@ $(CFLAGS) $(CPPFLAGS) -DTEST_DRIVER wcwidth.c $(LDFLAGS) $(LIBS)
    
    ################################################################################
    actual_xterm  = `echo xterm|        sed '$(transform)'`
    actual_resize = `echo resize|       sed '$(transform)'`
    actual_uxterm = `echo uxterm|       sed '$(transform)'`
    actual_k8term = `echo koi8rxterm|   sed '$(transform)'`
    
    binary_xterm  = $(actual_xterm)$x
    binary_resize = $(actual_resize)$x
    binary_uxterm = $(actual_uxterm)
    binary_k8term = $(actual_k8term)
    
    install \
    install-bin \
    install-full :: xterm$x resize$x $(BINDIR)
    @MAY_SETUID@	$(SHELL) $(srcdir)/sinstall.sh @SINSTALL_OPTS@ "$(INSTALL_PROGRAM)" xterm$x  @XTERM_PATH@ $(BINDIR)/$(binary_xterm)
    @NOT_SETUID@	$(INSTALL_PROGRAM) xterm$x $(BINDIR)/$(binary_xterm)
    	$(INSTALL_PROGRAM) -m  755 resize$x $(BINDIR)/$(binary_resize)
    
    EDIT_SCRIPT = sed -e s,=xterm,=\$$name, -e s,XTerm,$(CLASS),
    
    InstallLink = \
    	if test @XTERM_SYMLINK@ != NONE \
    	&& test \$$source != NONE \
    	&& test \$$source != \$$target ; then \
    		cd \$$TARGET && ( \
    			$(RM) \$$source ; \
    			$(LN_S) \$$target \$$source ; \
    			echo \"... created symbolic link:\" ; \
    			ls -l \$$target \$$source ) ; \
    	fi
    
    InstallBinLink = TARGET=$(BINDIR); $(InstallLink)
    InstallManLink = TARGET=$(MANDIR); $(InstallLink)
    
    InstallScript = \
    	echo \"... installing $(BINDIR)/\$$target\"; \
    	name=$(binary_xterm); \
    	$(EDIT_SCRIPT) $(srcdir)/\$$source >\$$source.tmp; \
    	$(INSTALL_SCRIPT) -m  755 \$$source.tmp $(BINDIR)/\$$target; \
    	$(RM) \$$source.tmp
    
    install \
    install-bin \
    install-scripts \
    install-full :: $(BINDIR)
    	@$(SHELL) -c "source=\"@XTERM_SYMLINK@\"; \
    		target=\"$(binary_xterm)\"; \
    		$(InstallBinLink)"
    	@$(SHELL) -c "source=\"resize\"; \
    		target=\"$(binary_resize)\"; \
    		$(InstallBinLink)"
    	@$(SHELL) -c "source=\"uxterm\"; \
    		target=\"$(binary_uxterm)\"; \
    		$(InstallScript); \
    		$(InstallBinLink)"
    	@$(SHELL) -c "source=\"koi8rxterm\"; \
    		target=\"$(binary_k8term)\"; \
    		$(InstallScript); \
    		$(InstallBinLink)"
    
    install \
    install-man \
    install-full :: $(MANDIR)
    	@-$(SHELL) -c "for source in xterm resize uxterm koi8rxterm ; \
    		do \
    			target=\`echo \"\$$source\" | sed '@program_transform_name@'\`; \
    			$(SHELL) ./minstall \"$(INSTALL_DATA)\" \
    				$(srcdir)/\$$source.man  \
    				$(MANDIR)/\$$target.$(manext) \
    				$(appsdir) \
    				$(CLASS) \
    				\$$source \
    				\$$target \
    				$(pixmapdir); \
    		done"
    	@-$(SHELL) -c "if test @XTERM_SYMLINK@ != NONE ; then \
    		source=$(actual_xterm).$(manext); \
    		target=@XTERM_SYMLINK@.$(manext); \
    		cd $(MANDIR) && ( \
    			$(RM) \$$target ; \
    			$(LN_S) \$$source \$$target ; \
    			echo '... created symbolic link:' ; \
    			ls -l \$$source \$$target ; \
    			) \
    		fi"
    
    APP_NAMES = XTerm UXTerm KOI8RXTerm
    
    @no_appsdir@install \
    @no_appsdir@install-app \
    @no_appsdir@install-full :: $(APPSDIR)
    @no_appsdir@	@-$(SHELL) -c 'for s in $(APP_NAMES); \
    @no_appsdir@	do \
    @no_appsdir@		echo "** $$s"; \
    @no_appsdir@		d=`echo $$s | sed -e s/XTerm/$(CLASS)/`; \
    @no_appsdir@		echo installing $(APPSDIR)/$$d; \
    @no_appsdir@		sed -e s/XTerm/$(CLASS)/ $(srcdir)/$$s.ad >XTerm.tmp; \
    @no_appsdir@		$(INSTALL_DATA) XTerm.tmp $(APPSDIR)/$$d; \
    @no_appsdir@		echo installing $(APPSDIR)/$$d-color; \
    @no_appsdir@		sed -e s/XTerm/$$d/ $(srcdir)/XTerm-col.ad >XTerm.tmp; \
    @no_appsdir@		$(INSTALL_DATA) XTerm.tmp $(APPSDIR)/$$d-color; \
    @no_appsdir@	done'
    @no_appsdir@	@$(RM) XTerm.tmp
    @no_icondir@	@echo "... installed app-defaults"
    
    @no_icondir@ICON_LIST = @ICON_LIST@
    @no_icondir@ICON_THEME = @ICON_THEME@
    @no_icondir@install \
    @no_icondir@install-icon \
    @no_icondir@install-full :: $(ICONDIR)
    @no_icondir@	@ECHO_CC@ACTUAL_XTERM=$(actual_xterm) $(SHELL) -c '\
    @no_icondir@		h=$(ICONDIR)/$(ICON_THEME); \
    @no_icondir@		for n in $(ICON_LIST); \
    @no_icondir@		do \
    @no_icondir@			x=$$ACTUAL_XTERM; \
    @no_icondir@			l=`echo "$$n" | cut -f1 -d:`; \
    @no_icondir@			r=`echo "$$n" | cut -f2 -d: |sed -e "s,xterm,$$ACTUAL_XTERM,"`; \
    @no_icondir@			test -z "$$r" && continue; \
    @no_icondir@			d=$$h/`echo "$$r" | sed -e "s,/[^/]*$$,,"`; \
    @no_icondir@			test -d "$$d" || mkdir -p "$$d"; \
    @no_icondir@			echo "installing icon $$h/$$r"; \
    @no_icondir@			$(INSTALL_DATA) $$l $$h/$$r; \
    @no_icondir@			s=`echo "$$r" | sed -e '"'s,^.*\.,.,'"'`; \
    @no_icondir@			t=$(ICON_SYMLINK)$$s; \
    @no_icondir@			b=`basename $$n $$s | sed -e "s,_[1-9][0-9]*x.*,,"`; \
    @no_icondir@			if test "$(ICON_SYMLINK)" != NONE ; then \
    @no_icondir@				if test "$$r" != "$$t" ; then \
    @no_icondir@					if test "x$$b" = "x$(ICON_NAME)" ; then \
    @no_icondir@						echo "linking $$r -> $$t"; \
    @no_icondir@						( cd $$h; $(RM) $$t; $(LN_S) $$r $$t; ) \
    @no_icondir@					fi \
    @no_icondir@				fi \
    @no_icondir@			fi \
    @no_icondir@		done'
    @no_icondir@	@echo "... installed icons"
    
    @no_pixmapdir@install \
    @no_pixmapdir@install-icon \
    @no_pixmapdir@install-full :: $(PIXMAPDIR)
    @no_pixmapdir@	@ECHO_CC@ACTUAL_XTERM=$(actual_xterm) $(SHELL) -c '\
    @no_pixmapdir@		h=$(PIXMAPDIR); \
    @no_pixmapdir@		for n in $(srcdir)/icons/*xterm*_32x32.xpm $(srcdir)/icons/*xterm*_48x48.xpm; \
    @no_pixmapdir@		do \
    @no_pixmapdir@			l=`basename $$n`; \
    @no_pixmapdir@			r=`echo "$$l" | sed -e "s,xterm,$$ACTUAL_XTERM,"`; \
    @no_pixmapdir@			echo "installing pixmap $$h/$$r"; \
    @no_pixmapdir@			$(INSTALL_DATA) $(srcdir)/icons/$$l $$h/$$r; \
    @no_pixmapdir@			s=`echo "$$r" | sed -e '"'s,^.*\.,.,'"'`; \
    @no_pixmapdir@			t=$(ICON_SYMLINK)$$s; \
    @no_pixmapdir@			b=`basename $$n $$s | sed -e "s,_[1-9][0-9]*x.*,,"`; \
    @no_pixmapdir@			if test "$(ICON_SYMLINK)" != NONE ; then \
    @no_pixmapdir@				if test "x$$r" != "$$t" ; then \
    @no_pixmapdir@					if test "x$$b" = "x$(ICON_NAME)" ; then \
    @no_pixmapdir@						echo "linking $$r -> $$t"; \
    @no_pixmapdir@						( cd $$h; $(RM) $$t; $(LN_S) $$r $$t; ) \
    @no_pixmapdir@					fi \
    @no_pixmapdir@				fi \
    @no_pixmapdir@			fi \
    @no_pixmapdir@		done'
    @no_pixmapdir@	@echo "... installed icons"
    
    install ::
    	@echo 'Completed installation of executables and documentation.'
    	@echo 'Use "make install-ti" to install terminfo description.'
    
    TERMINFO_DIR = @TERMINFO_DIR@
    SET_TERMINFO = @SET_TERMINFO@
    
    @no_ticprog@install-full \
    @no_ticprog@install-ti :: $(TERMINFO_DIR)
    @no_ticprog@	@$(SHELL) -c "$(SET_TERMINFO) $(srcdir)/run-tic.sh $(srcdir)/terminfo"
    @no_ticprog@	@echo 'Completed installation of terminfo description.'
    
    install-full \
    install-tc ::
    	@-$(SHELL) -c "if test -f /etc/termcap ; then echo 'You must install the termcap entry manually by editing /etc/termcap'; fi"
    
    installdirs : $(INSTALL_DIRS)
    ################################################################################
    
    UninstallLink = \
    	if test @XTERM_SYMLINK@ != NONE \
    	&& test \$$source != NONE \
    	&& test \$$source != \$$target \
    	&& test -h \$$TARGET/\$$source ; then \
    		echo \"... removing \$$TARGET/\$$source\"; \
    		cd \$$TARGET && \
    		$(RM) \$$source; \
    	fi
    
    UninstallBinLink = TARGET=$(BINDIR); $(UninstallLink)
    UninstallManLink = TARGET=$(MANDIR); $(UninstallLink)
    
    UninstallBinary = \
    	echo \"... removing $(BINDIR)/\$$target\"; \
    	$(RM) $(BINDIR)/\$$target
    
    uninstall \
    uninstall-bin \
    uninstall-full ::
    	@-$(SHELL) -c "source=\"@XTERM_SYMLINK@\"; \
    		target=\"$(binary_xterm)\"; \
    		$(UninstallBinLink); \
    		$(UninstallBinary)"
    	@-$(SHELL) -c "source=\"resize\"; \
    		target=\"$(binary_resize)\"; \
    		$(UninstallBinLink); \
    		$(UninstallBinary)"
    
    uninstall \
    uninstall-bin \
    uninstall-scripts \
    uninstall-full ::
    	@-$(SHELL) -c "source=\"uxterm\"; \
    		target=\"$(binary_uxterm)\"; \
    		$(UninstallBinLink); \
    		$(UninstallBinary)"
    	@-$(SHELL) -c "source=\"koi8rxterm\"; \
    		target=\"$(binary_k8term)\"; \
    		$(UninstallBinLink); \
    		$(UninstallBinary)"
    
    uninstall \
    uninstall-man \
    uninstall-full ::
    	@-$(SHELL) -c "\
    		source=@XTERM_SYMLINK@.$(manext); \
    		target=$(actual_xterm).$(manext); \
    		$(UninstallManLink)"
    	@-$(SHELL) -c "for source in \
    		$(actual_xterm).$(manext) \
    		$(actual_resize).$(manext) \
    		$(actual_uxterm).$(manext) \
    		$(actual_k8term).$(manext); \
    		do \
    			echo \"... removing $(MANDIR)/\$$source\"; \
    			$(RM) $(MANDIR)/\$$source; \
    		done"
    
    @no_appsdir@uninstall \
    @no_appsdir@uninstall-app \
    @no_appsdir@uninstall-full ::
    @no_appsdir@	-@ECHO_CC@$(SHELL) -c 'for s in $(APP_NAMES); \
    @no_appsdir@	do \
    @no_appsdir@		echo "** $$s"; \
    @no_appsdir@		d=`echo $$s | sed -e s/XTerm/$(CLASS)/`; \
    @no_appsdir@		echo uninstalling $(APPSDIR)/$$d; \
    @no_appsdir@		$(RM) $(APPSDIR)/$$d; \
    @no_appsdir@		echo uninstalling $(APPSDIR)/$$d-color; \
    @no_appsdir@		$(RM) $(APPSDIR)/$$d-color; \
    @no_appsdir@	done'
    
    @no_icondir@uninstall \
    @no_icondir@uninstall-icon \
    @no_icondir@uninstall-full ::
    @no_icondir@	-@ECHO_CC@$(SHELL) -c 'ACTUAL_XTERM=$(actual_xterm) ; \
    @no_icondir@		for n in $(ICON_LIST); \
    @no_icondir@		do \
    @no_icondir@		r=`echo "$$n" | sed -e s,\^.\*:,, -e s,xterm,$$ACTUAL_XTERM,`; \
    @no_icondir@		test -z "$$r" && continue; \
    @no_icondir@		h=$(ICONDIR)/$(ICON_THEME); \
    @no_icondir@		test -f $$h/$$r || continue; \
    @no_icondir@		echo removing $$h/$$r; \
    @no_icondir@		$(RM) $$h/$$r; \
    @no_icondir@		done'
    @no_icondir@	@echo "... removed icons"
    
    @no_pixmapdir@uninstall \
    @no_pixmapdir@uninstall-icon \
    @no_pixmapdir@uninstall-full ::
    @no_pixmapdir@	-@$(SHELL) -c 'ACTUAL_XTERM=$(actual_xterm) ; \
    @no_pixmapdir@		for n in $(srcdir)/icons/*xterm*_32x32.xpm $(srcdir)/icons/*xterm*_48x48.xpm; \
    @no_pixmapdir@		do \
    @no_pixmapdir@			l=`basename $$n`; \
    @no_pixmapdir@			r=`echo "$$l" | sed -e "s,xterm,$$ACTUAL_XTERM,"`; \
    @no_pixmapdir@			echo removing $(PIXMAPDIR)/$$r; \
    @no_pixmapdir@			$(RM) $(PIXMAPDIR)/$$r; \
    @no_pixmapdir@		done'
    @no_pixmapdir@	@echo "... removed icons"
    ################################################################################
    # Desktop-utils does not provide an uninstall, and is not uniformly available.
    @desktop_utils@DESKTOP_FILES = $(srcdir)/xterm.desktop $(srcdir)/uxterm.desktop
    @desktop_utils@DESKTOP_FLAGS = @DESKTOP_FLAGS@
    @desktop_utils@install-desktop \
    @desktop_utils@install-full ::
    @desktop_utils@	ACTUAL_XTERM=$(actual_xterm) \
    @desktop_utils@	$(SHELL) -c 'for n in $(DESKTOP_FILES); \
    @desktop_utils@		do $(SHELL) df-install $$ACTUAL_XTERM $(ICON_NAME) $(DESKTOP_FLAGS) $$n; \
    @desktop_utils@		done'
    ################################################################################
    check :
    	@ echo "There are no batch tests available (use vttest)"
    ################################################################################
    mostlyclean :
    	-$(RM) *$o *.[is] XTerm[1-9]*.* Xterm.log.* XtermLog.* .pure core *~ *.bak *.BAK *.out *.tmp
    
    clean : mostlyclean
    	-$(RM) $(PROGRAMS) $(TEST_PROGRAMS) $(AUTO_SOURCE)
    
    sources : $(AUTO_SOURCE)
    
    distclean :: clean
    	-$(RM) Makefile config.status config.cache config.log xtermcfg.h
    	-$(RM) df-install minstall
    
    distclean \
    docs-clean ::
    	-$(RM) *.ps *.pdf *.png
    	-$(SHELL) -c 'for p in xterm resize uxterm koi8rxterm; \
    	do \
    		$(RM) $$p.html $$p.$(manext) $$p.txt; \
    	done'
    	-$(RM) ctlseqs.html ctlseqs.$(manext)
    
    distclean ::
    	-$(RM) man2html.tmp
    
    realclean : distclean
    	-$(RM) tags TAGS
    
    maintainer-clean : realclean
    	-$(RM) 256colres.h 88colres.h
    ################################################################################
    terminfo.out : terminfo		; tic -a -I -1 terminfo >$@
    termcap.out : termcap		; tic -a -C -U termcap >$@
    ################################################################################
    docs-ctlseqs \
    docs :: $(srcdir)/ctlseqs.txt @MAN2HTML_NOTE@ ctlseqs.html @GROFF_NOTE@ ctlseqs.pdf ctlseqs.ps
    
    ctlseqs.html : $(srcdir)/ctlseqs.ms
    ctlseqs.pdf : ctlseqs.ps
    ctlseqs.ps : $(srcdir)/ctlseqs.ms
    ctlseqs.txt : $(srcdir)/ctlseqs.ms
    ################################################################################
    docs-resize \
    docs ::  resize.txt @MAN2HTML_NOTE@ resize.html @GROFF_NOTE@ resize.pdf resize.ps
    resize.html : resize.$(manext)
    resize.pdf : resize.ps
    resize.ps : resize.$(manext)
    resize.txt : resize.$(manext)
    ################################################################################
    docs-xterm \
    docs ::  xterm.txt @MAN2HTML_NOTE@ xterm.html @GROFF_NOTE@ xterm.pdf xterm.ps
    xterm.html : xterm.$(manext)
    xterm.pdf : xterm.ps
    xterm.ps : xterm.$(manext)
    xterm.txt : xterm.$(manext)
    ################################################################################
    docs-uxterm \
    docs ::  uxterm.txt @MAN2HTML_NOTE@ uxterm.html @GROFF_NOTE@ uxterm.pdf uxterm.ps
    uxterm.html : uxterm.$(manext)
    uxterm.pdf : uxterm.ps
    uxterm.ps : uxterm.$(manext)
    uxterm.txt : uxterm.$(manext)
    ################################################################################
    docs-koi8rxterm \
    docs ::  koi8rxterm.txt @MAN2HTML_NOTE@ koi8rxterm.html @GROFF_NOTE@ koi8rxterm.pdf koi8rxterm.ps
    koi8rxterm.html : koi8rxterm.$(manext)
    koi8rxterm.pdf : koi8rxterm.ps
    koi8rxterm.ps : koi8rxterm.$(manext)
    koi8rxterm.txt : koi8rxterm.$(manext)
    ################################################################################
    lint :
    	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(SRCS1)
    	$(LINT) $(LINT_OPTS) $(CPPFLAGS) $(SRCS2)
    
    tags :
    	$(CTAGS) $(SRCS) $(HDRS)
    
    TAGS :
    	$(ETAGS) $(SRCS) $(HDRS)
    
    $(TERMINFO_DIR) $(INSTALL_DIRS) :
    	mkdir -p $@
    
    ALWAYS :
    
    depend : $(TABLES)
    	makedepend -- $(CPPFLAGS) -- $(SRCS)
    
    # DO NOT DELETE THIS LINE -- make depend depends on it.
    xterm-353/sinstall.sh0000755000175100001440000001410711344500201013425 0ustar  tomusers#!/bin/sh
    # $XTermId: sinstall.sh,v 1.18 2010/03/06 16:19:13 tom Exp $
    # -----------------------------------------------------------------------------
    # this file is part of xterm
    #
    # Copyright 1999-2008,2010 by Thomas E. Dickey
    # 
    #                         All Rights Reserved
    # 
    # Permission is hereby granted, free of charge, to any person obtaining a
    # copy of this software and associated documentation files (the
    # "Software"), to deal in the Software without restriction, including
    # without limitation the rights to use, copy, modify, merge, publish,
    # distribute, sublicense, and/or sell copies of the Software, and to
    # permit persons to whom the Software is furnished to do so, subject to
    # the following conditions:
    # 
    # The above copyright notice and this permission notice shall be included
    # in all copies or substantial portions of the Software.
    # 
    # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
    # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    # 
    # Except as contained in this notice, the name(s) of the above copyright
    # holders shall not be used in advertising or otherwise to promote the
    # sale, use or other dealings in this Software without prior written
    # authorization.
    # -----------------------------------------------------------------------------
    #
    # Install program setuid if the installer is running as root, and if xterm is
    # already installed on the system with setuid privilege.  This is a safeguard
    # for ordinary users installing xterm for themselves on systems where the
    # setuid is not needed to access a PTY, but only for things like utmp.
    #
    # Options:
    #	u+s, g+s as in chmod
    #	-u, -g and -m as in install.  If any options are given, $3 is ignored.
    #
    # Parameters:
    #	$1 = program to invoke as "install"
    #	$2 = program to install
    #	$3 = previously-installed program, for reference
    #	$4 = final installed-path, if different from reference
    
    trace=:
    trace=echo
    
    # override locale...
    # (otherwise GNU ls displays date column in a locale-dependent manner).
    LANG=C;		export LANG
    LANGUAGE=C;	export LANGUAGE
    LC_ALL=C;	export LC_ALL
    LC_CTYPE=C;	export LC_CTYPE
    
    OPTS_SUID=
    OPTS_SGID=
    OPTS_MODE=
    OPTS_USR=
    OPTS_GRP=
    
    while test $# != 0
    do
    	case $1 in
    	-*)
    		OPT="$1"
    		shift
    		if test $# != 0
    		then
    			case $OPT in
    			-u)	OPTS_USR="$1"; shift;;
    			-g)	OPTS_GRP="$1"; shift;;
    			-m)	OPTS_MODE="$1"; shift;;
    			esac
    		else
    			break
    		fi
    		;;
    	u+s)	shift;	OPTS_SUID=4000;;
    	g+s)	shift;	OPTS_SGID=2000;;
    	*)	break
    		;;
    	esac
    done
    
    SINSTALL="$1"
    SRC_PROG="$2"
    REF_PROG="$3"
    DST_PROG="$4"
    
    test -z "$SINSTALL" && SINSTALL=install
    test -z "$SRC_PROG" && SRC_PROG=xterm
    test -z "$REF_PROG" && REF_PROG=/usr/bin/X11/xterm
    test -z "$DST_PROG" && DST_PROG="$REF_PROG"
    
    test -n "$OPTS_SUID" && test -n "$OPTS_USR" && REF_PROG=
    test -n "$OPTS_SGID" && test -n "$OPTS_GRP" && REF_PROG=
    
    echo checking for presumed installation-mode
    
    PROG_SUID=
    PROG_SGID=
    PROG_MODE=
    PROG_USR=
    PROG_GRP=
    
    if test -z "$REF_PROG" ; then
    	$trace "... reference program not used"
    elif test -f "$REF_PROG" ; then
    	cf_option="-l -L"
    	MYTEMP=${TMPDIR-/tmp}/sinstall$$
    
    	# Expect listing to have fields like this:
    	#-r--r--r--   1 user      group       34293 Jul 18 16:29 pathname
    	ls $cf_option $REF_PROG
    	ls $cf_option $REF_PROG >$MYTEMP
    	read cf_mode cf_links cf_usr cf_grp cf_size cf_date1 cf_date2 cf_date3 cf_rest <$MYTEMP
    	$trace "... if \"$cf_rest\" is null, try the ls -g option"
    	if test -z "$cf_rest" ; then
    		cf_option="$cf_option -g"
    		ls $cf_option $REF_PROG
    		ls $cf_option $REF_PROG >$MYTEMP
    		read cf_mode cf_links cf_usr cf_grp cf_size cf_date1 cf_date2 cf_date3 cf_rest <$MYTEMP
    	fi
    	rm -f $MYTEMP
    
    	# If we have a pathname, and the date fields look right, assume we've
    	# captured the group as well.
    	$trace "... if \"$cf_rest\" is null, we do not look for group"
    	if test -n "$cf_rest" ; then
    		cf_test=`echo "${cf_date2}${cf_date3}" | sed -e 's/[0-9:]//g'`
    		$trace "... if we have date in proper columns ($cf_date1 $cf_date2 $cf_date3), \"$cf_test\" is null"
    		if test -z "$cf_test" ; then
    			PROG_USR=$cf_usr;
    			PROG_GRP=$cf_grp;
    		fi
    	fi
    	$trace "... derived user \"$PROG_USR\", group \"$PROG_GRP\" of previously-installed $SRC_PROG"
    
    	$trace "... see if mode \"$cf_mode\" has s-bit set"
    	case ".$cf_mode" in #(vi
    	.???s??s*) #(vi
    		$trace "... both setuid/setgid"
    		PROG_SUID=4000
    		PROG_SGID=2000
    		;;
    	.???s*) #(vi
    		$trace "... setuid"
    		PROG_SUID=4000
    		PROG_GRP=
    		;;
    	.??????s*)
    		$trace "... setgid"
    		PROG_SGID=2000
    		PROG_USR=
    		;;
    	esac
    	PROG_MODE=`echo ".$cf_mode" | sed -e 's/^..//' -e 's/rw./7/g' -e 's/r-./5/g' -e 's/---/0/g' -e 's/--[sxt]/1/g' -e 's/[^0-7]//g'`
    fi
    
    # passed-in options override the reference
    test -n "$OPTS_SUID" && PROG_SUID="$OPTS_SUID"
    test -n "$OPTS_SGID" && PROG_SGID="$OPTS_SGID"
    test -n "$OPTS_MODE" && PROG_MODE="$OPTS_MODE"
    test -n "$OPTS_USR"  && PROG_USR="$OPTS_USR"
    test -n "$OPTS_GRP"  && PROG_GRP="$OPTS_GRP"
    
    # we always need a mode
    test -z "$PROG_MODE" && PROG_MODE=755
    
    if test -n "${PROG_USR}${PROG_GRP}" ; then
    	cf_uid=`id | sed -e 's/^[^=]*=//' -e 's/(.*$//'`
    	cf_usr=`id | sed -e 's/^[^(]*(//' -e 's/).*$//'`
    	cf_grp=`id | sed -e 's/^.* gid=[^(]*(//' -e 's/).*$//'`
    	$trace "... installing $SRC_PROG as user \"$cf_usr\", group \"$cf_grp\""
    	if test "$cf_uid" != 0 ; then
    		PROG_SUID=
    		PROG_SGID=
    		PROG_USR=""
    		PROG_GRP=""
    	fi
    	test "$PROG_USR" = "$cf_usr" && PROG_USR=""
    	test "$PROG_GRP" = "$cf_grp" && PROG_GRP=""
    fi
    
    test -n "${PROG_SUID}${PROG_SGID}" && PROG_MODE=`expr $PROG_MODE % 1000`
    test -n "$PROG_SUID" && PROG_MODE=`expr $PROG_SUID + $PROG_MODE`
    test -n "$PROG_SGID" && PROG_MODE=`expr $PROG_SGID + $PROG_MODE`
    
    test -n "$PROG_USR" && PROG_USR="-o $PROG_USR"
    test -n "$PROG_GRP" && PROG_GRP="-g $PROG_GRP"
    
    echo "$SINSTALL -m $PROG_MODE $PROG_USR $PROG_GRP $SRC_PROG $DST_PROG"
    eval "$SINSTALL -m $PROG_MODE $PROG_USR $PROG_GRP $SRC_PROG $DST_PROG"
    xterm-353/xterm.h0000644000175100001440000020510213615304645012563 0ustar  tomusers/* $XTermId: xterm.h,v 1.864 2020/02/01 14:22:29 tom Exp $ */
    
    /*
     * Copyright 1999-2019,2020 by Thomas E. Dickey
     *
     *                         All Rights Reserved
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     *
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * Except as contained in this notice, the name(s) of the above copyright
     * holders shall not be used in advertising or otherwise to promote the
     * sale, use or other dealings in this Software without prior written
     * authorization.
     */
    
    /*
     * Common/useful definitions for XTERM application.
     *
     * This is also where we put the fallback definitions if we do not build using
     * the configure script.
     */
    #ifndef included_xterm_h
    #define included_xterm_h
    /* *INDENT-OFF* */
    
    #ifdef HAVE_CONFIG_H
    #include 
    #endif
    
    #undef bcopy
    #include 
    
    #ifndef HAVE_CONFIG_H
    
    #define HAVE_LIB_XAW 1
    
    #ifdef CSRG_BASED
    /* Get definition of BSD */
    #include 
    #endif
    
    #ifndef DFT_TERMTYPE
    #define DFT_TERMTYPE "xterm"
    #endif
    
    #ifndef X_NOT_POSIX
    #define HAVE_WAITPID 1
    #define HAVE_SYS_WAIT_H 1
    #define HAVE_UNISTD_H 1
    #endif
    
    #define HAVE_STDLIB_H 1
    
    #if defined(sun)
    /* errno is declared in  */
    #else
    #define DECL_ERRNO 1
    #endif
    
    #undef DECL_PTSNAME		/* ptsname() is normally in stdlib.h */
    
    #ifndef NOPUTENV
    #define HAVE_PUTENV 1
    #endif
    
    #if defined(CSRG_BASED) || defined(__GNU__) || defined(__minix)
    #define USE_POSIX_TERMIOS 1
    #endif
    
    #ifdef __FreeBSD__
    #if __FreeBSD_version >= 900000
    #define USE_SYSV_UTMP 1
    #define UTMPX_FOR_UTMP 1
    #define HAVE_UTMP_UT_HOST 1
    #define HAVE_UTMP_UT_XTIME 1
    #define ut_name ut_user
    #define ut_xtime ut_tv.tv_sec
    #endif
    #endif
    
    #ifdef __NetBSD__
    #if __NetBSD_Version__ >= 106030000	/* 1.6C */
    #define BSD_UTMPX 1
    #define ut_xtime ut_tv.tv_sec
    #endif
    #endif
    
    #if defined(hpux) && !defined(__hpux)
    #define __hpux 1		/* HPUX 11.0 does not define this */
    #endif
    
    #if !defined(__SCO__) && (defined(SCO) || defined(sco) || defined(SCO325))
    #define __SCO__ 1
    #endif
    
    #ifdef USE_POSIX_TERMIOS
    #define HAVE_TERMIOS_H 1
    #define HAVE_TCGETATTR 1
    #endif
    
    #if defined(__SCO__) || defined(__UNIXWARE__) || defined(__minix)
    #define USE_TERMCAP 1
    #endif
    
    #if defined(UTMP)
    #define HAVE_UTMP 1
    #endif
    
    #if (defined(__MVS__) || defined(SVR4) || defined(__SCO__) || defined(BSD_UTMPX)) && !defined(__CYGWIN__)
    #define UTMPX_FOR_UTMP 1
    #endif
    
    #if !defined(ISC) && !defined(__QNX__)
    #define HAVE_UTMP_UT_HOST 1
    #endif
    
    #if defined(UTMPX_FOR_UTMP) && !(defined(__MVS__) || defined(__hpux) || defined(__FreeBSD__))
    #define HAVE_UTMP_UT_SESSION 1
    #endif
    
    #if !(defined(linux) && (!defined(__GLIBC__) || (__GLIBC__ < 2))) && !defined(SVR4) && !defined(__FreeBSD__)
    #define ut_xstatus ut_exit.e_exit
    #endif
    
    #if defined(SVR4) || defined(__SCO__) || defined(BSD_UTMPX) || (defined(linux) && defined(__GLIBC__) && (__GLIBC__ >= 2) && !(defined(__powerpc__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0)))
    #define HAVE_UTMP_UT_XTIME 1
    #endif
    
    #if defined(linux) || defined(__CYGWIN__)
    #define USE_LASTLOG
    #define HAVE_LASTLOG_H
    #define USE_STRUCT_LASTLOG
    #elif defined(BSD) && (BSD >= 199103)
    #ifdef BSD_UTMPX
    #define USE_LASTLOGX
    #elif defined(USE_SYSV_UTMP)
    #else
    #define USE_LASTLOG
    #define USE_STRUCT_LASTLOG
    #endif
    #endif
    
    #if defined(__OpenBSD__)
    #define DEFDELETE_DEL True
    #define DEF_BACKARO_ERASE True
    #define DEF_INITIAL_ERASE True
    #endif
    
    #if defined(__SCO__) || defined(__UNIXWARE__)
    #define DEFDELETE_DEL True
    #define OPT_SCO_FUNC_KEYS 1
    #endif
    
    #if defined(__SCO__) || defined(SVR4) || defined(_POSIX_SOURCE) || defined(__QNX__) || defined(__hpux) || (defined(BSD) && (BSD >= 199103)) || defined(__CYGWIN__)
    #define USE_POSIX_WAIT
    #endif
    
    #if defined(AIXV3) || defined(CRAY) || defined(__SCO__) || defined(SVR4) || (defined(SYSV) && defined(i386)) || defined(__MVS__) || defined(__hpux) || defined(__osf__) || defined(linux) || defined(macII) || defined(BSD_UTMPX)
    #define USE_SYSV_UTMP
    #endif
    
    #if defined(__GNU__) || defined(__MVS__) || defined(__osf__)
    #define USE_TTY_GROUP
    #endif
    
    #if defined(__CYGWIN__)
    #define HAVE_NCURSES_TERM_H 1
    #endif
    
    #ifdef __osf__
    #define TTY_GROUP_NAME "terminal"
    #endif
    
    #if defined(__MVS__)
    #undef ut_xstatus
    #define ut_name ut_user
    #define ut_xstatus ut_exit.ut_e_exit
    #define ut_xtime ut_tv.tv_sec
    #endif
    
    #if defined(ut_xstatus)
    #define HAVE_UTMP_UT_XSTATUS 1
    #endif
    
    #if defined(XKB)
    #define HAVE_XKB_BELL_EXT 1
    #endif
    
    #if (defined(SVR4) && !defined(__CYGWIN__)) || defined(linux) || (defined(BSD) && (BSD >= 199103))
    #define HAVE_POSIX_SAVED_IDS
    #endif
    
    #if defined(linux) || defined(__GLIBC__) || (defined(SYSV) && (defined(CRAY) || defined(macII) || defined(__hpux) || defined(__osf__) || defined(__sgi))) || !(defined(SYSV) || defined(__QNX__) || defined(VMS) || defined(__INTERIX))
    #define HAVE_INITGROUPS
    #endif
    
    #endif /* HAVE_CONFIG_H */
    
    #ifndef HAVE_X11_DECKEYSYM_H
    #define HAVE_X11_DECKEYSYM_H 1
    #endif
    
    #ifndef HAVE_X11_SUNKEYSYM_H
    #define HAVE_X11_SUNKEYSYM_H 1
    #endif
    
    #ifndef HAVE_X11_XF86KEYSYM_H
    #define HAVE_X11_XF86KEYSYM_H 0
    #endif
    
    #if defined(HAVE_X11_EXTENSIONS_XDBE_H) && defined(HAVE_XDBESWAPBUFFERS)
    #define USE_DOUBLE_BUFFER 1
    #else
    #define USE_DOUBLE_BUFFER 0
    #endif
    
    /***====================================================================***/
    
    /* if compiling with gcc -ansi -pedantic, we must fix POSIX definitions */
    #if defined(SVR4) && defined(sun)
    #ifndef __EXTENSIONS__
    #define __EXTENSIONS__ 1
    #endif
    #ifndef _POSIX_C_SOURCE
    #define _POSIX_C_SOURCE 1
    #endif
    #endif
    
    /***====================================================================***/
    
    #ifdef HAVE_STDLIB_H
    #include 
    #else
    extern char *calloc();
    extern char *getenv();
    extern char *malloc();
    extern char *realloc();
    extern void exit();
    extern void free();
    #endif
    
    #ifdef HAVE_UNISTD_H
    #include 
    #endif
    
    #ifdef HAVE_SYS_WAIT_H
    #include 
    #endif
    
    #include 
    #if defined(DECL_ERRNO) && !defined(errno)
    extern int errno;
    #endif
    
    /*
     * FIXME:  Toggling logging from xterm hangs under Linux 2.0.29 with libc5 if
     * we use 'waitpid()', while 'wait()' seems to work properly.
     */
    #ifdef linux
    #undef HAVE_WAITPID
    #endif
    
    #ifndef OPT_WIDE_CHARS
    #define OPT_WIDE_CHARS 0
    #endif
    
    #if OPT_WIDE_CHARS
    #define HIDDEN_CHAR 0xffff
    #endif
    
    /***====================================================================***/
    
    #define PROTO_XT_ACTIONS_ARGS \
    	(Widget w, XEvent *event, String *params, Cardinal *num_params)
    
    #define PROTO_XT_CALLBACK_ARGS \
    	(Widget gw, XtPointer closure, XtPointer data)
    
    #define PROTO_XT_CVT_SELECT_ARGS \
    	(Widget w, Atom *selection, Atom *target, Atom *type, XtPointer *value, unsigned long *length, int *format)
    
    #define PROTO_XT_EV_HANDLER_ARGS \
    	(Widget w, XtPointer closure, XEvent *event, Boolean *cont)
    
    #define PROTO_XT_SEL_CB_ARGS \
    	(Widget w, XtPointer client_data, Atom *selection, Atom *type, XtPointer value, unsigned long *length, int *format)
    
    #include 
    
    /***====================================================================***/
    
    #ifndef GCC_PRINTFLIKE
    #ifdef _X_ATTRIBUTE_PRINTF
    #define GCC_PRINTFLIKE(f,n)	_X_ATTRIBUTE_PRINTF(f,n)
    #else
    #define GCC_PRINTFLIKE(f,n)	/* nothing */
    #endif
    #endif
    
    #ifndef GCC_UNUSED
    #ifdef _X_UNUSED
    #define GCC_UNUSED		_X_UNUSED
    #else
    #define GCC_UNUSED		/* nothing */
    #endif
    #endif
    
    #ifndef GCC_NORETURN
    #ifdef _X_NORETURN
    #define GCC_NORETURN		_X_NORETURN
    #else
    #define GCC_NORETURN		/* nothing */
    #endif
    #endif
    
    /***====================================================================***/
    
    #if defined(__GNUC__) && defined(_FORTIFY_SOURCE)
    #define USE_IGNORE_RC
    #define IGNORE_RC(func) ignore_unused = (int) func
    #else
    #define IGNORE_RC(func) (void) func
    #endif /* gcc workarounds */
    #if (XtSpecificationRelease >= 6) && !defined(NO_XPOLL_H) && !defined(sun)
    #include 
    #define USE_XPOLL_H 1
    #else
    #define Select(n,r,w,e,t) select(n,(fd_set*)r,(fd_set*)w,(fd_set*)e,(struct timeval *)t)
    #define XFD_COPYSET(src,dst) memcpy((dst)->fds_bits, (src)->fds_bits, sizeof(fd_set))
    #if defined(__MVS__) && !defined(TIME_WITH_SYS_TIME)
    #define TIME_WITH_SYS_TIME
    #endif
    #endif
    
    #ifdef TIME_WITH_SYS_TIME
    # include 
    # include 
    #else
    # ifdef HAVE_SYS_TIME_H
    #  include 
    # else
    #  include 
    # endif
    #endif
    
    /* these may be needed for sig_atomic_t */
    #include 
    #include 
    
    #ifdef USE_SYS_SELECT_H
    
    #if defined(USE_XPOLL_H) && defined(AIXV3) && defined(NFDBITS)
    #undef NFDBITS			/* conflict between X11/Xpoll.h and sys/select.h */
    #endif
    
    #include 
    
    #endif /* USE_SYS_SELECT_H */
    
    #include 
    
    #if !defined(VMS) && !(defined(linux) && defined(__USE_GNU)) && !defined(__hpux) && !defined(_ALL_SOURCE) && !defined(__osf__)
    extern char **environ;
    #endif
    
    #ifndef _Xconst
    #define _Xconst const		/* Solaris 7 workaround */
    #endif /* _Xconst */
    
    #define XK_Fn(n)	(XK_F1 + (n) - 1)
    
    #define Maybe		2
    
    #define ALLOC_STRING(name) \
    	if (name != 0) \
    	    name = x_strdup(name)
    #define FREE_STRING(name) \
    	    free_string(name)
    
    /* strftime format and length of the result */
    #define FMT_TIMESTAMP ".%Y.%m.%d.%H.%M.%S"
    #define LEN_TIMESTAMP sizeof(".YYYY.MM.DD.hh.mm.ss")
    
    /***====================================================================***/
    
    #if OPT_TRACE
    #undef NDEBUG			/* turn on assert's */
    #else
    #ifndef NDEBUG
    #define NDEBUG			/* not debugging, don't do assert's */
    #endif
    #endif
    
    #include 
    
    #if OPT_TRACE && !defined(DEBUG)
    #define DEBUG 1
    #endif
    
    #ifdef DEBUG
    #define if_DEBUG(code) if(debug) code
    #else
    #define if_DEBUG(code) /*nothing*/
    #endif
    
    #define DEBUG_MSG(text) if_DEBUG({ IGNORE_RC(write(2, text, sizeof(text) - 1)); })
    
    /***====================================================================***/
    
    #define XtNallowBoldFonts	"allowBoldFonts"
    #define XtNallowC1Printable	"allowC1Printable"
    #define XtNallowColorOps	"allowColorOps"
    #define XtNallowFontOps		"allowFontOps"
    #define XtNallowMouseOps	"allowMouseOps"
    #define XtNallowPasteControls	"allowPasteControls"
    #define XtNallowScrollLock	"allowScrollLock"
    #define XtNallowSendEvents	"allowSendEvents"
    #define XtNallowTcapOps		"allowTcapOps"
    #define XtNallowTitleOps	"allowTitleOps"
    #define XtNallowWindowOps	"allowWindowOps"
    #define XtNaltIsNotMeta		"altIsNotMeta"
    #define XtNaltSendsEscape	"altSendsEscape"
    #define XtNalternateScroll	"alternateScroll"
    #define XtNalwaysBoldMode	"alwaysBoldMode"
    #define XtNalwaysHighlight	"alwaysHighlight"
    #define XtNalwaysUseMods	"alwaysUseMods"
    #define XtNanswerbackString	"answerbackString"
    #define XtNappcursorDefault	"appcursorDefault"
    #define XtNappkeypadDefault	"appkeypadDefault"
    #define XtNassumeAllChars	"assumeAllChars"
    #define XtNautoWrap		"autoWrap"
    #define XtNawaitInput		"awaitInput"
    #define XtNbackarrowKey		"backarrowKey"
    #define XtNbellIsUrgent		"bellIsUrgent"
    #define XtNbellOnReset		"bellOnReset"
    #define XtNbellSuppressTime	"bellSuppressTime"
    #define XtNboldColors		"boldColors"
    #define XtNboldFont		"boldFont"
    #define XtNboldMode		"boldMode"
    #define XtNbrokenLinuxOSC	"brokenLinuxOSC"
    #define XtNbrokenSelections	"brokenSelections"
    #define XtNbrokenStringTerm	"brokenStringTerm"
    #define XtNbuffered		"buffered"
    #define XtNbufferedFPS		"bufferedFPS"
    #define XtNc132			"c132"
    #define XtNcacheDoublesize	"cacheDoublesize"
    #define XtNcdXtraScroll		"cdXtraScroll"
    #define XtNcharClass		"charClass"
    #define XtNchecksumExtension	"checksumExtension"
    #define XtNcjkWidth		"cjkWidth"
    #define XtNcolorAttrMode	"colorAttrMode"
    #define XtNcolorBDMode		"colorBDMode"
    #define XtNcolorBLMode		"colorBLMode"
    #define XtNcolorITMode		"colorITMode"
    #define XtNcolorInnerBorder	"colorInnerBorder"
    #define XtNcolorMode		"colorMode"
    #define XtNcolorRVMode		"colorRVMode"
    #define XtNcolorULMode		"colorULMode"
    #define XtNcombiningChars	"combiningChars"
    #define XtNctrlFKeys		"ctrlFKeys"
    #define XtNcurses		"curses"
    #define XtNcursorBlink		"cursorBlink"
    #define XtNcursorBlinkXOR	"cursorBlinkXOR"
    #define XtNcursorColor		"cursorColor"
    #define XtNcursorOffTime	"cursorOffTime"
    #define XtNcursorOnTime		"cursorOnTime"
    #define XtNcursorUnderLine	"cursorUnderLine"
    #define XtNcutNewline		"cutNewline"
    #define XtNcutToBeginningOfLine	"cutToBeginningOfLine"
    #define XtNdecTerminalID	"decTerminalID"
    #define XtNdefaultString	"defaultString"
    #define XtNdeleteIsDEL		"deleteIsDEL"
    #define XtNdirectColor		"directColor"
    #define XtNdisallowedColorOps	"disallowedColorOps"
    #define XtNdisallowedFontOps	"disallowedFontOps"
    #define XtNdisallowedMouseOps	"disallowedMouseOps"
    #define XtNdisallowedPasteControls "disallowedPasteControls"
    #define XtNdisallowedTcapOps	"disallowedTcapOps"
    #define XtNdisallowedWindowOps	"disallowedWindowOps"
    #define XtNdynamicColors	"dynamicColors"
    #define XtNeightBitControl	"eightBitControl"
    #define XtNeightBitInput	"eightBitInput"
    #define XtNeightBitMeta		"eightBitMeta"
    #define XtNeightBitOutput	"eightBitOutput"
    #define XtNeightBitSelectTypes	"eightBitSelectTypes"
    #define XtNeraseSavedLines	"eraseSavedLines"
    #define XtNfaceName		"faceName"
    #define XtNfaceNameDoublesize	"faceNameDoublesize"
    #define XtNfaceSize		"faceSize"
    #define XtNfastScroll		"fastScroll"
    #define XtNfont1		"font1"
    #define XtNfont2		"font2"
    #define XtNfont3		"font3"
    #define XtNfont4		"font4"
    #define XtNfont5		"font5"
    #define XtNfont6		"font6"
    #define XtNfontDoublesize	"fontDoublesize"
    #define XtNfontWarnings		"fontWarnings"
    #define XtNforceBoxChars	"forceBoxChars"
    #define XtNforcePackedFont	"forcePackedFont"
    #define XtNformatOtherKeys	"formatOtherKeys"
    #define XtNfreeBoldBox		"freeBoldBox"
    #define XtNfullscreen		"fullscreen"
    #define XtNhighlightColor	"highlightColor"
    #define XtNhighlightColorMode	"highlightColorMode"
    #define XtNhighlightReverse	"highlightReverse"
    #define XtNhighlightSelection	"highlightSelection"
    #define XtNhighlightTextColor	"highlightTextColor"
    #define XtNhpLowerleftBugCompat	"hpLowerleftBugCompat"
    #define XtNi18nSelections	"i18nSelections"
    #define XtNiconHint		"iconHint"
    #define XtNinitialFont		"initialFont"
    #define XtNinternalBorder	"internalBorder"
    #define XtNitalicULMode		"italicULMode"
    #define XtNjumpScroll		"jumpScroll"
    #define XtNkeepClipboard	"keepClipboard"
    #define XtNkeepSelection	"keepSelection"
    #define XtNkeyboardDialect	"keyboardDialect"
    #define XtNlimitFontsets	"limitFontsets"
    #define XtNlimitResize		"limitResize"
    #define XtNlimitResponse	"limitResponse"
    #define XtNlocale		"locale"
    #define XtNlocaleFilter		"localeFilter"
    #define XtNlogFile		"logFile"
    #define XtNlogInhibit		"logInhibit"
    #define XtNlogging		"logging"
    #define XtNloginShell		"loginShell"
    #define XtNmarginBell		"marginBell"
    #define XtNmaxGraphicSize	"maxGraphicSize"
    #define XtNmaximized		"maximized"
    #define XtNmenuBar		"menuBar"	/* internal */
    #define XtNmenuHeight		"menuHeight"
    #define XtNmetaSendsEscape	"metaSendsEscape"
    #define XtNmkSamplePass		"mkSamplePass"
    #define XtNmkSampleSize		"mkSampleSize"
    #define XtNmkWidth		"mkWidth"
    #define XtNmodifyCursorKeys	"modifyCursorKeys"
    #define XtNmodifyFunctionKeys	"modifyFunctionKeys"
    #define XtNmodifyKeyboard	"modifyKeyboard"
    #define XtNmodifyKeypadKeys	"modifyKeypadKeys"
    #define XtNmodifyOtherKeys	"modifyOtherKeys"
    #define XtNmodifyStringKeys	"modifyStringKeys"
    #define XtNmultiClickTime	"multiClickTime"
    #define XtNmultiScroll		"multiScroll"
    #define XtNnMarginBell		"nMarginBell"
    #define XtNnextEventDelay	"nextEventDelay"
    #define XtNnumColorRegisters	"numColorRegisters"
    #define XtNnumLock		"numLock"
    #define XtNoldXtermFKeys	"oldXtermFKeys"
    #define XtNpointerColor		"pointerColor"
    #define XtNpointerColorBackground "pointerColorBackground"
    #define XtNpointerMode		"pointerMode"
    #define XtNpointerShape		"pointerShape"
    #define XtNpopOnBell		"popOnBell"
    #define XtNprecompose		"precompose"
    #define XtNprintAttributes	"printAttributes"
    #define XtNprinterAutoClose	"printerAutoClose"
    #define XtNprinterCommand	"printerCommand"
    #define XtNprinterControlMode	"printerControlMode"
    #define XtNprinterExtent	"printerExtent"
    #define XtNprinterFormFeed	"printerFormFeed"
    #define XtNprinterNewLine	"printerNewLine"
    #define XtNprivateColorRegisters "privateColorRegisters"
    #define XtNquietGrab		"quietGrab"
    #define XtNregisDefaultFont	"regisDefaultFont"
    #define XtNregisScreenSize	"regisScreenSize"
    #define XtNrenderFont		"renderFont"
    #define XtNresizeGravity	"resizeGravity"
    #define XtNretryInputMethod	"retryInputMethod"
    #define XtNreverseWrap		"reverseWrap"
    #define XtNrightScrollBar	"rightScrollBar"
    #define XtNsaveLines		"saveLines"
    #define XtNscaleHeight		"scaleHeight"
    #define XtNscrollBar		"scrollBar"
    #define XtNscrollBarBorder	"scrollBarBorder"
    #define XtNscrollKey		"scrollKey"
    #define XtNscrollLines		"scrollLines"
    #define XtNscrollTtyOutput	"scrollTtyOutput"
    #define XtNselectToClipboard	"selectToClipboard"
    #define XtNshiftFonts		"shiftFonts"
    #define XtNshowBlinkAsBold	"showBlinkAsBold"
    #define XtNshowMissingGlyphs	"showMissingGlyphs"
    #define XtNshowWrapMarks	"showWrapMarks"
    #define XtNsignalInhibit	"signalInhibit"
    #define XtNsixelScrolling	"sixelScrolling"
    #define XtNsixelScrollsRight	"sixelScrollsRight"
    #define XtNtekGeometry		"tekGeometry"
    #define XtNtekInhibit		"tekInhibit"
    #define XtNtekSmall		"tekSmall"
    #define XtNtekStartup		"tekStartup"
    #define XtNtiXtraScroll		"tiXtraScroll"
    #define XtNtiteInhibit		"titeInhibit"
    #define XtNtitleModes		"titleModes"
    #define XtNtoolBar		"toolBar"
    #define XtNtrimSelection	"trimSelection"
    #define XtNunderLine		"underLine"
    #define XtNuseBorderClipping	"useBorderClipping"
    #define XtNuseClipping		"useClipping"
    #define XtNutf8			"utf8"
    #define XtNutf8Fonts		"utf8Fonts"
    #define XtNutf8Latin1		"utf8Latin1"
    #define XtNutf8SelectTypes	"utf8SelectTypes"
    #define XtNutf8Title		"utf8Title"
    #define XtNveryBoldColors	"veryBoldColors"
    #define XtNvisualBell		"visualBell"
    #define XtNvisualBellDelay	"visualBellDelay"
    #define XtNvisualBellLine	"visualBellLine"
    #define XtNvt100Graphics	"vt100Graphics"
    #define XtNwideBoldFont		"wideBoldFont"
    #define XtNwideChars		"wideChars"
    #define XtNwideFont		"wideFont"
    #define XtNximFont		"ximFont"
    #define XtNxmcAttributes	"xmcAttributes"	/* ncurses-testing */
    #define XtNxmcGlitch		"xmcGlitch"	/* ncurses-testing */
    #define XtNxmcInline		"xmcInline"	/* ncurses-testing */
    #define XtNxmcMoveSGR		"xmcMoveSGR"	/* ncurses-testing */
    
    #define XtCAllowBoldFonts	"AllowBoldFonts"
    #define XtCAllowC1Printable	"AllowC1Printable"
    #define XtCAllowColorOps	"AllowColorOps"
    #define XtCAllowFontOps		"AllowFontOps"
    #define XtCAllowMouseOps	"AllowMouseOps"
    #define XtCAllowPasteControls	"AllowPasteControls"
    #define XtCAllowScrollLock	"AllowScrollLock"
    #define XtCAllowSendEvents	"AllowSendEvents"
    #define XtCAllowTcapOps		"AllowTcapOps"
    #define XtCAllowTitleOps	"AllowTitleOps"
    #define XtCAllowWindowOps	"AllowWindowOps"
    #define XtCAltIsNotMeta		"AltIsNotMeta"
    #define XtCAltSendsEscape	"AltSendsEscape"
    #define XtCAlwaysBoldMode	"AlwaysBoldMode"
    #define XtCAlwaysHighlight	"AlwaysHighlight"
    #define XtCAlwaysUseMods	"AlwaysUseMods"
    #define XtCAnswerbackString	"AnswerbackString"
    #define XtCAppcursorDefault	"AppcursorDefault"
    #define XtCAppkeypadDefault	"AppkeypadDefault"
    #define XtCAssumeAllChars	"AssumeAllChars"
    #define XtCAutoWrap		"AutoWrap"
    #define XtCAwaitInput		"AwaitInput"
    #define XtCBackarrowKey		"BackarrowKey"
    #define XtCBellIsUrgent		"BellIsUrgent"
    #define XtCBellOnReset		"BellOnReset"
    #define XtCBellSuppressTime	"BellSuppressTime"
    #define XtCBoldFont		"BoldFont"
    #define XtCBoldMode		"BoldMode"
    #define XtCBrokenLinuxOSC	"BrokenLinuxOSC"
    #define XtCBrokenSelections	"BrokenSelections"
    #define XtCBrokenStringTerm	"BrokenStringTerm"
    #define XtCBuffered		"Buffered"
    #define XtCBufferedFPS		"BufferedFPS"
    #define XtCC132			"C132"
    #define XtCCacheDoublesize	"CacheDoublesize"
    #define XtCCdXtraScroll		"CdXtraScroll"
    #define XtCCharClass		"CharClass"
    #define XtCChecksumExtension	"ChecksumExtension"
    #define XtCCjkWidth		"CjkWidth"
    #define XtCColorAttrMode	"ColorAttrMode"
    #define XtCColorInnerBorder	"ColorInnerBorder"
    #define XtCColorMode		"ColorMode"
    #define XtCColumn		"Column"
    #define XtCCombiningChars	"CombiningChars"
    #define XtCCtrlFKeys		"CtrlFKeys"
    #define XtCCurses		"Curses"
    #define XtCCursorBlink		"CursorBlink"
    #define XtCCursorBlinkXOR	"CursorBlinkXOR"
    #define XtCCursorOffTime	"CursorOffTime"
    #define XtCCursorOnTime		"CursorOnTime"
    #define XtCCursorUnderLine	"CursorUnderLine"
    #define XtCCutNewline		"CutNewline"
    #define XtCCutToBeginningOfLine	"CutToBeginningOfLine"
    #define XtCDecTerminalID	"DecTerminalID"
    #define XtCDefaultString	"DefaultString"
    #define XtCDeleteIsDEL		"DeleteIsDEL"
    #define XtCDirectColor		"DirectColor"
    #define XtCDisallowedColorOps	"DisallowedColorOps"
    #define XtCDisallowedFontOps	"DisallowedFontOps"
    #define XtCDisallowedMouseOps	"DisallowedMouseOps"
    #define XtCDisallowedPasteControls "DisallowedPasteControls"
    #define XtCDisallowedTcapOps	"DisallowedTcapOps"
    #define XtCDisallowedWindowOps	"DisallowedWindowOps"
    #define XtCDynamicColors	"DynamicColors"
    #define XtCEightBitControl	"EightBitControl"
    #define XtCEightBitInput	"EightBitInput"
    #define XtCEightBitMeta		"EightBitMeta"
    #define XtCEightBitOutput	"EightBitOutput"
    #define XtCEightBitSelectTypes	"EightBitSelectTypes"
    #define XtCEraseSavedLines	"EraseSavedLines"
    #define XtCFaceName		"FaceName"
    #define XtCFaceNameDoublesize	"FaceNameDoublesize"
    #define XtCFaceSize		"FaceSize"
    #define XtCFastScroll		"FastScroll"
    #define XtCFont1		"Font1"
    #define XtCFont2		"Font2"
    #define XtCFont3		"Font3"
    #define XtCFont4		"Font4"
    #define XtCFont5		"Font5"
    #define XtCFont6		"Font6"
    #define XtCFontDoublesize	"FontDoublesize"
    #define XtCFontWarnings		"FontWarnings"
    #define XtCForceBoxChars	"ForceBoxChars"
    #define XtCForcePackedFont	"ForcePackedFont"
    #define XtCFormatOtherKeys	"FormatOtherKeys"
    #define XtCFreeBoldBox		"FreeBoldBox"
    #define XtCFullscreen		"Fullscreen"
    #define XtCHighlightColorMode	"HighlightColorMode"
    #define XtCHighlightReverse	"HighlightReverse"
    #define XtCHighlightSelection	"HighlightSelection"
    #define XtCHpLowerleftBugCompat	"HpLowerleftBugCompat"
    #define XtCI18nSelections	"I18nSelections"
    #define XtCIconHint		"IconHint"
    #define XtCInitialFont		"InitialFont"
    #define XtCJumpScroll		"JumpScroll"
    #define XtCKeepClipboard	"KeepClipboard"
    #define XtCKeepSelection	"KeepSelection"
    #define XtCKeyboardDialect	"KeyboardDialect"
    #define XtCLimitFontsets	"LimitFontsets"
    #define XtCLimitResize		"LimitResize"
    #define XtCLimitResponse	"LimitResponse"
    #define XtCLocale		"Locale"
    #define XtCLocaleFilter		"LocaleFilter"
    #define XtCLogInhibit		"LogInhibit"
    #define XtCLogfile		"Logfile"
    #define XtCLogging		"Logging"
    #define XtCLoginShell		"LoginShell"
    #define XtCMarginBell		"MarginBell"
    #define XtCMaxGraphicSize	"MaxGraphicSize"
    #define XtCMaximized		"Maximized"
    #define XtCMenuBar		"MenuBar"	/* internal */
    #define XtCMenuHeight		"MenuHeight"
    #define XtCMetaSendsEscape	"MetaSendsEscape"
    #define XtCMkSamplePass		"MkSamplePass"
    #define XtCMkSampleSize		"MkSampleSize"
    #define XtCMkWidth		"MkWidth"
    #define XtCModifyCursorKeys	"ModifyCursorKeys"
    #define XtCModifyFunctionKeys	"ModifyFunctionKeys"
    #define XtCModifyKeyboard	"ModifyKeyboard"
    #define XtCModifyKeypadKeys	"ModifyKeypadKeys"
    #define XtCModifyOtherKeys	"ModifyOtherKeys"
    #define XtCModifyStringKeys	"ModifyStringKeys"
    #define XtCMultiClickTime	"MultiClickTime"
    #define XtCMultiScroll		"MultiScroll"
    #define XtCNextEventDelay	"NextEventDelay"
    #define XtCNumColorRegisters	"NumColorRegisters"
    #define XtCNumLock		"NumLock"
    #define XtCOldXtermFKeys	"OldXtermFKeys"
    #define XtCPointerMode		"PointerMode"
    #define XtCPopOnBell		"PopOnBell"
    #define XtCPrecompose		"Precompose"
    #define XtCPrintAttributes	"PrintAttributes"
    #define XtCPrinterAutoClose	"PrinterAutoClose"
    #define XtCPrinterCommand	"PrinterCommand"
    #define XtCPrinterControlMode	"PrinterControlMode"
    #define XtCPrinterExtent	"PrinterExtent"
    #define XtCPrinterFormFeed	"PrinterFormFeed"
    #define XtCPrinterNewLine	"PrinterNewLine"
    #define XtCPrivateColorRegisters "PrivateColorRegisters"
    #define XtCQuietGrab		"QuietGrab"
    #define XtCRegisDefaultFont	"RegisDefaultFont"
    #define XtCRegisScreenSize	"RegisScreenSize"
    #define XtCRenderFont		"RenderFont"
    #define XtCResizeGravity	"ResizeGravity"
    #define XtCRetryInputMethod	"RetryInputMethod"
    #define XtCReverseWrap		"ReverseWrap"
    #define XtCRightScrollBar	"RightScrollBar"
    #define XtCSaveLines		"SaveLines"
    #define XtCScaleHeight		"ScaleHeight"
    #define XtCScrollBar		"ScrollBar"
    #define XtCScrollBarBorder	"ScrollBarBorder"
    #define XtCScrollCond		"ScrollCond"
    #define XtCScrollLines		"ScrollLines"
    #define XtCSelectToClipboard	"SelectToClipboard"
    #define XtCShiftFonts		"ShiftFonts"
    #define XtCShowBlinkAsBold	"ShowBlinkAsBold"
    #define XtCShowMissingGlyphs	"ShowMissingGlyphs"
    #define XtCShowWrapMarks	"ShowWrapMarks"
    #define XtCSignalInhibit	"SignalInhibit"
    #define XtCSixelScrolling	"SixelScrolling"
    #define XtCSixelScrollsRight	"SixelScrollsRight"
    #define XtCTekInhibit		"TekInhibit"
    #define XtCTekSmall		"TekSmall"
    #define XtCTekStartup		"TekStartup"
    #define XtCTiXtraScroll		"TiXtraScroll"
    #define XtCTiteInhibit		"TiteInhibit"
    #define XtCTitleModes		"TitleModes"
    #define XtCToolBar		"ToolBar"
    #define XtCTrimSelection	"TrimSelection"
    #define XtCUnderLine		"UnderLine"
    #define XtCUseBorderClipping	"UseBorderClipping"
    #define XtCUseClipping		"UseClipping"
    #define XtCUtf8			"Utf8"
    #define XtCUtf8Fonts		"Utf8Fonts"
    #define XtCUtf8Latin1		"Utf8Latin1"
    #define XtCUtf8SelectTypes	"Utf8SelectTypes"
    #define XtCUtf8Title		"Utf8Title"
    #define XtCVT100Graphics	"VT100Graphics"
    #define XtCVeryBoldColors	"VeryBoldColors"
    #define XtCVisualBell		"VisualBell"
    #define XtCVisualBellDelay	"VisualBellDelay"
    #define XtCVisualBellLine	"VisualBellLine"
    #define XtCWideBoldFont		"WideBoldFont"
    #define XtCWideChars		"WideChars"
    #define XtCWideFont		"WideFont"
    #define XtCXimFont		"XimFont"
    #define XtCXmcAttributes	"XmcAttributes"	/* ncurses-testing */
    #define XtCXmcGlitch		"XmcGlitch"	/* ncurses-testing */
    #define XtCXmcInline		"XmcInline"	/* ncurses-testing */
    #define XtCXmcMoveSGR		"XmcMoveSGR"	/* ncurses-testing */
    
    #if defined(NO_ACTIVE_ICON) && !defined(XtNgeometry)
    #define XtNgeometry		"geometry"
    #define XtCGeometry		"Geometry"
    #endif
    
    #if OPT_COLOR_CLASS
    #define XtCCursorColor		"CursorColor"
    #define XtCPointerColor		"PointerColor"
    #define XtCHighlightColor	"HighlightColor"
    #define XtCHighlightTextColor	"HighlightTextColor"
    #else
    #define XtCCursorColor		XtCForeground
    #define XtCPointerColor		XtCForeground
    #define XtCHighlightColor	XtCForeground
    #define XtCHighlightTextColor	XtCBackground
    #endif
    
    /***====================================================================***/
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    struct XTERM_RESOURCE;
    
    /* Tekproc.c */
    #if OPT_TEK4014
    extern TekWidget getTekWidget(Widget /* w */);
    extern int TekGetFontSize (const char * /* param */);
    extern int TekInit (void);
    extern void ChangeTekColors (TekWidget /* tw */, TScreen * /* screen */, ScrnColors * /* pNew */);
    extern void HandleGINInput             PROTO_XT_ACTIONS_ARGS;
    extern void TCursorToggle (TekWidget /* tw */, int /* toggle */);
    extern void TekCopy (TekWidget /* tw */);
    extern void TekEnqMouse (TekWidget /* tw */, int /* c */);
    extern void TekExpose (Widget  /* w */, XEvent * /* event */, Region  /* region */);
    extern void TekGINoff (TekWidget /* tw */);
    extern void TekRefresh (TekWidget /* tw */);
    extern void TekRepaint (TekWidget /* xw */);
    extern void TekReverseVideo (XtermWidget /* xw */, TekWidget /* tw */);
    extern void TekRun (void);
    extern void TekSetFontSize (TekWidget /* tw */, Bool /* fromMenu */, int  /* newitem */);
    extern void TekSetWinSize (TekWidget /* tw */);
    extern void TekSimulatePageButton (TekWidget /* tw */, Bool /* reset */);
    #endif
    
    /* button.c */
    #define	MotionOff( s, t ) if (!(screen->hide_pointer)) {		\
    	    (s)->event_mask |= ButtonMotionMask;			\
    	    (s)->event_mask &= ~PointerMotionMask;			\
    	    XSelectInput(XtDisplay((t)), XtWindow((t)), (long) (s)->event_mask); }
    
    #define	MotionOn( s, t ) {						\
    	    (s)->event_mask &= ~ButtonMotionMask;			\
    	    (s)->event_mask |= PointerMotionMask;			\
    	    XSelectInput(XtDisplay((t)), XtWindow((t)), (long) (s)->event_mask); }
    
    extern Bool SendMousePosition (XtermWidget  /* w */, XEvent*  /* event */);
    extern XtermMouseModes okSendMousePos(XtermWidget /* xw */);
    extern void DiredButton                PROTO_XT_ACTIONS_ARGS;
    extern void DisownSelection (XtermWidget  /* xw */);
    extern void UnhiliteSelection (XtermWidget  /* xw */);
    extern void HandleCopySelection        PROTO_XT_ACTIONS_ARGS;
    extern void HandleInsertSelection      PROTO_XT_ACTIONS_ARGS;
    extern void HandleKeyboardSelectEnd    PROTO_XT_ACTIONS_ARGS;
    extern void HandleKeyboardSelectExtend PROTO_XT_ACTIONS_ARGS;
    extern void HandleKeyboardSelectStart  PROTO_XT_ACTIONS_ARGS;
    extern void HandleKeyboardStartExtend  PROTO_XT_ACTIONS_ARGS;
    extern void HandleSelectEnd            PROTO_XT_ACTIONS_ARGS;
    extern void HandleSelectExtend         PROTO_XT_ACTIONS_ARGS;
    extern void HandleSelectSet            PROTO_XT_ACTIONS_ARGS;
    extern void HandleSelectStart          PROTO_XT_ACTIONS_ARGS;
    extern void HandleStartExtend          PROTO_XT_ACTIONS_ARGS;
    extern void ResizeSelection (TScreen * /* screen */, int  /* rows */, int  /* cols */);
    extern void ScrollSelection (TScreen * /* screen */, int  /* amount */,  Bool /* always */);
    extern void TrackMouse (XtermWidget /* xw */, int /* func */, CELL * /* start */, int /* firstrow */, int /* lastrow */);
    extern void ViButton                   PROTO_XT_ACTIONS_ARGS;
    
    extern int xtermUtf8ToTextList(XtermWidget /* xw */, XTextProperty * /* text_prop */, char *** /* text_list */, int * /* text_list_count */);
    
    #if OPT_DEC_LOCATOR
    extern void GetLocatorPosition (XtermWidget  /* w */);
    extern void InitLocatorFilter (XtermWidget  /* w */);
    #endif	/* OPT_DEC_LOCATOR */
    
    #if OPT_FOCUS_EVENT
    extern void SendFocusButton(XtermWidget /* xw */, XFocusChangeEvent * /* event */);
    #else
    #define SendFocusBotton(xw, event) /* nothing */
    #endif
    
    #if OPT_PASTE64
    extern void AppendToSelectionBuffer (TScreen * /* screen */, unsigned  /* c */, String /* selection */);
    extern void ClearSelectionBuffer (TScreen * /* screen */, String /* selection */);
    extern void CompleteSelection (XtermWidget  /* xw */, String * /* args */, Cardinal  /* len */);
    extern void xtermGetSelection (Widget  /* w */, Time  /* ev_time */, String * /* params */, Cardinal  /* num_params */, Atom * /* targets */);
    #endif
    
    #if OPT_READLINE
    extern void ReadLineButton             PROTO_XT_ACTIONS_ARGS;
    #endif
    
    #if OPT_REPORT_CCLASS
    extern void report_char_class(XtermWidget);
    #endif
    
    #define IsLatin1(n)  (((n) >= 32 && (n) <= 126) || ((n) >= 160 && (n) <= 255))
    
    #if OPT_WIDE_CHARS
    #define WideCells(n) (((IChar)(n) >= first_widechar) ? my_wcwidth((wchar_t) (n)) : 1)
    #define isWideFrg(n) (((n) == HIDDEN_CHAR) || (WideCells((n)) == 2))
    #define isWide(n)    (((IChar)(n) >= first_widechar) && isWideFrg(n))
    #define CharWidth(n) (((n) < 256) ? (IsLatin1(n) ? 1 : 0) : my_wcwidth((wchar_t) (n)))
    #else
    #define WideCells(n) 1
    #define CharWidth(n) (IsLatin1(n) ? 1 : 0)
    #endif
    
    /* cachedCgs.c */
    extern CgsEnum getCgsId(XtermWidget /*xw*/, VTwin * /*cgsWin*/, GC /*gc*/);
    extern GC freeCgs(XtermWidget /*xw*/, VTwin * /*cgsWin*/, CgsEnum /*cgsId*/);
    extern GC getCgsGC(XtermWidget /*xw*/, VTwin * /*cgsWin*/, CgsEnum /*cgsId*/);
    extern Pixel getCgsBack(XtermWidget /*xw*/, VTwin * /*cgsWin*/, GC /*gc*/);
    extern Pixel getCgsFore(XtermWidget /*xw*/, VTwin * /*cgsWin*/, GC /*gc*/);
    extern XTermFonts * getCgsFont(XtermWidget /*xw*/, VTwin * /*cgsWin*/, GC /*gc*/);
    extern void clrCgsFonts(XtermWidget /*xw*/, VTwin * /*cgsWin*/, XTermFonts * /*font*/);
    extern void copyCgs(XtermWidget /*xw*/, VTwin * /*cgsWin*/, CgsEnum /*dstCgsId*/, CgsEnum /*srcCgsId*/);
    extern void redoCgs(XtermWidget /*xw*/, Pixel /*fg*/, Pixel /*bg*/, CgsEnum /*cgsId*/);
    extern void setCgsBack(XtermWidget /*xw*/, VTwin * /*cgsWin*/, CgsEnum /*cgsId*/, Pixel /*bg*/);
    extern void setCgsCSet(XtermWidget /*xw*/, VTwin * /*cgsWin*/, CgsEnum /*cgsId*/, unsigned /*cset*/);
    extern void setCgsFont(XtermWidget /*xw*/, VTwin * /*cgsWin*/, CgsEnum /*cgsId*/, XTermFonts * /*font*/);
    extern void setCgsFont2(XtermWidget /*xw*/, VTwin * /*cgsWin*/, CgsEnum /*cgsId*/, XTermFonts * /*font*/, unsigned /*which*/);
    extern void setCgsFore(XtermWidget /*xw*/, VTwin * /*cgsWin*/, CgsEnum /*cgsId*/, Pixel /*fg*/);
    extern void swapCgs(XtermWidget /*xw*/, VTwin * /*cgsWin*/, CgsEnum /*dstCgsId*/, CgsEnum /*srcCgsId*/);
    
    #ifdef NO_LEAKS
    extern void noleaks_cachedCgs (XtermWidget /* xw */);
    #endif
    
    /* charproc.c */
    extern Bool CheckBufPtrs (TScreen * /* screen */);
    extern Bool set_cursor_gcs (XtermWidget /* xw */);
    extern char * vt100ResourceToString (XtermWidget /* xw */, const char * /* name */);
    extern int VTInit (XtermWidget /* xw */);
    extern void FindFontSelection (XtermWidget /* xw */, const char * /* atom_name */, Bool  /* justprobe */);
    extern void HideCursor (void);
    extern void RestartBlinking(XtermWidget /* xw */);
    extern void ShowCursor (void);
    extern void SwitchBufPtrs (TScreen * /* screen */, int /* toBuf */);
    extern void ToggleAlternate (XtermWidget /* xw */);
    extern void VTInitTranslations (void);
    extern void VTReset (XtermWidget /* xw */, int /* full */, int /* saved */) GCC_NORETURN;
    extern void VTRun (XtermWidget /* xw */);
    extern void dotext (XtermWidget /* xw */, DECNRCM_codes /* charset */, IChar * /* buf */, Cardinal  /* len */);
    extern void getKeymapResources(Widget /* w */, const char * /*mapName */, const char * /* mapClass */, const char * /* type */, void * /* result */, size_t /* size */);
    extern void initBorderGC (XtermWidget /* xw */, VTwin * /* win */);
    extern void lookupSelectUnit(XtermWidget /* xw */, Cardinal /* item */, String /* value */);
    extern void releaseCursorGCs(XtermWidget /*xw*/);
    extern void releaseWindowGCs(XtermWidget /*xw*/, VTwin * /*win*/);
    extern void resetCharsets (TScreen * /* screen */);
    extern void resetMargins (XtermWidget /* xw */);
    extern void restoreCharsets (TScreen * /* screen */, DECNRCM_codes * /* source */);
    extern void saveCharsets (TScreen * /* screen */, DECNRCM_codes * /* target */);
    extern void set_max_col(TScreen *  /* screen */, int  /* cols */);
    extern void set_max_row(TScreen *  /* screen */, int  /* rows */);
    extern void unparse_end (XtermWidget /* xw */);
    extern void unparseputc (XtermWidget /* xw */, int  /* c */);
    extern void unparseputc1 (XtermWidget /* xw */, int  /* c */);
    extern void unparseputn (XtermWidget /* xw */, unsigned /* n */);
    extern void unparseputs (XtermWidget /* xw */, const char * /* s */);
    extern void unparseseq (XtermWidget /* xw */, ANSI * /* ap */);
    extern void v_write (int  /* f */, const Char * /* d */, unsigned  /* len */);
    extern void xtermAddInput (Widget  /* w */);
    extern void xtermDecodeSCS (XtermWidget /* xw */, int /* which */, int /* prefix */, int /* suffix */);
    
    #if OPT_BLINK_CURS
    extern void ToggleCursorBlink(XtermWidget /* xw */);
    #endif
    
    #if OPT_BLINK_TEXT
    extern Bool LineHasBlinking(TScreen * /* screen */, CLineData * /* ld */);
    #endif
    
    #if OPT_INPUT_METHOD
    extern TInput *lookupTInput (XtermWidget /* xw */, Widget /* w */);
    #endif
    
    #if OPT_ISO_COLORS
    extern void SGR_Background (XtermWidget /* xw */, int  /* color */);
    extern void SGR_Foreground (XtermWidget /* xw */, int  /* color */);
    extern void setExtendedColors (XtermWidget /* xw */);
    #endif
    
    #ifdef NO_LEAKS
    extern void noleaks_charproc (void);
    #endif
    
    /* charsets.c */
    extern unsigned xtermCharSetIn (XtermWidget /* xw */, unsigned  /* code */, DECNRCM_codes /* charset */);
    extern int xtermCharSetOut (XtermWidget /* xw */, IChar * /* buf */, IChar * /* ptr */, DECNRCM_codes /* charset */);
    
    /* cursor.c */
    extern int CursorCol (XtermWidget /* xw */);
    extern int CursorRow (XtermWidget /* xw */);
    extern void AdjustSavedCursor (XtermWidget /* xw */, int /* adjust */);
    extern void CarriageReturn (XtermWidget /* xw */);
    extern void CursorBack (XtermWidget /* xw */, int /* n */);
    extern void CursorDown (TScreen * /* screen */, int /* n */);
    extern void CursorForward (XtermWidget /* xw */, int /* n */);
    extern void CursorNextLine (XtermWidget /* xw */, int /* count */);
    extern void CursorPrevLine (XtermWidget /* xw */, int /* count */);
    extern void CursorRestore (XtermWidget  /* xw */);
    extern void CursorSave (XtermWidget  /* xw */);
    extern void CursorSet (TScreen * /* screen */, int  /* row */, int  /* col */, unsigned  /* flags */);
    extern void CursorUp (TScreen * /* screen */, int   /* n */);
    extern void RevIndex (XtermWidget /* xw */, int  /* amount */);
    extern void xtermIndex (XtermWidget /* xw */, int  /* amount */);
    
    #if OPT_TRACE
    extern int set_cur_col(TScreen * /* screen */, int  /* value */);
    extern int set_cur_row(TScreen * /* screen */, int  /* value */);
    #else
    #define set_cur_col(screen, value) screen->cur_col = value
    #define set_cur_row(screen, value) screen->cur_row = value
    #endif
    
    /* doublechr.c */
    extern void xterm_DECDHL (XtermWidget /* xw */, Bool  /* top */);
    extern void xterm_DECSWL (XtermWidget /* xw */);
    extern void xterm_DECDWL (XtermWidget /* xw */);
    extern void xterm_ResetDouble(XtermWidget /* xw */);
    #if OPT_DEC_CHRSET
    extern GC xterm_DoubleGC(XTermDraw * /* params */, GC /* old_gc */, int * /* inxp */);
    #if OPT_RENDERFONT
    extern XftFont * xterm_DoubleFT(XTermDraw * /* params */, unsigned /* chrset */, unsigned /* attr_flags */);
    extern void freeall_DoubleFT(XtermWidget /* xw */);
    #endif
    #endif
    
    /* input.c */
    extern unsigned xtermParamToState (XtermWidget /* xw */, unsigned /* param */);
    extern unsigned xtermStateToParam (XtermWidget /* xw */, unsigned /* state */);
    extern Bool xtermDeleteIsDEL (XtermWidget /* xw */);
    extern void Input (XtermWidget /* xw */, XKeyEvent */* event */, Bool /* eightbit */);
    extern void StringInput (XtermWidget /* xw */, const Char * /* string */, size_t  /* nbytes */);
    
    #if OPT_NUM_LOCK
    extern void VTInitModifiers(XtermWidget /* xw */);
    #else
    #define VTInitModifiers(xw) /* nothing */
    #endif
    
    /* linedata.c */
    extern LineData *getLineData(TScreen * /* screen */, int /* row */);
    extern void copyLineData(LineData * /* dst */, CLineData * /* src */);
    extern void initLineData(XtermWidget /* xw */);
    
    extern CellData *newCellData(XtermWidget /* xw */, Cardinal /* count */);
    extern void saveCellData(TScreen * /* screen */, CellData * /* data */, Cardinal /* cell */, CLineData * /* ld */, XTermRect * /* limits */, int /* column */);
    extern void restoreCellData(TScreen * /* screen */, const CellData * /* data */, Cardinal /* cell */, LineData * /* ld */, XTermRect * /* limits */, int /* column */);
    
    /* main.c */
    #define ENVP_ARG /**/
    
    extern int main (int  /* argc */, char ** /* argv */ ENVP_ARG);
    extern int GetBytesAvailable (int  /* fd */);
    extern int kill_process_group (int  /* pid */, int  /* sig */);
    extern int nonblocking_wait (void);
    
    #if OPT_PTY_HANDSHAKE
    extern void first_map_occurred (void);
    #else
    #define first_map_occurred() /* nothing */
    #endif
    
    extern void Exit (int /* n */) GCC_NORETURN;
    
    #ifndef SIG_ATOMIC_T
    #define SIG_ATOMIC_T int
    #endif
    
    #if OPT_WIDE_CHARS
    extern unsigned first_widechar;
    extern int (*my_wcwidth)(wchar_t);
    #endif
    
    /* menu.c */
    extern void do_hangup          PROTO_XT_CALLBACK_ARGS;
    extern void repairSizeHints    (void);
    extern void show_8bit_control  (Bool /* value */);
    
    /* misc.c */
    
    #define TIMESTAMP_LEN 20	/* length of TIMESTAMP_FMT */
    
    extern Bool AllocateTermColor(XtermWidget, ScrnColors *, int, const char *, Bool);
    extern Boolean allocateBestRGB(XtermWidget /* xw */, XColor * /* def */);
    extern Boolean validProgram(const char * /* pathname */);
    extern Boolean xtermGetWinAttrs(Display * /* dpy */, Window /* win */, XWindowAttributes * /* attrs */);
    extern Boolean xtermGetWinProp(Display * /* dpy */, Window /* win */, Atom /* property */, long /* long_offset */, long /* long_length */, Atom /* req_type */, Atom * /* actual_type_return */, int * /* actual_format_return */, unsigned long * /* nitems_return */, unsigned long * /* bytes_after_return */, unsigned char ** /* prop_return */);
    extern Boolean xtermIsIconified (XtermWidget /* xw */);
    extern Cursor make_colored_cursor (unsigned /* cursorindex */, unsigned long /* fg */, unsigned long /* bg */);
    extern FILE * create_printfile(XtermWidget /* xw */, const char * /* suffix */);
    extern OptionHelp * sortedOpts(OptionHelp *, XrmOptionDescRec *, Cardinal);
    extern String xtermEnvLocale (void);
    extern Widget xtermOpenApplication (XtAppContext * /* app_context_return */, String /* application_class */, XrmOptionDescRec */* options */, Cardinal /* num_options */, int * /* argc_in_out */, char **/* argv_in_out */, String * /* fallback_resources */, WidgetClass /* widget_class */, ArgList /* args */, Cardinal /* num_args */);
    extern Window WMFrameWindow (XtermWidget /* xw */);
    extern XtInputMask xtermAppPending (void);
    extern XrmOptionDescRec * sortedOptDescs (XrmOptionDescRec *, Cardinal);
    extern XtermWidget getXtermWidget (Widget /* w */);
    extern char *udk_lookup (XtermWidget /* xw */, int /* keycode */, int * /* len */);
    extern char *xtermEnvEncoding (void);
    extern char *xtermFindShell (char * /* leaf */, Bool /* warning */);
    extern char *xtermFormatSGR (XtermWidget /* xw */, char * /* target */, unsigned /* attrs */, int /* fg */, int /* bg */);
    extern const char *SysErrorMsg (int /* n */);
    extern const char *SysReasonMsg (int /* n */);
    extern int ResetAnsiColorRequest (XtermWidget, char *, int);
    extern int XStrCmp (char * /* s1 */, char * /* s2 */);
    extern int creat_as (uid_t /* uid */, gid_t /* gid */, Bool /* append */, char * /* pathname */, unsigned /* mode */);
    extern int getVisualDepth (XtermWidget /* xw */);
    extern int getVisualInfo (XtermWidget /* xw */);
    extern int open_userfile (uid_t /* uid */, gid_t /* gid */, char * /* path */, Bool /* append */);
    extern int xerror (Display * /* d */, XErrorEvent * /* ev */);
    extern int xioerror (Display * /* dpy */);
    extern int xtermClosestColor (XtermWidget /* xw */, int /* red */, int /* green */, int /* blue */);
    extern int xtermResetIds (TScreen * /* screen */);
    extern void Bell (XtermWidget /* xw */, int /* which */, int /* percent */);
    extern void ChangeGroup(XtermWidget /* xw */, const char * /* attribute */, char * /* value */);
    extern void ChangeIconName (XtermWidget /* xw */, char * /* name */);
    extern void ChangeTitle (XtermWidget /* xw */, char * /* name */);
    extern void ChangeXprop (char * /* name */);
    extern void Cleanup (int /* code */) GCC_NORETURN;
    extern void HandleBellPropertyChange   PROTO_XT_EV_HANDLER_ARGS;
    extern void HandleEightBitKeyPressed   PROTO_XT_ACTIONS_ARGS;
    extern void HandleEnterWindow          PROTO_XT_EV_HANDLER_ARGS;
    extern void HandleFocusChange          PROTO_XT_EV_HANDLER_ARGS;
    extern void HandleInterpret            PROTO_XT_ACTIONS_ARGS;
    extern void HandleKeyPressed           PROTO_XT_ACTIONS_ARGS;
    extern void HandleLeaveWindow          PROTO_XT_EV_HANDLER_ARGS;
    extern void HandleSpawnTerminal        PROTO_XT_ACTIONS_ARGS;
    extern void HandleStringEvent          PROTO_XT_ACTIONS_ARGS;
    extern void NormalExit (void);
    extern void Panic (const char * /* s */, int /* a */);
    extern void Redraw (void);
    extern void ReverseOldColors (XtermWidget /* xw */);
    extern void SysError (int /* i */) GCC_NORETURN;
    extern void VisualBell (void);
    extern void cleanup_colored_cursor (void);
    extern void do_ansi_rqm (XtermWidget /* xw */, int /* nparam */, int * /* params */);
    extern void do_dcs (XtermWidget /* xw */, Char * /* buf */, size_t /* len */);
    extern void do_dec_rqm (XtermWidget /* xw */, int /* nparam */, int * /* params */);
    extern void do_osc (XtermWidget /* xw */, Char * /* buf */, size_t /* len */, int /* final */);
    extern void do_xevents (XtermWidget /* xw */);
    extern void end_tek_mode (void);
    extern void end_vt_mode (void);
    extern void free_string(String value);
    extern void hide_tek_window (void);
    extern void hide_vt_window (void);
    extern void ice_error (IceConn /* iceConn */);
    extern void init_colored_cursor (Display * /* dpy */);
    extern void reset_decudk (XtermWidget /* xw */);
    extern void set_tek_visibility (Bool /* on */);
    extern void set_vt_visibility (Bool /* on */);
    extern void switch_modes (Bool /* tovt */);
    extern void timestamp_filename(char * /* dst */, const char * /* src */);
    extern void update_winsize(int /* fd */, int /* rows */, int /* cols */, int /* height */, int /* width */);
    extern void xevents (XtermWidget /* xw */);
    extern void xt_error (String /* message */) GCC_NORETURN;
    extern void xtermBell(XtermWidget /* xw */, int /* which */, int /* percent */);
    extern void xtermCopyEnv (char ** /* oldenv */);
    extern void xtermDisplayCursor (XtermWidget /* xw */);
    extern void xtermDeiconify (XtermWidget /* xw */);
    extern void xtermEmbedWindow (Window /* winToEmbedInfo */);
    extern void xtermIconify (XtermWidget /* xw */);
    extern void xtermLoadIcon (XtermWidget /* xw */, const char * /* icon_hint */);
    extern void xtermPerror (const char * /*fmt*/,...) GCC_PRINTFLIKE(1,2);
    extern void xtermSetenv (const char * /* var */, const char * /* value */);
    extern void xtermSetWinSize (XtermWidget /* xw */);
    extern void xtermShowPointer (XtermWidget /* xw */, Bool /* enable */);
    extern void xtermUnsetenv (const char * /* var */);
    extern void xtermWarning (const char * /*fmt*/,...) GCC_PRINTFLIKE(1,2);
    
    #if OPT_DABBREV
    extern void HandleDabbrevExpand        PROTO_XT_ACTIONS_ARGS;
    #endif
    
    #if OPT_DIRECT_COLOR
    extern int getDirectColor(XtermWidget /* xw */, int /* red */, int /* green */, int /* blue */);
    #endif /* OPT_DIRECT_COLOR */
    
    #if USE_DOUBLE_BUFFER
    extern void xtermFlushDbe(XtermWidget /* xw */);
    extern void xtermTimedDbe(XtermWidget /* xw */);
    #define xtermNeedSwap(xw,why)	TScreenOf(xw)->needSwap |= (why)
    #else
    #define xtermFlushDbe(xw)	/* nothing */
    #define xtermTimedDbe(xw)	/* nothing */
    #define xtermNeedSwap(xw,why)	/* nothing */
    #endif /* USE_DOUBLE_BUFFER */
    
    #if OPT_EXEC_XTERM
    extern char *ProcGetCWD(pid_t /* pid */);
    #else
    #define ProcGetCWD(pid) NULL
    #endif
    
    #if OPT_MAXIMIZE
    extern int QueryMaximize (XtermWidget  /* xw */, unsigned * /* width */, unsigned * /* height */);
    extern void HandleDeIconify            PROTO_XT_ACTIONS_ARGS;
    extern void HandleIconify              PROTO_XT_ACTIONS_ARGS;
    extern void HandleMaximize             PROTO_XT_ACTIONS_ARGS;
    extern void HandleRestoreSize          PROTO_XT_ACTIONS_ARGS;
    extern void RequestMaximize (XtermWidget  /* xw */, int  /* maximize */);
    #endif
    
    #if OPT_REPORT_ICONS
    extern void report_icons(const char *fmt,...) GCC_PRINTFLIKE(1,2);
    #define ReportIcons(params)	report_icons params
    #else
    #define ReportIcons(params)	TRACE(params)
    #endif
    
    #if OPT_SCROLL_LOCK
    extern void GetScrollLock (TScreen * /* screen */);
    extern void HandleScrollLock           PROTO_XT_ACTIONS_ARGS;
    extern void ShowScrollLock (TScreen * /* screen */, Bool /* enable */);
    extern void SetScrollLock (TScreen * /* screen */, Bool /* enable */);
    extern void xtermShowLED (TScreen * /* screen */, Cardinal /* led_number */, Bool /* enable */);
    extern void xtermClearLEDs (TScreen * /* screen */);
    #else
    #define ShowScrollLock(screen, enable) /* nothing */
    #define SetScrollLock(screen, enable) /* nothing */
    #define GetScrollLock(screen) /* nothing */
    #endif
    
    #if OPT_SELECTION_OPS
    extern void HandleExecFormatted        PROTO_XT_ACTIONS_ARGS;
    extern void HandleExecSelectable       PROTO_XT_ACTIONS_ARGS;
    extern void HandleInsertFormatted      PROTO_XT_ACTIONS_ARGS;
    extern void HandleInsertSelectable     PROTO_XT_ACTIONS_ARGS;
    #endif
    
    #if OPT_SESSION_MGT
    extern void xtermCloseSession (void);
    extern void xtermOpenSession (void);
    #else
    #define xtermCloseSession() /* nothing */
    #define xtermOpenSession() /* nothing */
    #endif
    
    #if OPT_WIDE_CHARS
    extern Bool xtermEnvUTF8(void);
    #else
    #define xtermEnvUTF8() False
    #endif
    
    #if OPT_XTERM_SGR
    extern void xtermPushSGR (XtermWidget /* xw */, int /* value */);
    extern void xtermReportSGR (XtermWidget /* xw */, XTermRect * /* value */);
    extern void xtermPopSGR (XtermWidget /* xw */);
    #endif
    
    #ifdef ALLOWLOGGING
    extern void StartLog (XtermWidget /* xw */);
    extern void CloseLog (XtermWidget /* xw */);
    extern void FlushLog (XtermWidget /* xw */);
    #else
    #define FlushLog(xw) /*nothing*/
    #endif
    
    /* print.c */
    extern Bool xtermHasPrinter (XtermWidget /* xw */);
    extern PrinterFlags *getPrinterFlags (XtermWidget /* xw */, String * /* params */, Cardinal * /* param_count */);
    extern int xtermPrinterControl (XtermWidget /* xw */, int /* chr */);
    extern void setPrinterControlMode (XtermWidget /* xw */, int /* mode */);
    extern void xtermAutoPrint (XtermWidget /* xw */, unsigned /* chr */);
    extern void xtermMediaControl (XtermWidget /* xw */, int  /* param */, int  /* private_seq */);
    extern void xtermPrintScreen (XtermWidget /* xw */, Bool  /* use_DECPEX */, PrinterFlags * /* p */);
    extern void xtermPrintEverything (XtermWidget /* xw */, PrinterFlags * /* p */);
    extern void xtermPrintImmediately (XtermWidget /* xw */, String /* filename */, int /* opts */, int /* attributes */);
    extern void xtermPrintOnXError (XtermWidget /* xw */, int /* n */);
    
    #if OPT_SCREEN_DUMPS
    /* html.c */
    extern void xtermDumpHtml (XtermWidget /* xw */);
    extern char *PixelToCSSColor(XtermWidget /* xw */, Pixel /* p */);
    /* svg.c */
    extern void xtermDumpSvg (XtermWidget /* xw */);
    #endif
    
    /* ptydata.c */
    #ifdef VMS
    #define PtySelect int
    #else
    #define PtySelect fd_set
    #endif
    
    extern Bool decodeUtf8 (TScreen * /* screen */, PtyData * /* data */);
    extern int readPtyData (XtermWidget /* xw */, PtySelect * /* select_mask */, PtyData * /* data */);
    extern void fillPtyData (XtermWidget /* xw */, PtyData * /* data */, const char * /* value */, int  /* length */);
    extern void initPtyData (PtyData ** /* data */);
    extern void trimPtyData (XtermWidget /* xw */, PtyData * /* data */);
    
    #ifdef NO_LEAKS
    extern void noleaks_ptydata ( void );
    #endif
    
    #if OPT_WIDE_CHARS
    extern Boolean isValidUTF8 (Char * /* lp */);
    extern Char *convertToUTF8 (Char * /* lp */, unsigned  /* c */);
    extern Char *convertFromUTF8 (Char * /* lp */, unsigned * /* cp */);
    extern IChar nextPtyData (TScreen * /* screen */, PtyData * /* data */);
    extern PtyData * fakePtyData (PtyData * /* result */, Char * /* next */, Char * /* last */);
    extern void switchPtyData (TScreen * /* screen */, int  /* f */);
    extern void writePtyData (int  /* f */, IChar * /* d */, unsigned  /* len */);
    
    #define morePtyData(screen, data) \
    	(((data)->last > (data)->next) \
    	 ? (((screen)->utf8_inparse && !(data)->utf_size) \
    	    ? decodeUtf8(screen, data) \
    	    : True) \
    	 : False)
    
    #define skipPtyData(data, result) \
    	do { \
    	    result = (data)->utf_data; \
    	    (data)->next += (data)->utf_size; \
    	    (data)->utf_size = 0; \
    	} while (0)
    #else
    #define morePtyData(screen, data) ((data)->last > (data)->next)
    #define nextPtyData(screen, data) (IChar) (*((data)->next++) & \
    					   (screen->output_eight_bits \
    					    ? 0xff \
    					    : 0x7f))
    #define writePtyData(f,d,len) v_write(f,d,len)
    #endif
    
    /* screen.c */
    
    /*
     * See http://standards.freedesktop.org/wm-spec/wm-spec-latest.html
     */
    #define _NET_WM_STATE_REMOVE	0	/* remove/unset property */
    #define _NET_WM_STATE_ADD	1	/* add/set property */
    #define _NET_WM_STATE_TOGGLE	2	/* toggle property */
    
    extern Bool non_blank_line (TScreen */* screen */, int  /* row */, int  /* col */, int  /* len */);
    extern Char * allocScrnData (TScreen * /* screen */, unsigned /* nrow */, unsigned /* ncol */);
    extern ScrnBuf allocScrnBuf (XtermWidget /* xw */, unsigned  /* nrow */, unsigned  /* ncol */, ScrnPtr * /* addr */);
    extern ScrnBuf scrnHeadAddr (TScreen * /* screen */, ScrnBuf /* base */, unsigned /* offset */);
    extern int ScreenResize (XtermWidget /* xw */, int  /* width */, int  /* height */, unsigned * /* flags */);
    extern size_t ScrnPointers (TScreen * /* screen */, size_t  /* len */);
    extern void ClearBufRows (XtermWidget /* xw */, int  /* first */, int  /* last */);
    extern void ClearCells (XtermWidget /* xw */, int /* flags */, unsigned /* len */, int /* row */, int /* col */);
    extern void CopyCells (TScreen * /* screen */, LineData * /* src */, LineData * /* dst */, int /* col */, int /* len */, Bool /* down */);
    extern void FullScreen (XtermWidget /* xw */, int /* mode */);
    extern void ScrnAllocBuf (XtermWidget /* xw */);
    extern void ScrnClearCells (XtermWidget /* xw */, int /* row */, int /* col */, unsigned /* len */);
    extern void ScrnDeleteChar (XtermWidget /* xw */, unsigned  /* n */);
    extern void ScrnDeleteCol (XtermWidget /* xw */, unsigned  /* n */);
    extern void ScrnDeleteLine (XtermWidget /* xw */, ScrnBuf  /* sb */, int  /* n */, int  /* last */, unsigned /* where */);
    extern void ScrnDisownSelection (XtermWidget /* xw */);
    extern void ScrnFillRectangle (XtermWidget /* xw */, XTermRect *,  int ,  unsigned /* flags */, Bool /* keepColors */);
    extern void ScrnInsertChar (XtermWidget /* xw */, unsigned  /* n */);
    extern void ScrnInsertCol (XtermWidget /* xw */, unsigned  /* n */);
    extern void ScrnInsertLine (XtermWidget /* xw */, ScrnBuf /* sb */, int  /* last */, int  /* where */, unsigned  /* n */);
    extern void ScrnRefresh (XtermWidget /* xw */, int  /* toprow */, int  /* leftcol */, int  /* nrows */, int  /* ncols */, Bool  /* force */);
    extern void ScrnUpdate (XtermWidget /* xw */, int  /* toprow */, int  /* leftcol */, int  /* nrows */, int  /* ncols */, Bool  /* force */);
    extern void ScrnWriteText (XtermWidget /* xw */, IChar * /* str */, unsigned  /* flags */, CellColor /* cur_fg_bg */, unsigned  /* length */);
    extern void ShowWrapMarks (XtermWidget /* xw */, int /* row */, CLineData * /* ld */);
    extern void setupLineData (TScreen * /* screen */, ScrnBuf /* base */, Char * /* data */, unsigned /* nrow */, unsigned /* ncol */);
    extern void xtermParseRect (XtermWidget /* xw */, int, int *, XTermRect *);
    
    #if OPT_TRACE && OPT_TRACE_FLAGS
    extern int  LineTstFlag(LineData /* ld */, int /* flag */);
    extern void LineClrFlag(LineData /* ld */, int /* flag */);
    extern void LineSetFlag(LineData /* ld */, int /* flag */);
    #else
    
    #define LineFlags(ld)         GetLineFlags(ld)
    
    #define LineClrFlag(ld, flag) SetLineFlags(ld, (GetLineFlags(ld) & ~ (flag)))
    #define LineSetFlag(ld, flag) SetLineFlags(ld, (GetLineFlags(ld) | (flag)))
    #define LineTstFlag(ld, flag) ((GetLineFlags(ld) & flag) != 0)
    
    #endif /* OPT_TRACE && OPT_TRACE_FLAGS */
    
    #define LineClrBlinked(ld) LineClrFlag(ld, LINEBLINKED)
    #define LineSetBlinked(ld) LineSetFlag(ld, LINEBLINKED)
    #define LineTstBlinked(ld) LineTstFlag(ld, LINEBLINKED)
    
    #define LineClrWrapped(ld) LineClrFlag(ld, LINEWRAPPED)
    #define LineSetWrapped(ld) LineSetFlag(ld, LINEWRAPPED)
    #define LineTstWrapped(ld) LineTstFlag(ld, LINEWRAPPED)
    
    #define ScrnHaveSelection(screen) \
    			((screen)->startH.row != (screen)->endH.row \
    			|| (screen)->startH.col != (screen)->endH.col)
    
    #define ScrnAreRowsInSelection(screen, first, last) \
    	((last) >= (screen)->startH.row && (first) <= (screen)->endH.row)
    
    #define ScrnIsRowInSelection(screen, line) \
    	((line) >= (screen)->startH.row && (line) <= (screen)->endH.row)
    
    #define ScrnHaveRowMargins(screen) \
    			((screen)->top_marg != 0 \
    			|| ((screen)->bot_marg != screen->max_row))
    
    #define ScrnIsRowInMargins(screen, line) \
    	((line) >= (screen)->top_marg && (line) <= (screen)->bot_marg)
    
    #define ScrnHaveColMargins(screen) \
    			((screen)->rgt_marg > (screen)->max_col)
    
    #define ScrnIsColInMargins(screen, col) \
    	((col) >= (screen)->lft_marg && (col) <= (screen)->rgt_marg)
    
    /*
     * If the vertical scrolling margins are active, they will be something other
     * than the first/last row of the visible screen, as well as being distinct.
     */
    #define IsTopBottomMode(xw)	(ScrnTopMargin(xw) < ScrnBottomMargin(xw))
    #define ScrnTopMargin(xw)	TScreenOf(xw)->top_marg
    #define ScrnBottomMargin(xw)	TScreenOf(xw)->bot_marg
    
    /*
     * Left/right horizontal scrolling margins are only active when DECLRMM is.
     */
    #define IsLeftRightMode(xw) ((xw)->flags & LEFT_RIGHT)
    #define ScrnLeftMargin(xw)  (IsLeftRightMode(xw) \
    			     ? TScreenOf(xw)->lft_marg \
    			     : 0)
    #define ScrnRightMargin(xw) (IsLeftRightMode(xw) \
    			     ? TScreenOf(xw)->rgt_marg \
    			     : MaxCols(TScreenOf(xw)) - 1)
    
    #if OPT_DEC_RECTOPS
    extern void ScrnCopyRectangle (XtermWidget /* xw */, XTermRect *, int, int *);
    extern void ScrnMarkRectangle (XtermWidget /* xw */, XTermRect *, Bool, int, int *);
    extern void ScrnWipeRectangle (XtermWidget /* xw */, XTermRect *);
    extern void xtermCheckRect(XtermWidget /* xw */, int /* nparam */, int */* params */, int * /* result */);
    #endif
    
    #if OPT_WIDE_CHARS
    extern void ChangeToWide(XtermWidget /* xw */);
    #endif
    
    /* scrollback.c */
    extern LineData *getScrollback (TScreen * /* screen */, int /* row */);
    extern LineData *addScrollback (TScreen * /* screen */);
    extern void deleteScrollback (TScreen * /* screen */);
    
    /* scrollbar.c */
    extern void DoResizeScreen (XtermWidget /* xw */);
    extern void HandleScrollBack           PROTO_XT_ACTIONS_ARGS;
    extern void HandleScrollForward        PROTO_XT_ACTIONS_ARGS;
    extern void HandleScrollTo             PROTO_XT_ACTIONS_ARGS;
    extern void ResizeScrollBar (XtermWidget  /* xw */);
    extern void ScrollBarDrawThumb (XtermWidget  /* xw */, int /* mode */);
    extern void ScrollBarOff (XtermWidget  /* xw */);
    extern void ScrollBarOn (XtermWidget  /* xw */, Bool /* init */);
    extern void ScrollBarReverseVideo (Widget  /* scrollWidget */);
    extern void ToggleScrollBar (XtermWidget  /* xw */);
    extern void WindowScroll (XtermWidget /* xw */, int  /* top */, Bool /* always */);
    
    #ifdef SCROLLBAR_RIGHT
    extern void updateRightScrollbar(XtermWidget  /* xw */);
    #else
    #define updateRightScrollbar(xw) /* nothing */
    #endif
    
    /* tabs.c */
    extern Bool TabToNextStop (XtermWidget /* xw */);
    extern Bool TabToPrevStop (XtermWidget /* xw */);
    extern void TabClear (Tabs /* tabs */, int /* col */);
    extern void TabReset (Tabs /* tabs */);
    extern void TabSet (Tabs /* tabs */, int /* col */);
    extern void TabZonk (Tabs /* tabs */);
    extern Bool TabIsSet(Tabs /* tabs */, int /* col */);
    
    /* util.c */
    extern Boolean isDefaultBackground(const char * /* name */);
    extern Boolean isDefaultForeground(const char * /* name */);
    extern CgsEnum whichXtermCgs(XtermWidget /* xw */, unsigned /* attr_flags */, Bool /* hilite */);
    extern GC updatedXtermGC (XtermWidget /* xw */, unsigned  /* flags */, CellColor /* fg_bg */, Bool  /* hilite */);  
    extern Pixel getXtermBackground(XtermWidget /* xw */, unsigned /* flags */, int /* color */);
    extern Pixel getXtermForeground(XtermWidget /* xw */, unsigned /* flags */, int /* color */);
    extern int ClearInLine (XtermWidget /* xw */, int /* row */, int /* col */, unsigned /* len */);
    extern int HandleExposure (XtermWidget /* xw */, XEvent * /* event */);
    extern int dimRound (double /* value */);
    extern int drawXtermText (XTermDraw * /* param */, GC /* gc */, int /* x */, int /* y */, const IChar * /* text */, Cardinal /* len */);
    extern int extendedBoolean(const char * /* value */, const FlagList * /* table */, Cardinal /* limit */);
    extern void ChangeColors (XtermWidget  /* xw */, ScrnColors * /* pNew */);
    extern void ClearRight (XtermWidget /* xw */, int /* n */);
    extern void ClearScreen (XtermWidget /* xw */);
    extern void DeleteChar (XtermWidget /* xw */, unsigned /* n */);
    extern void DeleteLine (XtermWidget /* xw */, int /* n */);
    extern void FlushScroll (XtermWidget /* xw */);
    extern void GetColors (XtermWidget  /* xw */, ScrnColors * /* pColors */);
    extern void InsertChar (XtermWidget /* xw */, unsigned /* n */);
    extern void InsertLine (XtermWidget /* xw */, int  /* n */);
    extern void RevScroll (XtermWidget /* xw */, int  /* amount */);
    extern void ReverseVideo (XtermWidget /* xw */);
    extern void WriteText (XtermWidget /* xw */, IChar * /* str */, Cardinal /* len */);
    extern void decode_keyboard_type (XtermWidget /* xw */, struct XTERM_RESOURCE * /* rp */);
    extern void decode_wcwidth (XtermWidget  /* xw */);
    extern void do_cd_xtra_scroll (XtermWidget /* xw */);
    extern void do_erase_display (XtermWidget /* xw */, int  /* param */, int  /* mode */);
    extern void do_erase_line (XtermWidget /* xw */, int  /* param */, int  /* mode */);
    extern void do_ti_xtra_scroll (XtermWidget /* xw */);
    extern void getXtermSizeHints (XtermWidget /* xw */);
    extern void recolor_cursor (TScreen * /* screen */, Cursor  /* cursor */, unsigned long  /* fg */, unsigned long  /* bg */);
    extern void resetXtermGC (XtermWidget /* xw */, unsigned  /* flags */, Bool  /* hilite */);
    extern void scrolling_copy_area (XtermWidget /* xw */, int  /* firstline */, int  /* nlines */, int  /* amount */);
    extern void set_keyboard_type (XtermWidget /* xw */, xtermKeyboardType  /* type */, Bool  /* set */);
    extern void toggle_keyboard_type (XtermWidget /* xw */, xtermKeyboardType  /* type */);
    extern void update_keyboard_type (void);
    extern void xtermClear (XtermWidget /* xw */);
    extern void xtermClear2 (XtermWidget /* xw */, int /* x */, int /* y */, unsigned /* width */, unsigned /* height */);
    extern void xtermColIndex (XtermWidget /* xw */, Bool /* toLeft */);
    extern void xtermColScroll (XtermWidget /* xw */, int /* amount */, Bool /* toLeft */, int /* at_col */);
    extern void xtermRepaint (XtermWidget /* xw */);
    extern void xtermScroll (XtermWidget /* xw */, int /* amount */);
    extern void xtermScrollLR (XtermWidget /* xw */, int /* amount */, Bool /* toLeft */);
    extern void xtermSizeHints (XtermWidget  /* xw */, int /* scrollbarWidth */);
    
    struct Xinerama_geometry {
        int x;
        int y;
        unsigned w;
        unsigned h;
        int scr_x;
        int scr_y;
        int scr_w;
        int scr_h;
    };
    extern int XParseXineramaGeometry(Display * /* display */, char * /* parsestring */, struct Xinerama_geometry * /* ret */);
    
    #if OPT_ISO_COLORS
    
    extern Pixel extract_fg (XtermWidget /* xw */, CellColor /* color */, unsigned  /* flags */);
    extern Pixel extract_bg (XtermWidget /* xw */, CellColor /* color */, unsigned  /* flags */);
    extern CellColor makeColorPair (XtermWidget /* xw */);
    extern void ClearCurBackground (XtermWidget /* xw */, int  /* top */, int  /* left */, unsigned  /* height */, unsigned  /* width */, unsigned /* fw */);
    
    #define xtermColorPair(xw) makeColorPair(xw)
    
    #if OPT_COLOR_RES
    #define GET_COLOR_RES(xw, res) xtermGetColorRes(xw, &(res))
    #define SET_COLOR_RES(res,color) (res)->value = color
    #define EQL_COLOR_RES(res,color) (res)->value == color
    #define T_COLOR(v,n) (v)->Tcolors[n].value
    extern Pixel xtermGetColorRes(XtermWidget /* xw */, ColorRes * /* res */);
    #else
    #define GET_COLOR_RES(xw, res) res
    #define SET_COLOR_RES(res,color) *res = color
    #define EQL_COLOR_RES(res,color) *res == color
    #define T_COLOR(v,n) (v)->Tcolors[n]
    #endif
    
    #define ExtractForeground(color) (unsigned) GetCellColorFG(color)
    #define ExtractBackground(color) (unsigned) GetCellColorBG(color)
    
    #if OPT_RENDERFONT
    extern void discardRenderDraw(TScreen * /* screen */);
    #else
    #define discardRenderDraw(screen) /* nothing */
    #endif
    
    #if OPT_WIDE_ATTRS
    #define MapToWideColorMode(fg, screen, flags) \
    	(((screen)->colorITMode && ((flags) & ATR_ITALIC)) \
    	 ? COLOR_IT \
    	 : fg)
    #else
    #define MapToWideColorMode(fg, screen, flags) fg
    #endif
    
    #define MapToColorMode(fg, screen, flags) \
    	(((screen)->colorBLMode && ((flags) & BLINK)) \
    	 ? COLOR_BL \
    	 : (((screen)->colorBDMode && ((flags) & BOLD)) \
    	    ? COLOR_BD \
    	    : (((screen)->colorULMode && ((flags) & UNDERLINE)) \
    	       ? COLOR_UL \
    	       : MapToWideColorMode(fg, screen, flags))))
    
    #define checkVeryBoldAttr(flags, fg, code, attr) \
    	if ((flags & FG_COLOR) != 0 \
    	 && (screen->veryBoldColors & attr) == 0 \
    	 && (flags & attr) != 0 \
    	 && (fg == code)) \
    		 UIntClr(flags, attr)
    
    #if OPT_WIDE_ATTRS
    #define checkVeryBoldWideAttr(flags, fg, it, atr) \
    	    checkVeryBoldAttr(flags, fg, it, atr)
    #else
    #define checkVeryBoldWideAttr(flags, fg, it, atr) (void) flags
    #endif
    
    #define checkVeryBoldColors(flags, fg) \
    	checkVeryBoldAttr(flags, fg, COLOR_RV, INVERSE); \
    	checkVeryBoldAttr(flags, fg, COLOR_UL, UNDERLINE); \
    	checkVeryBoldAttr(flags, fg, COLOR_BD, BOLD); \
    	checkVeryBoldAttr(flags, fg, COLOR_BL, BLINK); \
    	checkVeryBoldWideAttr(flags, fg, COLOR_IT, ATR_ITALIC)
    
    #else /* !OPT_ISO_COLORS */
    
    #define MapToColorMode(fg, screen, flags) fg
    
    #define ClearCurBackground(xw, top, left, height, width, fw) \
    	XClearArea (TScreenOf(xw)->display, \
    		    VDrawable(TScreenOf(xw)), \
    		    CursorX2(TScreenOf(xw), left, fw), \
    		    CursorY(TScreenOf(xw), top), \
    		    ((width) * (unsigned) fw), \
    		    ((height) * (unsigned) FontHeight(TScreenOf(xw))), \
    		    False)
    
    #define extract_fg(xw, color, flags) (unsigned) (xw)->cur_foreground
    #define extract_bg(xw, color, flags) (unsigned) (xw)->cur_background
    
    		/* FIXME: Reverse-Video? */
    #define T_COLOR(v,n) (v)->Tcolors[n]
    #define xtermColorPair(xw) 0
    
    #define checkVeryBoldColors(flags, fg) /* nothing */
    #define discardRenderDraw(screen) /* nothing */
    
    #endif	/* OPT_ISO_COLORS */
    
    #define getXtermFG(xw, flags, color) getXtermForeground(xw, flags, color)
    #define getXtermBG(xw, flags, color) getXtermBackground(xw, flags, color)
    
    #if OPT_ZICONBEEP
    extern void initZIconBeep(void);
    extern void resetZIconBeep(XtermWidget /* xw */);
    extern Boolean showZIconBeep(XtermWidget /* xw */, char * /* name */);
    #else
    #define initZIconBeep() /* nothing */
    #define resetZIconBeep(xw) /* nothing */
    #define showZIconBeep(xw, name) False
    #endif
    
    #define XTERM_CELL(row,col)    getXtermCell(screen,     ROW2INX(screen, row), col)
    
    extern unsigned getXtermCell (TScreen * /* screen */, int  /* row */, int  /* col */);
    extern unsigned getXtermCombining(TScreen * /* screen */, int /* row */, int /* col */, int /* off */);
    extern void putXtermCell (TScreen * /* screen */, int  /* row */, int  /* col */, int  /* ch */);
    
    #define IsCellCombined(screen, row, col) (getXtermCombining(screen, row, col, 0) != 0)
    
    #if OPT_HIGHLIGHT_COLOR
    #define isNotForeground(xw, fg, bg, sel) \
    		(Boolean) ((sel) != T_COLOR(TScreenOf(xw), TEXT_FG) \
    			   && (sel) != (fg) \
    			   && (sel) != (bg) \
    			   && (sel) != (xw)->dft_foreground)
    #define isNotBackground(xw, fg, bg, sel) \
    		(Boolean) ((sel) != T_COLOR(TScreenOf(xw), TEXT_BG) \
    			   && (sel) != (fg) \
    			   && (sel) != (bg) \
    			   && (sel) != (xw)->dft_background)
    #endif
    
    #if OPT_WIDE_CHARS
    extern Boolean isWideControl(unsigned /* ch */);
    extern int DamagedCells(TScreen * /* screen */, unsigned /* n */, int * /* klp */, int * /* krp */, int /* row */, int /* col */);
    extern int DamagedCurCells(TScreen * /* screen */, unsigned /* n */, int * /* klp */, int * /* krp */);
    extern unsigned AsciiEquivs(unsigned /* ch */);
    extern void addXtermCombining (TScreen * /* screen */, int  /* row */, int  /* col */, unsigned  /* ch */);
    extern void allocXtermChars(ScrnPtr * /* buffer */, Cardinal /* length */);
    #endif
    
    #if OPT_XMC_GLITCH
    extern void Mark_XMC (XtermWidget /* xw */, int  /* param */);
    extern void Jump_XMC (XtermWidget /* xw */);
    extern void Resolve_XMC (XtermWidget /* xw */);
    #endif
    
    #if OPT_WIDE_CHARS
    unsigned visual_width(const IChar * /* str */, Cardinal  /* len */);
    #else
    #define visual_width(a, b) (b)
    #endif
    
    #define BtoS(b)    ((b) ? "on" : "off")
    #define MtoS(b)    (((b) == Maybe) ? "maybe" : BtoS(b))
    #define NonNull(s) ((s) ? (s) : "")
    
    #define UIntSet(dst,bits) dst = dst | (unsigned) (bits)
    #define UIntClr(dst,bits) dst = dst & (unsigned) ~(bits)
    
    #ifdef __cplusplus
    	}
    #endif
    /* *INDENT-ON* */
    
    #endif /* included_xterm_h */
    xterm-353/cachedGCs.c0000644000175100001440000004653313563106234013232 0ustar  tomusers/* $XTermId: cachedGCs.c,v 1.79 2019/11/13 23:07:08 tom Exp $ */
    
    /*
     * Copyright 2007-2018,2019 by Thomas E. Dickey
     *
     *                         All Rights Reserved
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     *
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * Except as contained in this notice, the name(s) of the above copyright
     * holders shall not be used in advertising or otherwise to promote the
     * sale, use or other dealings in this Software without prior written
     * authorization.
     */
    
    #include 
    #include 
    #include 
    
    #include 
    
    /*
     * hide (or eliminate) calls to
     *	XCreateGC()
     *	XFreeGC()
     *	XGetGCValues()
     *	XSetBackground()
     *	XSetFont()
     *	XSetForeground()
     *	XtGetGC()
     *	XtReleaseGC()
     * by associating an integer with each GC, maintaining a cache which
     * reflects frequency of use rather than most recent usage.
     *
     * FIXME: XTermFonts should hold gc, font, fs.
     */
    typedef struct {
        GC gc;
        unsigned used;
        unsigned cset;
        XTermFonts *font;
        Pixel tile;
        Pixel fg;
        Pixel bg;
    } CgsCacheData;
    
    #define DEPTH 8
    #define ITEM()      (int) (me->data - me->list)
    #define LIST(item)  me->list[item]
    #define LINK(item)  me->data = (me->list + (item))
    #define THIS(field) me->data->field
    #define NEXT(field) me->next.field
    
    #define HaveFont(font) (Boolean) ((font) != 0 && (font)->fs != 0)
    
    #define GC_CSet GCFunction
    
    typedef struct {
        CgsCacheData list[DEPTH];
        CgsCacheData *data;		/* points to current list[] entry */
        XtGCMask mask;		/* changes since the last getCgsGC() */
        CgsCacheData next;		/* updated values, apply in getCgsGC() */
    } CgsCache;
    
    #if OPT_TRACE
    #define CASE(name) case gc##name: result = #name; break
    static const char *
    traceCgsEnum(CgsEnum value)
    {
        const char *result = "?";
        switch (value) {
    	CASE(Norm);
    	CASE(Bold);
    	CASE(NormReverse);
    	CASE(BoldReverse);
    	CASE(Border);
    	CASE(Filler);
    #if OPT_BOX_CHARS
    	CASE(Line);
    	CASE(Dots);
    #endif
    #if OPT_DEC_CHRSET
    	CASE(CNorm);
    	CASE(CBold);
    #endif
    #if OPT_WIDE_CHARS
    	CASE(Wide);
    	CASE(WBold);
    	CASE(WideReverse);
    	CASE(WBoldReverse);
    #endif
    	CASE(VTcursNormal);
    	CASE(VTcursFilled);
    	CASE(VTcursReverse);
    	CASE(VTcursOutline);
    #if OPT_TEK4014
    	CASE(TKcurs);
    #endif
    	CASE(MAX);
        }
        return result;
    }
    
    #undef CASE
    
    static const char *
    traceVTwin(XtermWidget xw, VTwin *value)
    {
        const char *result = "?";
        if (value == 0)
    	result = "null";
        else if (value == &(TScreenOf(xw)->fullVwin))
    	result = "fullVwin";
    #ifndef NO_ACTIVE_ICON
        else if (value == &(TScreenOf(xw)->iconVwin))
    	result = "iconVwin";
    #endif
        return result;
    }
    
    #if OPT_TRACE > 1
    static String
    traceCSet(unsigned cset)
    {
        static char result[80];
        switch (cset) {
        case CSET_SWL:
    	strcpy(result, "SWL");
    	break;
        case CSET_DHL_TOP:
    	strcpy(result, "DHL_TOP");
    	break;
        case CSET_DHL_BOT:
    	strcpy(result, "DHL_BOT");
    	break;
        case CSET_DWL:
    	strcpy(result, "DWL");
    	break;
        default:
    	sprintf(result, "%#x", cset);
    	break;
        }
        return result;
    }
    
    static String
    traceFont(XTermFonts * font)
    {
        static char result[80];
    
        if (HaveFont(font)) {
    	XFontStruct *fs = font->fs;
    	sprintf(result, "%p(%dx%d %d %#lx)",
    		fs,
    		fs->max_bounds.width,
    		fs->max_bounds.ascent + fs->max_bounds.descent,
    		fs->max_bounds.descent,
    		(unsigned long) (fs->fid));
        } else {
    	strcpy(result, "null");
        }
        return result;
    }
    
    static String
    tracePixel(XtermWidget xw, Pixel value)
    {
    #define CASE(name) { name, #name }
        static struct {
    	TermColors code;
    	String name;
        } t_colors[] = {
    	CASE(TEXT_FG),
    	    CASE(TEXT_BG),
    	    CASE(TEXT_CURSOR),
    	    CASE(MOUSE_FG),
    	    CASE(MOUSE_BG),
    #if OPT_TEK4014
    	    CASE(TEK_FG),
    	    CASE(TEK_BG),
    #endif
    #if OPT_HIGHLIGHT_COLOR
    	    CASE(HIGHLIGHT_BG),
    	    CASE(HIGHLIGHT_FG),
    #endif
    #if OPT_TEK4014
    	    CASE(TEK_CURSOR),
    #endif
        };
        TScreen *screen = TScreenOf(xw);
        String result = 0;
        int n;
    
        for (n = 0; n < NCOLORS; ++n) {
    	if (value == T_COLOR(screen, t_colors[n].code)) {
    	    result = t_colors[n].name;
    	    break;
    	}
        }
    
        if (result == 0) {
    	for (n = 0; n < MAXCOLORS; ++n) {
    #if OPT_COLOR_RES
    	    if (screen->Acolors[n].mode > 0
    		&& value == screen->Acolors[n].value) {
    		result = screen->Acolors[n].resource;
    		break;
    	    }
    #else
    	    if (value == screen->Acolors[n]) {
    		char temp[80];
    		sprintf(temp, "Acolors[%d]", n);
    		result = x_strdup(temp);
    		break;
    	    }
    #endif
    	}
        }
    
        if (result == 0) {
    	char temp[80];
    	sprintf(temp, "%#lx", value);
    	result = x_strdup(temp);
        }
    
        return result;
    }
    
    #undef CASE
    
    #endif /* OPT_TRACE > 1 */
    #endif /* OPT_TRACE */
    
    static CgsCache *
    allocCache(void **cache_pointer)
    {
        if (*cache_pointer == 0) {
    	*cache_pointer = TypeCallocN(CgsCache, gcMAX);
    	TRACE(("allocCache %p\n", *cache_pointer));
        }
        return *((CgsCache **) cache_pointer);
    }
    
    #define ALLOC_CACHE(p) ((*(p) == 0) ? allocCache(p) : *(p))
    
    static int
    dataIndex(CgsCache * me)
    {
        return ITEM();
    }
    
    static void
    relinkData(CgsCache * me, int item)
    {
        LINK(item);
    }
    
    /*
     * Returns the appropriate cache pointer.
     */
    static CgsCache *
    myCache(XtermWidget xw, VTwin *cgsWin, CgsEnum cgsId)
    {
        CgsCache *result = 0;
    
        if ((int) cgsId >= 0 && cgsId < gcMAX) {
    #ifdef NO_ACTIVE_ICON
    	(void) xw;
    	(void) cgsWin;
    #else
    	if (cgsWin == &(TScreenOf(xw)->iconVwin))
    	    result = ALLOC_CACHE(&(TScreenOf(xw)->icon_cgs_cache));
    	else
    #endif
    	    result = ALLOC_CACHE(&(TScreenOf(xw)->main_cgs_cache));
    
    	result += cgsId;
    	if (result->data == 0) {
    	    result->data = result->list;
    	}
        }
    
        return result;
    }
    
    static Display *
    myDisplay(XtermWidget xw)
    {
        return TScreenOf(xw)->display;
    }
    
    static Drawable
    myDrawable(XtermWidget xw, VTwin *cgsWin)
    {
        Drawable drawable = 0;
    
        if (cgsWin != 0 && cgsWin->window != 0)
    	drawable = cgsWin->window;
        if (drawable == 0)
    	drawable = RootWindowOfScreen(XtScreen(xw));
        return drawable;
    }
    
    static GC
    newCache(XtermWidget xw, VTwin *cgsWin, CgsEnum cgsId, CgsCache * me)
    {
        XGCValues xgcv;
        XtGCMask mask;
    
        THIS(font) = NEXT(font);
        THIS(cset) = NEXT(cset);
        THIS(fg) = NEXT(fg);
        THIS(bg) = NEXT(bg);
    
        memset(&xgcv, 0, sizeof(xgcv));
        xgcv.font = NEXT(font)->fs->fid;
        mask = (GCForeground | GCBackground | GCFont);
    
        switch (cgsId) {
        case gcFiller:
        case gcBorder:
    	mask &= (XtGCMask) ~ GCFont;
    	/* FALLTHRU */
        case gcNorm:
        case gcBold:
        case gcNormReverse:
        case gcBoldReverse:
    #if OPT_WIDE_CHARS
        case gcWide:
        case gcWBold:
        case gcWideReverse:
        case gcWBoldReverse:
    #endif
    	mask |= (GCGraphicsExposures | GCFunction);
    	xgcv.graphics_exposures = True;		/* default */
    	xgcv.function = GXcopy;
    	break;
    #if OPT_BOX_CHARS
        case gcLine:
    	mask |= (GCGraphicsExposures | GCFunction);
    	xgcv.graphics_exposures = True;		/* default */
    	xgcv.function = GXcopy;
    	break;
        case gcDots:
    	xgcv.fill_style = FillTiled;
    	xgcv.tile =
    	    XmuCreateStippledPixmap(XtScreen((Widget) xw),
    				    THIS(fg),
    				    THIS(bg),
    				    xw->core.depth);
    	THIS(tile) = xgcv.tile;
    	mask = (GCForeground | GCBackground);
    	mask |= (GCGraphicsExposures | GCFunction | GCTile | GCFillStyle);
    	xgcv.graphics_exposures = True;		/* default */
    	xgcv.function = GXcopy;
    	break;
    #endif
    #if OPT_DEC_CHRSET
        case gcCNorm:
        case gcCBold:
    	break;
    #endif
        case gcVTcursNormal:	/* FALLTHRU */
        case gcVTcursFilled:	/* FALLTHRU */
        case gcVTcursReverse:	/* FALLTHRU */
        case gcVTcursOutline:	/* FALLTHRU */
    	break;
    #if OPT_TEK4014
        case gcTKcurs:		/* FALLTHRU */
    	/* FIXME */
    #endif
        case gcMAX:		/* should not happen */
    	return 0;
        }
        xgcv.foreground = NEXT(fg);
        xgcv.background = NEXT(bg);
    
        THIS(gc) = XCreateGC(myDisplay(xw), myDrawable(xw, cgsWin), mask, &xgcv);
        TRACE(("getCgsGC(%s) created gc %p(%d)\n",
    	   traceCgsEnum(cgsId), (void *) THIS(gc), ITEM()));
    
        THIS(used) = 0;
        return THIS(gc);
    }
    
    #define SameFont(a, b) \
    	(Boolean) (HaveFont(a) \
    		   && HaveFont(b) \
    		   && (((a)->fs == (b)->fs) \
    		       || !memcmp((a)->fs, (b)->fs, sizeof(*((a)->fs)))))
    
    #define SameColor(a,b) ((a) == (b))
    #define SameCSet(a,b)  ((a) == (b))
    
    static GC
    chgCache(XtermWidget xw, CgsEnum cgsId GCC_UNUSED, CgsCache * me, Bool both)
    {
        XGCValues xgcv;
        XtGCMask mask = (GCForeground | GCBackground | GCFont);
    
        memset(&xgcv, 0, sizeof(xgcv));
    
        TRACE2(("chgCache(%s) old data fg=%s, bg=%s, font=%s cset %s\n",
    	    traceCgsEnum(cgsId),
    	    tracePixel(xw, THIS(fg)),
    	    tracePixel(xw, THIS(bg)),
    	    traceFont(THIS(font)),
    	    traceCSet(THIS(cset))));
    #if OPT_TRACE > 1
        if (!SameFont(THIS(font), NEXT(font)))
    	TRACE2(("...chgCache new font=%s\n", traceFont(NEXT(font))));
        if (!SameCSet(THIS(cset), NEXT(cset)))
    	TRACE2(("...chgCache new cset=%s\n", traceCSet(NEXT(cset))));
        if (!SameColor(THIS(fg), NEXT(fg)))
    	TRACE2(("...chgCache new fg=%s\n", tracePixel(xw, NEXT(fg))));
        if (!SameColor(THIS(bg), NEXT(bg)))
    	TRACE2(("...chgCache new bg=%s\n", tracePixel(xw, NEXT(bg))));
    #endif
    
        if (both) {
    	THIS(font) = NEXT(font);
    	THIS(cset) = NEXT(cset);
        }
        THIS(fg) = NEXT(fg);
        THIS(bg) = NEXT(bg);
    
        xgcv.font = THIS(font)->fs->fid;
        xgcv.foreground = THIS(fg);
        xgcv.background = THIS(bg);
    
        XChangeGC(myDisplay(xw), THIS(gc), mask, &xgcv);
        TRACE2(("...chgCache(%s) updated gc %p(%d)\n",
    	    traceCgsEnum(cgsId), THIS(gc), ITEM()));
    
        THIS(used) = 0;
        return THIS(gc);
    }
    
    /*
     * Use the "setCgsXXXX()" calls to initialize parameters for a new GC.
     */
    void
    setCgsFore(XtermWidget xw, VTwin *cgsWin, CgsEnum cgsId, Pixel fg)
    {
        CgsCache *me;
    
        if ((me = myCache(xw, cgsWin, cgsId)) != 0) {
    	NEXT(fg) = fg;
    	me->mask |= GCForeground;
    	TRACE2(("setCgsFore(%s) %s\n",
    		traceCgsEnum(cgsId),
    		tracePixel(xw, NEXT(fg))));
        }
    }
    
    void
    setCgsBack(XtermWidget xw, VTwin *cgsWin, CgsEnum cgsId, Pixel bg)
    {
        CgsCache *me;
    
        if ((me = myCache(xw, cgsWin, cgsId)) != 0) {
    	NEXT(bg) = bg;
    	me->mask |= GCBackground;
    	TRACE2(("setCgsBack(%s) %s\n",
    		traceCgsEnum(cgsId),
    		tracePixel(xw, NEXT(bg))));
        }
    }
    
    #if OPT_DEC_CHRSET
    void
    setCgsCSet(XtermWidget xw, VTwin *cgsWin, CgsEnum cgsId, unsigned cset)
    {
        CgsCache *me;
    
        if ((me = myCache(xw, cgsWin, cgsId)) != 0) {
    	NEXT(cset) = cset;
    	me->mask |= GC_CSet;
        }
    }
    #else
    #define setCgsCSet(xw, cgsWin, dstCgsId, cset)	/* nothing */
    #endif
    
    void
    setCgsFont2(XtermWidget xw, VTwin *cgsWin, CgsEnum cgsId, XTermFonts * font, unsigned which)
    {
        CgsCache *me;
    
        if ((me = myCache(xw, cgsWin, cgsId)) != 0) {
    	TScreen *screen = TScreenOf(xw);
    	if (!HaveFont(font)) {
    	    if (cgsId != gcNorm)
    		(void) getCgsGC(xw, cgsWin, gcNorm);
    #ifndef NO_ACTIVE_ICON
    	    if (cgsWin == &(TScreenOf(xw)->iconVwin))
    		font = getIconicFont(screen);
    	    else
    #endif
    		font = GetNormalFont(screen, which);
    	}
    	if (HaveFont(font) && okFont(font->fs)) {
    	    TRACE2(("setCgsFont next: %s for %s slot %p, gc %p\n",
    		    traceFont(font), traceCgsEnum(cgsId),
    		    me, THIS(gc)));
    	    TRACE2(("...next font was %s\n", traceFont(NEXT(font))));
    	    NEXT(font) = font;
    	    me->mask |= GCFont;
    	} else {
    	    /* EMPTY */
    	    TRACE2(("...NOT updated font for %s\n",
    		    traceCgsEnum(cgsId)));
    	}
        }
    }
    
    void
    setCgsFont(XtermWidget xw, VTwin *cgsWin, CgsEnum cgsId, XTermFonts * font)
    {
        setCgsFont2(xw, cgsWin, cgsId, font, fNorm);
    }
    
    /*
     * Discard all of the font information, e.g., we are resizing the font.
     * Keep the GC's so we can simply change them rather than creating new ones.
     */
    void
    clrCgsFonts(XtermWidget xw, VTwin *cgsWin, XTermFonts * font)
    {
        if (HaveFont(font)) {
    	int j;
    	for_each_gc(j) {
    	    CgsCache *me;
    	    if ((me = myCache(xw, cgsWin, (CgsEnum) j)) != 0) {
    		int k;
    		for (k = 0; k < DEPTH; ++k) {
    		    if (SameFont(LIST(k).font, font)) {
    			TRACE2(("clrCgsFonts %s gc %p(%d) %s\n",
    				traceCgsEnum((CgsEnum) j),
    				LIST(k).gc,
    				k,
    				traceFont(font)));
    			LIST(k).font = 0;
    			LIST(k).cset = 0;
    		    }
    		}
    		if (SameFont(NEXT(font), font)) {
    		    TRACE2(("clrCgsFonts %s next %s\n",
    			    traceCgsEnum((CgsEnum) j),
    			    traceFont(font)));
    		    NEXT(font) = 0;
    		    NEXT(cset) = 0;
    		    me->mask &= (unsigned) ~(GCFont | GC_CSet);
    		}
    	    }
    	}
        }
    }
    
    /*
     * Return a GC associated with the given id, allocating if needed.
     */
    GC
    getCgsGC(XtermWidget xw, VTwin *cgsWin, CgsEnum cgsId)
    {
        CgsCache *me;
        GC result = 0;
    
        if ((me = myCache(xw, cgsWin, cgsId)) != 0) {
    	TRACE2(("getCgsGC(%s, %s)\n",
    		traceVTwin(xw, cgsWin), traceCgsEnum(cgsId)));
    	if (me->mask != 0) {
    	    int j;
    	    unsigned used = 0;
    
    	    /* fill in the unchanged fields */
    	    if (!(me->mask & GC_CSet))
    		NEXT(cset) = 0;	/* OPT_DEC_CHRSET */
    	    if (!(me->mask & GCFont))
    		NEXT(font) = THIS(font);
    	    if (!(me->mask & GCForeground))
    		NEXT(fg) = THIS(fg);
    	    if (!(me->mask & GCBackground))
    		NEXT(bg) = THIS(bg);
    
    	    if (NEXT(font) == 0) {
    		setCgsFont(xw, cgsWin, cgsId, 0);
    	    }
    
    	    TRACE2(("...Cgs new data fg=%s, bg=%s, font=%s cset %s\n",
    		    tracePixel(xw, NEXT(fg)),
    		    tracePixel(xw, NEXT(bg)),
    		    traceFont(NEXT(font)),
    		    traceCSet(NEXT(cset))));
    
    	    /* try to find the given data in an already-created GC */
    	    for (j = 0; j < DEPTH; ++j) {
    		if (LIST(j).gc != 0
    		    && SameFont(LIST(j).font, NEXT(font))
    		    && SameCSet(LIST(j).cset, NEXT(cset))
    		    && SameColor(LIST(j).fg, NEXT(fg))
    		    && SameColor(LIST(j).bg, NEXT(bg))) {
    		    LINK(j);
    		    result = THIS(gc);
    		    TRACE2(("getCgsGC existing %p(%d)\n", result, ITEM()));
    		    break;
    		}
    	    }
    
    	    if (result == 0) {
    		/* try to find an empty slot, to create a new GC */
    		used = 0;
    		for (j = 0; j < DEPTH; ++j) {
    		    if (LIST(j).gc == 0) {
    			LINK(j);
    			result = newCache(xw, cgsWin, cgsId, me);
    			break;
    		    }
    		    if (used < LIST(j).used)
    			used = LIST(j).used;
    		}
    	    }
    
    	    if (result == 0) {
    		int k;
    		/* if none were empty, pick the least-used slot, to modify */
    		for (j = 0, k = -1; j < DEPTH; ++j) {
    		    if (used >= LIST(j).used) {
    			used = LIST(j).used;
    			k = j;
    		    }
    		}
    		if (k >= 0) {
    		    LINK(k);
    		    TRACE2(("...getCgsGC least-used(%d) was %d\n", k, THIS(used)));
    		    result = chgCache(xw, cgsId, me, True);
    		}
    	    }
    	    me->next = *(me->data);
    	} else {
    	    result = THIS(gc);
    	}
    	me->mask = 0;
    	THIS(used) += 1;
    	TRACE2(("...getCgsGC(%s, %s) gc %p(%d), used %d\n",
    		traceVTwin(xw, cgsWin),
    		traceCgsEnum(cgsId), result, ITEM(), THIS(used)));
        }
        return result;
    }
    
    /*
     * Return the font for the given GC.
     */
    CgsEnum
    getCgsId(XtermWidget xw, VTwin *cgsWin, GC gc)
    {
        int n;
        CgsEnum result = gcNorm;
    
        for_each_gc(n) {
    	CgsCache *me;
    
    	if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) {
    	    if (THIS(gc) == gc) {
    		result = (CgsEnum) n;
    		break;
    	    }
    	}
        }
        return result;
    }
    
    /*
     * Return the font for the given GC.
     */
    XTermFonts *
    getCgsFont(XtermWidget xw, VTwin *cgsWin, GC gc)
    {
        int n;
        XTermFonts *result = 0;
    
        for_each_gc(n) {
    	CgsCache *me;
    
    	if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) {
    	    if (THIS(gc) == gc) {
    		result = THIS(font);
    		break;
    	    }
    	}
        }
        return result;
    }
    
    /*
     * Return the foreground color for the given GC.
     */
    Pixel
    getCgsFore(XtermWidget xw, VTwin *cgsWin, GC gc)
    {
        int n;
        Pixel result = 0;
    
        for_each_gc(n) {
    	CgsCache *me;
    
    	if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) {
    	    if (THIS(gc) == gc) {
    		result = THIS(fg);
    		break;
    	    }
    	}
        }
        return result;
    }
    
    /*
     * Return the background color for the given GC.
     */
    Pixel
    getCgsBack(XtermWidget xw, VTwin *cgsWin, GC gc)
    {
        int n;
        Pixel result = 0;
    
        for_each_gc(n) {
    	CgsCache *me;
    
    	if ((me = myCache(xw, cgsWin, (CgsEnum) n)) != 0) {
    	    if (THIS(gc) == gc) {
    		result = THIS(bg);
    		break;
    	    }
    	}
        }
        return result;
    }
    
    /*
     * Copy the parameters (except GC of course) from one cache record to another.
     */
    void
    copyCgs(XtermWidget xw, VTwin *cgsWin, CgsEnum dstCgsId, CgsEnum srcCgsId)
    {
        if (dstCgsId != srcCgsId) {
    	CgsCache *me;
    
    	if ((me = myCache(xw, cgsWin, srcCgsId)) != 0) {
    	    TRACE(("copyCgs from %s to %s\n",
    		   traceCgsEnum(srcCgsId),
    		   traceCgsEnum(dstCgsId)));
    	    TRACE2(("copyCgs from %s (me %p, fg %s, bg %s, cset %s) to %s {{\n",
    		    traceCgsEnum(srcCgsId),
    		    me,
    		    tracePixel(xw, THIS(fg)),
    		    tracePixel(xw, THIS(bg)),
    		    traceCSet(THIS(cset)),
    		    traceCgsEnum(dstCgsId)));
    	    setCgsCSet(xw, cgsWin, dstCgsId, THIS(cset));
    	    setCgsFore(xw, cgsWin, dstCgsId, THIS(fg));
    	    setCgsBack(xw, cgsWin, dstCgsId, THIS(bg));
    	    setCgsFont(xw, cgsWin, dstCgsId, THIS(font));
    	    TRACE2(("...copyCgs }}\n"));
    	}
        }
    }
    
    /*
     * Interchange colors in the cache, e.g., for reverse-video.
     */
    void
    redoCgs(XtermWidget xw, Pixel fg, Pixel bg, CgsEnum cgsId)
    {
        VTwin *cgsWin = WhichVWin(TScreenOf(xw));
        CgsCache *me = myCache(xw, cgsWin, cgsId);
    
        if (me != 0) {
    	CgsCacheData *save_data = me->data;
    	int n;
    
    	for (n = 0; n < DEPTH; ++n) {
    	    if (LIST(n).gc != 0 && HaveFont(LIST(n).font)) {
    		LINK(n);
    
    		if (LIST(n).fg == fg
    		    && LIST(n).bg == bg) {
    		    setCgsFore(xw, cgsWin, cgsId, bg);
    		    setCgsBack(xw, cgsWin, cgsId, fg);
    		} else if (LIST(n).fg == bg
    			   && LIST(n).bg == fg) {
    		    setCgsFore(xw, cgsWin, cgsId, fg);
    		    setCgsBack(xw, cgsWin, cgsId, bg);
    		} else {
    		    continue;
    		}
    
    		(void) chgCache(xw, cgsId, me, False);
    	    }
    	}
    	me->data = save_data;
        }
    }
    
    /*
     * Swap the cache records, e.g., when doing reverse-video.
     */
    void
    swapCgs(XtermWidget xw, VTwin *cgsWin, CgsEnum dstCgsId, CgsEnum srcCgsId)
    {
        if (dstCgsId != srcCgsId) {
    	CgsCache *src;
    
    	if ((src = myCache(xw, cgsWin, srcCgsId)) != 0) {
    	    CgsCache *dst;
    
    	    if ((dst = myCache(xw, cgsWin, dstCgsId)) != 0) {
    		CgsCache tmp;
    		int srcIndex = dataIndex(src);
    		int dstIndex = dataIndex(dst);
    
    		EXCHANGE(*src, *dst, tmp);
    
    		relinkData(src, dstIndex);
    		relinkData(dst, srcIndex);
    	    }
    	}
        }
    }
    
    /*
     * Free any GC associated with the given id.
     */
    GC
    freeCgs(XtermWidget xw, VTwin *cgsWin, CgsEnum cgsId)
    {
        CgsCache *me;
    
        if ((me = myCache(xw, cgsWin, cgsId)) != 0) {
    	int j;
    
    	for (j = 0; j < DEPTH; ++j) {
    	    if (LIST(j).gc != 0) {
    		TRACE(("freeCgs(%s, %s) gc %p(%d)\n",
    		       traceVTwin(xw, cgsWin),
    		       traceCgsEnum(cgsId), (void *) LIST(j).gc, j));
    		clrCgsFonts(xw, cgsWin, LIST(j).font);
    #if OPT_BOX_CHARS
    		if (cgsId == gcDots) {
    		    XmuReleaseStippledPixmap(XtScreen((Widget) xw), LIST(j).tile);
    		}
    #endif
    		XFreeGC(TScreenOf(xw)->display, LIST(j).gc);
    		memset(&LIST(j), 0, sizeof(LIST(j)));
    	    }
    	    LINK(0);
    	}
        }
        return 0;
    }
    
    #ifdef NO_LEAKS
    void
    noleaks_cachedCgs(XtermWidget xw)
    {
    #ifndef NO_ACTIVE_ICON
        free(TScreenOf(xw)->icon_cgs_cache);
    #endif
        free(TScreenOf(xw)->main_cgs_cache);
    }
    #endif
    xterm-353/unicode/0000755000175100001440000000000013345253320012672 5ustar  tomusersxterm-353/unicode/convmap.pl0000755000175100001440000001451013345253320014676 0ustar  tomusers#!/usr/bin/perl -w
    # $XTermId: convmap.pl,v 1.15 2018/09/09 17:22:24 tom Exp $
    #
    # Generate keysym2ucs.c file
    #
    # See also:
    # http://mail.nl.linux.org/linux-utf8/2001-04/msg00248.html
    #
    # $XFree86: xc/programs/xterm/unicode/convmap.pl,v 1.5 2000/01/24 22:22:05 dawes Exp $
    
    use strict;
    
    our $keysym;
    our %name;
    our %keysym_to_ucs;
    our %keysym_to_keysymname;
    
    sub utf8 ($);
    
    sub utf8 ($) {
        my $c = shift(@_);
    
        if ($c < 0x80) {
            return sprintf("%c", $c);
        } elsif ($c < 0x800) {
            return sprintf("%c%c", 0xc0 | ($c >> 6), 0x80 | ($c & 0x3f));
        } elsif ($c < 0x10000) {
            return sprintf("%c%c%c",
                           0xe0 |  ($c >> 12),
                           0x80 | (($c >>  6) & 0x3f),
                           0x80 | ( $c        & 0x3f));
        } elsif ($c < 0x200000) {
            return sprintf("%c%c%c%c",
                           0xf0 |  ($c >> 18),
                           0x80 | (($c >> 12) & 0x3f),
                           0x80 | (($c >>  6) & 0x3f),
                           0x80 | ( $c        & 0x3f));
        } elsif ($c < 0x4000000) {
            return sprintf("%c%c%c%c%c",
                           0xf8 |  ($c >> 24),
                           0x80 | (($c >> 18) & 0x3f),
                           0x80 | (($c >> 12) & 0x3f),
                           0x80 | (($c >>  6) & 0x3f),
                           0x80 | ( $c        & 0x3f));
    
        } elsif ($c < 0x80000000) {
            return sprintf("%c%c%c%c%c%c",
                           0xfe |  ($c >> 30),
                           0x80 | (($c >> 24) & 0x3f),
                           0x80 | (($c >> 18) & 0x3f),
                           0x80 | (($c >> 12) & 0x3f),
                           0x80 | (($c >> 6)  & 0x3f),
                           0x80 | ( $c        & 0x3f));
        } else {
            return utf8(0xfffd);
        }
    }
    
    my $unicodedata = "UnicodeData.txt";
    
    # read list of all Unicode names
    if (!open(UDATA, $unicodedata) && !open(UDATA, "$unicodedata")) {
        die ("Can't open Unicode database '$unicodedata':\n$!\n\n" .
             "Please make sure that you have downloaded the file\n" .
             "ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt\n");
    }
    while () {
        if (/^([0-9,A-F]{4,6});([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*);([^;]*)$/) {
            $name{hex($1)} = $2;
        } else {
            die("Syntax error in line '$_' in file '$unicodedata'");
        }
    }
    close(UDATA);
    
    # read mapping (from http://wsinwp07.win.tue.nl:1234/unicode/keysym.map)
    open(LIST, ") {
        if (/^0x([0-9a-f]{4})\s+U([0-9a-f]{4})\s*(\#.*)?$/){
            my $keysym = hex($1);
            my $ucs = hex($2);
            my $comment = $3;
            $comment =~ s/^#\s*//;
            $keysym_to_ucs{$keysym} = $ucs;
            $keysym_to_keysymname{$keysym} = $comment;
        } elsif (/^\s*\#/ || /^\s*$/) {
        } else {
            die("Syntax error in 'list' in line\n$_\n");
        }
    }
    close(LIST);
    
    # read entries in keysymdef.h
    open(LIST, ") {
        if (/^\#define\s+XK_([A-Za-z_0-9]+)\s+0x([0-9a-fA-F]+)\s*(\/.*)?$/) {
            next if /\/\* deprecated \*\//;
            my $keysymname = $1;
            my $keysym = hex($2);
            $keysym_to_keysymname{$keysym} = $keysymname;
        }
    }
    close(LIST);
    
    print < UTF-8 conversion will hopefully one day be provided
     * by Xlib via XmbLookupString() and should ideally not have to be
     * done in X applications. But we are not there yet.
     *
     * We allow to represent any UCS character in the range U-00000000 to
     * U-00FFFFFF by a keysym value in the range 0x01000000 to 0x01ffffff.
     * This admittedly does not cover the entire 31-bit space of UCS, but
     * it does cover all of the characters up to U-10FFFF, which can be
     * represented by UTF-16, and more, and it is very unlikely that higher
     * UCS codes will ever be assigned by ISO. So to get Unicode character
     * U+ABCD you can directly use keysym 0x0100abcd.
     *
     * NOTE: The comments in the table below contain the actual character
     * encoded in UTF-8, so for viewing and editing best use an editor in
     * UTF-8 mode.
     *
     * Author: Markus G. Kuhn , University of Cambridge, April 2001
     *
     * Special thanks to Richard Verhoeven  for preparing
     * an initial draft of the mapping table.
     *
     * This software is in the public domain. Share and enjoy!
     *
     * AUTOMATICALLY GENERATED FILE, DO NOT EDIT !!! (unicode/convmap.pl)
     */
    
    #ifndef KEYSYM2UCS_INCLUDED
    
    #include "keysym2ucs.h"
    #define VISIBLE /* */
    
    #else
    
    #define VISIBLE static
    
    #endif
    
    static struct codepair {
      unsigned short keysym;
      unsigned short ucs;
    } keysymtab[] = {
    EOT
    
    for $keysym (sort {$a <=> $b} keys(%keysym_to_keysymname)) {
        my $ucs = $keysym_to_ucs{$keysym};
        next if $keysym >= 0xf000 || $keysym < 0x100;
        if ($ucs) {
            printf("  { 0x%04x, 0x%04x }, /*%28s %s %s */\n",
                   $keysym, $ucs, $keysym_to_keysymname{$keysym}, utf8($ucs),
                   defined($name{$ucs}) ? $name{$ucs} : "???" );
        } else {
            printf("/*  0x%04x   %39s ? ??? */\n",
                   $keysym, $keysym_to_keysymname{$keysym});
        }
    }
    
    print <= 0x0020 && keysym <= 0x007e) ||
            (keysym >= 0x00a0 && keysym <= 0x00ff))
            return (long) keysym;
    
        /* also check for directly encoded 24-bit UCS characters */
        if ((keysym & 0xff000000) == 0x01000000)
            return (long) (keysym & 0x00ffffff);
    
        /* binary search in table */
        while (max >= min) {
            int mid = (min + max) / 2;
            if (keysymtab[mid].keysym < keysym)
                min = mid + 1;
            else if (keysymtab[mid].keysym > keysym)
                max = mid - 1;
            else {
                /* found it */
                return keysymtab[mid].ucs;
            }
        }
    
        /* no matching Unicode value found */
        return -1;
    }
    EOT
    xterm-353/unicode/keysym.map0000644000175100001440000010073613315301234014714 0ustar  tomusers# $XTermId: keysym.map,v 1.10 2018/06/29 00:51:40 Brad.Town Exp $
    #
    # This list can be used to convert X11 Keysyms to Unicode 2.1 character.
    # The list is not checked for correctness by Unicode officials.  Use it
    # at your own risk and the creator is not responsible for any damage that
    # occurred due to using this list.
    #
    # The list is created by looking at the Keysym names and the Unicode data
    # file.  Other mapping tables were used as a reference where needed.
    # Due to a lack of knowledge of the Hebrew, Thai and Hangul symbols,
    # expect errors in these sections.  The mapping of the keypad keys
    # might also require some adjustments.
    #
    # The following fields are used:
    # 1    The X11 keysym numbers from the include file keysymdef.h
    # 2    The Unicode (2.1) position (U0000 means unknown Unicode position)
    # #
    # 3    the name of the X11 keysym (without XK_)
    #
    # Authors:  Richard Verhoeven, TUE, 
    #           Markus Kuhn, University of Cambridge, 
    #
    # You are free to use and modify this table.  If you introduce errors
    # in the table, please remove the copyright line. If you remove errors,
    # please let me know, so I can update my version.
    #
    # $XFree86: xc/programs/xterm/unicode/keysym.map,v 1.1 1999/06/12 15:37:24 dawes Exp $
    #
    0x0020     U0020  # space
    0x0021     U0021  # exclam
    0x0022     U0022  # quotedbl
    0x0023     U0023  # numbersign
    0x0024     U0024  # dollar
    0x0025     U0025  # percent
    0x0026     U0026  # ampersand
    0x0027     U0027  # apostrophe
    0x0028     U0028  # parenleft
    0x0029     U0029  # parenright
    0x002a     U002a  # asterisk
    0x002b     U002b  # plus
    0x002c     U002c  # comma
    0x002d     U002d  # minus
    0x002e     U002e  # period
    0x002f     U002f  # slash
    0x0030     U0030  # 0
    0x0031     U0031  # 1
    0x0032     U0032  # 2
    0x0033     U0033  # 3
    0x0034     U0034  # 4
    0x0035     U0035  # 5
    0x0036     U0036  # 6
    0x0037     U0037  # 7
    0x0038     U0038  # 8
    0x0039     U0039  # 9
    0x003a     U003a  # colon
    0x003b     U003b  # semicolon
    0x003c     U003c  # less
    0x003d     U003d  # equal
    0x003e     U003e  # greater
    0x003f     U003f  # question
    0x0040     U0040  # at
    0x0041     U0041  # A
    0x0042     U0042  # B
    0x0043     U0043  # C
    0x0044     U0044  # D
    0x0045     U0045  # E
    0x0046     U0046  # F
    0x0047     U0047  # G
    0x0048     U0048  # H
    0x0049     U0049  # I
    0x004a     U004a  # J
    0x004b     U004b  # K
    0x004c     U004c  # L
    0x004d     U004d  # M
    0x004e     U004e  # N
    0x004f     U004f  # O
    0x0050     U0050  # P
    0x0051     U0051  # Q
    0x0052     U0052  # R
    0x0053     U0053  # S
    0x0054     U0054  # T
    0x0055     U0055  # U
    0x0056     U0056  # V
    0x0057     U0057  # W
    0x0058     U0058  # X
    0x0059     U0059  # Y
    0x005a     U005a  # Z
    0x005b     U005b  # bracketleft
    0x005c     U005c  # backslash
    0x005d     U005d  # bracketright
    0x005e     U005e  # asciicircum
    0x005f     U005f  # underscore
    0x0060     U0060  # grave
    0x0061     U0061  # a
    0x0062     U0062  # b
    0x0063     U0063  # c
    0x0064     U0064  # d
    0x0065     U0065  # e
    0x0066     U0066  # f
    0x0067     U0067  # g
    0x0068     U0068  # h
    0x0069     U0069  # i
    0x006a     U006a  # j
    0x006b     U006b  # k
    0x006c     U006c  # l
    0x006d     U006d  # m
    0x006e     U006e  # n
    0x006f     U006f  # o
    0x0070     U0070  # p
    0x0071     U0071  # q
    0x0072     U0072  # r
    0x0073     U0073  # s
    0x0074     U0074  # t
    0x0075     U0075  # u
    0x0076     U0076  # v
    0x0077     U0077  # w
    0x0078     U0078  # x
    0x0079     U0079  # y
    0x007a     U007a  # z
    0x007b     U007b  # braceleft
    0x007c     U007c  # bar
    0x007d     U007d  # braceright
    0x007e     U007e  # asciitilde
    0x00a0     U00a0  # nobreakspace
    0x00a1     U00a1  # exclamdown
    0x00a2     U00a2  # cent
    0x00a3     U00a3  # sterling
    0x00a4     U00a4  # currency
    0x00a5     U00a5  # yen
    0x00a6     U00a6  # brokenbar
    0x00a7     U00a7  # section
    0x00a8     U00a8  # diaeresis
    0x00a9     U00a9  # copyright
    0x00aa     U00aa  # ordfeminine
    0x00ab     U00ab  # guillemotleft	/* left angle quotation mark */
    0x00ac     U00ac  # notsign
    0x00ad     U00ad  # hyphen
    0x00ae     U00ae  # registered
    0x00af     U00af  # macron
    0x00b0     U00b0  # degree
    0x00b1     U00b1  # plusminus
    0x00b2     U00b2  # twosuperior
    0x00b3     U00b3  # threesuperior
    0x00b4     U00b4  # acute
    0x00b5     U00b5  # mu
    0x00b6     U00b6  # paragraph
    0x00b7     U00b7  # periodcentered
    0x00b8     U00b8  # cedilla
    0x00b9     U00b9  # onesuperior
    0x00ba     U00ba  # masculine
    0x00bb     U00bb  # guillemotright	/* right angle quotation mark */
    0x00bc     U00bc  # onequarter
    0x00bd     U00bd  # onehalf
    0x00be     U00be  # threequarters
    0x00bf     U00bf  # questiondown
    0x00c0     U00c0  # Agrave
    0x00c1     U00c1  # Aacute
    0x00c2     U00c2  # Acircumflex
    0x00c3     U00c3  # Atilde
    0x00c4     U00c4  # Adiaeresis
    0x00c5     U00c5  # Aring
    0x00c6     U00c6  # AE
    0x00c7     U00c7  # Ccedilla
    0x00c8     U00c8  # Egrave
    0x00c9     U00c9  # Eacute
    0x00ca     U00ca  # Ecircumflex
    0x00cb     U00cb  # Ediaeresis
    0x00cc     U00cc  # Igrave
    0x00cd     U00cd  # Iacute
    0x00ce     U00ce  # Icircumflex
    0x00cf     U00cf  # Idiaeresis
    0x00d0     U00d0  # ETH
    0x00d1     U00d1  # Ntilde
    0x00d2     U00d2  # Ograve
    0x00d3     U00d3  # Oacute
    0x00d4     U00d4  # Ocircumflex
    0x00d5     U00d5  # Otilde
    0x00d6     U00d6  # Odiaeresis
    0x00d7     U00d7  # multiply
    0x00d8     U00d8  # Oslash
    0x00d9     U00d9  # Ugrave
    0x00da     U00da  # Uacute
    0x00db     U00db  # Ucircumflex
    0x00dc     U00dc  # Udiaeresis
    0x00dd     U00dd  # Yacute
    0x00de     U00de  # THORN
    0x00df     U00df  # ssharp
    0x00e0     U00e0  # agrave
    0x00e1     U00e1  # aacute
    0x00e2     U00e2  # acircumflex
    0x00e3     U00e3  # atilde
    0x00e4     U00e4  # adiaeresis
    0x00e5     U00e5  # aring
    0x00e6     U00e6  # ae
    0x00e7     U00e7  # ccedilla
    0x00e8     U00e8  # egrave
    0x00e9     U00e9  # eacute
    0x00ea     U00ea  # ecircumflex
    0x00eb     U00eb  # ediaeresis
    0x00ec     U00ec  # igrave
    0x00ed     U00ed  # iacute
    0x00ee     U00ee  # icircumflex
    0x00ef     U00ef  # idiaeresis
    0x00f0     U00f0  # eth
    0x00f1     U00f1  # ntilde
    0x00f2     U00f2  # ograve
    0x00f3     U00f3  # oacute
    0x00f4     U00f4  # ocircumflex
    0x00f5     U00f5  # otilde
    0x00f6     U00f6  # odiaeresis
    0x00f7     U00f7  # division
    0x00f8     U00f8  # oslash
    0x00f9     U00f9  # ugrave
    0x00fa     U00fa  # uacute
    0x00fb     U00fb  # ucircumflex
    0x00fc     U00fc  # udiaeresis
    0x00fd     U00fd  # yacute
    0x00fe     U00fe  # thorn
    0x00ff     U00ff  # ydiaeresis
    0x01a1     U0104  # Aogonek
    0x01a2     U02d8  # breve
    0x01a3     U0141  # Lstroke
    0x01a5     U013d  # Lcaron
    0x01a6     U015a  # Sacute
    0x01a9     U0160  # Scaron
    0x01aa     U015e  # Scedilla
    0x01ab     U0164  # Tcaron
    0x01ac     U0179  # Zacute
    0x01ae     U017d  # Zcaron
    0x01af     U017b  # Zabovedot
    0x01b1     U0105  # aogonek
    0x01b2     U02db  # ogonek
    0x01b3     U0142  # lstroke
    0x01b5     U013e  # lcaron
    0x01b6     U015b  # sacute
    0x01b7     U02c7  # caron
    0x01b9     U0161  # scaron
    0x01ba     U015f  # scedilla
    0x01bb     U0165  # tcaron
    0x01bc     U017a  # zacute
    0x01bd     U02dd  # doubleacute
    0x01be     U017e  # zcaron
    0x01bf     U017c  # zabovedot
    0x01c0     U0154  # Racute
    0x01c3     U0102  # Abreve
    0x01c5     U0139  # Lacute
    0x01c6     U0106  # Cacute
    0x01c8     U010c  # Ccaron
    0x01ca     U0118  # Eogonek
    0x01cc     U011a  # Ecaron
    0x01cf     U010e  # Dcaron
    0x01d0     U0110  # Dstroke
    0x01d1     U0143  # Nacute
    0x01d2     U0147  # Ncaron
    0x01d5     U0150  # Odoubleacute
    0x01d8     U0158  # Rcaron
    0x01d9     U016e  # Uring
    0x01db     U0170  # Udoubleacute
    0x01de     U0162  # Tcedilla
    0x01e0     U0155  # racute
    0x01e3     U0103  # abreve
    0x01e5     U013a  # lacute
    0x01e6     U0107  # cacute
    0x01e8     U010d  # ccaron
    0x01ea     U0119  # eogonek
    0x01ec     U011b  # ecaron
    0x01ef     U010f  # dcaron
    0x01f0     U0111  # dstroke
    0x01f1     U0144  # nacute
    0x01f2     U0148  # ncaron
    0x01f5     U0151  # odoubleacute
    0x01f8     U0159  # rcaron
    0x01f9     U016f  # uring
    0x01fb     U0171  # udoubleacute
    0x01fe     U0163  # tcedilla
    0x01ff     U02d9  # abovedot
    0x02a1     U0126  # Hstroke
    0x02a6     U0124  # Hcircumflex
    0x02a9     U0130  # Iabovedot
    0x02ab     U011e  # Gbreve
    0x02ac     U0134  # Jcircumflex
    0x02b1     U0127  # hstroke
    0x02b6     U0125  # hcircumflex
    0x02b9     U0131  # idotless
    0x02bb     U011f  # gbreve
    0x02bc     U0135  # jcircumflex
    0x02c5     U010a  # Cabovedot
    0x02c6     U0108  # Ccircumflex
    0x02d5     U0120  # Gabovedot
    0x02d8     U011c  # Gcircumflex
    0x02dd     U016c  # Ubreve
    0x02de     U015c  # Scircumflex
    0x02e5     U010b  # cabovedot
    0x02e6     U0109  # ccircumflex
    0x02f5     U0121  # gabovedot
    0x02f8     U011d  # gcircumflex
    0x02fd     U016d  # ubreve
    0x02fe     U015d  # scircumflex
    0x03a2     U0138  # kra
    0x03a3     U0156  # Rcedilla
    0x03a5     U0128  # Itilde
    0x03a6     U013b  # Lcedilla
    0x03aa     U0112  # Emacron
    0x03ab     U0122  # Gcedilla
    0x03ac     U0166  # Tslash
    0x03b3     U0157  # rcedilla
    0x03b5     U0129  # itilde
    0x03b6     U013c  # lcedilla
    0x03ba     U0113  # emacron
    0x03bb     U0123  # gcedilla
    0x03bc     U0167  # tslash
    0x03bd     U014a  # ENG
    0x03bf     U014b  # eng
    0x03c0     U0100  # Amacron
    0x03c7     U012e  # Iogonek
    0x03cc     U0116  # Eabovedot
    0x03cf     U012a  # Imacron
    0x03d1     U0145  # Ncedilla
    0x03d2     U014c  # Omacron
    0x03d3     U0136  # Kcedilla
    0x03d9     U0172  # Uogonek
    0x03dd     U0168  # Utilde
    0x03de     U016a  # Umacron
    0x03e0     U0101  # amacron
    0x03e7     U012f  # iogonek
    0x03ec     U0117  # eabovedot
    0x03ef     U012b  # imacron
    0x03f1     U0146  # ncedilla
    0x03f2     U014d  # omacron
    0x03f3     U0137  # kcedilla
    0x03f9     U0173  # uogonek
    0x03fd     U0169  # utilde
    0x03fe     U016b  # umacron
    0x047e     U203e  # overline
    0x04a1     U3002  # kana_fullstop
    0x04a2     U300c  # kana_openingbracket
    0x04a3     U300d  # kana_closingbracket
    0x04a4     U3001  # kana_comma
    0x04a5     U30fb  # kana_conjunctive
    0x04a6     U30f2  # kana_WO
    0x04a7     U30a1  # kana_a
    0x04a8     U30a3  # kana_i
    0x04a9     U30a5  # kana_u
    0x04aa     U30a7  # kana_e
    0x04ab     U30a9  # kana_o
    0x04ac     U30e3  # kana_ya
    0x04ad     U30e5  # kana_yu
    0x04ae     U30e7  # kana_yo
    0x04af     U30c3  # kana_tsu
    0x04b0     U30fc  # prolongedsound
    0x04b1     U30a2  # kana_A
    0x04b2     U30a4  # kana_I
    0x04b3     U30a6  # kana_U
    0x04b4     U30a8  # kana_E
    0x04b5     U30aa  # kana_O
    0x04b6     U30ab  # kana_KA
    0x04b7     U30ad  # kana_KI
    0x04b8     U30af  # kana_KU
    0x04b9     U30b1  # kana_KE
    0x04ba     U30b3  # kana_KO
    0x04bb     U30b5  # kana_SA
    0x04bc     U30b7  # kana_SHI
    0x04bd     U30b9  # kana_SU
    0x04be     U30bb  # kana_SE
    0x04bf     U30bd  # kana_SO
    0x04c0     U30bf  # kana_TA
    0x04c1     U30c1  # kana_CHI
    0x04c2     U30c4  # kana_TSU
    0x04c3     U30c6  # kana_TE
    0x04c4     U30c8  # kana_TO
    0x04c5     U30ca  # kana_NA
    0x04c6     U30cb  # kana_NI
    0x04c7     U30cc  # kana_NU
    0x04c8     U30cd  # kana_NE
    0x04c9     U30ce  # kana_NO
    0x04ca     U30cf  # kana_HA
    0x04cb     U30d2  # kana_HI
    0x04cc     U30d5  # kana_FU
    0x04cd     U30d8  # kana_HE
    0x04ce     U30db  # kana_HO
    0x04cf     U30de  # kana_MA
    0x04d0     U30df  # kana_MI
    0x04d1     U30e0  # kana_MU
    0x04d2     U30e1  # kana_ME
    0x04d3     U30e2  # kana_MO
    0x04d4     U30e4  # kana_YA
    0x04d5     U30e6  # kana_YU
    0x04d6     U30e8  # kana_YO
    0x04d7     U30e9  # kana_RA
    0x04d8     U30ea  # kana_RI
    0x04d9     U30eb  # kana_RU
    0x04da     U30ec  # kana_RE
    0x04db     U30ed  # kana_RO
    0x04dc     U30ef  # kana_WA
    0x04dd     U30f3  # kana_N
    0x04de     U309b  # voicedsound
    0x04df     U309c  # semivoicedsound
    0x05ac     U060c  # Arabic_comma
    0x05bb     U061b  # Arabic_semicolon
    0x05bf     U061f  # Arabic_question_mark
    0x05c1     U0621  # Arabic_hamza
    0x05c2     U0622  # Arabic_maddaonalef
    0x05c3     U0623  # Arabic_hamzaonalef
    0x05c4     U0624  # Arabic_hamzaonwaw
    0x05c5     U0625  # Arabic_hamzaunderalef
    0x05c6     U0626  # Arabic_hamzaonyeh
    0x05c7     U0627  # Arabic_alef
    0x05c8     U0628  # Arabic_beh
    0x05c9     U0629  # Arabic_tehmarbuta
    0x05ca     U062a  # Arabic_teh
    0x05cb     U062b  # Arabic_theh
    0x05cc     U062c  # Arabic_jeem
    0x05cd     U062d  # Arabic_hah
    0x05ce     U062e  # Arabic_khah
    0x05cf     U062f  # Arabic_dal
    0x05d0     U0630  # Arabic_thal
    0x05d1     U0631  # Arabic_ra
    0x05d2     U0632  # Arabic_zain
    0x05d3     U0633  # Arabic_seen
    0x05d4     U0634  # Arabic_sheen
    0x05d5     U0635  # Arabic_sad
    0x05d6     U0636  # Arabic_dad
    0x05d7     U0637  # Arabic_tah
    0x05d8     U0638  # Arabic_zah
    0x05d9     U0639  # Arabic_ain
    0x05da     U063a  # Arabic_ghain
    0x05e0     U0640  # Arabic_tatweel
    0x05e1     U0641  # Arabic_feh
    0x05e2     U0642  # Arabic_qaf
    0x05e3     U0643  # Arabic_kaf
    0x05e4     U0644  # Arabic_lam
    0x05e5     U0645  # Arabic_meem
    0x05e6     U0646  # Arabic_noon
    0x05e7     U0647  # Arabic_ha
    0x05e8     U0648  # Arabic_waw
    0x05e9     U0649  # Arabic_alefmaksura
    0x05ea     U064a  # Arabic_yeh
    0x05eb     U064b  # Arabic_fathatan
    0x05ec     U064c  # Arabic_dammatan
    0x05ed     U064d  # Arabic_kasratan
    0x05ee     U064e  # Arabic_fatha
    0x05ef     U064f  # Arabic_damma
    0x05f0     U0650  # Arabic_kasra
    0x05f1     U0651  # Arabic_shadda
    0x05f2     U0652  # Arabic_sukun
    0x06a1     U0452  # Serbian_dje
    0x06a2     U0453  # Macedonia_gje
    0x06a3     U0451  # Cyrillic_io
    0x06a4     U0454  # Ukrainian_ie
    0x06a5     U0455  # Macedonia_dse
    0x06a6     U0456  # Ukrainian_i
    0x06a7     U0457  # Ukrainian_yi
    0x06a8     U0458  # Cyrillic_je
    0x06a9     U0459  # Cyrillic_lje
    0x06aa     U045a  # Cyrillic_nje
    0x06ab     U045b  # Serbian_tshe
    0x06ac     U045c  # Macedonia_kje
    0x06ad     U0491  # Ukrainian_ghe_with_upturn
    0x06ae     U045e  # Byelorussian_shortu
    0x06af     U045f  # Cyrillic_dzhe
    0x06b0     U2116  # numerosign
    0x06b1     U0402  # Serbian_DJE
    0x06b2     U0403  # Macedonia_GJE
    0x06b3     U0401  # Cyrillic_IO
    0x06b4     U0404  # Ukrainian_IE
    0x06b5     U0405  # Macedonia_DSE
    0x06b6     U0406  # Ukrainian_I
    0x06b7     U0407  # Ukrainian_YI
    0x06b8     U0408  # Cyrillic_JE
    0x06b9     U0409  # Cyrillic_LJE
    0x06ba     U040a  # Cyrillic_NJE
    0x06bb     U040b  # Serbian_TSHE
    0x06bc     U040c  # Macedonia_KJE
    0x06bd     U0490  # Ukrainian_GHE_WITH_UPTURN
    0x06be     U040e  # Byelorussian_SHORTU
    0x06bf     U040f  # Cyrillic_DZHE
    0x06c0     U044e  # Cyrillic_yu
    0x06c1     U0430  # Cyrillic_a
    0x06c2     U0431  # Cyrillic_be
    0x06c3     U0446  # Cyrillic_tse
    0x06c4     U0434  # Cyrillic_de
    0x06c5     U0435  # Cyrillic_ie
    0x06c6     U0444  # Cyrillic_ef
    0x06c7     U0433  # Cyrillic_ghe
    0x06c8     U0445  # Cyrillic_ha
    0x06c9     U0438  # Cyrillic_i
    0x06ca     U0439  # Cyrillic_shorti
    0x06cb     U043a  # Cyrillic_ka
    0x06cc     U043b  # Cyrillic_el
    0x06cd     U043c  # Cyrillic_em
    0x06ce     U043d  # Cyrillic_en
    0x06cf     U043e  # Cyrillic_o
    0x06d0     U043f  # Cyrillic_pe
    0x06d1     U044f  # Cyrillic_ya
    0x06d2     U0440  # Cyrillic_er
    0x06d3     U0441  # Cyrillic_es
    0x06d4     U0442  # Cyrillic_te
    0x06d5     U0443  # Cyrillic_u
    0x06d6     U0436  # Cyrillic_zhe
    0x06d7     U0432  # Cyrillic_ve
    0x06d8     U044c  # Cyrillic_softsign
    0x06d9     U044b  # Cyrillic_yeru
    0x06da     U0437  # Cyrillic_ze
    0x06db     U0448  # Cyrillic_sha
    0x06dc     U044d  # Cyrillic_e
    0x06dd     U0449  # Cyrillic_shcha
    0x06de     U0447  # Cyrillic_che
    0x06df     U044a  # Cyrillic_hardsign
    0x06e0     U042e  # Cyrillic_YU
    0x06e1     U0410  # Cyrillic_A
    0x06e2     U0411  # Cyrillic_BE
    0x06e3     U0426  # Cyrillic_TSE
    0x06e4     U0414  # Cyrillic_DE
    0x06e5     U0415  # Cyrillic_IE
    0x06e6     U0424  # Cyrillic_EF
    0x06e7     U0413  # Cyrillic_GHE
    0x06e8     U0425  # Cyrillic_HA
    0x06e9     U0418  # Cyrillic_I
    0x06ea     U0419  # Cyrillic_SHORTI
    0x06eb     U041a  # Cyrillic_KA
    0x06ec     U041b  # Cyrillic_EL
    0x06ed     U041c  # Cyrillic_EM
    0x06ee     U041d  # Cyrillic_EN
    0x06ef     U041e  # Cyrillic_O
    0x06f0     U041f  # Cyrillic_PE
    0x06f1     U042f  # Cyrillic_YA
    0x06f2     U0420  # Cyrillic_ER
    0x06f3     U0421  # Cyrillic_ES
    0x06f4     U0422  # Cyrillic_TE
    0x06f5     U0423  # Cyrillic_U
    0x06f6     U0416  # Cyrillic_ZHE
    0x06f7     U0412  # Cyrillic_VE
    0x06f8     U042c  # Cyrillic_SOFTSIGN
    0x06f9     U042b  # Cyrillic_YERU
    0x06fa     U0417  # Cyrillic_ZE
    0x06fb     U0428  # Cyrillic_SHA
    0x06fc     U042d  # Cyrillic_E
    0x06fd     U0429  # Cyrillic_SHCHA
    0x06fe     U0427  # Cyrillic_CHE
    0x06ff     U042a  # Cyrillic_HARDSIGN
    0x07a1     U0386  # Greek_ALPHAaccent
    0x07a2     U0388  # Greek_EPSILONaccent
    0x07a3     U0389  # Greek_ETAaccent
    0x07a4     U038a  # Greek_IOTAaccent
    0x07a5     U03aa  # Greek_IOTAdieresis
    0x07a7     U038c  # Greek_OMICRONaccent
    0x07a8     U038e  # Greek_UPSILONaccent
    0x07a9     U03ab  # Greek_UPSILONdieresis
    0x07ab     U038f  # Greek_OMEGAaccent
    0x07ae     U0385  # Greek_accentdieresis
    0x07af     U2015  # Greek_horizbar
    0x07b1     U03ac  # Greek_alphaaccent
    0x07b2     U03ad  # Greek_epsilonaccent
    0x07b3     U03ae  # Greek_etaaccent
    0x07b4     U03af  # Greek_iotaaccent
    0x07b5     U03ca  # Greek_IOTAdieresis
    0x07b6     U0390  # Greek_iotaaccentdieresis
    0x07b7     U03cc  # Greek_omicronaccent
    0x07b8     U03cd  # Greek_upsilonaccent
    0x07b9     U03cb  # Greek_upsilondieresis
    0x07ba     U03b0  # Greek_upsilonaccentdieresis
    0x07bb     U03ce  # Greek_omegaaccent
    0x07c1     U0391  # Greek_ALPHA
    0x07c2     U0392  # Greek_BETA
    0x07c3     U0393  # Greek_GAMMA
    0x07c4     U0394  # Greek_DELTA
    0x07c5     U0395  # Greek_EPSILON
    0x07c6     U0396  # Greek_ZETA
    0x07c7     U0397  # Greek_ETA
    0x07c8     U0398  # Greek_THETA
    0x07c9     U0399  # Greek_IOTA
    0x07ca     U039a  # Greek_KAPPA
    0x07cb     U039b  # Greek_LAMBDA
    0x07cb     U039b  # Greek_LAMDA
    0x07cc     U039c  # Greek_MU
    0x07cd     U039d  # Greek_NU
    0x07ce     U039e  # Greek_XI
    0x07cf     U039f  # Greek_OMICRON
    0x07d0     U03a0  # Greek_PI
    0x07d1     U03a1  # Greek_RHO
    0x07d2     U03a3  # Greek_SIGMA
    0x07d4     U03a4  # Greek_TAU
    0x07d5     U03a5  # Greek_UPSILON
    0x07d6     U03a6  # Greek_PHI
    0x07d7     U03a7  # Greek_CHI
    0x07d8     U03a8  # Greek_PSI
    0x07d9     U03a9  # Greek_OMEGA
    0x07e1     U03b1  # Greek_alpha
    0x07e2     U03b2  # Greek_beta
    0x07e3     U03b3  # Greek_gamma
    0x07e4     U03b4  # Greek_delta
    0x07e5     U03b5  # Greek_epsilon
    0x07e6     U03b6  # Greek_zeta
    0x07e7     U03b7  # Greek_eta
    0x07e8     U03b8  # Greek_theta
    0x07e9     U03b9  # Greek_iota
    0x07ea     U03ba  # Greek_kappa
    0x07eb     U03bb  # Greek_lambda
    0x07ec     U03bc  # Greek_mu
    0x07ed     U03bd  # Greek_nu
    0x07ee     U03be  # Greek_xi
    0x07ef     U03bf  # Greek_omicron
    0x07f0     U03c0  # Greek_pi
    0x07f1     U03c1  # Greek_rho
    0x07f2     U03c3  # Greek_sigma
    0x07f3     U03c2  # Greek_finalsmallsigma
    0x07f4     U03c4  # Greek_tau
    0x07f5     U03c5  # Greek_upsilon
    0x07f6     U03c6  # Greek_phi
    0x07f7     U03c7  # Greek_chi
    0x07f8     U03c8  # Greek_psi
    0x07f9     U03c9  # Greek_omega
    0x08a1     U23b7  # leftradical
    0x08a2     U250c  # topleftradical
    0x08a3     U2500  # horizconnector
    0x08a4     U2320  # topintegral
    0x08a5     U2321  # botintegral
    0x08a6     U2502  # vertconnector
    0x08a7     U23a1  # topleftsqbracket
    0x08a8     U23a3  # botleftsqbracket
    0x08a9     U23a4  # toprightsqbracket
    0x08aa     U23a6  # botrightsqbracket
    0x08ab     U239b  # topleftparens
    0x08ac     U239d  # botleftparens
    0x08ad     U239e  # toprightparens
    0x08ae     U23a0  # botrightparens
    0x08af     U23a8  # leftmiddlecurlybrace
    0x08b0     U23ac  # rightmiddlecurlybrace
    0x08b1     U0000  # topleftsummation
    0x08b2     U0000  # botleftsummation
    0x08b3     U0000  # topvertsummationconnector
    0x08b4     U0000  # botvertsummationconnector
    0x08b5     U0000  # toprightsummation
    0x08b6     U0000  # botrightsummation
    0x08b7     U0000  # rightmiddlesummation
    0x08bc     U2264  # lessthanequal
    0x08bd     U2260  # notequal
    0x08be     U2265  # greaterthanequal
    0x08bf     U222b  # integral
    0x08c0     U2234  # therefore
    0x08c1     U221d  # variation
    0x08c2     U221e  # infinity
    0x08c5     U2207  # nabla
    0x08c8     U223c  # approximate
    0x08c9     U2243  # similarequal
    0x08cd     U21d4  # ifonlyif
    0x08ce     U21d2  # implies
    0x08cf     U2261  # identical
    0x08d6     U221a  # radical
    0x08da     U2282  # includedin
    0x08db     U2283  # includes
    0x08dc     U2229  # intersection
    0x08dd     U222a  # union
    0x08de     U2227  # logicaland
    0x08df     U2228  # logicalor
    0x08ef     U2202  # partialderivative
    0x08f6     U0192  # function
    0x08fb     U2190  # leftarrow
    0x08fc     U2191  # uparrow
    0x08fd     U2192  # rightarrow
    0x08fe     U2193  # downarrow
    0x09df     U2422  # blank
    0x09e0     U25c6  # soliddiamond
    0x09e1     U2592  # checkerboard
    0x09e2     U2409  # ht
    0x09e3     U240c  # ff
    0x09e4     U240d  # cr
    0x09e5     U240a  # lf
    0x09e8     U2424  # nl
    0x09e9     U240b  # vt
    0x09ea     U2518  # lowrightcorner
    0x09eb     U2510  # uprightcorner
    0x09ec     U250c  # upleftcorner
    0x09ed     U2514  # lowleftcorner
    0x09ee     U253c  # crossinglines
    0x09ef     U23ba  # horizlinescan1
    0x09f0     U23bb  # horizlinescan3
    0x09f1     U2500  # horizlinescan5
    0x09f2     U23bc  # horizlinescan7
    0x09f3     U23bd  # horizlinescan9
    0x09f4     U251c  # leftt
    0x09f5     U2524  # rightt
    0x09f6     U2534  # bott
    0x09f7     U252c  # topt
    0x09f8     U2502  # vertbar
    0x0aa1     U2003  # emspace
    0x0aa2     U2002  # enspace
    0x0aa3     U2004  # em3space
    0x0aa4     U2005  # em4space
    0x0aa5     U2007  # digitspace
    0x0aa6     U2008  # punctspace
    0x0aa7     U2009  # thinspace
    0x0aa8     U200a  # hairspace
    0x0aa9     U2014  # emdash
    0x0aaa     U2013  # endash
    0x0aac     U2423  # signifblank
    0x0aae     U2026  # ellipsis
    0x0aaf     U2025  # doubbaselinedot
    0x0ab0     U2153  # onethird
    0x0ab1     U2154  # twothirds
    0x0ab2     U2155  # onefifth
    0x0ab3     U2156  # twofifths
    0x0ab4     U2157  # threefifths
    0x0ab5     U2158  # fourfifths
    0x0ab6     U2159  # onesixth
    0x0ab7     U215a  # fivesixths
    0x0ab8     U2105  # careof
    0x0abb     U2012  # figdash
    0x0abc     U2329  # leftanglebracket (not U+27E8)
    0x0abd     U002e  # decimalpoint
    0x0abe     U232a  # rightanglebracket (not U+27E9)
    0x0abf     U0000  # marker
    0x0ac3     U215b  # oneeighth
    0x0ac4     U215c  # threeeighths
    0x0ac5     U215d  # fiveeighths
    0x0ac6     U215e  # seveneighths
    0x0ac9     U2122  # trademark
    0x0aca     U2613  # signaturemark
    0x0acb     U0000  # trademarkincircle
    0x0acc     U25c1  # leftopentriangle
    0x0acd     U25b7  # rightopentriangle
    0x0ace     U25cb  # emopencircle
    0x0acf     U25af  # emopenrectangle
    0x0ad0     U2018  # leftsinglequotemark
    0x0ad1     U2019  # rightsinglequotemark
    0x0ad2     U201c  # leftdoublequotemark
    0x0ad3     U201d  # rightdoublequotemark
    0x0ad4     U211e  # prescription
    0x0ad5     U2030  # per mille
    0x0ad6     U2032  # minutes
    0x0ad7     U2033  # seconds
    0x0ad9     U271d  # latincross
    0x0ada     U0000  # hexagram
    0x0adb     U25ac  # filledrectbullet
    0x0adc     U25c0  # filledlefttribullet
    0x0add     U25b6  # filledrighttribullet
    0x0ade     U25cf  # emfilledcircle
    0x0adf     U25ae  # emfilledrect
    0x0ae0     U25e6  # enopencircbullet
    0x0ae1     U25ab  # enopensquarebullet
    0x0ae2     U25ad  # openrectbullet
    0x0ae3     U25b3  # opentribulletup
    0x0ae4     U25bd  # opentribulletdown
    0x0ae5     U2606  # openstar
    0x0ae6     U2022  # enfilledcircbullet
    0x0ae7     U25aa  # enfilledsqbullet
    0x0ae8     U25b2  # filledtribulletup
    0x0ae9     U25bc  # filledtribulletdown
    0x0aea     U261c  # leftpointer
    0x0aeb     U261e  # rightpointer
    0x0aec     U2663  # club
    0x0aed     U2666  # diamond
    0x0aee     U2665  # heart
    0x0af0     U2720  # maltesecross
    0x0af1     U2020  # dagger
    0x0af2     U2021  # doubledagger
    0x0af3     U2713  # checkmark
    0x0af4     U2717  # ballotcross
    0x0af5     U266f  # musicalsharp
    0x0af6     U266d  # musicalflat
    0x0af7     U2642  # malesymbol
    0x0af8     U2640  # femalesymbol
    0x0af9     U260e  # telephone
    0x0afa     U2315  # telephonerecorder
    0x0afb     U2117  # phonographcopyright
    0x0afc     U2038  # caret
    0x0afd     U201a  # singlelowquotemark
    0x0afe     U201e  # doublelowquotemark
    0x0aff     U0000  # cursor
    0x0ba3     U003c  # leftcaret
    0x0ba6     U003e  # rightcaret
    0x0ba8     U2228  # downcaret
    0x0ba9     U2227  # upcaret
    0x0bc0     U00af  # overbar
    0x0bc2     U22a4  # downtack
    0x0bc3     U2229  # upshoe
    0x0bc4     U230a  # downstile
    0x0bc6     U005f  # underbar
    0x0bca     U2218  # jot
    0x0bcc     U2395  # quad
    0x0bce     U22a5  # uptack
    0x0bcf     U25cb  # circle
    0x0bd3     U2308  # upstile
    0x0bd6     U222a  # downshoe
    0x0bd8     U2283  # rightshoe
    0x0bda     U2282  # leftshoe
    0x0bdc     U22a3  # lefttack
    0x0bfc     U22a2  # righttack
    0x0cdf     U2017  # hebrew_doublelowline
    0x0ce0     U05d0  # hebrew_aleph
    0x0ce1     U05d1  # hebrew_bet
    0x0ce2     U05d2  # hebrew_gimel
    0x0ce3     U05d3  # hebrew_dalet
    0x0ce4     U05d4  # hebrew_he
    0x0ce5     U05d5  # hebrew_waw
    0x0ce6     U05d6  # hebrew_zain
    0x0ce7     U05d7  # hebrew_chet
    0x0ce8     U05d8  # hebrew_tet
    0x0ce9     U05d9  # hebrew_yod
    0x0cea     U05da  # hebrew_finalkaph
    0x0ceb     U05db  # hebrew_kaph
    0x0cec     U05dc  # hebrew_lamed
    0x0ced     U05dd  # hebrew_finalmem
    0x0cee     U05de  # hebrew_mem
    0x0cef     U05df  # hebrew_finalnun
    0x0cf0     U05e0  # hebrew_nun
    0x0cf1     U05e1  # hebrew_samech
    0x0cf2     U05e2  # hebrew_ayin
    0x0cf3     U05e3  # hebrew_finalpe
    0x0cf4     U05e4  # hebrew_pe
    0x0cf5     U05e5  # hebrew_finalzade
    0x0cf6     U05e6  # hebrew_zade
    0x0cf7     U05e7  # hebrew_qoph
    0x0cf8     U05e8  # hebrew_resh
    0x0cf9     U05e9  # hebrew_shin
    0x0cfa     U05ea  # hebrew_taw
    0x0da1     U0e01  # Thai_kokai
    0x0da2     U0e02  # Thai_khokhai
    0x0da3     U0e03  # Thai_khokhuat
    0x0da4     U0e04  # Thai_khokhwai
    0x0da5     U0e05  # Thai_khokhon
    0x0da6     U0e06  # Thai_khorakhang
    0x0da7     U0e07  # Thai_ngongu
    0x0da8     U0e08  # Thai_chochan
    0x0da9     U0e09  # Thai_choching
    0x0daa     U0e0a  # Thai_chochang
    0x0dab     U0e0b  # Thai_soso
    0x0dac     U0e0c  # Thai_chochoe
    0x0dad     U0e0d  # Thai_yoying
    0x0dae     U0e0e  # Thai_dochada
    0x0daf     U0e0f  # Thai_topatak
    0x0db0     U0e10  # Thai_thothan
    0x0db1     U0e11  # Thai_thonangmontho
    0x0db2     U0e12  # Thai_thophuthao
    0x0db3     U0e13  # Thai_nonen
    0x0db4     U0e14  # Thai_dodek
    0x0db5     U0e15  # Thai_totao
    0x0db6     U0e16  # Thai_thothung
    0x0db7     U0e17  # Thai_thothahan
    0x0db8     U0e18  # Thai_thothong
    0x0db9     U0e19  # Thai_nonu
    0x0dba     U0e1a  # Thai_bobaimai
    0x0dbb     U0e1b  # Thai_popla
    0x0dbc     U0e1c  # Thai_phophung
    0x0dbd     U0e1d  # Thai_fofa
    0x0dbe     U0e1e  # Thai_phophan
    0x0dbf     U0e1f  # Thai_fofan
    0x0dc0     U0e20  # Thai_phosamphao
    0x0dc1     U0e21  # Thai_moma
    0x0dc2     U0e22  # Thai_yoyak
    0x0dc3     U0e23  # Thai_rorua
    0x0dc4     U0e24  # Thai_ru
    0x0dc5     U0e25  # Thai_loling
    0x0dc6     U0e26  # Thai_lu
    0x0dc7     U0e27  # Thai_wowaen
    0x0dc8     U0e28  # Thai_sosala
    0x0dc9     U0e29  # Thai_sorusi
    0x0dca     U0e2a  # Thai_sosua
    0x0dcb     U0e2b  # Thai_hohip
    0x0dcc     U0e2c  # Thai_lochula
    0x0dcd     U0e2d  # Thai_oang
    0x0dce     U0e2e  # Thai_honokhuk
    0x0dcf     U0e2f  # Thai_paiyannoi
    0x0dd0     U0e30  # Thai_saraa
    0x0dd1     U0e31  # Thai_maihanakat
    0x0dd2     U0e32  # Thai_saraaa
    0x0dd3     U0e33  # Thai_saraam
    0x0dd4     U0e34  # Thai_sarai
    0x0dd5     U0e35  # Thai_saraii
    0x0dd6     U0e36  # Thai_saraue
    0x0dd7     U0e37  # Thai_sarauee
    0x0dd8     U0e38  # Thai_sarau
    0x0dd9     U0e39  # Thai_sarauu
    0x0dda     U0e3a  # Thai_phinthu
    0x0dde     U0000  # Thai_maihanakat_maitho
    0x0ddf     U0e3f  # Thai_baht
    0x0de0     U0e40  # Thai_sarae
    0x0de1     U0e41  # Thai_saraae
    0x0de2     U0e42  # Thai_sarao
    0x0de3     U0e43  # Thai_saraaimaimuan
    0x0de4     U0e44  # Thai_saraaimaimalai
    0x0de5     U0e45  # Thai_lakkhangyao
    0x0de6     U0e46  # Thai_maiyamok
    0x0de7     U0e47  # Thai_maitaikhu
    0x0de8     U0e48  # Thai_maiek
    0x0de9     U0e49  # Thai_maitho
    0x0dea     U0e4a  # Thai_maitri
    0x0deb     U0e4b  # Thai_maichattawa
    0x0dec     U0e4c  # Thai_thanthakhat
    0x0ded     U0e4d  # Thai_nikhahit
    0x0df0     U0e50  # Thai_leksun
    0x0df1     U0e51  # Thai_leknung
    0x0df2     U0e52  # Thai_leksong
    0x0df3     U0e53  # Thai_leksam
    0x0df4     U0e54  # Thai_leksi
    0x0df5     U0e55  # Thai_lekha
    0x0df6     U0e56  # Thai_lekhok
    0x0df7     U0e57  # Thai_lekchet
    0x0df8     U0e58  # Thai_lekpaet
    0x0df9     U0e59  # Thai_lekkao
    0x0ea1     U3131  # Hangul_Kiyeog
    0x0ea2     U3132  # Hangul_SsangKiyeog
    0x0ea3     U3133  # Hangul_KiyeogSios
    0x0ea4     U3134  # Hangul_Nieun
    0x0ea5     U3135  # Hangul_NieunJieuj
    0x0ea6     U3136  # Hangul_NieunHieuh
    0x0ea7     U3137  # Hangul_Dikeud
    0x0ea8     U3138  # Hangul_SsangDikeud
    0x0ea9     U3139  # Hangul_Rieul
    0x0eaa     U313a  # Hangul_RieulKiyeog
    0x0eab     U313b  # Hangul_RieulMieum
    0x0eac     U313c  # Hangul_RieulPieub
    0x0ead     U313d  # Hangul_RieulSios
    0x0eae     U313e  # Hangul_RieulTieut
    0x0eaf     U313f  # Hangul_RieulPhieuf
    0x0eb0     U3140  # Hangul_RieulHieuh
    0x0eb1     U3141  # Hangul_Mieum
    0x0eb2     U3142  # Hangul_Pieub
    0x0eb3     U3143  # Hangul_SsangPieub
    0x0eb4     U3144  # Hangul_PieubSios
    0x0eb5     U3145  # Hangul_Sios
    0x0eb6     U3146  # Hangul_SsangSios
    0x0eb7     U3147  # Hangul_Ieung
    0x0eb8     U3148  # Hangul_Jieuj
    0x0eb9     U3149  # Hangul_SsangJieuj
    0x0eba     U314a  # Hangul_Cieuc
    0x0ebb     U314b  # Hangul_Khieuq
    0x0ebc     U314c  # Hangul_Tieut
    0x0ebd     U314d  # Hangul_Phieuf
    0x0ebe     U314e  # Hangul_Hieuh
    0x0ebf     U314f  # Hangul_A
    0x0ec0     U3150  # Hangul_AE
    0x0ec1     U3151  # Hangul_YA
    0x0ec2     U3152  # Hangul_YAE
    0x0ec3     U3153  # Hangul_EO
    0x0ec4     U3154  # Hangul_E
    0x0ec5     U3155  # Hangul_YEO
    0x0ec6     U3156  # Hangul_YE
    0x0ec7     U3157  # Hangul_O
    0x0ec8     U3158  # Hangul_WA
    0x0ec9     U3159  # Hangul_WAE
    0x0eca     U315a  # Hangul_OE
    0x0ecb     U315b  # Hangul_YO
    0x0ecc     U315c  # Hangul_U
    0x0ecd     U315d  # Hangul_WEO
    0x0ece     U315e  # Hangul_WE
    0x0ecf     U315f  # Hangul_WI
    0x0ed0     U3160  # Hangul_YU
    0x0ed1     U3161  # Hangul_EU
    0x0ed2     U3162  # Hangul_YI
    0x0ed3     U3163  # Hangul_I
    0x0ed4     U11a8  # Hangul_J_Kiyeog
    0x0ed5     U11a9  # Hangul_J_SsangKiyeog
    0x0ed6     U11aa  # Hangul_J_KiyeogSios
    0x0ed7     U11ab  # Hangul_J_Nieun
    0x0ed8     U11ac  # Hangul_J_NieunJieuj
    0x0ed9     U11ad  # Hangul_J_NieunHieuh
    0x0eda     U11ae  # Hangul_J_Dikeud
    0x0edb     U11af  # Hangul_J_Rieul
    0x0edc     U11b0  # Hangul_J_RieulKiyeog
    0x0edd     U11b1  # Hangul_J_RieulMieum
    0x0ede     U11b2  # Hangul_J_RieulPieub
    0x0edf     U11b3  # Hangul_J_RieulSios
    0x0ee0     U11b4  # Hangul_J_RieulTieut
    0x0ee1     U11b5  # Hangul_J_RieulPhieuf
    0x0ee2     U11b6  # Hangul_J_RieulHieuh
    0x0ee3     U11b7  # Hangul_J_Mieum
    0x0ee4     U11b8  # Hangul_J_Pieub
    0x0ee5     U11b9  # Hangul_J_PieubSios
    0x0ee6     U11ba  # Hangul_J_Sios
    0x0ee7     U11bb  # Hangul_J_SsangSios
    0x0ee8     U11bc  # Hangul_J_Ieung
    0x0ee9     U11bd  # Hangul_J_Jieuj
    0x0eea     U11be  # Hangul_J_Cieuc
    0x0eeb     U11bf  # Hangul_J_Khieuq
    0x0eec     U11c0  # Hangul_J_Tieut
    0x0eed     U11c1  # Hangul_J_Phieuf
    0x0eee     U11c2  # Hangul_J_Hieuh
    0x0eef     U316d  # Hangul_RieulYeorinHieuh
    0x0ef0     U3171  # Hangul_SunkyeongeumMieum
    0x0ef1     U3178  # Hangul_SunkyeongeumPieub
    0x0ef2     U317f  # Hangul_PanSios
    0x0ef3     U3181  # Hangul_KkogjiDalrinIeung
    0x0ef4     U3184  # Hangul_SunkyeongeumPhieuf
    0x0ef5     U3186  # Hangul_YeorinHieuh
    0x0ef6     U318d  # Hangul_AraeA
    0x0ef7     U318e  # Hangul_AraeAE
    0x0ef8     U11eb  # Hangul_J_PanSios
    0x0ef9     U11f0  # Hangul_J_KkogjiDalrinIeung
    0x0efa     U11f9  # Hangul_J_YeorinHieuh
    0x0eff     U20a9  # Korean_Won
    0x13a4     U20ac  # Euro
    0x13bc     U0152  # OE
    0x13bd     U0153  # oe
    0x13be     U0178  # Ydiaeresis
    0x20a0     U20a0  # EcuSign
    0x20a1     U20a1  # ColonSign
    0x20a2     U20a2  # CruzeiroSign
    0x20a3     U20a3  # FFrancSign
    0x20a4     U20a4  # LiraSign
    0x20a5     U20a5  # MillSign
    0x20a6     U20a6  # NairaSign
    0x20a7     U20a7  # PesetaSign
    0x20a8     U20a8  # RupeeSign
    0x20a9     U20a9  # WonSign
    0x20aa     U20aa  # NewSheqelSign
    0x20ab     U20ab  # DongSign
    0x20ac     U20ac  # EuroSign
    0xfe50     U0300  # dead_grave
    0xfe51     U0301  # dead_acute
    0xfe52     U0302  # dead_circumflex
    0xfe53     U0303  # dead_tilde
    0xfe54     U0304  # dead_macron
    0xfe55     U0306  # dead_breve
    0xfe56     U0307  # dead_abovedot
    0xfe57     U0308  # dead_diaeresis
    0xfe58     U030a  # dead_abovering
    0xfe59     U030b  # dead_doubleacute
    0xfe5a     U030c  # dead_caron
    0xfe5b     U0327  # dead_cedilla
    0xfe5c     U0328  # dead_ogonek
    0xfe5d     U0345  # dead_iota
    0xfe5e     U3099  # dead_voiced_sound
    0xfe5f     U309a  # dead_semivoiced_sound
    0xff08     U0008  # BackSpace	/* back space, back char */
    0xff09     U0009  # Tab
    0xff0a     U000a  # Linefeed	/* Linefeed, LF */
    0xff0b     U000b  # Clear
    0xff0d     U000d  # Return	/* Return, enter */
    0xff13     U0013  # Pause	/* Pause, hold */
    0xff14     U0014  # Scroll_Lock
    0xff15     U0015  # Sys_Req
    0xff1b     U001b  # Escape
    0xff80     U0032  # KP_Space	/* space */
    0xff89     U0009  # KP_Tab
    0xff8d     U000d  # KP_Enter	/* enter */
    0xffaa     U002a  # KP_Multiply
    0xffab     U002b  # KP_Add
    0xffac     U002c  # KP_Separator	/* separator, often comma */
    0xffad     U002d  # KP_Subtract
    0xffae     U002e  # KP_Decimal
    0xffaf     U002f  # KP_Divide
    0xffb0     U0030  # KP_0
    0xffb1     U0031  # KP_1
    0xffb2     U0032  # KP_2
    0xffb3     U0033  # KP_3
    0xffb4     U0034  # KP_4
    0xffb5     U0035  # KP_5
    0xffb6     U0036  # KP_6
    0xffb7     U0037  # KP_7
    0xffb8     U0038  # KP_8
    0xffb9     U0039  # KP_9
    0xffbd     U003d  # KP_Equal	/* equals */
    xterm-353/unicode/make-precompose.sh0000755000175100001440000000125210561501434016317 0ustar  tomusers#!/bin/sh
    # $XTermId: make-precompose.sh,v 1.6 2007/02/05 01:06:36 Thomas.Wolff Exp $
    # $XFree86: xc/programs/xterm/unicode/make-precompose.sh,v 1.4 2005/03/29 04:00:32 tsi Exp $
    
    cat precompose.c.head | sed -e's/@/$/g'
    
    # extract canonical decomposition data from UnicodeData.txt,
    # pad hex values to 5 digits,
    # sort numerically on base character, then combining character,
    # then reduce to 4 digits again where possible
    cut UnicodeData.txt -d ";" -f 1,6 |
     grep ";[0-9,A-F]" | grep " " |
     sed -e "s/ /, 0x/;s/^/{ 0x/;s/;/, 0x/;s/$/},/" |
     sed -e "s,0x\(....\)\([^0-9A-Fa-f]\),0x0\1\2,g" |
     (sort -k 3 || sort +2) |
     sed -e "s,0x0\(...[0-9A-Fa-f]\),0x\1,g"
    
    cat precompose.c.tail
    xterm-353/unicode/precompose.c.head0000644000175100001440000000037012361315250016110 0ustar  tomusers/*
     * Canonical Compositions
     *
     * DO NOT EDIT BY HAND! This is generated by the script
     * unicode/make-precompose.sh
     */
    /* @XTermId@ */
    
    #include 
    
    static struct {
      int replacement;
      int base;
      int comb; 
    } precompositions[] = {
    xterm-353/unicode/README0000644000175100001440000000150112720410061013540 0ustar  tomusers-- $XTermId: README,v 1.11 2016/05/22 20:01:53 tom Exp $
    -- $XFree86: xc/programs/xterm/unicode/README,v 1.5 2004/12/01 01:27:49 dickey Exp $
    -- Thomas E. Dickey
    
    These scripts and datafiles are used for generating tables used in the
    UTF-8 implementation in xterm.
    
    To run the convmap.pl script, you will need a copy of UnicodeData.txt
    which is currently available as
    
             ftp://ftp.unicode.org/Public/UNIDATA/UnicodeData.txt
    
    It is a large file (>1Mb), so it is not included in this distribution.
    
    convmap.pl is used to generate ../keysym2ucs.c, e.g.,
    
    	./convmap.pl >../keysym2ucs.c
    
    keysym.map is input data for convmap.pl
    
    The make-precompose.sh script makes the precompose.c file, which is used to
    handle canonical composition. This also needs UnicodeData.txt. It uses
    precompose.c.head and precompose.c.tail as templates.
    xterm-353/unicode/precompose.c.tail0000644000175100001440000000120412720401621016132 0ustar  tomusers};
    
    #define UNICODE_SHIFT 21
    
    int do_precomposition(int base, int comb) {
      int min = 0;
      int max = sizeof(precompositions) / sizeof(precompositions[0]) - 1;
      unsigned long sought = ((unsigned) base << UNICODE_SHIFT) | (unsigned) comb;
    
      /* binary search */
      while (max >= min) {
        int mid = (min + max) / 2;
        unsigned long that = ((unsigned long) precompositions[mid].base << UNICODE_SHIFT) | ((unsigned) precompositions[mid].comb);
        if (that < sought) {
          min = mid + 1;
        } else if (that > sought) {
          max = mid - 1;
        } else {
          return precompositions[mid].replacement;
        }
      }
      /* no match */
      return -1;
    }
    xterm-353/icons/0000755000175100001440000000000012035000420012341 5ustar  tomusersxterm-353/icons/filled-xterm_32x32.xpm0000644000175100001440000001332212034404160016335 0ustar  tomusers/* XPM */
    static char * filled_xterm_32x32_xpm[] = {
    "32 32 225 2",
    "  	c None",
    ". 	c #000000",
    "+ 	c #D9C2C2",
    "@ 	c #EEE5E5",
    "# 	c #EBE0E0",
    "$ 	c #EBE1E1",
    "% 	c #EDE1E1",
    "& 	c #918484",
    "* 	c #FFEEEE",
    "= 	c #F2DCDC",
    "- 	c #403838",
    "; 	c #5A5A5A",
    "> 	c #5B4545",
    ", 	c #FEF2F2",
    "' 	c #E9E9E9",
    ") 	c #856868",
    "! 	c #271D1D",
    "~ 	c #FBCFCF",
    "{ 	c #746060",
    "] 	c #FFFBFB",
    "^ 	c #FFFFFF",
    "/ 	c #FAF0F0",
    "( 	c #5E4949",
    "_ 	c #E3DCDC",
    ": 	c #BAA8A8",
    "< 	c #292020",
    "[ 	c #F1C0C0",
    "} 	c #D9C6C6",
    "| 	c #FFECEC",
    "1 	c #FFE8E8",
    "2 	c #FFFAFA",
    "3 	c #FFF0F0",
    "4 	c #FFEFEF",
    "5 	c #705D5D",
    "6 	c #DED5D5",
    "7 	c #F9E6E6",
    "8 	c #D3C3C3",
    "9 	c #392F2F",
    "0 	c #FCF6F6",
    "a 	c #BAA7A7",
    "b 	c #524646",
    "c 	c #D9D1D1",
    "d 	c #F2EAEA",
    "e 	c #796666",
    "f 	c #FEF7F7",
    "g 	c #BBAAAA",
    "h 	c #918383",
    "i 	c #1D1515",
    "j 	c #EBDADA",
    "k 	c #B5B5B5",
    "l 	c #FFF4F4",
    "m 	c #DDD0D0",
    "n 	c #110A0A",
    "o 	c #FEFBFB",
    "p 	c #D3C7C7",
    "q 	c #FFF3F3",
    "r 	c #968484",
    "s 	c #F2E9E9",
    "t 	c #908484",
    "u 	c #FFFDFD",
    "v 	c #A89191",
    "w 	c #776262",
    "x 	c #CCB4B4",
    "y 	c #9E7979",
    "z 	c #705F5F",
    "A 	c #FFCCCC",
    "B 	c #FFEAEA",
    "C 	c #FFE6E6",
    "D 	c #FFF1F1",
    "E 	c #FFFEFE",
    "F 	c #FFE1E1",
    "G 	c #FFF2F2",
    "H 	c #FFF7F7",
    "I 	c #C7B8B8",
    "J 	c #AE9494",
    "K 	c #5A4848",
    "L 	c #C0AFAF",
    "M 	c #D1BDBD",
    "N 	c #4F3D3D",
    "O 	c #513636",
    "P 	c #BCB0B0",
    "Q 	c #665757",
    "R 	c #1A0C0C",
    "S 	c #E4DCDC",
    "T 	c #FCF3F3",
    "U 	c #1F0C0C",
    "V 	c #C3C3C3",
    "W 	c #726363",
    "X 	c #443A3A",
    "Y 	c #FFF8F8",
    "Z 	c #583D3D",
    "` 	c #FCF4F4",
    " .	c #615757",
    "..	c #6C5656",
    "+.	c #A09393",
    "@.	c #9B8E8E",
    "#.	c #856464",
    "$.	c #4A3F3F",
    "%.	c #BBBBBB",
    "&.	c #C0BCBC",
    "*.	c #452F2F",
    "=.	c #736C6C",
    "-.	c #775656",
    ";.	c #878787",
    ">.	c #A38888",
    ",.	c #624D4D",
    "'.	c #C9B4B4",
    ").	c #F8F0F0",
    "!.	c #FFEDED",
    "~.	c #604242",
    "{.	c #B5A8A8",
    "].	c #FAE9E9",
    "^.	c #FBF3F3",
    "/.	c #BAB2B2",
    "(.	c #F8DEDE",
    "_.	c #7F6F6F",
    ":.	c #B5A2A2",
    "<.	c #806F6F",
    "[.	c #AA8E8E",
    "}.	c #FEFDFD",
    "|.	c #BD9F9F",
    "1.	c #C3B4B4",
    "2.	c #E0DCDC",
    "3.	c #F9EEEE",
    "4.	c #080303",
    "5.	c #F3C1C1",
    "6.	c #B7A2A2",
    "7.	c #4C3A3A",
    "8.	c #DFD6D6",
    "9.	c #7E6D6D",
    "0.	c #FFE9E9",
    "a.	c #B39A9A",
    "b.	c #BBA5A5",
    "c.	c #DEC9C9",
    "d.	c #715D5D",
    "e.	c #F3DDDD",
    "f.	c #8B7979",
    "g.	c #060303",
    "h.	c #FFEBEB",
    "i.	c #EFE9E9",
    "j.	c #EAEAEA",
    "k.	c #FAEFEF",
    "l.	c #D1C3C3",
    "m.	c #0B0707",
    "n.	c #312222",
    "o.	c #584141",
    "p.	c #685252",
    "q.	c #5D5858",
    "r.	c #5F5F5F",
    "s.	c #5B5B5B",
    "t.	c #5C5858",
    "u.	c #473232",
    "v.	c #181111",
    "w.	c #ECD8D8",
    "x.	c #F9EFEF",
    "y.	c #DBC6C6",
    "z.	c #DEC5C5",
    "A.	c #F7EDED",
    "B.	c #DCC4C4",
    "C.	c #F8EDED",
    "D.	c #DEC3C3",
    "E.	c #E0C9C9",
    "F.	c #DEC1C1",
    "G.	c #DBC7C7",
    "H.	c #F7E8E8",
    "I.	c #E1CACA",
    "J.	c #DBC2C2",
    "K.	c #F8EFEF",
    "L.	c #796868",
    "M.	c #422B2B",
    "N.	c #B5A3A3",
    "O.	c #F8ECEC",
    "P.	c #F8EEEE",
    "Q.	c #FDF7F7",
    "R.	c #FEF9F9",
    "S.	c #F7EAEA",
    "T.	c #FDF6F6",
    "U.	c #F7EBEB",
    "V.	c #FDF5F5",
    "W.	c #F7EEEE",
    "X.	c #F8EBEB",
    "Y.	c #786565",
    "Z.	c #2C2121",
    "`.	c #F6E9E9",
    " +	c #F6E8E8",
    ".+	c #F9EDED",
    "++	c #FEFCFC",
    "@+	c #F7ECEC",
    "#+	c #F7E9E9",
    "$+	c #837070",
    "%+	c #806C6C",
    "&+	c #D4C3C3",
    "*+	c #DCC8C8",
    "=+	c #DDC2C2",
    "-+	c #DBBFBF",
    ";+	c #E1C8C8",
    ">+	c #DEC8C8",
    ",+	c #DEC7C7",
    "'+	c #DFC8C8",
    ")+	c #DEBBBB",
    "!+	c #FAEEEE",
    "~+	c #221B1B",
    "{+	c #3E3131",
    "]+	c #F8E8E8",
    "^+	c #8D8181",
    "/+	c #F6E7E7",
    "(+	c #696969",
    "_+	c #6D6D6D",
    ":+	c #6F6C6C",
    "<+	c #835D5D",
    "[+	c #875D5D",
    "}+	c #9D7474",
    "|+	c #A27A7A",
    "1+	c #958989",
    "2+	c #919191",
    "3+	c #9D9797",
    "4+	c #917E7E",
    "5+	c #E3C8C8",
    "6+	c #241B1B",
    "7+	c #695959",
    "8+	c #CEBCBC",
    "9+	c #D1D1D1",
    "0+	c #CFCBCB",
    "a+	c #322424",
    "b+	c #201818",
    "                                                                ",
    "      . + @ # $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % @ & .         ",
    "      . * = - ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; > , ' ) !       ",
    "      . ~ { ] ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ / ( _ : / <     ",
    "      . [ } | 1 1 2 3 1 4 ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 : ^ 7 .   ",
    "      . [ } 8 9   0 a b * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 : ^ 4 .   ",
    "      . [ } ^ c   d e f ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 g ^ 4 .   ",
    "      . [ } ^ ^ h i j ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 k ^ l .   ",
    "      . [ } ^ ^ m n | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 k ^ ^ .   ",
    "      . [ } ^ o { p   q ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 k ^ ^ .   ",
    "      . [ } ^ r s ^ t   u ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 k ^ ^ .   ",
    "      . [ } v w x ^ y z A ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 : ^ ^ .   ",
    "      . [ } ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 : ^ ^ .   ",
    "      . [ } B C C C D C C C E F G G ^ l C ^ ^ H ] 5 6 : ^ ^ .   ",
    "      . [ } I J K L M N L L E O P Q l B R S T U V 5 6 : ^ ^ .   ",
    "      . [ } ^ * W ^ * X ^ Y ^ Z `  .q B ..+.@.#.V 5 6 : ^ ^ .   ",
    "      . [ } ^ * W ^ * $.%.&.^ *.=.-.u B ;.>.,.'.V 5 6 : ^ )..   ",
    "      . [ } ^ * W ^ * ,.!.!.E ~.^ {.].B ;.^./.(.V 5 6 : ^ _.    ",
    "      . [ } ^ q :.^ l <.<.<.E [.^ }.|.3 1.^ ^ B 2.5 6 : 3.4.    ",
    "      . 5.6.^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ] 7.8.: 9.      ",
    "      . 0.a.b.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.d.e.' f.g.      ",
    "      . h.2 i.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.k.^ l.m.        ",
    "        . . . . . . . . . . . . . . . . . . . . . . .           ",
    "                                                                ",
    "        n.o.p.p.p.p.q.; r.s.; ; ; t.p.p.p.p.p.p.p.p.u..         ",
    "      v.w.x.y.z.A.3.} B.C.3.D.E.C.C.F.G.C.H.I.J.C.K.L.M.        ",
    "      N.O.P.Q.R.S.S.f T.U.S.V.f W.A.Q.Q.P.P.Q.f O.X._.Y.        ",
    "    Z.Y `. +V.f .+A.T.Q.O..+++V.K.@+f f #+A.R.V.`.$+x.%+        ",
    "    &+B.X.).*+=+C.#+-+;+C.O.>+,+U.#+'+)+@+#+F.*+!+9.k.~+        ",
    "  {+]+^+/+(+_+_+_+_+_+_+_+_+:+<+[+}+|+1+2+3+S.^+4+5+6+          ",
    "  7+8+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+0+a+b+            ",
    "                                                                "};
    xterm-353/icons/xterm_16x16.xpm0000644000175100001440000000062712034404343015113 0ustar  tomusers/* XPM */
    static char * xterm_16x16_xpm[] = {
    "16 16 2 1",
    " 	c None",
    ".	c #000000",
    "                ",
    "             .  ",
    "   ....      .  ",
    "    ..       .  ",
    "    ..       .  ",
    "   .. .      .  ",
    "             .  ",
    "   ....   .. .  ",
    "    . . . .. .  ",
    "          .  .  ",
    "          .  .  ",
    "          .     ",
    "             .  ",
    "                ",
    "                ",
    "            .   "};
    xterm-353/icons/filled-xterm.xpms0000644000175100001440000004177612034404371015701 0ustar  tomusers/* $XTermId: filled-xterm.xpms,v 1.1 2012/10/07 22:58:01 tom Exp $ */
    /* generated by ./make-xpms  */
    /* vile:xpmmode */
    /* XPM */
    static const char * const filled_xterm_16x16_xpm[] = {
    "16 16 110 2",
    "  	c None",
    ". 	c #BAA9A9",
    "+ 	c #C59C9C",
    "@ 	c #C49999",
    "# 	c #C6AAAA",
    "$ 	c #4D4242",
    "% 	c #F0E4E4",
    "& 	c #CEBABA",
    "* 	c #D5BEBE",
    "= 	c #C6B5B5",
    "- 	c #CEBEBE",
    "; 	c #796D6D",
    "> 	c #DEC5C5",
    ", 	c #B19B9B",
    "' 	c #C6B8B8",
    ") 	c #B19696",
    "! 	c #EBE5E5",
    "~ 	c #FFFFFF",
    "{ 	c #D6D6D6",
    "] 	c #D0BDBD",
    "^ 	c #FFF4F4",
    "/ 	c #FEFDFD",
    "( 	c #706969",
    "_ 	c #CCC3C3",
    ": 	c #FFF0F0",
    "< 	c #978989",
    "[ 	c #A9A5A5",
    "} 	c #A7A3A3",
    "| 	c #E3E1E1",
    "1 	c #DACBCB",
    "2 	c #DEDEDE",
    "3 	c #FFF8F8",
    "4 	c #FFF6F6",
    "5 	c #FFFCFC",
    "6 	c #FFFEFE",
    "7 	c #D2D2D2",
    "8 	c #9C9C9C",
    "9 	c #9B8787",
    "0 	c #B3A0A0",
    "a 	c #FFD5D5",
    "b 	c #D4C2C2",
    "c 	c #FFE7E7",
    "d 	c #7A6F6F",
    "e 	c #786F6F",
    "f 	c #C2C2C2",
    "g 	c #B4B4B4",
    "h 	c #FFE3E3",
    "i 	c #E1CECE",
    "j 	c #FED8D8",
    "k 	c #908888",
    "l 	c #878080",
    "m 	c #898383",
    "n 	c #F3ECEC",
    "o 	c #D8C2C2",
    "p 	c #FFFAFA",
    "q 	c #FFF2F2",
    "r 	c #FFF9F9",
    "s 	c #EFEFEF",
    "t 	c #FEFEFE",
    "u 	c #C8C3C3",
    "v 	c #D2BFBF",
    "w 	c #8A8383",
    "x 	c #FCE5E5",
    "y 	c #D9B6B6",
    "z 	c #DDBCBC",
    "A 	c #BCA0A0",
    "B 	c #F0D2D2",
    "C 	c #AB9C9C",
    "D 	c #000000",
    "E 	c #B0A2A2",
    "F 	c #AE9F9F",
    "G 	c #C6ABAB",
    "H 	c #B48E8E",
    "I 	c #C8ABAB",
    "J 	c #C39A9A",
    "K 	c #D0B2B2",
    "L 	c #C3A0A0",
    "M 	c #CFB2B2",
    "N 	c #C59999",
    "O 	c #CCC1C1",
    "P 	c #3C3535",
    "Q 	c #A39C9C",
    "R 	c #FAEDED",
    "S 	c #FEFCFC",
    "T 	c #F9F2F2",
    "U 	c #FEF7F7",
    "V 	c #FAEBEB",
    "W 	c #FEFAFA",
    "X 	c #F9F1F1",
    "Y 	c #FEF4F4",
    "Z 	c #FAEFEF",
    "` 	c #EBE0E0",
    " .	c #DFB9B9",
    "..	c #E8E3E3",
    "+.	c #BBB0B0",
    "@.	c #BBA9A9",
    "#.	c #CEC8C8",
    "$.	c #BCADAD",
    "%.	c #CDC8C8",
    "&.	c #C78D8D",
    "*.	c #E3B2B2",
    "=.	c #E3BCBC",
    "-.	c #BBAAAA",
    ";.	c #746C6C",
    ">.	c #858585",
    ",.	c #8A7F7F",
    "'.	c #977878",
    ").	c #A38686",
    "!.	c #A78686",
    "~.	c #201717",
    "    . + @ @ @ @ @ @ @ @ # $     ",
    "    % & * * * * * * * * = - ;   ",
    "    > , ' ) ! ~ ~ ~ ~ ~ { ] ^   ",
    "    > / ( _ ~ ~ ~ ~ ~ ~ { ] :   ",
    "    > ~ < [ ~ ~ ~ ~ ~ ~ { ] :   ",
    "    > } | 1 2 ~ ~ ~ ~ ~ { ] :   ",
    "    > ~ ~ 3 ~ 4 4 5 6 4 7 ] :   ",
    "    > 7 8 9 0 a b c d e f ] :   ",
    "    > ~ g h i j k c l m f ] n   ",
    "    o ~ ~ p ~ q 6 r s t u v w   ",
    "    x y z z z z z z A z B C     ",
    "                    D           ",
    "    E F G H I J K L M N O P     ",
    "  Q R S T U V W X Y Z U ` Q     ",
    "   ...+._ @.#.$.%.&.*.=.-.;.    ",
    "  >.>.>.,.'.).).).).).!.~.      "};
    /* XPM */
    static const char * const filled_xterm_32x32_xpm[] = {
    "32 32 225 2",
    "  	c None",
    ". 	c #000000",
    "+ 	c #D9C2C2",
    "@ 	c #EEE5E5",
    "# 	c #EBE0E0",
    "$ 	c #EBE1E1",
    "% 	c #EDE1E1",
    "& 	c #918484",
    "* 	c #FFEEEE",
    "= 	c #F2DCDC",
    "- 	c #403838",
    "; 	c #5A5A5A",
    "> 	c #5B4545",
    ", 	c #FEF2F2",
    "' 	c #E9E9E9",
    ") 	c #856868",
    "! 	c #271D1D",
    "~ 	c #FBCFCF",
    "{ 	c #746060",
    "] 	c #FFFBFB",
    "^ 	c #FFFFFF",
    "/ 	c #FAF0F0",
    "( 	c #5E4949",
    "_ 	c #E3DCDC",
    ": 	c #BAA8A8",
    "< 	c #292020",
    "[ 	c #F1C0C0",
    "} 	c #D9C6C6",
    "| 	c #FFECEC",
    "1 	c #FFE8E8",
    "2 	c #FFFAFA",
    "3 	c #FFF0F0",
    "4 	c #FFEFEF",
    "5 	c #705D5D",
    "6 	c #DED5D5",
    "7 	c #F9E6E6",
    "8 	c #D3C3C3",
    "9 	c #392F2F",
    "0 	c #FCF6F6",
    "a 	c #BAA7A7",
    "b 	c #524646",
    "c 	c #D9D1D1",
    "d 	c #F2EAEA",
    "e 	c #796666",
    "f 	c #FEF7F7",
    "g 	c #BBAAAA",
    "h 	c #918383",
    "i 	c #1D1515",
    "j 	c #EBDADA",
    "k 	c #B5B5B5",
    "l 	c #FFF4F4",
    "m 	c #DDD0D0",
    "n 	c #110A0A",
    "o 	c #FEFBFB",
    "p 	c #D3C7C7",
    "q 	c #FFF3F3",
    "r 	c #968484",
    "s 	c #F2E9E9",
    "t 	c #908484",
    "u 	c #FFFDFD",
    "v 	c #A89191",
    "w 	c #776262",
    "x 	c #CCB4B4",
    "y 	c #9E7979",
    "z 	c #705F5F",
    "A 	c #FFCCCC",
    "B 	c #FFEAEA",
    "C 	c #FFE6E6",
    "D 	c #FFF1F1",
    "E 	c #FFFEFE",
    "F 	c #FFE1E1",
    "G 	c #FFF2F2",
    "H 	c #FFF7F7",
    "I 	c #C7B8B8",
    "J 	c #AE9494",
    "K 	c #5A4848",
    "L 	c #C0AFAF",
    "M 	c #D1BDBD",
    "N 	c #4F3D3D",
    "O 	c #513636",
    "P 	c #BCB0B0",
    "Q 	c #665757",
    "R 	c #1A0C0C",
    "S 	c #E4DCDC",
    "T 	c #FCF3F3",
    "U 	c #1F0C0C",
    "V 	c #C3C3C3",
    "W 	c #726363",
    "X 	c #443A3A",
    "Y 	c #FFF8F8",
    "Z 	c #583D3D",
    "` 	c #FCF4F4",
    " .	c #615757",
    "..	c #6C5656",
    "+.	c #A09393",
    "@.	c #9B8E8E",
    "#.	c #856464",
    "$.	c #4A3F3F",
    "%.	c #BBBBBB",
    "&.	c #C0BCBC",
    "*.	c #452F2F",
    "=.	c #736C6C",
    "-.	c #775656",
    ";.	c #878787",
    ">.	c #A38888",
    ",.	c #624D4D",
    "'.	c #C9B4B4",
    ").	c #F8F0F0",
    "!.	c #FFEDED",
    "~.	c #604242",
    "{.	c #B5A8A8",
    "].	c #FAE9E9",
    "^.	c #FBF3F3",
    "/.	c #BAB2B2",
    "(.	c #F8DEDE",
    "_.	c #7F6F6F",
    ":.	c #B5A2A2",
    "<.	c #806F6F",
    "[.	c #AA8E8E",
    "}.	c #FEFDFD",
    "|.	c #BD9F9F",
    "1.	c #C3B4B4",
    "2.	c #E0DCDC",
    "3.	c #F9EEEE",
    "4.	c #080303",
    "5.	c #F3C1C1",
    "6.	c #B7A2A2",
    "7.	c #4C3A3A",
    "8.	c #DFD6D6",
    "9.	c #7E6D6D",
    "0.	c #FFE9E9",
    "a.	c #B39A9A",
    "b.	c #BBA5A5",
    "c.	c #DEC9C9",
    "d.	c #715D5D",
    "e.	c #F3DDDD",
    "f.	c #8B7979",
    "g.	c #060303",
    "h.	c #FFEBEB",
    "i.	c #EFE9E9",
    "j.	c #EAEAEA",
    "k.	c #FAEFEF",
    "l.	c #D1C3C3",
    "m.	c #0B0707",
    "n.	c #312222",
    "o.	c #584141",
    "p.	c #685252",
    "q.	c #5D5858",
    "r.	c #5F5F5F",
    "s.	c #5B5B5B",
    "t.	c #5C5858",
    "u.	c #473232",
    "v.	c #181111",
    "w.	c #ECD8D8",
    "x.	c #F9EFEF",
    "y.	c #DBC6C6",
    "z.	c #DEC5C5",
    "A.	c #F7EDED",
    "B.	c #DCC4C4",
    "C.	c #F8EDED",
    "D.	c #DEC3C3",
    "E.	c #E0C9C9",
    "F.	c #DEC1C1",
    "G.	c #DBC7C7",
    "H.	c #F7E8E8",
    "I.	c #E1CACA",
    "J.	c #DBC2C2",
    "K.	c #F8EFEF",
    "L.	c #796868",
    "M.	c #422B2B",
    "N.	c #B5A3A3",
    "O.	c #F8ECEC",
    "P.	c #F8EEEE",
    "Q.	c #FDF7F7",
    "R.	c #FEF9F9",
    "S.	c #F7EAEA",
    "T.	c #FDF6F6",
    "U.	c #F7EBEB",
    "V.	c #FDF5F5",
    "W.	c #F7EEEE",
    "X.	c #F8EBEB",
    "Y.	c #786565",
    "Z.	c #2C2121",
    "`.	c #F6E9E9",
    " +	c #F6E8E8",
    ".+	c #F9EDED",
    "++	c #FEFCFC",
    "@+	c #F7ECEC",
    "#+	c #F7E9E9",
    "$+	c #837070",
    "%+	c #806C6C",
    "&+	c #D4C3C3",
    "*+	c #DCC8C8",
    "=+	c #DDC2C2",
    "-+	c #DBBFBF",
    ";+	c #E1C8C8",
    ">+	c #DEC8C8",
    ",+	c #DEC7C7",
    "'+	c #DFC8C8",
    ")+	c #DEBBBB",
    "!+	c #FAEEEE",
    "~+	c #221B1B",
    "{+	c #3E3131",
    "]+	c #F8E8E8",
    "^+	c #8D8181",
    "/+	c #F6E7E7",
    "(+	c #696969",
    "_+	c #6D6D6D",
    ":+	c #6F6C6C",
    "<+	c #835D5D",
    "[+	c #875D5D",
    "}+	c #9D7474",
    "|+	c #A27A7A",
    "1+	c #958989",
    "2+	c #919191",
    "3+	c #9D9797",
    "4+	c #917E7E",
    "5+	c #E3C8C8",
    "6+	c #241B1B",
    "7+	c #695959",
    "8+	c #CEBCBC",
    "9+	c #D1D1D1",
    "0+	c #CFCBCB",
    "a+	c #322424",
    "b+	c #201818",
    "                                                                ",
    "      . + @ # $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % @ & .         ",
    "      . * = - ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; ; > , ' ) !       ",
    "      . ~ { ] ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ / ( _ : / <     ",
    "      . [ } | 1 1 2 3 1 4 ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 : ^ 7 .   ",
    "      . [ } 8 9   0 a b * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 : ^ 4 .   ",
    "      . [ } ^ c   d e f ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 g ^ 4 .   ",
    "      . [ } ^ ^ h i j ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 k ^ l .   ",
    "      . [ } ^ ^ m n | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 k ^ ^ .   ",
    "      . [ } ^ o { p   q ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 k ^ ^ .   ",
    "      . [ } ^ r s ^ t   u ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 k ^ ^ .   ",
    "      . [ } v w x ^ y z A ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 : ^ ^ .   ",
    "      . [ } ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 5 6 : ^ ^ .   ",
    "      . [ } B C C C D C C C E F G G ^ l C ^ ^ H ] 5 6 : ^ ^ .   ",
    "      . [ } I J K L M N L L E O P Q l B R S T U V 5 6 : ^ ^ .   ",
    "      . [ } ^ * W ^ * X ^ Y ^ Z `  .q B ..+.@.#.V 5 6 : ^ ^ .   ",
    "      . [ } ^ * W ^ * $.%.&.^ *.=.-.u B ;.>.,.'.V 5 6 : ^ )..   ",
    "      . [ } ^ * W ^ * ,.!.!.E ~.^ {.].B ;.^./.(.V 5 6 : ^ _.    ",
    "      . [ } ^ q :.^ l <.<.<.E [.^ }.|.3 1.^ ^ B 2.5 6 : 3.4.    ",
    "      . 5.6.^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ] 7.8.: 9.      ",
    "      . 0.a.b.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.c.d.e.' f.g.      ",
    "      . h.2 i.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.j.k.^ l.m.        ",
    "        . . . . . . . . . . . . . . . . . . . . . . .           ",
    "                                                                ",
    "        n.o.p.p.p.p.q.; r.s.; ; ; t.p.p.p.p.p.p.p.p.u..         ",
    "      v.w.x.y.z.A.3.} B.C.3.D.E.C.C.F.G.C.H.I.J.C.K.L.M.        ",
    "      N.O.P.Q.R.S.S.f T.U.S.V.f W.A.Q.Q.P.P.Q.f O.X._.Y.        ",
    "    Z.Y `. +V.f .+A.T.Q.O..+++V.K.@+f f #+A.R.V.`.$+x.%+        ",
    "    &+B.X.).*+=+C.#+-+;+C.O.>+,+U.#+'+)+@+#+F.*+!+9.k.~+        ",
    "  {+]+^+/+(+_+_+_+_+_+_+_+_+:+<+[+}+|+1+2+3+S.^+4+5+6+          ",
    "  7+8+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+9+0+a+b+            ",
    "                                                                "};
    /* XPM */
    static const char * const filled_xterm_48x48_xpm[] = {
    "48 48 246 2",
    "  	c None",
    ". 	c #000000",
    "+ 	c #F6D5D5",
    "@ 	c #FFEAEA",
    "# 	c #FFD6D6",
    "$ 	c #FFD2D2",
    "% 	c #FFD3D3",
    "& 	c #F8D6D6",
    "* 	c #FFEFEF",
    "= 	c #FFFFFF",
    "- 	c #F6DBDB",
    "; 	c #0F0707",
    "> 	c #090505",
    ", 	c #F6DCDC",
    "' 	c #FFEEEE",
    ") 	c #C99999",
    "! 	c #030101",
    "~ 	c #F7DEDE",
    "{ 	c #150B0B",
    "] 	c #E3C5C5",
    "^ 	c #FFEDED",
    "/ 	c #E4CBCB",
    "( 	c #140B0B",
    "_ 	c #F7DDDD",
    ": 	c #E0C9C9",
    "< 	c #080303",
    "[ 	c #FFD9D9",
    "} 	c #0D0707",
    "| 	c #E5CACA",
    "1 	c #E5CBCB",
    "2 	c #0B0606",
    "3 	c #FFDCDC",
    "4 	c #E2CECE",
    "5 	c #090303",
    "6 	c #E1CBCB",
    "7 	c #9F8A8A",
    "8 	c #3B2929",
    "9 	c #312020",
    "0 	c #FFD5D5",
    "a 	c #ECC8C8",
    "b 	c #402525",
    "c 	c #351F1F",
    "d 	c #663E3E",
    "e 	c #E6DBDB",
    "f 	c #FFFAFA",
    "g 	c #FFFEFE",
    "h 	c #8C7272",
    "i 	c #B4A1A1",
    "j 	c #A69494",
    "k 	c #D8C0C0",
    "l 	c #675353",
    "m 	c #FFFDFD",
    "n 	c #584545",
    "o 	c #E1BFBF",
    "p 	c #3C2929",
    "q 	c #FCF3F3",
    "r 	c #F6EAEA",
    "s 	c #160F0F",
    "t 	c #E9D3D3",
    "u 	c #6E5C5C",
    "v 	c #D6BABA",
    "w 	c #CBBBBB",
    "x 	c #0D0808",
    "y 	c #F8E8E8",
    "z 	c #FFE2E2",
    "A 	c #F4EDED",
    "B 	c #FFF2F2",
    "C 	c #4B3A3A",
    "D 	c #FFFBFB",
    "E 	c #AD9292",
    "F 	c #FFE1E1",
    "G 	c #A28E8E",
    "H 	c #CCBDBD",
    "I 	c #8B7777",
    "J 	c #231515",
    "K 	c #ECCECE",
    "L 	c #FFDADA",
    "M 	c #251414",
    "N 	c #9A8686",
    "O 	c #FFF1F1",
    "P 	c #FFECEC",
    "Q 	c #FFE4E4",
    "R 	c #FFDFDF",
    "S 	c #FFDBDB",
    "T 	c #FFF0F0",
    "U 	c #FFDDDD",
    "V 	c #FFEBEB",
    "W 	c #FFF4F4",
    "X 	c #FFE5E5",
    "Y 	c #FFDEDE",
    "Z 	c #B29E9E",
    "` 	c #A08F8F",
    " .	c #8A7373",
    "..	c #1C1111",
    "+.	c #D7CACA",
    "@.	c #645555",
    "#.	c #5E4B4B",
    "$.	c #FFF7F7",
    "%.	c #BD9F9F",
    "&.	c #392B2B",
    "*.	c #A19090",
    "=.	c #867474",
    "-.	c #9C8D8D",
    ";.	c #A99494",
    ">.	c #0E0606",
    ",.	c #FFE9E9",
    "'.	c #D5C6C6",
    ").	c #564545",
    "!.	c #FFE7E7",
    "~.	c #5B3D3D",
    "{.	c #352121",
    "].	c #5B4242",
    "^.	c #FFD7D7",
    "/.	c #E7D2D2",
    "(.	c #1F1313",
    "_.	c #786363",
    ":.	c #AC9191",
    "<.	c #FFE8E8",
    "[.	c #DBC7C7",
    "}.	c #897474",
    "|.	c #574E4E",
    "1.	c #999999",
    "2.	c #FFF6F6",
    "3.	c #170F0F",
    "4.	c #3B2B2B",
    "5.	c #190E0E",
    "6.	c #C7B6B6",
    "7.	c #5F4D4D",
    "8.	c #F6E1E1",
    "9.	c #FCE9E9",
    "0.	c #F1EAEA",
    "a.	c #FEFAFA",
    "b.	c #3D2828",
    "c.	c #382626",
    "d.	c #947D7D",
    "e.	c #FFFCFC",
    "f.	c #B09B9B",
    "g.	c #C2B2B2",
    "h.	c #EEDADA",
    "i.	c #FDEFEF",
    "j.	c #0B0505",
    "k.	c #DACACA",
    "l.	c #7D6565",
    "m.	c #C6A7A7",
    "n.	c #FDF9F9",
    "o.	c #6C4D4D",
    "p.	c #AB9797",
    "q.	c #927B7B",
    "r.	c #FCEDED",
    "s.	c #0A0404",
    "t.	c #120B0B",
    "u.	c #E8D1D1",
    "v.	c #E2CACA",
    "w.	c #0F0808",
    "x.	c #907979",
    "y.	c #F9DFDF",
    "z.	c #1D1111",
    "A.	c #E8D0D0",
    "B.	c #E1C8C8",
    "C.	c #1A0C0C",
    "D.	c #F8E0E0",
    "E.	c #F7D4D4",
    "F.	c #090404",
    "G.	c #FAE1E1",
    "H.	c #100A0A",
    "I.	c #100808",
    "J.	c #7C4F4F",
    "K.	c #F6D3D3",
    "L.	c #FFD8D8",
    "M.	c #F8D5D5",
    "N.	c #AF9393",
    "O.	c #FDE5E5",
    "P.	c #FDE9E9",
    "Q.	c #FDE2E2",
    "R.	c #FDF8F8",
    "S.	c #FDE6E6",
    "T.	c #FEECEC",
    "U.	c #FEE5E5",
    "V.	c #FFE6E6",
    "W.	c #F8D1D1",
    "X.	c #0D0404",
    "Y.	c #291D1D",
    "Z.	c #583030",
    "`.	c #FFF8F8",
    " +	c #683737",
    ".+	c #5B3333",
    "++	c #582D2D",
    "@+	c #593030",
    "#+	c #5D3232",
    "$+	c #5A2D2D",
    "%+	c #663737",
    "&+	c #5B3030",
    "*+	c #897272",
    "=+	c #996F6F",
    "-+	c #DBC1C1",
    ";+	c #110808",
    ">+	c #FDDDDD",
    ",+	c #473636",
    "'+	c #563232",
    ")+	c #FFF5F5",
    "!+	c #5C3636",
    "~+	c #FFF9F9",
    "{+	c #582E2E",
    "]+	c #6F4040",
    "^+	c #5B3434",
    "/+	c #6D3E3E",
    "(+	c #5A3333",
    "_+	c #EFD7D7",
    ":+	c #FCEFEF",
    "<+	c #140A0A",
    "[+	c #6A5252",
    "}+	c #583333",
    "|+	c #5C2A2A",
    "1+	c #653737",
    "2+	c #6B3C3C",
    "3+	c #643434",
    "4+	c #6A3C3C",
    "5+	c #613535",
    "6+	c #9C8787",
    "7+	c #907A7A",
    "8+	c #DDC3C3",
    "9+	c #F8E5E5",
    "0+	c #FDF3F3",
    "a+	c #190D0D",
    "b+	c #FAEAEA",
    "c+	c #DCC4C4",
    "d+	c #876E6E",
    "e+	c #461F1F",
    "f+	c #472020",
    "g+	c #261414",
    "h+	c #070000",
    "i+	c #220000",
    "j+	c #230101",
    "k+	c #3A1818",
    "l+	c #3F1D1D",
    "m+	c #3E1E1E",
    "n+	c #553333",
    "o+	c #724646",
    "p+	c #431F1F",
    "q+	c #AB8F8F",
    "r+	c #887171",
    "s+	c #DAC0C0",
    "t+	c #FBD1D1",
    "u+	c #1A1010",
    "v+	c #B27C7C",
    "w+	c #020101",
    "                                                                                                ",
    "            . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                 ",
    "          . + @ @ # $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % @ @ & . .             ",
    "          . * = - ; . . . . . . . . . . . . . . . . . . . . . . . . . . > , = ' . ) !           ",
    "          . * ~ { ] ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ / ( _ ' . ^ : <         ",
    "          . [ } | = = = = = = = = = = = = = = = = = = = = = = = = = = = = 1 2 3 . ^ = 4 5       ",
    "          . [ . * = = = = = = = = = = = = = = = = = = = = = = = = = = = = * . [ . ^ = = 6 .     ",
    "          . [ . * 7 8 9   0 = a b c d = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = e     f = g h i = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = j     = k l g = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = m n   o p q = = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = = r s . t = = = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = = = u . v = = = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = = w     x y = = = = = = = = = = = = = = = = = = = = * . [ . z = = * .     ",
    "          . [ . * = = A   B B   C D = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = E z = = F   G = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * H I J K = = L M } N O = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * P Q Q R = = S Q Q Q T = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = = = = = = = = = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = = = = = = = = = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * [ U U U U U V z U U U U W X   Y X ^ = = V U O = = O F ' * . [ . ' = = * .     ",
    "          . [ . * Z `  ...` Q +.@.#.` ` Q $.%.&.*.=.  ^ = -.    = = ;.>.,.* . [ . ' = = * .     ",
    "          . [ . * = = '.  = = =   Q = = = = %.  = = ).!.= -.~.  f f {.].,.* . [ . ' = = * .     ",
    "          . [ . * = = '.  = = =     U U ^.= %.  ^ /.(.' = -._.:.<.[.}.@.,.* . [ . ' = = * .     ",
    "          . [ . * = = '.  = = = @.|.1.1.2.= %.3.4.5.  = = -.  6.  7.8.@.,.* . [ . ' = = 9..     ",
    "          . [ . * = = '.  = = =   Q = = = = %.  = 0.  ' = -.  a.b.c.f @.,.* . [ . ' = = d..     ",
    "          . [ . * = = '.  = = =   0 ^ ^ ^ e.%.  = = f.  m -.  = g.h.= @.,.* . [ . ' = i.j.      ",
    "          . [ . * = = k.  = = = l.9 9 9   ' m.  = = n.o.z p.  = = = = l.X * . [ . ' = q..       ",
    "          . [ . * = = = = = = = = = = = = = = = = = = = = = = = = = = = = * . [ . ' r.s.        ",
    "          . 3 t.u.= = = = = = = = = = = = = = = = = = = = = = = = = = = = v.w.S . ' x..         ",
    "          . * y.z.A.^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ B.C.D.' . E.F.          ",
    "          . * = G.H.. . . . . . . . . . . . . . . . . . . . . . . . . . I.D.= ' . J..           ",
    "          . K.P P # $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ L.P P M.. .             ",
    "            . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                 ",
    "                                                                                                ",
    "                                                                                                ",
    "            . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .             ",
    "          . N.O.P.O.P.Q.R.S.P.O.P.O.P.O.T.U.T.U.T.,.^ ,.^ ,.^ V.^ ,.= D W ,.^ W.X..             ",
    "          Y.W Z.`. +e..+e.++D @+$.Z.`. +e.#+e.$+D @+$.Z.`.%+e.#+e.$+e.&+$.Z.D *+=+.             ",
    "        . -+D f e.m D `.= D e.D D f D m D `.= D e.D D f D m D `.= D e.D D f r.;+>+.             ",
    "        ,+`.'+)+!+~+{+= ]+f .+`.Z.)+^+~+{+= /+f .+`.Z.)+^+~+{+= /+f (+`.Z.f q.q.T .             ",
    "      . _+m f = D m ~+e.`.m f m f = D m ~+e.`.m f e.f = D m ~+e.`.m f m f :+<+i.T .             ",
    "    . [+~+}+)+|+~+1+g 2+g 3+`.}+)+|+~+1+g 4+= 3+`.}+)+|+~+1+g 4+= 3+~+5+e.6+7+= 8+.             ",
    "    ! 9+= ~+= T ' @ ' ,.' <.' <.' ' ' @ e.f = ~+= ~+= = = D = f = ~+= = 0+a+b+c+!               ",
    "  . d+m e+f+e.g+. . . . . . . . . . . . h+i+i+j+k+l+l+c m+l+l+n+o+e.e+p+q+r+s+!                 ",
    "  . t+* @ @ P S [ L S S S S S S S S S S z ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ P z u+v+w+                  ",
    "  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                     ",
    "                                                                                                "};
    static const XPM_DATA filled_xterm_xpms[] = {
    	{ "filled-xterm_16x16", filled_xterm_16x16_xpm }, 
    	{ "filled-xterm_32x32", filled_xterm_32x32_xpm }, 
    	{ "filled-xterm_48x48", filled_xterm_48x48_xpm }
    };
    xterm-353/icons/xterm-color_48x48.xpm0000644000175100001440000000522612034777373016261 0ustar  tomusers/* XPM */
    static char * xterm_color_48x48_xpm[] = {
    "48 48 10 1",
    ".	c None",
    " 	c #555500",
    "+	c #000000",
    "@	c #FFFFFF",
    "#	c #FF0000",
    "$	c #070700",
    "%	c #0B0B00",
    "&	c #FF8400",
    "*	c #49FF00",
    "=	c #60B7FF",
    "................................................",
    "......++++++++++++++++++++++++++++++++++........",
    ".....+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@++......",
    ".....+@@@++++++++++++++++++++++++++++@@@+@+.....",
    ".....+@@++++++++++++++++++++++++++++++@@+@@+....",
    ".....+@++++++++++++++++++++++++++++++++@+@@@+...",
    ".....+@++###++++###++++++++++++++++++++@+@@@@+..",
    ".....+@+++##++++##+++++++++++++++++++++@+@@@@+..",
    ".....+@++++##++##++++++++++++++++++++++@+@@@@+..",
    ".....+@++++##++##++++++++++++++++++++++@+@@@@+..",
    ".....+@+++++####+++++++++++++++++++++++@+@@@@+..",
    ".....+@+++++####+++++++++++++++++++++++@+@@@@+..",
    ".....+@++++++##++++++++++++++++++++++++@+@@@@+..",
    ".....+@+++++####+++++++++++++++++++++++@+@@@@+..",
    ".....+@+++++####+++++++++++++++++++++++@+@@@@+..",
    ".....+@++++##++##++++++++++++++++++++++@+@@@@+..",
    ".....+@++++##++##++++++++++++++++++++++@+@@@@+..",
    ".....+@+++##++++##+++++++++++++++++++++@+@@@@+..",
    ".....+@++###++++###++++++++++++++++++++@+@@@@+..",
    ".....+@++++++++++++++++++++++++++++++++@+@@@@+..",
    ".....+@$+++++++++++++++++++++++++++++++@+@@@@+..",
    ".....+@%@@@@@@@+&&&&&++****+++==+++==++@+@@@@+..",
    ".....+@++++@++++&++++++*+++*++==+++==++@+@@@@+..",
    ".....+@++++@++++&++++++*+++*++=+=+=+=++@+@@@@+..",
    ".....+@++++@++++&&&&+++****+++=+=+=+=++@+@@@@+..",
    ".....+@++++@++++&++++++*+*++++=++=++=++@+@@@+...",
    ".....+@++++@++++&++++++*++*+++=++=++=++@+@@@+...",
    ".....+@++++@++++&&&&&++*+++*++=+++++=++@+@@+....",
    ".....+@++++++++++++++++++++++++++++++++@+@@+....",
    ".....+@++++++++++++++++++++++++++++++++@+@+.....",
    ".....+@@++++++++++++++++++++++++++++++@@+@+.....",
    ".....+@@@++++++++++++++++++++++++++++@@@++......",
    ".....+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@++......",
    "......++++++++++++++++++++++++++++++++++........",
    "................................................",
    "................................................",
    "......++++++++++++++++++++++++++++++++++++......",
    ".....+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@++......",
    ".....+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@@++......",
    "....+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+@+......",
    "....+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@@+@+......",
    "...+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+@@+......",
    "...+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@@+@@+......",
    "..+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+@@+.......",
    "..+@++@++++++++++++++++++++++++++@++@+@+........",
    ".+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+@+.........",
    ".+++++++++++++++++++++++++++++++++++++..........",
    "................................................"};
    xterm-353/icons/xterm_32x32.xpm0000644000175100001440000000232712034404307015106 0ustar  tomusers/* XPM */
    static char * xterm_32x32_xpm[] = {
    "32 32 2 1",
    " 	c None",
    ".	c #000000",
    "                                ",
    "   .                      ..    ",
    "   .  ................... ...   ",
    "   . .                   ... .  ",
    "   .                     ...  . ",
    "   .  .. ...             ...  . ",
    "   .   .  .              ...  . ",
    "   .    ..               ...  . ",
    "   .    ..               ...  . ",
    "   .    ..               ...  . ",
    "   .   .  .              ...  . ",
    "   .  ... ..             ...  . ",
    "   .                     ...  . ",
    "   .                     ...  . ",
    "   .  ........ ...  .. .....  . ",
    "   .    .  .   . .  ........  . ",
    "   .    .  ... ..   . . ....  . ",
    "   .    .  .   . .  . . .... .  ",
    "   .    .  ... . .. .   .... .  ",
    "   . .                   ....   ",
    "   . .                  . ...   ",
    "   .                      ..    ",
    "    .......................     ",
    "                                ",
    "    ........................    ",
    "   .                      ..    ",
    "                          ..    ",
    "  .                      . .    ",
    "                         . .    ",
    " . . ................. .. .     ",
    " .                      ..      ",
    "                                "};
    xterm-353/icons/xterm.xpms0000644000175100001440000001066512034404371014435 0ustar  tomusers/* $XTermId: xterm.xpms,v 1.3 2012/10/07 22:58:01 tom Exp $ */
    /* generated by ./make-xpms  */
    /* vile:xpmmode */
    /* XPM */
    static const char * const xterm_16x16_xpm[] = {
    "16 16 2 1",
    " 	c None",
    ".	c #000000",
    "                ",
    "             .  ",
    "   ....      .  ",
    "    ..       .  ",
    "    ..       .  ",
    "   .. .      .  ",
    "             .  ",
    "   ....   .. .  ",
    "    . . . .. .  ",
    "          .  .  ",
    "          .  .  ",
    "          .     ",
    "             .  ",
    "                ",
    "                ",
    "            .   "};
    /* XPM */
    static const char * const xterm_32x32_xpm[] = {
    "32 32 2 1",
    " 	c None",
    ".	c #000000",
    "                                ",
    "   .                      ..    ",
    "   .  ................... ...   ",
    "   . .                   ... .  ",
    "   .                     ...  . ",
    "   .  .. ...             ...  . ",
    "   .   .  .              ...  . ",
    "   .    ..               ...  . ",
    "   .    ..               ...  . ",
    "   .    ..               ...  . ",
    "   .   .  .              ...  . ",
    "   .  ... ..             ...  . ",
    "   .                     ...  . ",
    "   .                     ...  . ",
    "   .  ........ ...  .. .....  . ",
    "   .    .  .   . .  ........  . ",
    "   .    .  ... ..   . . ....  . ",
    "   .    .  .   . .  . . .... .  ",
    "   .    .  ... . .. .   .... .  ",
    "   . .                   ....   ",
    "   . .                  . ...   ",
    "   .                      ..    ",
    "    .......................     ",
    "                                ",
    "    ........................    ",
    "   .                      ..    ",
    "                          ..    ",
    "  .                      . .    ",
    "                         . .    ",
    " . . ................. .. .     ",
    " .                      ..      ",
    "                                "};
    /* XPM */
    static const char * const xterm_48x48_xpm[] = {
    "48 48 2 1",
    " 	c None",
    ".	c #000000",
    "                                                ",
    "      ..................................        ",
    "     .                                  ..      ",
    "     .   ............................   . .     ",
    "     .  .                            .  .  .    ",
    "     . .                              . .   .   ",
    "     . .                              . .    .  ",
    "     . . ...    ...                   . .    .  ",
    "     . .  .      .                    . .    .  ",
    "     . .   .    .                     . .    .  ",
    "     . .    .  .                      . .    .  ",
    "     . .     ..                       . .    .  ",
    "     . .     ..                       . .    .  ",
    "     . .    .  .                      . .    .  ",
    "     . .   .    .                     . .    .  ",
    "     . .  .      .                    . .    .  ",
    "     . . ...    ...                   . .    .  ",
    "     . .                              . .    .  ",
    "     . .                              . .    .  ",
    "     . .                              . .    .  ",
    "     . .                              . .    .  ",
    "     . . ..... .....  ....   .     .  . .    .  ",
    "     . .   .   .      .   .  ..   ..  . .    .  ",
    "     . .   .   .      .   .  ..   ..  . .    .  ",
    "     . .   .   .....  ....   . . . .  . .    .  ",
    "     . .   .   .      .  .   . ... .  . .   ..  ",
    "     . .   .   .      .   .  .  .  .  . .   .   ",
    "     . .   .   .....  .    . .     .  . .  ..   ",
    "     . .                              . .  .    ",
    "     . .                              . . ..    ",
    "     .  .                            .  . .     ",
    "     .   ............................   ...     ",
    "     .                                  ..      ",
    "      ..................................        ",
    "                                                ",
    "                                                ",
    "      ....................................      ",
    "     .                                  ..      ",
    "     . . . . . . . . . . . . . . . . . ...      ",
    "    .                                  . .      ",
    "    . . . . . . . . . . . . . . . . . .. .      ",
    "   .                                  .  .      ",
    "  .. . . . . . . . . . . . . . . . . ..  .      ",
    "  .                                  .  .       ",
    " .. .. .......................... .... .        ",
    " .                                  . .         ",
    " .....................................          ",
    "                                                "};
    static const XPM_DATA xterm_xpms[] = {
    	{ "xterm_16x16", xterm_16x16_xpm }, 
    	{ "xterm_32x32", xterm_32x32_xpm }, 
    	{ "xterm_48x48", xterm_48x48_xpm }
    };
    xterm-353/icons/mini.xterm.svg0000644000175100001440000001126612034054344015177 0ustar  tomusers
    
    
    
      
        
      
      
        
      
      
        
          
            image/svg+xml
            
            XTerm mini-icon
            August 21, 2012
            
              
                Thomas E. Dickey
              
            
            
          
          
            
            
            
            
            
          
        
      
      
        X
      
      
        T
      
    
    xterm-353/icons/filled-xterm.png0000644000175100001440000000444512034405232015463 0ustar  tomusers‰PNG
    
    
    IHDR00Wù‡sRGB®ÎébKGDÿÿÿ ½§“	pHYs
    ×
    ×B(›xtIMEÜ
    :ÅFÿ¯¥IDAThÞíY{PT×ÿÝ}åµò¢‘"‚Â*&Vâ+Æ™R8šdÒPŸSg¢ÓIF|TAÅiŒ‰¢u2M:m§­ÚÔˆFcí(fQ@(/eÙ]Ø{ï¹÷ë°[D…¥DÓ~3wv÷|¿9÷ûïqÎùøžÊ,ô”<³ú3”{Â8uÞ¹Óìhm%062KÇq@h(|k«UÜ£™
    à+O§!²Ù$"¢ÎªªûþZ툭¸—ZMÕÕMDDdµº~ôè'JŽ»ÿ8opý6›%2>ž3ž?_?h¸{·4qÖ¬˜ºâbIÊéõ ‹¥ÌT]Ý3}z¼S’–{â	¢Š
    ÁW«¥†7®ÐKCaáU†¨ºš ²Xî™Æ¯¼”Êûå…‹€³Çö‘&@6›½Ç±7""SaáÅžp(Ú½›Èn¯i*OâÉðÂß&N,Ýš™	ˆ¢o¯’«¼uëó^´SF:‰="€Q£Ý£¢^{æªÐÓ&žy ²ò#¨TŒûù¥¢««¢XüÐxhèFØí-åÓE
    ´Z?èts ×ÇõÜðn¢½ý,‚‚Òáçho¯E[Û)øú.Ç=7¤G‰¿?Nù¹¹´oË
    ¤üÜ\¢úúüò7hÝòå´&5•òssÝãÔÕõ àÄ	z9.ŽN<(ï޺ի׿AK9ÑÇ99䬤êê_ºró³¼¼³~
    QsóçÃVFï\»Fôé§qUŒŠŠuT_ o!)8q‚¨¤d…ë÷ŠyóÔØxÂE =%¥Œ?z4ž'Aà§Ž_‘>gΠ	¨†$Íæ‹àùv€ è“	°Û°Zk›lׯPhµîkiDt´é¯Nç[K­Ö¿Wß»¾léÒo«L¦èáÉ~dýŽÇð<椦ÞÌÈøK7:5õÏQáá¸[W×õû¬¬#ÜåÒ-ž;÷œ%™LéY»wþM^žã[·ø>I¬ü†ŒÀ±¬¬õðñ‰Åر›z†Ò\º¦«WŠÉ“?k¿?rKFFãV¯.B`à‹i¡ädß™		«DY.÷
    ó¨$˜—WàC[Fív«µÍýH’üP±
    öùɲe9.¼YîŽ_Æ©ÕÜ®}ûVž;s&jµr ×ÈmmuÛöîM°ÿ¿ò€Z¥8î¡8ýUvö±3_~éþmܳ'	óçŸóÒéFÃáw/X³Æòeë¿ôR¡¿·w²K—Ò}4O€°€€1_h4}ÿ‘ììêQ,Ðôlu%¬Ö:f±˜½U*€ÑžíÄJ¥Bïãƒf³ù_#½»ÖUUýu:@¡pßò²³«:Ëï»úývæ„¶6{TR’\xéRMhDDôHo®ª*zùÕWãï––BëçÄéõè*--Ô'&Nèb,Γðy¨7*˜L–oïëèt䬭½ß»7ºãõ×ÏÈ\wº¤¤É+,¬;ÞZZ$0F#?
    ‡  %ðÍÍ-º¸¸WgÇÓÕ¦þø¿|×ò¤˜ €mÞ¡à=\¶>‰Àßþtø°fá’% Rq`ŒƒJEày!!¬V‚R©p3F.§Õú€ç9hµ
    ð¼­VÁIA¥B/ RÁ¥cÝó2ð<‡Ž‚JÅñõõµÁCäÆôýØúˆ¼6)"â.9Ž´ÄD#9ÒÛÓ¦Ý&Æ(Ý`("Æ(->ÞH¢H+ÔÕÅúâ2’’nc´ê	¸7‡cŒÒ‹Ü8Q”~½yóù£6\öäãÞW]¾|™DQ&A bL&I"E™œÎî–(v‹"¹q¢8ŽzáäpÌb¹¨ÓY¤ššºÁX;?9¹ˆœNqERÒ7ÔÑA«““‹ˆç¥´„#цY³JIXºÁPDN§”–˜h¤ŽJŸ2å!\æ+¯” HžâVõÆ	Ú¾½àÐöí©­<%à ÁV^~“$‰H\«#‘$ñ<#ƈœNÑ­÷ÇØ æc6[C··E²Ù̃!ðþ;K–\&ž§4ƒÁHÒêØØ"âyyý´i·I–éç3f“,Óº)Sn“ÓùDÜ;3f”Ñàpû^ˆ8-€±=zŽã”¡¡¡P«Õ*èT(àEŽˆ€eĨQÖœsçôóÇkåÛ7š7¬[×V[V¦˜4{vBÆ»<àÀ!Þ¾] ŠŒœQì¹)(›MYæÀqZpœÖ³mKøøþàGtv²±		A¾ûîoíÚ5_Àx—ø?E·ÞÏôÿ‰³Ð¿Ž
    êè†ðNIEND®B`‚xterm-353/icons/xterm.png0000644000175100001440000000151311766601046014233 0ustar  tomusers‰PNG
    
    
    IHDR00Wù‡sRGB®ÎébKGDÿÿÿ ½§“	pHYs
    ×
    ×B(›xtIMEÜ	$&R?ÌÖËIDAThÞíÙÏkUðOL"Ö‚46jŠ.¢›TZˆAUÅ.J
    *‚v©—­wíª›.ŠèRòdeÁ…P¤"þ ¥MU\ÔÛ*Ò`^6˜.Þ˜^æ½7ïGf&!.oÞ¹÷Ìœï¹çÜsæ;”f±Ž¤âñ/^èÀz¯‚[`Èž€$îF¬l‚ü—»0gJ´z¬lÒ‚_@U®”îzì
    …A$9ÂeS+²à
    72>:—Yw0òß22l,<_0Ÿ³ö4¾ÃÞ:€§pG3¼7ñ++Ñ…zÏbGðR¨§K޾¤Gë︅ç*âûxôpã;X7­k-Ô
    ý–q(ä‡ÕÛÂ…å_Ìð^¼Gë`?â휵ïã2¬3€l²z&ZÛØ‰¬NqØ÷)T+Ú°]ä½9µãgçþè†OðFôŒ3ƒŒ¹V”tq¤sã¾æ®`(üÅRŽjÄéÃöDü«8®ßÂ¥2ް¤ kÅsßb:š›Â7a–2/Gt˜ÀÆ w`(ñÜ8®áÉhî7ü‰ñs(Í‹Ðø°ÌHãàì‹æÒ¾Ïó92y:Lâ/ì/Ë…²ô>ê¼€‹8ßo¯ª”ȵ~§hTØjäT½ŸàŸnÐwÝÒÅÝÀ¤ßÏóÅÙ¨dÞêïzÒï§T·îôF·­›²­^t7v©*z¨]GÓør¥ÆP&ûöK£Ø,
    à3|OŒÖúŸ%ÈX¨f7‹½‚Ÿ0ŒÅÀ«ê7=>ÿÇHåGpÇkà÷ÙäUÀ»ø¼b«/æn…<¢Ùq>\3ëp5´þ1ÍO¯Ãí”ãñšYÿUÜÖü°Ò–p.\/‡‘^ou¹°=7µþ|P~¦H¢YÑìù¯×`Vñ.à$¾ê`\ódʆ»x
    _ïø"éþ9·¯¬nuIEND®B`‚xterm-353/icons/xterm-color_16x16.xpm0000644000175100001440000000306012034777545016242 0ustar  tomusers/* XPM */
    static char * xterm_color_16x16_xpm[] = {
    "16 16 80 1",
    ".	c None",
    " 	c #555500",
    "+	c #545400",
    "@	c #3A3A00",
    "#	c #222200",
    "$	c #2A2A00",
    "%	c #2B2B00",
    "&	c #151500",
    "*	c #5E5E00",
    "=	c #5A5A00",
    "-	c #909098",
    ";	c #3E3E3E",
    ">	c #000000",
    ",	c #F2F2F2",
    "'	c #2E2E36",
    ")	c #343400",
    "!	c #4C0000",
    "~	c #140000",
    "{	c #7C0000",
    "]	c #7F7F7F",
    "^	c #858588",
    "/	c #EA0000",
    "(	c #0B0000",
    "_	c #460000",
    ":	c #8E0000",
    "<	c #A80000",
    "[	c #474747",
    "}	c #868686",
    "|	c #404548",
    "1	c #8F3400",
    "2	c #451200",
    "3	c #299000",
    "4	c #1F6C00",
    "5	c #192E48",
    "6	c #1B3448",
    "7	c #888888",
    "8	c #CF4C00",
    "9	c #3B0700",
    "0	c #39C700",
    "a	c #42E800",
    "b	c #2D5181",
    "c	c #55A3E3",
    "d	c #305C81",
    "e	c #989898",
    "f	c #D84F00",
    "g	c #3A0600",
    "h	c #258100",
    "i	c #376599",
    "j	c #396D99",
    "k	c #7E7E7E",
    "l	c #010100",
    "m	c #000101",
    "n	c #9A9A9A",
    "o	c #101000",
    "p	c #5B5B00",
    "q	c #3D3D00",
    "r	c #272700",
    "s	c #2F2F00",
    "t	c #303000",
    "u	c #1A1A00",
    "v	c #464636",
    "w	c #7A7A7F",
    "x	c #8B8B90",
    "y	c #1B1B00",
    "z	c #0F0F00",
    "A	c #FFFFFF",
    "B	c #5B5B5B",
    "C	c #C9C9C9",
    "D	c #BFBFBF",
    "E	c #B5B5B5",
    "F	c #5C5C5C",
    "G	c #79797F",
    "H	c #7F7F88",
    "I	c #484835",
    "J	c #3C3C00",
    "K	c #1E1E00",
    "L	c #909090",
    "M	c #333336",
    "N	c #464600",
    "O	c #575700",
    ".+@#$$$$$$$$%&*+",
    ".=-;>>>>>>>>>,')",
    ".=>!~{>>>>>>>>]^",
    ".=>>/(>>>>>>>>]]",
    ".=>_:<>>>>>>>>]]",
    ".=>>>>>>>>>>>>]]",
    ".=>[}|12345>6>]]",
    ".=>>7>890abcd>]]",
    ".=>>e>fgh0i>j>k^",
    ".=>>>l>>>>>m>>no",
    ".=-;>>>>>>>>>,>p",
    ".+qrsssssssstu*.",
    ".pvwwwwwwwwwwxy.",
    "+zABABCDDDEAFG*.",
    "*HBABAEDDDCBAIJ.",
    "KL]]]]]]]]]]MNO."};
    xterm-353/icons/mini.xterm_16x16.png0000644000175100001440000000133412034362166016030 0ustar  tomusers‰PNG
    
    
    IHDRóÿasRGB®ÎébKGDÿÿÿ ½§“	pHYs
    ×
    ×B(›xtIMEÜ
    ž@Å\IDAT8Ë“KH”qÅÿQqtЬ)+K©1mTÌ,í	YHÐ¥ˆ‚ÈAÑ"hÓº0µ‘.’ ˆˆ*"
    ¡"¤è¡fo±Ñïcü,gæ´p,ݽ~÷.×°˜sÄã&
    ! ›NóžtM¥™L6ñ¿‚éÄ X Ø©x.ªG+¼\¬‰ø%‚íŠážVb+‘S‚Dä2ÐaàÊÖýךZ?çÝïôûh_”±9§úù7å3j?SzÒz³63µ•¼‡¦V
    æ’Ú§z%n?Åc)q~Wh}Á
    æ>øJ’%¢ä/xÜ»:û¶cÒì~<–˜f¢F¾ß€£ß·1Í–+'PoMO¨Ó^Â*f8&»¿¯­·}¶|T€âðêðÚb×ÐÁ߀R§åƒ
    ‘Ìy*¦YehFÖ‡ ^[¯‹2ŒÛx™s-CÍc: ˜ÑJq×nzfåv
    ¯­CGj
    ÆgVØÙ®‘Æ”v0ÿ|‡ó´Ð2ZæÛÏf˜$¼˜ 7Ì$/Ž
    ¬k»S-"wŸ IA,s8EÀ	º€è¹Á4r©ù/Ig+q¨¸<‘„€›
    -!ÿŸŸöÐÍ-óŽÛ
    aèöÊ¡jRfÁTy8¦b,¥p8ª|ð*ùƒwH¶E²-wfß“U%w?~Ù—"-ÅQÅ‚$#8LUx€aàÐËuÓA)€b9K>•ô‘‰|zF>Ò²ÿ„h/¼ŠlXÌûÃŒ¦Ÿú‚¦½_IEND®B`‚xterm-353/icons/xterm-color_32x32.xpm0000644000175100001440000000410412034777553016235 0ustar  tomusers/* XPM */
    static char * xterm_color_32x32_xpm[] = {
    "32 32 60 1",
    ".	c None",
    " 	c #FFFFFF",
    "+	c #000000",
    "@	c #EFEFEF",
    "#	c #FEFEFE",
    "$	c #FBFBFB",
    "%	c #F3F3F3",
    "&	c #ADADAD",
    "*	c #909090",
    "=	c #737373",
    "-	c #D2D2D2",
    ";	c #646464",
    ">	c #9A9A9A",
    ",	c #8D8D8D",
    "'	c #D3D3D3",
    ")	c #0E0E0E",
    "!	c #F6F6F6",
    "~	c #5E5E5E",
    "{	c #B1B1B1",
    "]	c #777777",
    "^	c #949494",
    "/	c #757575",
    "(	c #C4C4C4",
    "_	c #E7E7E7",
    ":	c #F1F1F1",
    "<	c #F8F8F8",
    "[	c #EEEEEE",
    "}	c #F0F0F0",
    "|	c #FAFAFA",
    "1	c #7B7B7B",
    "2	c #3D3D3D",
    "3	c #868686",
    "4	c #4F4F4F",
    "5	c #ABABAB",
    "6	c #545454",
    "7	c #5B5B5B",
    "8	c #AFAFAF",
    "9	c #292929",
    "0	c #181818",
    "a	c #C7C7C7",
    "b	c #CFCFCF",
    "c	c #7F7F7F",
    "d	c #A3A3A3",
    "e	c #4D4D4D",
    "f	c #6A6A6A",
    "g	c #A1A1A1",
    "h	c #8E8E8E",
    "i	c #696969",
    "j	c #474747",
    "k	c #5A5A5A",
    "l	c #959595",
    "m	c #767676",
    "n	c #8B8B8B",
    "o	c #BCBCBC",
    "p	c #BFBFBF",
    "q	c #D7D7D7",
    "r	c #404040",
    "s	c #636363",
    "t	c #989898",
    "u	c #8A8A8A",
    "................................",
    ".....+++++++++++++++++++++++....",
    "....+..+++++++++++++++++++..++..",
    "....+.+...................+.+.+.",
    "....++.@#.$%................+..+",
    "....++.&*.=-................+..+",
    "....++..;>,.................+..+",
    "....++..')!.................+..+",
    "....++.#~{].................+..+",
    "....++.^{./(................+..+",
    "....++......................+..+",
    "....++......................+..+",
    "....++.____:___<_[..<}..[|..+..+",
    "....++.1;21341156]7.89$:0a..+..+",
    "....++..bc.8^__8d.e.8fghia..+..+",
    "....++..bc.84115jkl.887mna..+..+",
    "....++..bc.8d..8dof.88pqna..+..+",
    "....++..bc.8rss5d.tu88..na..+...",
    "....++......................+.+.",
    "....++......................+.+.",
    "....+.+...................+.++..",
    "....+..+++++++++++++++++++..+...",
    ".....+++++++++++++++++++++++....",
    "................................",
    ".....++++++++++++++++++++++++...",
    "....+.......................+...",
    "...+.......................+....",
    "...+..++..++.++..++..+..++.+....",
    "....++..++..+..++..++.++........",
    "..+.......................+.+...",
    ".+.......................+......",
    ".++++++++++++++++++++++++++....."};
    xterm-353/icons/mini.xterm_256x256.png0000644000175100001440000002650312034362025016203 0ustar  tomusers‰PNG
    
    
    IHDR\r¨fsRGB®ÎébKGDÿÿÿ ½§“	pHYs
    ×
    ×B(›xtIMEÜ
    %Ê^R IDATxÚíy˜SÕÝÇ?'“Y˜a_QAqÁ¶Z¬Õº´jµUa­ZµµZÛj­¶¶.µUkmÕªuôUßöíb[ë®,"n¨ˆ¢AÙ—Ù2IÎûǹ3“drî;$¹7Éïó~çm`qž¯«µ˜ ß
    õ]`˜ó
    Šý€í2rµ }ÎgçßànIYË\ %À¿_	LÁg%!Tì
    õQ>¼Pš¿ø 	˜ð5ÆJ?*JútcÙ·µt«¤ø6W|
    }¥?ÀgœŸ]å#à½Ò®–â<xh¸1†œ¡úí&
    î™~£W_)еn°~:8*àÚ[Œ×ÉÇGó|”«B…†	ÀîìÞ—Y?LõùO«]K\¼^ÈÖ¦ÌVxp@#úð{kƒ^kà	`µÄF`_ŸÈœ·GP,öÊZ 8èáãKßqÖþv¾¯LØsYäyzrð¸µÀ«À–€çOSp;LíÜ«åÜ ŸÜdíü‡úìüveç)àfÙ(çZÇØð"ÁÑôv& v޾)ý4/£ÿ	ÀùÖc€]||a¯#¿
    Àeæ~"d×ç¹>’ Ãevv-q£†=¤Ëæ´óÁ̳ÓÇS˜;óŠçŒò—R=Å>¶‚?X,Ö|‘“jë§uÀlíïJ°w~Ü²¶êÃðgçº
    XêZâ§"ßÁXdm¼ˆ±Ú
    ŠZ`¢k‰I¸íT~¸cÍŸñÀßÖ„±2µópq)VdÑ€2öXgZWh[1{ÁA2ÒyÙù‰öo‹&¤ký8à—ÖC€}|~é\ Ùúi˜¦‚µ<pDàYàk¥¿B›è̲SÌÒn‹Á­óWaÛׯ¿¯ÆÏ6óKµN‹Ñ–íJà-W5Òa¨ÚÙ°3¸Vºs·¸ØÏu‘UçãÛ6ãuä÷pc)WhÑ	€2“µéØœJ›0±	‚dg¼²$}WÃg¥?ûý§—XŒò\~¥Óvä—°–ØLWn%J€ð¨ÌÖßBóe¯b{®}äˆõ+ìGk}ñg’‡Ë:{k‰V7ÍÛóÐùñH4!ÝÛcRo©œ´lþ¤ÊDkö¥Sæ<ÀOkÞŠëªþÝ÷Z¼ªßðµyèqÿbººI é*šùãt+¥È&jÆ©ªI–†E¾"_(qúÑÂ)a¹˜h¨ªFgXü]ÙÍZšŒPÜT×÷Lmçç³d	¾öƒfIû5=ƒû›¥ñ¥A}
    Y•:÷Þ‡iêYtpnš =Ó*F(2Ûs’sd Çt43Úߘ€å²9.”+°,­M×s¿®hâdR­·ŸŽIƒJgÓÚu¢œ,`®¢Ã_¾QÃü¸4¡ôX7í»
    íâæ^60Gï‹fJûû—Z!V&;ÿµ
    êôT°Sļz9ÿWJG+0÷Ô+å>ëœûŒ–‘´h˜—¶p÷뽂¼¤à«?™¡‚Å>ýƒ"
    }§ôvo½"¦Ãw%3Í6
    ë’æõIÇÍþH˜“Tì	QØ­ÂÔàôéÂaS“†Í¶jØš4ÿÞ¤aMV'`m2Xwï\ñL+Lm?
    PTp.ðÝ .'ØcÀÇtOšY…‰ßKp]y]öQ¦¡ïV#+`—ˆä·V·jø{ü'H.9+c£pj5ìž§˜'I`}>NÂ
    µéSêbáê:Õ^OëÙÌp.R¸°;hækíÌÙ˜é§`Ÿ(Œ‹Â^Ðßÿ<½R·20¶žÉ&zlo¢¦ÁØ:ôjÚFE2Á溾h›êúéG4'U$Ý£¡·‚Ójà¨*c'ñfÀÃb˜^GTYÇv`5ŠMκwP¢§ó¾O¿†Mýþ›êú¹/VÛfTDÛÖа:	ïÅaqÞŽ‡ <ƒQíu }9x¸üf³ôBà öéîw¶…kš§0#ÚÄJØ7
    ;»wx¥5#›—³Gã2F5Èî°{ÓmYÍÀÖõŠ­£o|sÇ/Ä01퓞¥'|çñ£?ø¸=Ñ|Íq¤BOw6Á‚§ßì“ÓÖ3›QüÍ_QÌcºr®¯Mä¾¹@UK´šu½±ºïPÖö̇;bécxoôh–ÖaeµG„Ïffðf^m5³…0R£à7=ÍOG¨WG”—ÌÒ‘há1x$$–£œNpÚ;ýnMÿå­/sàÖE¸mn]DŸ¸Ï8åk€»–ø­‚‹LoÑŠÙLîÆD¼7‚ùƒífz\hÆTÀêR[Ó"âÇLµ¦+¿®÷þ"lÎÓ5˜¸¿ÎiùÖho^î}úLd~ŸI,è3‘u•ƒì`Eæ¶ÂüV³Ÿ&άÏWuT…f/f¨÷ÊGÔ¿Gñö©ÜeÛ͆Oª<¥Ò<”]²wúA­ë˜ºá)ŽÜôŽÜøF4­ÈÍß^ˆ‰Lcí'¥à?)âùEàï´Ûjf…æüpheÇZ6Ê8NW]v¡ÕpÆ4;Ÿ†»Ç’º±<1àhžx4Ï÷ù,Í5ÙkpIžj53ƒ0ؘ¬€ŸÕ¥^ãMÌPß/xL÷q6ÿÌ:ðí8ü¢1˜14bÖÓ“+¡GçêÑ´‚S>ý_¾¶öQܶ¥ó0’$€¿á’z%°¿ÂYG¸8»ý÷/Úf–Q…¢—‚[{¥î"]K½ºÊGç?ø‹}vWÕtbÐø¯ZžÝõpþtà‰üñà“ɺ§°1	O·šý¦mÏ
    ~Zg6
    ë¨a8§ªXéÀƒú·wLr›`a×±Ã"pB5LªìTcë9cÍC|mí£LÚ:??>“
    À?q;⛣L$$Ãl=ÍKíïo/ð^ÀQøNZðÃéWÏu±óÁdsÈ>ï‹¿-êçåo[¢Õüsÿc˜3y,Í•3ƒ8ðB³|³q:3íºN£^=Rú0K¿	ìk¶Œ4\²­pÓ²#ð•j³ÆÏ¸û‰[pÁª;øÚšG©ÖœÊ¼‰WºÉSüÁ™EUÑÌVÚŒ>ƒÙÜCùJ5œT:àjc:¿þɘԙð%LRµ®ò¤HaçéSÿ]~½ë-­Dq™	KãÀó1økÌÌ
    ½ìLÝÔ<ÅudiÀz
    ^lÿ×øC:[/eìáUié9¢‰8§Íÿ.yâèûìà”P;³€õ®ó„qN¶$˜¥—#X‡[¸Œ:¯‡Ù3i[ÿ׫A]¼Åï¿¶Ï,ðÖ{›³|juÝa9LAŒ«u„ÝøŠ‹€#ÓÚ³,øsKa—gÕ˜6ÙV=Œáõ~¡þ|á
    N#)–x6ÏÓÖ
    ŒåÕ/{šŸ¿þÅY¼óý™uW=¬xÍŒÀAfRxe´ÜÓžlT¥ì	ÔøZÓ÷K»ØùÇá•ò}oŸ‚ù‚kçoÀÄô7ëê«U’êoÔ«£H0ÁÙƒ0½=
    |¡
    nìi~*‡Sº›°"îì딤<¨_mÿF<¿ë¯±Q¸¶'̨1vç†ä×<Ú°äò±`÷ÄúXp¯:³aVüĹâìâó^ÖcÎüí<Ü™÷»ªWÿe3‡¡¹­ýÿz)3ÈÅ)A瀸_`–Þ­¸ 5òiœÛü+ëÒ
    44ó‰r(ÓÕŽvÑ;'¬Ÿ.ÂØEÿ†2ÁŒþ‡—[Œ ÓßVŒµŸ}ÐXœ­vlXé:©f¨o3i[n´ÍHO¬Þñç“:<‚vŒ¾ŠRÔÀãÚß/lí¾õ\UÃÓ.ùÏôàóœ®vØ€×i@gµ¯ó2‰ãuöœvŸ©lá;`6¶í±Z̦¦^ÆØûÛwf*“ˆ½°Ô«0ö
    ›Ú÷N¬6B°#‡Ë°2™Ú0gòŒŽ§Dø©ÕÑ]Ë¿¡s¾Ÿƒï·ÔðÕ\¦YVÆä›®SÑÅ÷²€~¡Õ€;°™ô´ùUûø¶åO?;¿Qn³¶ü‹Às$˜œv•“+Í)ÁެÒgCùˆã‹OžÑÑ´éË'Iõ×/;GàŠŒÝVÍ/¨WqªÊ¹±‚ÿÅØ¬g'h‡¡ˆÓ‘B–7@Ãé˜WvöÆ8ût•¼Žü».5
    ÅLõ.Q&‘Þn|¾[ÕÝ\¼Ôš~–Éßf`þšÑ*¾Dj@§gbþ§ÏÜΟn}u3T¾ü·1Qx:“ÄX	VªŸ3	UñX%¤xɤ¿Ïëm;ò³O›1G~á"yºZO„#«6ì5›ÕµÝF
    /·¦ÖÇyH(.HJÇ€}žýŒ˜
    ì­R‡ç«©WWæûy:¡·Î²®ø·¼ÃÐÞìØ43‡ìºá£]€¾Y?¬>ã³¥½
    ¸G¼LÁ[¡šMS[i⋤Æn]Ñ}x&c30™7áüÀýz$š/¶¿_Ð
    
    >†ÿ^
    .«M_ók~ÌtõÓB=O'ço­–¬Ã¸‡€±&»ßA¤f~ðf=^Q‘þéú\‚ä<ÕH‚ã1!J»WB¿¾ï'ÒÚkÎÊÇf`~À¤;ŠXÔÌc>©ÌúipÚ¥ýŽêšé帗Ì%X‡¡
    ÂÍpl¿³ÓvÒbwû8K{ãµ'ÐL
    'ÿ꘭Eá‚ZÿÏ+}3p˜³¬¹˜`gµ¿ÿ¨S^t;Qà’™é¥¦†o4Ⱥ;5`Ž©„ÎÔàß„y!n¶sÞ¿&ô÷~ªŠÑÄI¤ÚNˆÂ9=üÙ	¼˜±¨sï&œ{0ÁwŒþ>ÖþÓjÌæIOSÃÌ|ìöûW€k­>$x‡¡02[ìŸì|„±Ç´s§JZ‡óT#5|‰ÔƒãÉ•ðu•Ò á•´þs÷é]¾èØükÖæH£+L­JÍ”°˜N*tœt×ãå0Ô$}¾1x&ôH£˜çZâàÒ¢«‡SÕâL–utá*·<ŠÉÜ¬Èíf`nàA=èÈq6¯S¤“ìì5£ëˆs,§ª-axŽÊ¬Në±ù†Áa(,ô¡-Ûc×yÉ©C¬µ{†*V‰=K­Cq©ÖŠÓkL›ï
    KƆ¦£1žÍcº"œ`"þ*_ÓÿÁ¸°GêI8‰³ÔÊ0=G'¸ä¬>&x‡¡ ‰`Žüü4Ï·ñ:M¹By„éjðuR}¾Ý#s£ÛNúfàpš8&|p¿®A3£cmœ€åK÷*e*¢WÚÎÈÔ«Cú(ï uw7“ †‚æü%ôؼæZâ?À-%Q7õêià‚ö÷uÊIJèŠÀ‹­é‘ªS£k…F"|ÿÍðz\ò§UîiÃÅo¨W÷†õ:ÇOgf‡¡ ðÓ?Žñò³ùmêU)Õf½ºÅuÉL
    –>ÿhæèáa€t'š“ªM¨®SªMà„Ì¿thejF€Ôðý°?Ce&ûX„Áa(€Jñàc^Ù¾¡‚Íœ{ªù!:%fáÄJ82˦à€^i–Ç·÷2bÑA”dÊQûË¢ÇtZ¨qƾŽf0¢Â¼Ž¯6*öVÜ„_›ÌT¾M$øzHvü»ÒÞÕðeà´¬ÞÄDñP&P‹¿ÌD«<÷KîVðç’¬«SU‚‡õÄy¶`©§×Àª„Ég±oÆE¬£Â#f·þ î×C¨àhÇ¢ù©F uʨÝÄNìÍÙÌTË‹ìQ^|Öéêé$¥Àq„ßZ/ø1smÂëÄd)ðÝ’®¯ÓÕZféÓ0Ñ‹+ˆbœÞÜyø7š'iæ9ÎSá€6fª5˜ððŒŽ²‚ÉD88†¶lÀ¹êOE8ëݤMT˜eü¶9ŒÊ\Ü|øb˜#¿†’¯‡zõ³õÑ\g)±xxÍ“ÌPçã2ò—üÌæ|Þy]Æ=œÇ:g¢S1#_¥†ïñÒ÷I
    ·ÅTy	°þüàK™%˜;?qBµ—Óø9søš£Yœ‹âß$ù7õ¼ž‘Ȇâ€N7«Vwwñ˜®¢‘éàÃbY÷»p9&4Tv·——€ãñï
    VjlÂË…úà—eU'JiÖõ$8€FžO›ÖÏ(Ì%D¹qÓéÿ]ÏЄo˜îLn;×g›ÃÐaeÜù˜#¿„«<ÌP¹MW<û†5‹ äBâå0´¢Œ+èU`³k‰s•-“ P$\Gj\¸LæSžCã•®ãæ#Pì³€8f) Cm4{Þó2&Öƒ XŠ[¤Ú1.EåÂ\×YO˜¦Ü}"EÈm˜óÛ켂[¢‹Òa)ÆâÏÎÕÊ-Æ‚ P¤³1Úd÷JÝah©)4³ñ"pƒ´€Rw‡¡u„-¨uîHâuä·Ù™ú'¤¥ˆ”²<A×gA@èÆ, ã0”}Åß–a(ÜÜ¢ÉMÚjA E`^C…úz³ty$EòÂ5¸eÈ
    ¿ÃÐg9#ˆݘ´õÖnÞL18]­a¼ƒÙy+uÀ!®%&âfê,ˆ”1ßޱ~:¯Ýöp0
    éZâ*îyŒ€PðÑðKk!À>EtC1çÙ©ÄÄè!O^@:¿ÙÒ{›]ÆÓ¾˜Ѫý;cä鋦#ìgýt’³¶.6vör-ñm
    GÊã(çÑÿ(à;Ö»{®§ÃÍÌÉEvÆa¨Ÿ´€rìü¬“û^xí¨‡Ÿ(ÆJо|Ü.­A ¹›éŒr:Ne	Üå@×Ài¾&ÍA œFÿs¬ö•Ð
    ïç;4“–!P/àWÖƒðr±->Úf4v#¦þÀ}â0$Pê¿
    è#û¾~%ÆÚ¯»Aoà@×GJ+(e~êÚ
    &=KøîÇ`ŽíüB›R‚@ÉþGà–8c$å‘\k2nÞŒµ˜°âQi1"¥ÔùûZë½cðSÔ:3;WI«(%îvÉúIÛY•o‹ymxÏv®Ð^2!ˆÉè&pеÀ8`°/l¦òxsn&ÎQŒÃP´ €bîü£p=sæï‡¹@²*§
    /‡¡Ñ¸yH
    "!ïüQL`Ï^Ö1î0ŸOb)&?`©0·È‡çk8ZZ“@1rnëØCps”éÌÜ’‡/pˤ0Bý¥9‰Óè?ø‘µÀ®ø™^Ää,5*0ÆO×yÂÒªDŠ¥ó÷ÆXûe~YêóK_6”p¥õÇk/ä
    Ó¤u‰·áæÅ?a½×ï”A­ÃËê·Úv”*ˆ„dô?˜n-°7^±óÓ‰/™/.y¼†úˆÃ@X;ÿÜ‚[ôÇ+{Ngæ
    eT‰½ðŠüyÜ"(	"uþ
    `–3JuÆ{£«3+ʰ2GcâÙù¹6s)A 4\|ÖúéA¸uufð²ýãÆªÚí%]›‡â¶ORƒqª’f'†Ñÿ`à'ÖÃñçàª1G~­Ö
    K‡ŽYZÒ•Ú¯“’	À¥õ‰Ýù{bbúWZǪÉ>¿ô
    `k‰‹ªëšJ¾rwÅDEv™uiÿµ+ˆä”_{Z?‚-ÝGvÖ‹]KüIÁ=eS»îC‡¡žÒE‚ýOζØa.[©¿ýÈo5pNYUr%^Y‘vÇ-¾¢ §Î?ø½µ@_¼âßuffóϾ30C•¶=`v†àµçކã¤UŠªó+LtŸþÖ‰ég°gg9ð¡k‰[¯üA¿×¥H] Ä\
    Lµ~zþ’]5ó]K¼	\QÖ5^—ëôLÔ%A ¯£ÿxà:k¡ø3QÑS_{ˆ¯fà-e_ùýqµs¢}IÈKç¯Åùe7@©vF)?¼qö±ó}oIí;ì
    ìäZâV]ÜéTEBÌM®ãûdŒKWÙ¼îZâŸHâÌt¼s&öÆ8IûÈéèðMkÑøsTcŽüì±ýÖg©òðôGOŒí¥Ïß•ŠÈUç‚É䫬cÎA>¿ôLˆ/ûÎÀÙÊkqPÎìá)¸×êÒ˰(@çWÀ}Ö•gsäç'ÍJà=×w*x\j߃Cq³²¬æˆÃÀŽr!pŒõÓñÀßÖ„ññ·ó.𽢩D€»/‡¡ý€k¤	‹twôÜh-0ØÇç—¾„9ØËN˜¦ ±h*©!`دગj77mÁÒù«1G~Ù'™U˜Ýh?Á©–Ÿ¸–¸R[àï&`iŒ-ó¢µ[	!78SÈìLÂ_ÒªÍÀ«®%žn.ÊšZ¬
    ðï{;n•&-ÐÕ|i.Ÿ·IDATÑÿ(ÜâÎíŽ?S“ð‚ëTyÆÑ'Y¬ÆK¸0É?;y.ÇfjøŠ´n¯¶<xÀ:žôÂø¨ûáU§‹Û9O™³âe;°0àkWþ »µ¿4¬"eÈ}Øw{[¡uægŠlçÿ»CWÜ[¡e+cçùؽ0áæÂ-Pö£ÿ¹À	ÖûãÏá´Å™Ûù¸¨[«R¢à:]Xc‡à$"½mn§ù§/^CÇkø†´v€Ìοn‘eáß®l.æÜ?;q̑߶n^p‡éQ³.xeµÏük2¢q5;÷$c1¶›vnqÒ¶‹àX‹ÍÁ¶¯_‰±öósä÷žçtøåeäNG^áBo¦NkE–õÐ*g9
    s*`·쉉%X! ü·^ñvr+ÆÖßÎ<Üb
    ø4xršÑXU›½ÌBº;·É
    ux9M~  £ÿÀ÷­Fâo²˜ÄùÙ×åÛœ©ÿŽÙÏ©”ÙJ¡-ñZ:§¹ÊbŒßJð9
    wÇ$k³sµàE L;?Ll¿
    ë(2Éç—¾ŽWØÎ•Wô¿®Q“­C„qk‰º¤9þ”à³OÂ-FC&ÃP@yr'6§Ò¶#??¾dk1~ì<ª`ö_õcºŠÔÄY…–±äØÐsÀ_¬e_ÃË"¿Tã•:dÜ/ÇDŠrô?8ÕµYø1‰áÓ%p~N.¾ÓÞo*ð.à–ô›<óœ®Ç» éÔKCÃ0[ì\ì,Eʤó~c-0sæï‡ù¸¥ñNõ*WcaeÆ!׿/6§Î߯W‡I’ýB6áú,ÿ„›;PF¬¯@éwþ(ÆË/{sˆâ~º3bâúÛ¹QÁ³9»‰DÆÖÖ†ÏÖëÌåÒpÿî¶þÎ;ë0Ôö\íG¹»º
    "%ÃU¸míLê	»7Û1}ì,Â-sp÷žÜ^iï?)°¬IfŽõcŸßÃf‡!oc®é¾*Pº£ÿdàG®cÀžþ¾\u#æÈ/–ÓI¦$ߢÓLsB‹ÎœuŒ5¶õÖ†öÃ+‚ÓÚæ"PÔ¿·3õÏ~äW‹Wx©Î,Æ+÷%Ê„øÊ-*ÅhiE@»k+Òà€ŽKcðëï…ßahp¯ög÷)P܆›ÿRÖº°Þp-ñWå¶&î.ëÁ¤îi/
    HÞK³tÁ}:õ8õ§¸Å	
    Úa¨0ÁµÄ1Ày"¥3úŸL·Ø“¾VgêoŸy¯!_g	>—öþÝx0•º$Cx*:®ËYòL·vófvÌ"Œõ|æ7iB€vþÀÖý=GƒÎ¼ŒWï3•×â û7tRû¿7iXÔ ë“©­é¤ôU
    oã–Ðt%Á:µÍúì†^u+Á
    €âíüSßìç»mi¼ýÔÄ
    à׿Qð¯¼ÜÐýº/&C‘aakp¶öx9žúþÖ3JÝŠ‰u˜…˜Á ¨Å8zÙ™H	ge.‡Àå1eNå g=ØUñJãý–ó7óCç“ê²ü|k°µû|,U€jHpaÆ, 	ÌÄ–©/ëÉü³^ñ¯Òþó>‰„`ô?·ó÷ár˜ÖµïEÜìîÛÒxçg{k¶Jªûê[qø(l%’„7Òf—2GϸE=
    ƒÃÐDg6JLì€"ÅÓù{bŽü²Gï«ÁËA¤3ïà•©ïroæç†´Âd	îXÊ<Ge?Þ’:‚÷"ÉÎõ¦ŠÀ,àÿ¬ßñ:aw‹	/P$ü·Ü)øs݈Wò‹“O3ÒÙ\ŽæÄö÷ó[aI<5ý~^L[ŠÏl®ÏRò<«„&ÞahgȰ¯ÌäÛŽÿè"Æ1%;{a¼ÃºJsäg·¶]ÙõÏÏJv¶¾ŒTwÕIx¨9\•þp3¬M¦ï½<¨¯Ê˜¬Çíh4Cp3W‡¡~"áíüÀ{¬úàø+;‹pKã
    &÷êœßÌcºêûÐÜ@›UZ£†›;¹ãNƒ†_7šŸÝågÌÒñî—ÒƒþŽ[Xîwœ= ðv†Û‘r‘¡J¬ó+àI`jÖÀ—ð§ß«€§]KÜ­rm1vîO瓚’|cÒtþ•!N4,—ÖÂÀHæéV4¿c†ÚàìϼŽ	ØÕ™žÀñøË½kÞÀËÊó4ˆ„K¾‡[&߃0]¥	x·=ý÷€	Ê-
    @W¸ZGÅÞ(>ƒæGÀÒ›ÿüV˜Ó[uøD/gÔÀäÊl‹©§€Ç¯ý¿+·þð/?¿?¢“ÙlöÀÿ&mŽÿt¤Ë¾`ÙWÁÇ"áèüã1N¹Ùíº†_ðù¥OáöxcÀd×L¾÷ëÌ®}_*鋦/šþΨ>Åp4c0‡‘ÙWž+“ðh3¼/¾‡2.
    §UÃ.Ùûxu¼%¶ïÊÅUcV/eئºy5ƒ¶­£ÿöômÜLß}7ÓwàfúÆ7Ó#ÑTøëß
    ü
    ·à®O_TÁZ1ˆ8糯XÇ÷jL®?§¸ïbÌ}-ü}ü±·wÉßbDœŽMû«OÊ¿»h2¼‡§cðZ¼ˆ›—ÓÂöÂÔ*#Ý4ª­Ö-ô1èôjÝÌôÕ³Ù§áíÜ_ÿR¼b=\¤à·"Á
    À¸ÅÚ;ãçßU¶8Êo?’z®ú¾–{bѪÙ9¹ðI>HϾÅñôÍ´R¡NÁ¾Qس¼vŽ@UnšàCoÁékÎÏu»Ï›œeà»ÅøH¢%Ðù¾i-0ÚgçOÏã™Æ;­šb-ÇìÖg¾´1%Þ’„mÚÄñ[›45J°¿w¢A›½Œù­ÃOÿŽ@_½W‚Ú”Ÿ©¯ Zìdà¯Ø,@{`¬§¨`c•Ÿh“ýíëL¦7þ-¸½CXŸï˜¶¦ÀýÍðz«ÙŒ•CoÎÍdCÒ_<Ã*eÁ梀û´±Ü ÛÑÿ(Œ}|vvÇ+²K:m9ëÜÓxŸ¡ÜJ´Q	앎Y´…‘û6Ñ¡˜¤³§È wð€urß³Iã‡7p³õcåõ´x¡ýñÊùUí…:$¨"€?_¶ÞÅј´O]åSLØNû©Ý”›‚?¦{Òšâ©'䜻î=ïÀ#ßúÏÿ`3 I{:’Z?¥g|{Á%Oàûy3°¿òÚað¬çs»¬Æ»î
    t&†ñò³ûð­rÜFé†?û€Ë¬>‰íÛœ¶d_$>L
    «ÃP¤ÀàWÖÞÉ;³Àµó'1i¼¥ó‡ƒãæ™?—`3õÂØÚ9·}+×Î_…9ò˾¯_‰ÿ#¿ÿ:/;7+·8öB¡§¨1`6Küf¼Â´çŸ==g!×kÿ–)áZ8‰5—øúÜc÷†—yf:Û1^~îÁtÈu&_;ï(sÅTŽSÔ—F¿84cb8jc6šLBNˆ…†(`oÂ*°±¸»Ïé»Ë.Ë*L0ufvæ¹÷þϹÿ½çœ{ÏÿXX xz
    ´ž”~±ÃÐר÷$ÐBáax¬ê=ÀÈ
    ¥¤!˜€&=ÆÆŸ 8÷Ö9§î²Aï$x(tšó»	hÅá×x×Ha{lT§
    —˜ýŸ.¿pŽÀLc
    d³ÚM£¨ ˆ
    üž•^NQLRÈ®¢q‡jlüîĽbÀKöØ
    ©°o“ˆ{ZWÄ'ë=§t> fm.ÅÝÃÀ@©é•̈¬%ê®Y.&d”·$9ۗ奷^š¸€
    Ú8Sui¶¹ÉëæÔ /L´:ëÑólË™Ûm‹€E’æ]é:´ó­îÖW"Ery‘h¬±‡›¶Ó%.1]Âç²Öˆ$‚šª×fÉž•Ù
    “ÌÍnÜ\«ƒ¶eþ	ì²Gu‚·ôžÿ&e]¾DqBr÷or~ÕŠ*¦[L·
    ÇÄ$0UôÔI"3pH$ó©d“þ ,B€EØõð+Ï-U/­ŽùhÀFÃdêw¬«(ÚM+FþàŒ³BïuûeD×½@tœ$ƒZ€V®+mìc—rŠM†},
    ¬Ä˜µä¡	äÉsܰ'2;à6‡Ù¦Ô(àr)e
    ½ÜtkÌó=¼ü‚;Hˆž'¨ÀB'éîÅ7”bÖò™¬¶qÝ‘ÈAÛb_m3¤‘
    ßóºrÚ#Mšösšf Ç}O’'1§2‡I\¦=Ù
    X¼{•#¼`¸H·4¨nñÍ‚u;y¡Ysyˆûú¬ô‘I)fLä>úä¾8.¡@¾ÒFñ16#à„ΦŽFœÂz2ÉäBÉN“Â’M&‘ñü6R»ê^­>`+˜ðPjóy]n©½t°lÌ8IT#|a½VãkHb5acJÀIâhø}K²ÏÂDTªýø~4	lµGê:|&Ý$ÊBÙóž>©/nÈÒf1PÇnI'uÔ	„ ã™DÑâ
    $¡RÇyy•ÀÑ=•/I!±×ë,~q“ Œ”qrÔl%š4ˆ£„Þ‚´—ÞŒ±XÃË݃E@#kÄÄÆMÀåw–“Ht¼tÑË>i¨+·‡c§¹¿ˆÒ€Û“Õψ	xù½è¤L1ó!íŽñôz{à§Ø%ÅœãJ¿	DL壯]uX~Wá:÷i'³ÿÙ–…´k¸æ½ÛJ':nS䞟t,iì1/¿_¦•Lé#«g)Uö¬2¶
    Z•l6-¹tÄ~E—HUîÔ\Ôr@2™é·1ñã÷oYÇÊpœ‹[õyVTÑ›4h*šBµŸª|fŒWE}
    Jc3lÏvþÜ_ÖM´°8%ͧ(˜èñ4‡ ãk2‰¢håN{¤ñXBjC7iü]Ð1ÔÞ¬÷ƒ£,ak®žÉ.¹[O+H‰á8'özvG®ÎHÜÝŒ˜Äß9/W“ò(â÷Ô¶£òñèp8•º}@©ÇßtvG®a)Ä{Yì–ÚÅŒÝÕÑ)±”“Â3îñ`lšowä"ð+§(NSùˆµ:)æÝjäÿ ÿ„ê” ´ïIEND®B`‚xterm-353/icons/mini.xterm_48x48.png0000644000175100001440000000422212034054407016035 0ustar  tomusers‰PNG
    
    
    IHDR00Wù‡sRGB®ÎébKGDÿÿÿ ½§“	pHYs
    ×
    ×B(›xtIMEÜ
    ÄDߌIDAThÞí™{pUGÇ?{Î}åm¹IHÒ6¤¥Ò@)Q^R‚ÒŽS¡m¨ÁRZµV*õÅ`[êØŽ2µ:>*j)‚ÓÊ#€e¨4mxE IHy$¹Ü$7¹÷Ü{ÎúGÜœûIgüÍìgÏo»ßÝßþö÷€ÿqÀ˜A’yB@G¤ŸÆ
    @¶& ÆJh¾9HmR´T~¸<[¯¯‡€¤ìÏëqò}ÚOÙÀnê£hü=¾@²…°N k@[բߤà	û×
    @Zt{-„α¡€w"ô—›PÃYË;Ù€bÞäz"¼¡RÅ´>š—L:°qbXÞs¤0„ܸFÎq–ÑÀTË5YˆH:ói¦‹Z‹²±¡²^Æ’ì#'w‚ìż, :n3jIoȉÌ,רéÇvWˆÛ¥BBOä1¡É»{Ǧ{çîïïÚ+ÿùúÌ’ÓµÓ)\ÐñŸäzPÕVÍúö¯4›C7Í–…*‡ú`•QÍ
    ßdòæ¾TNÏ'`±2Ùê·ÍÚÊ|óh5"Ÿ[
    …
    	n
    —ôƒ@÷Èt?ƒI4èÖãF¨0Ñц@ªß;Äp	­^S:´EØ(Ÿ„3¡\ÖÈá,
    ñÝË<Ã6­ ¯
    $ÏRúõã,-…ÃEShwdÒJ6­[³C[2~Á|ç^2,Äf*0Ϲ‹Qöt¹Ã±ßûV–hq¹Ù|×—ypÚ®Ža¶û˜`“–:±]˧ËXß‘m’*ËõZðÊ«Íæ•ÌöûÆW¼]×”åöËG²2¬ÍDJ>cÑÎ3¾SöWRê“üZ.”Ù<,R–›ãŠø·„z	é<šÃ3Z-c|}ǯÔßçE©Ä>v Z»öNf)ðlR#êÌwÖ—Ýéö|XÏaúêH6PŒ¬8ºñIìÖºœhxYËhÓdž£‰Ó•<üÒ¶…W%Ìp¬¤ÒÕÖKÁßÖ†Oyl¹˜ê`&Ãøš«–õN~f?(ÀOˆ¹œ,YŠj·S"îóU?z.Ód†Øƒ
    ¬áOè+öàV>Ǣċ$š:µ;8¯\Àe.õF>~	ÃXà:ÎÛx–oû{É2¢õr;èv”bÃ	@²§#Ÿ)¦±‹4Ë,™_¶W“j›ÌÓ	—p‰îËüah$ëåÈÚXÄv.O&4Rh+c®°òz^ †¿ê»Ê(÷«ÈtŽqŠV
    y´ˆü/Š“$Ër¾šàA	æÑÆ‘t)̲7òB’§ñ‰Ë¬¨Nˆ/ÒDˆº~Øt7ÐF;ÿ ø–€“1Ǽàø©Ê–&ú™fo¤ÝH=ÑïdJ<ë‘ð„T	Ê9׬ѺïUHÊ,¬PY§\÷Ý
    )]ÔIØÒW]Z:úÖïÀã¢=N±¯{,>«7élR#~\ÀÂ~¨¾øÄJt*iÆoéð…Qâ¹N70_\ñî”
    pƒÇ8‚Þ'	£º¡#w
    øÛ`ºJÊ`Ý:ý&ÕÑUI³9üƒíë)ƒ&Éà)Úñp62KISíç%Œ½%ð⢃óQ˜†!QØ$Áu˹|….FpGERÅE>°ò– ³È¦™ß0H¨Sp"X$aÚ­sÕ¤bç`hJ0*ïP Âzî sø)mŒbR÷Eè:‘p1æ ±($“Âê›
    @ºÏEže‚™j9Â1g{àc1ªÀTœH*$̾)$8ðQE‚@+j(ÚW’q0ð£QM"°\À!Ó¤
    ¬©&	ù~Þ³ð–F9¨¨lÖyëÁ sY—ÑL2GVQ‡ÁI`ÅU¦€1Ÿ…G×!Y7î‘79ŠaéL*cï|$d.c¹Àî1_Û÷8Áeò€
    A4‹B.[dôÚ$»
    îó!XË>}3.àS8,—p× `£¿’ƒÂ(à2m¼K>ð´ ÌÿÔäÎ[8o@—¼ƒoÒI3ïÒ—i¸ø+l–Ýå•A:7›	‘IÝÕ“4o	XÛ#£—ÆjýûlÑr-c	lÕrÅjý‡o›ð8ÇÁÒs€
    '½ÔòºÒëWæÍæa.°™fVa?5œ!uÈOšÛL¯ Ù¸„@Å#쌠ÉȈ¾J³œ§GŠÓî_SnóíYbnèO,køá5ž@:’é±ê¶¨‹O#=,xŽ3å-jÚtÎè%Ô÷ЄR;”ÆÜ´L.™uRG!\R𦧆Ç
    0Áq6HƒâhæùJ8Í4f½)•MØ(â~ DˆØ€*`éŽ:÷HÀƲ/zíÓ}±V¾ó¥ÏŒQ
    ýª™Ìñ4•d{ϯN×…«0,ÚÔmhg’çÂò•zñÛ-g}Ð̦í>ˆ¸¶É±jcæ<‘#æ/@Ÿ
    ØqçEoJ¢»N‰¦FèƒNŒ8mžŠÆTäÅÉŸT†õ…Õ‹m=ìwwý¶ÿÁLbܼ:Z-vº?V/î}‰Rû—Žšm`”Æÿé¡ÿš"9¤D!êIEND®B`‚xterm-353/icons/xterm-color.png0000644000175100001440000000350412034362541015342 0ustar  tomusers‰PNG
    
    
    IHDR00Wù‡sRGB®ÎébKGDÿÿÿ ½§“	pHYs
    ×
    ×B(›xtIMEÜ
    	¬‘?ÄIDAThÞí™}lS×À/¶ŸILb’1.͵Ba[‘è&4JÉAHº-ƒI먺þ±NdhšP‘–5`
    %£-ÓÔÁ(´­ÛTMÐVÐMŒÑ’0ÈÇ@I‹É§“@êØ$¡‰÷|ö‡?H N	NØv¤§ë{|î»çóžsσÿRxò<9£Êxq¹\gívûÒмÐb¤<#ÐÚÚz)===/„_ü=Ú—H\.×YUUc¦qUU¥³³ó£Ðö^@jkkß2Ý£YCGÚÛÛÿ‘ãpäÌöù>õCN,Ô?ê½fs޳¹ùªÍfËQÅ*"­ííí-‡#Ççó•Dc	‘>“É$©ðq¬ý~œQUUDÄâ¥%ì
    f³¹{¢¸àÄ:
    ;n†.€ˆHKKËéqјõ{)PÿtÁ'káñ?¶AC8×ÂoÒcáiiiŽhƒx„æÿ3H×fD¦­‹yÈ÷çÅÎaܤ,ЭÁ®÷!u1ü.+ˆûé#pkŽvϼD6f\^‹žG
    “ÏžBãb_Øa(8
    Þ}^¬†¾ÀôjzÒ´û¡¡)x`;â§ßU&-@ñ\˜c×'ð|>d™ ŒÀðÄ	Xy:¼¿&&|ªS"À;__×µAhõÁÏþ
    ¹ðËûŸâïI€GM°ß+3¡ñÖm|µú\°k}0©Í‰‹½£!ZdÅÇ®@V"¼w3ˆÏI‚7.gZ!Å^ßÏÓTy§,Ì4ˆÊ…^Yög?~þØÅ?!_®Âšwû0ôCÅ®ëÌ·Y·9‰@ÜÝ5Õ\ï
    ºÛ¦Í,/}ò,žúze÷ê\þýoñüåS{Œ::iô8ñxÜ|ýçÛhô8iô8éðõ`ø¡ÊÍÅ Ý´‚¯;˜š3f¶nO¡«cû#&Þ=÷(©vYßú.½³£àµc‘=6y‡~ë²¾½uê-pèê	¸z‚¯‘ÆFïxöTEä¿çHå¡…—˯ߵ®ç3OôðØWX¶<>b…³—€òðmâ„t扇ÞûáBAÓ7tJßN
    fœ&¨ØÆhR˜;ßÈÂ•%_ŠçåÝ]Ãî²ñ³¼ì%†8âô>Äh¹?10XÝq‚Ãçmz¿ly<ßJ#m‘Ê›‡Ü¸Z‡F¬«;ü
    ˶¿€‚pþÕݬØñ«	÷ê¿§Zh4H©QØ_~ƒýå78xÄÁ_:ÿ9[ó¯±:§‘u›“"1†z
    YHœ	çñ£ÀÄ¥í¾}ûÚ€Ê)µÀ„Zó•/^§ü€ç¾ÓÔœ-uùH½îènDº®7•••­žþBô2ˆû‚s.±	ê7
    ñÍus#¸s+<ôzu.×FpgO÷SXbe¾ÍH¿«¤EA¦¯¼~ðvöôÐßÑ:æþ{÷îmÔ4í
    ÐõÀeb¿ßï4nÀmUU%>ØŠ)ÄCªª#<$¤ý?Ü©ý	;sÙGŽÙçk襱`~ÔÝ2›—:››?µÙlKE±ú|¾K			麮/Æ}FôFÛÚÚÎLwotÇŽöO¶;ýO»Ý¾d:µpwZQDdA´Ú ¾ü¦ÆŠ\ ðLÁf á~ñ:–'?.[¶lY (ÊlEQîÌØZ+ã¼@EAQ”Àtw¾G~^2øýþkV«5spp0e‚}FÀºÌÌL§ˆôçççW‰ˆžŸŸ^Dô7V‹ˆ„æ’——w>ôÿdèaúU«V}<]AAA•ˆHyyùÉÊÊÊSÃïÀ¨khhø[è„F=4jwÌõ{¤sÔ4íšÅbqkšÖ>¶¯^½ú‚ˆè………Õ""6l¨
    i©JD¤¤¤ä_ÃçaºðŸ¯87Þø¥²²²³f³¹(77·Å`0kkkÎÌÌlnnnÎe]Òd¹LLLÄh¼ûþ´páBW]]%77×e0Œ¥¥¥M;wîìkkk›=óaX€~ŸÏ÷ªªÀ:»¡äääù‡>ZRR²A×õ§Æc>ÒT˜A…ÛðgåÿD-ôóvYáwü IEND®B`‚xterm-353/icons/mini.xterm_32x32.xpm0000644000175100001440000001066012034362314016041 0ustar  tomusers/* XPM */
    static char * mini_xterm_32x32_xpm[] = {
    "32 32 143 2",
    "  	c None",
    ". 	c #FF0000",
    "+ 	c #FF1900",
    "@ 	c #FF1F00",
    "# 	c #FF0B00",
    "$ 	c #FF1D00",
    "% 	c #FF4A00",
    "& 	c #FF5100",
    "* 	c #FF5B00",
    "= 	c #FF5E00",
    "- 	c #FF5300",
    "; 	c #FF3600",
    "> 	c #FF0C00",
    ", 	c #FF5A00",
    "' 	c #FF5C00",
    ") 	c #FF0A00",
    "! 	c #FF0D00",
    "~ 	c #FF2E00",
    "{ 	c #FF5800",
    "] 	c #FF2700",
    "^ 	c #FF0500",
    "/ 	c #0073FB",
    "( 	c #0041F7",
    "_ 	c #0074FB",
    ": 	c #0059F9",
    "< 	c #0000F1",
    "[ 	c #0505EC",
    "} 	c #3A44BE",
    "| 	c #615A9A",
    "1 	c #784285",
    "2 	c #3466C8",
    "3 	c #004DF8",
    "4 	c #0053F8",
    "5 	c #006CF9",
    "6 	c #3C44BD",
    "7 	c #2729CF",
    "8 	c #002CF5",
    "9 	c #2D2EC9",
    "0 	c #8D6E71",
    "a 	c #E96416",
    "b 	c #FF4400",
    "c 	c #FF1800",
    "d 	c #0019F3",
    "e 	c #FF1400",
    "f 	c #D66729",
    "g 	c #73498A",
    "h 	c #091FEB",
    "i 	c #002CF4",
    "j 	c #006FFC",
    "k 	c #0002F1",
    "l 	c #0059F8",
    "m 	c #AD3252",
    "n 	c #FF1700",
    "o 	c #FF2B00",
    "p 	c #B84A47",
    "q 	c #0026F4",
    "r 	c #FF0700",
    "s 	c #FF1600",
    "t 	c #003FF6",
    "u 	c #0003F1",
    "v 	c #006FFA",
    "w 	c #0058F9",
    "x 	c #0055FA",
    "y 	c #FF3D00",
    "z 	c #C3363C",
    "A 	c #FF0400",
    "B 	c #FF3F00",
    "C 	c #FF1000",
    "D 	c #003DF6",
    "E 	c #005AF8",
    "F 	c #002AF4",
    "G 	c #FF0100",
    "H 	c #FF5600",
    "I 	c #C3643C",
    "J 	c #A73958",
    "K 	c #FF3100",
    "L 	c #0020F3",
    "M 	c #002DF5",
    "N 	c #0089FD",
    "O 	c #0022F4",
    "P 	c #0085FD",
    "Q 	c #C36E3C",
    "R 	c #BC3943",
    "S 	c #FF1300",
    "T 	c #007AFC",
    "U 	c #FF2200",
    "V 	c #C3693C",
    "W 	c #FF4600",
    "X 	c #C3563C",
    "Y 	c #FF1100",
    "Z 	c #BD6C42",
    "` 	c #C12F3E",
    " .	c #B13B4E",
    "..	c #C32F3C",
    "+.	c #C0283F",
    "@.	c #C34D3C",
    "#.	c #FF2400",
    "$.	c #BC3E43",
    "%.	c #C36D3C",
    "&.	c #FF3400",
    "*.	c #FF0800",
    "=.	c #C36B3C",
    "-.	c #FF4E00",
    ";.	c #C3523C",
    ">.	c #FF3E00",
    ",.	c #FF1C00",
    "'.	c #FF0200",
    ").	c #BF3240",
    "!.	c #FF1A00",
    "~.	c #B4624B",
    "{.	c #FF5900",
    "].	c #FF1200",
    "^.	c #B82E47",
    "/.	c #FF4800",
    "(.	c #FF3A00",
    "_.	c #001EF4",
    ":.	c #001DF4",
    "<.	c #7D4882",
    "[.	c #FF4F00",
    "}.	c #0076FB",
    "|.	c #000CF2",
    "1.	c #0276F9",
    "2.	c #FF3800",
    "3.	c #FF5D00",
    "4.	c #004CF7",
    "5.	c #004CF8",
    "6.	c #FB0104",
    "7.	c #FF5500",
    "8.	c #B53E4A",
    "9.	c #0055F8",
    "0.	c #0038F6",
    "a.	c #0028F4",
    "b.	c #0039F6",
    "c.	c #0254F6",
    "d.	c #C66E39",
    "e.	c #FF3500",
    "f.	c #248ADB",
    "g.	c #785587",
    "h.	c #DE3121",
    "i.	c #FF1E00",
    "j.	c #FF2800",
    "k.	c #FF5700",
    "l.	c #FF1B00",
    "                                                                ",
    "                                                                ",
    "  . + @ @ @ @ @ @ @ @ @ # $             . @ @ @ @ @ @ @ @ .     ",
    "  . % & & * = = = - & & ; @             > & & & , ' & & & )     ",
    "  . . . . ! = = = ~ . . .               . . . . { ] ^ . . .     ",
    "        / ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( _         ",
    "        : < < < [ } | 1 2 3 < < < < 4   5 6 7 < < < < :         ",
    "        8 < < 9 0 a = b c   d < < d       e f g h < < i         ",
    "      j k < l m n = = = o p q < < q     r { ] s   t < u v       ",
    "      w < x     . y = = ' z q < < q   A % B C       D < E       ",
    "      8 F         G H = = I q < < q J K & !           L M       ",
    "    N O P           r = = Q q < < q R ' S             T O N     ",
    "                    . U = Q q < < q V ] s                       ",
    "                      . W Q q < < q X Y                         ",
    "                        G Z q < < q `                           ",
    "                           .q < < q ..                          ",
    "                          +.q < < q @.#.                        ",
    "                          $.q < < q %.+ &.                      ",
    "                        *.=.q < < q Q - Y                       ",
    "                      A -.;.q < < q Q = >.,.                    ",
    "                    '.; -.).q < < q Q = = U ~                   ",
    "                    !., Y   q < < q ~.= = {.].                  ",
    "                  *., U     q < < q ^., = = /.s                 ",
    "                A -.(.].    _.< < :.<.C = = = ~ ]               ",
    "              '.; [.!     }.|.< < |.1.. 2.= = 3.s               ",
    "              !., Y       4.< < < < 5.  6.7.= = & ].            ",
    "            *., U 8.9.0.a.< < < < < < a.b.c.d.= = (.@           ",
    "          A -.e.#   f.                    g.h.= = = i.j.        ",
    "  . @ @ ,.y , Y ,.@ @ G               '.@ ,.].* = = k.l.@ @ .   ",
    "  . & & & & & & & & & )               ,.& & & & & & & & & & )   ",
    "  . . . . . . . . . . .               . . . . . . . . . . . .   ",
    "                                                                "};
    xterm-353/icons/xterm.svg0000644000175100001440000005215312034403221014234 0ustar  tomusers
    
    
    
      terminal
      
        
      
      
        
      
      
        
          
            image/svg+xml
            
            xterm
            
            
              
                Thomas E. Dickey
              
            
            
              
                MIT-X11
              
            
            XTerm icon, in SVG format.
            June 14, 2012
            http://invisible-island.net/xterm/
            http://invisible-island.net/xterm/xterm
          
          
            
            
            
            
            
          
        
      
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        X
        TERM
      
    
    xterm-353/icons/xterm-color.svg0000644000175100001440000014206312034361330015354 0ustar  tomusers
    
    
    
      terminal
      
        
      
      
        
      
      
        
          
            image/svg+xml
            
            xterm
            
            
              
                Thomas E. Dickey
              
            
            
              
                MIT-X11
              
            
            XTerm icon, in SVG format.
            June 14, 2012
            http://invisible-island.net/xterm/
            http://invisible-island.net/xterm/xterm
          
          
            
            
            
            
            
          
        
      
      
        
      
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
      
        X
        TERM
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
    
    xterm-353/icons/xterm-color.xpms0000644000175100001440000001515212035000420015531 0ustar  tomusers/* $XTermId: xterm-color.xpms,v 1.3 2012/10/09 10:48:48 tom Exp $ */
    /* generated by ./make-xpms  */
    /* vile:xpmmode */
    /* XPM */
    static const char * const xterm_color_16x16_xpm[] = {
    "16 16 80 1",
    ".	c None",
    " 	c #555500",
    "+	c #545400",
    "@	c #3A3A00",
    "#	c #222200",
    "$	c #2A2A00",
    "%	c #2B2B00",
    "&	c #151500",
    "*	c #5E5E00",
    "=	c #5A5A00",
    "-	c #909098",
    ";	c #3E3E3E",
    ">	c #000000",
    ",	c #F2F2F2",
    "'	c #2E2E36",
    ")	c #343400",
    "!	c #4C0000",
    "~	c #140000",
    "{	c #7C0000",
    "]	c #7F7F7F",
    "^	c #858588",
    "/	c #EA0000",
    "(	c #0B0000",
    "_	c #460000",
    ":	c #8E0000",
    "<	c #A80000",
    "[	c #474747",
    "}	c #868686",
    "|	c #404548",
    "1	c #8F3400",
    "2	c #451200",
    "3	c #299000",
    "4	c #1F6C00",
    "5	c #192E48",
    "6	c #1B3448",
    "7	c #888888",
    "8	c #CF4C00",
    "9	c #3B0700",
    "0	c #39C700",
    "a	c #42E800",
    "b	c #2D5181",
    "c	c #55A3E3",
    "d	c #305C81",
    "e	c #989898",
    "f	c #D84F00",
    "g	c #3A0600",
    "h	c #258100",
    "i	c #376599",
    "j	c #396D99",
    "k	c #7E7E7E",
    "l	c #010100",
    "m	c #000101",
    "n	c #9A9A9A",
    "o	c #101000",
    "p	c #5B5B00",
    "q	c #3D3D00",
    "r	c #272700",
    "s	c #2F2F00",
    "t	c #303000",
    "u	c #1A1A00",
    "v	c #464636",
    "w	c #7A7A7F",
    "x	c #8B8B90",
    "y	c #1B1B00",
    "z	c #0F0F00",
    "A	c #FFFFFF",
    "B	c #5B5B5B",
    "C	c #C9C9C9",
    "D	c #BFBFBF",
    "E	c #B5B5B5",
    "F	c #5C5C5C",
    "G	c #79797F",
    "H	c #7F7F88",
    "I	c #484835",
    "J	c #3C3C00",
    "K	c #1E1E00",
    "L	c #909090",
    "M	c #333336",
    "N	c #464600",
    "O	c #575700",
    ".+@#$$$$$$$$%&*+",
    ".=-;>>>>>>>>>,')",
    ".=>!~{>>>>>>>>]^",
    ".=>>/(>>>>>>>>]]",
    ".=>_:<>>>>>>>>]]",
    ".=>>>>>>>>>>>>]]",
    ".=>[}|12345>6>]]",
    ".=>>7>890abcd>]]",
    ".=>>e>fgh0i>j>k^",
    ".=>>>l>>>>>m>>no",
    ".=-;>>>>>>>>>,>p",
    ".+qrsssssssstu*.",
    ".pvwwwwwwwwwwxy.",
    "+zABABCDDDEAFG*.",
    "*HBABAEDDDCBAIJ.",
    "KL]]]]]]]]]]MNO."};
    /* XPM */
    static const char * const xterm_color_32x32_xpm[] = {
    "32 32 60 1",
    ".	c None",
    " 	c #FFFFFF",
    "+	c #000000",
    "@	c #EFEFEF",
    "#	c #FEFEFE",
    "$	c #FBFBFB",
    "%	c #F3F3F3",
    "&	c #ADADAD",
    "*	c #909090",
    "=	c #737373",
    "-	c #D2D2D2",
    ";	c #646464",
    ">	c #9A9A9A",
    ",	c #8D8D8D",
    "'	c #D3D3D3",
    ")	c #0E0E0E",
    "!	c #F6F6F6",
    "~	c #5E5E5E",
    "{	c #B1B1B1",
    "]	c #777777",
    "^	c #949494",
    "/	c #757575",
    "(	c #C4C4C4",
    "_	c #E7E7E7",
    ":	c #F1F1F1",
    "<	c #F8F8F8",
    "[	c #EEEEEE",
    "}	c #F0F0F0",
    "|	c #FAFAFA",
    "1	c #7B7B7B",
    "2	c #3D3D3D",
    "3	c #868686",
    "4	c #4F4F4F",
    "5	c #ABABAB",
    "6	c #545454",
    "7	c #5B5B5B",
    "8	c #AFAFAF",
    "9	c #292929",
    "0	c #181818",
    "a	c #C7C7C7",
    "b	c #CFCFCF",
    "c	c #7F7F7F",
    "d	c #A3A3A3",
    "e	c #4D4D4D",
    "f	c #6A6A6A",
    "g	c #A1A1A1",
    "h	c #8E8E8E",
    "i	c #696969",
    "j	c #474747",
    "k	c #5A5A5A",
    "l	c #959595",
    "m	c #767676",
    "n	c #8B8B8B",
    "o	c #BCBCBC",
    "p	c #BFBFBF",
    "q	c #D7D7D7",
    "r	c #404040",
    "s	c #636363",
    "t	c #989898",
    "u	c #8A8A8A",
    "................................",
    ".....+++++++++++++++++++++++....",
    "....+..+++++++++++++++++++..++..",
    "....+.+...................+.+.+.",
    "....++.@#.$%................+..+",
    "....++.&*.=-................+..+",
    "....++..;>,.................+..+",
    "....++..')!.................+..+",
    "....++.#~{].................+..+",
    "....++.^{./(................+..+",
    "....++......................+..+",
    "....++......................+..+",
    "....++.____:___<_[..<}..[|..+..+",
    "....++.1;21341156]7.89$:0a..+..+",
    "....++..bc.8^__8d.e.8fghia..+..+",
    "....++..bc.84115jkl.887mna..+..+",
    "....++..bc.8d..8dof.88pqna..+..+",
    "....++..bc.8rss5d.tu88..na..+...",
    "....++......................+.+.",
    "....++......................+.+.",
    "....+.+...................+.++..",
    "....+..+++++++++++++++++++..+...",
    ".....+++++++++++++++++++++++....",
    "................................",
    ".....++++++++++++++++++++++++...",
    "....+.......................+...",
    "...+.......................+....",
    "...+..++..++.++..++..+..++.+....",
    "....++..++..+..++..++.++........",
    "..+.......................+.+...",
    ".+.......................+......",
    ".++++++++++++++++++++++++++....."};
    /* XPM */
    static const char * const xterm_color_48x48_xpm[] = {
    "48 48 10 1",
    ".	c None",
    " 	c #555500",
    "+	c #000000",
    "@	c #FFFFFF",
    "#	c #FF0000",
    "$	c #070700",
    "%	c #0B0B00",
    "&	c #FF8400",
    "*	c #49FF00",
    "=	c #60B7FF",
    "................................................",
    "......++++++++++++++++++++++++++++++++++........",
    ".....+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@++......",
    ".....+@@@++++++++++++++++++++++++++++@@@+@+.....",
    ".....+@@++++++++++++++++++++++++++++++@@+@@+....",
    ".....+@++++++++++++++++++++++++++++++++@+@@@+...",
    ".....+@++###++++###++++++++++++++++++++@+@@@@+..",
    ".....+@+++##++++##+++++++++++++++++++++@+@@@@+..",
    ".....+@++++##++##++++++++++++++++++++++@+@@@@+..",
    ".....+@++++##++##++++++++++++++++++++++@+@@@@+..",
    ".....+@+++++####+++++++++++++++++++++++@+@@@@+..",
    ".....+@+++++####+++++++++++++++++++++++@+@@@@+..",
    ".....+@++++++##++++++++++++++++++++++++@+@@@@+..",
    ".....+@+++++####+++++++++++++++++++++++@+@@@@+..",
    ".....+@+++++####+++++++++++++++++++++++@+@@@@+..",
    ".....+@++++##++##++++++++++++++++++++++@+@@@@+..",
    ".....+@++++##++##++++++++++++++++++++++@+@@@@+..",
    ".....+@+++##++++##+++++++++++++++++++++@+@@@@+..",
    ".....+@++###++++###++++++++++++++++++++@+@@@@+..",
    ".....+@++++++++++++++++++++++++++++++++@+@@@@+..",
    ".....+@$+++++++++++++++++++++++++++++++@+@@@@+..",
    ".....+@%@@@@@@@+&&&&&++****+++==+++==++@+@@@@+..",
    ".....+@++++@++++&++++++*+++*++==+++==++@+@@@@+..",
    ".....+@++++@++++&++++++*+++*++=+=+=+=++@+@@@@+..",
    ".....+@++++@++++&&&&+++****+++=+=+=+=++@+@@@@+..",
    ".....+@++++@++++&++++++*+*++++=++=++=++@+@@@+...",
    ".....+@++++@++++&++++++*++*+++=++=++=++@+@@@+...",
    ".....+@++++@++++&&&&&++*+++*++=+++++=++@+@@+....",
    ".....+@++++++++++++++++++++++++++++++++@+@@+....",
    ".....+@++++++++++++++++++++++++++++++++@+@+.....",
    ".....+@@++++++++++++++++++++++++++++++@@+@+.....",
    ".....+@@@++++++++++++++++++++++++++++@@@++......",
    ".....+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@++......",
    "......++++++++++++++++++++++++++++++++++........",
    "................................................",
    "................................................",
    "......++++++++++++++++++++++++++++++++++++......",
    ".....+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@++......",
    ".....+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@@++......",
    "....+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+@+......",
    "....+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@@+@+......",
    "...+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+@@+......",
    "...+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@+@@+@@+......",
    "..+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+@@+.......",
    "..+@++@++++++++++++++++++++++++++@++@+@+........",
    ".+@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+@+.........",
    ".+++++++++++++++++++++++++++++++++++++..........",
    "................................................"};
    static const XPM_DATA xterm_color_xpms[] = {
    	{ "xterm-color_16x16", xterm_color_16x16_xpm }, 
    	{ "xterm-color_32x32", xterm_color_32x32_xpm }, 
    	{ "xterm-color_48x48", xterm_color_48x48_xpm }
    };
    xterm-353/icons/mini.xterm_16x16.xpm0000644000175100001440000000315312034362210016037 0ustar  tomusers/* XPM */
    static char * mini_xterm_16x16_xpm[] = {
    "16 16 84 1",
    " 	c None",
    ".	c #FF3200",
    "+	c #FF3C00",
    "@	c #FF3F00",
    "#	c #FF3B00",
    "$	c #FF3800",
    "%	c #FF2000",
    "&	c #FF1100",
    "*	c #FF3D00",
    "=	c #FF3900",
    "-	c #FF2200",
    ";	c #FF0A00",
    ">	c #FF5D00",
    ",	c #FF1300",
    "'	c #FF0500",
    ")	c #D0412F",
    "!	c #DD6722",
    "~	c #DA3E25",
    "{	c #D84727",
    "]	c #D03C2F",
    "^	c #0023F3",
    "/	c #000BF2",
    "(	c #0E21E6",
    "_	c #4433B4",
    ":	c #352EC3",
    "<	c #0010F2",
    "[	c #0004F1",
    "}	c #2C33CB",
    "|	c #3E2ABA",
    "1	c #011EF3",
    "2	c #0012F3",
    "3	c #022DF5",
    "4	c #F2140D",
    "5	c #FF5E00",
    "6	c #052AF0",
    "7	c #0013F3",
    "8	c #DD4822",
    "9	c #002CF5",
    "0	c #004FF7",
    "a	c #003AF6",
    "b	c #1529E1",
    "c	c #D83827",
    "d	c #0037F7",
    "e	c #004CF8",
    "f	c #FF5900",
    "g	c #182EDE",
    "h	c #FF2100",
    "i	c #152CE1",
    "j	c #DD3B22",
    "k	c #FF2300",
    "l	c #FF2A00",
    "m	c #0C28E9",
    "n	c #E1571E",
    "o	c #FF2E00",
    "p	c #012AF4",
    "q	c #E1661E",
    "r	c #FF3600",
    "s	c #FF3500",
    "t	c #0028F4",
    "u	c #0011F2",
    "v	c #D64E29",
    "w	c #FF5C00",
    "x	c #FF2B00",
    "y	c #FF1D00",
    "z	c #FF2F00",
    "A	c #000EF2",
    "B	c #0003F1",
    "C	c #8C4072",
    "D	c #FF4C00",
    "E	c #FF2D00",
    "F	c #0360F6",
    "G	c #0031F6",
    "H	c #0016F3",
    "I	c #0827EE",
    "J	c #3D47BE",
    "K	c #E5631A",
    "L	c #FF4300",
    "M	c #FF3E00",
    "N	c #FF2400",
    "O	c #FF0700",
    "P	c #FF3400",
    "Q	c #FF5700",
    "R	c #FF5600",
    "S	c #FF3700",
    " .+@#$% &$$*=-  ",
    "  ;>#,    '+    ",
    "   )!~    {]    ",
    "  ^/(_:<[}|1/2  ",
    "  2345=678  97  ",
    " 0a  =>b7c   de ",
    "      fg7       ",
    "      hg7       ",
    "      $i7j      ",
    "     klm7no     ",
    "     # p7qr     ",
    "    sk tuvwx    ",
    "   yz  ABCfDE   ",
    "   = FGHHIJKr   ",
    " $LM$N  O$PQRS- ",
    "                "};
    xterm-353/icons/filled-xterm_48x48.xpm0000644000175100001440000002114212034404120016346 0ustar  tomusers/* XPM */
    static char * filled_xterm_48x48_xpm[] = {
    "48 48 246 2",
    "  	c None",
    ". 	c #000000",
    "+ 	c #F6D5D5",
    "@ 	c #FFEAEA",
    "# 	c #FFD6D6",
    "$ 	c #FFD2D2",
    "% 	c #FFD3D3",
    "& 	c #F8D6D6",
    "* 	c #FFEFEF",
    "= 	c #FFFFFF",
    "- 	c #F6DBDB",
    "; 	c #0F0707",
    "> 	c #090505",
    ", 	c #F6DCDC",
    "' 	c #FFEEEE",
    ") 	c #C99999",
    "! 	c #030101",
    "~ 	c #F7DEDE",
    "{ 	c #150B0B",
    "] 	c #E3C5C5",
    "^ 	c #FFEDED",
    "/ 	c #E4CBCB",
    "( 	c #140B0B",
    "_ 	c #F7DDDD",
    ": 	c #E0C9C9",
    "< 	c #080303",
    "[ 	c #FFD9D9",
    "} 	c #0D0707",
    "| 	c #E5CACA",
    "1 	c #E5CBCB",
    "2 	c #0B0606",
    "3 	c #FFDCDC",
    "4 	c #E2CECE",
    "5 	c #090303",
    "6 	c #E1CBCB",
    "7 	c #9F8A8A",
    "8 	c #3B2929",
    "9 	c #312020",
    "0 	c #FFD5D5",
    "a 	c #ECC8C8",
    "b 	c #402525",
    "c 	c #351F1F",
    "d 	c #663E3E",
    "e 	c #E6DBDB",
    "f 	c #FFFAFA",
    "g 	c #FFFEFE",
    "h 	c #8C7272",
    "i 	c #B4A1A1",
    "j 	c #A69494",
    "k 	c #D8C0C0",
    "l 	c #675353",
    "m 	c #FFFDFD",
    "n 	c #584545",
    "o 	c #E1BFBF",
    "p 	c #3C2929",
    "q 	c #FCF3F3",
    "r 	c #F6EAEA",
    "s 	c #160F0F",
    "t 	c #E9D3D3",
    "u 	c #6E5C5C",
    "v 	c #D6BABA",
    "w 	c #CBBBBB",
    "x 	c #0D0808",
    "y 	c #F8E8E8",
    "z 	c #FFE2E2",
    "A 	c #F4EDED",
    "B 	c #FFF2F2",
    "C 	c #4B3A3A",
    "D 	c #FFFBFB",
    "E 	c #AD9292",
    "F 	c #FFE1E1",
    "G 	c #A28E8E",
    "H 	c #CCBDBD",
    "I 	c #8B7777",
    "J 	c #231515",
    "K 	c #ECCECE",
    "L 	c #FFDADA",
    "M 	c #251414",
    "N 	c #9A8686",
    "O 	c #FFF1F1",
    "P 	c #FFECEC",
    "Q 	c #FFE4E4",
    "R 	c #FFDFDF",
    "S 	c #FFDBDB",
    "T 	c #FFF0F0",
    "U 	c #FFDDDD",
    "V 	c #FFEBEB",
    "W 	c #FFF4F4",
    "X 	c #FFE5E5",
    "Y 	c #FFDEDE",
    "Z 	c #B29E9E",
    "` 	c #A08F8F",
    " .	c #8A7373",
    "..	c #1C1111",
    "+.	c #D7CACA",
    "@.	c #645555",
    "#.	c #5E4B4B",
    "$.	c #FFF7F7",
    "%.	c #BD9F9F",
    "&.	c #392B2B",
    "*.	c #A19090",
    "=.	c #867474",
    "-.	c #9C8D8D",
    ";.	c #A99494",
    ">.	c #0E0606",
    ",.	c #FFE9E9",
    "'.	c #D5C6C6",
    ").	c #564545",
    "!.	c #FFE7E7",
    "~.	c #5B3D3D",
    "{.	c #352121",
    "].	c #5B4242",
    "^.	c #FFD7D7",
    "/.	c #E7D2D2",
    "(.	c #1F1313",
    "_.	c #786363",
    ":.	c #AC9191",
    "<.	c #FFE8E8",
    "[.	c #DBC7C7",
    "}.	c #897474",
    "|.	c #574E4E",
    "1.	c #999999",
    "2.	c #FFF6F6",
    "3.	c #170F0F",
    "4.	c #3B2B2B",
    "5.	c #190E0E",
    "6.	c #C7B6B6",
    "7.	c #5F4D4D",
    "8.	c #F6E1E1",
    "9.	c #FCE9E9",
    "0.	c #F1EAEA",
    "a.	c #FEFAFA",
    "b.	c #3D2828",
    "c.	c #382626",
    "d.	c #947D7D",
    "e.	c #FFFCFC",
    "f.	c #B09B9B",
    "g.	c #C2B2B2",
    "h.	c #EEDADA",
    "i.	c #FDEFEF",
    "j.	c #0B0505",
    "k.	c #DACACA",
    "l.	c #7D6565",
    "m.	c #C6A7A7",
    "n.	c #FDF9F9",
    "o.	c #6C4D4D",
    "p.	c #AB9797",
    "q.	c #927B7B",
    "r.	c #FCEDED",
    "s.	c #0A0404",
    "t.	c #120B0B",
    "u.	c #E8D1D1",
    "v.	c #E2CACA",
    "w.	c #0F0808",
    "x.	c #907979",
    "y.	c #F9DFDF",
    "z.	c #1D1111",
    "A.	c #E8D0D0",
    "B.	c #E1C8C8",
    "C.	c #1A0C0C",
    "D.	c #F8E0E0",
    "E.	c #F7D4D4",
    "F.	c #090404",
    "G.	c #FAE1E1",
    "H.	c #100A0A",
    "I.	c #100808",
    "J.	c #7C4F4F",
    "K.	c #F6D3D3",
    "L.	c #FFD8D8",
    "M.	c #F8D5D5",
    "N.	c #AF9393",
    "O.	c #FDE5E5",
    "P.	c #FDE9E9",
    "Q.	c #FDE2E2",
    "R.	c #FDF8F8",
    "S.	c #FDE6E6",
    "T.	c #FEECEC",
    "U.	c #FEE5E5",
    "V.	c #FFE6E6",
    "W.	c #F8D1D1",
    "X.	c #0D0404",
    "Y.	c #291D1D",
    "Z.	c #583030",
    "`.	c #FFF8F8",
    " +	c #683737",
    ".+	c #5B3333",
    "++	c #582D2D",
    "@+	c #593030",
    "#+	c #5D3232",
    "$+	c #5A2D2D",
    "%+	c #663737",
    "&+	c #5B3030",
    "*+	c #897272",
    "=+	c #996F6F",
    "-+	c #DBC1C1",
    ";+	c #110808",
    ">+	c #FDDDDD",
    ",+	c #473636",
    "'+	c #563232",
    ")+	c #FFF5F5",
    "!+	c #5C3636",
    "~+	c #FFF9F9",
    "{+	c #582E2E",
    "]+	c #6F4040",
    "^+	c #5B3434",
    "/+	c #6D3E3E",
    "(+	c #5A3333",
    "_+	c #EFD7D7",
    ":+	c #FCEFEF",
    "<+	c #140A0A",
    "[+	c #6A5252",
    "}+	c #583333",
    "|+	c #5C2A2A",
    "1+	c #653737",
    "2+	c #6B3C3C",
    "3+	c #643434",
    "4+	c #6A3C3C",
    "5+	c #613535",
    "6+	c #9C8787",
    "7+	c #907A7A",
    "8+	c #DDC3C3",
    "9+	c #F8E5E5",
    "0+	c #FDF3F3",
    "a+	c #190D0D",
    "b+	c #FAEAEA",
    "c+	c #DCC4C4",
    "d+	c #876E6E",
    "e+	c #461F1F",
    "f+	c #472020",
    "g+	c #261414",
    "h+	c #070000",
    "i+	c #220000",
    "j+	c #230101",
    "k+	c #3A1818",
    "l+	c #3F1D1D",
    "m+	c #3E1E1E",
    "n+	c #553333",
    "o+	c #724646",
    "p+	c #431F1F",
    "q+	c #AB8F8F",
    "r+	c #887171",
    "s+	c #DAC0C0",
    "t+	c #FBD1D1",
    "u+	c #1A1010",
    "v+	c #B27C7C",
    "w+	c #020101",
    "                                                                                                ",
    "            . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                 ",
    "          . + @ @ # $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ % @ @ & . .             ",
    "          . * = - ; . . . . . . . . . . . . . . . . . . . . . . . . . . > , = ' . ) !           ",
    "          . * ~ { ] ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ / ( _ ' . ^ : <         ",
    "          . [ } | = = = = = = = = = = = = = = = = = = = = = = = = = = = = 1 2 3 . ^ = 4 5       ",
    "          . [ . * = = = = = = = = = = = = = = = = = = = = = = = = = = = = * . [ . ^ = = 6 .     ",
    "          . [ . * 7 8 9   0 = a b c d = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = e     f = g h i = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = j     = k l g = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = m n   o p q = = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = = r s . t = = = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = = = u . v = = = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = = w     x y = = = = = = = = = = = = = = = = = = = = * . [ . z = = * .     ",
    "          . [ . * = = A   B B   C D = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = E z = = F   G = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * H I J K = = L M } N O = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * P Q Q R = = S Q Q Q T = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = = = = = = = = = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * = = = = = = = = = = = = = = = = = = = = = = = = = = = = * . [ . ' = = * .     ",
    "          . [ . * [ U U U U U V z U U U U W X   Y X ^ = = V U O = = O F ' * . [ . ' = = * .     ",
    "          . [ . * Z `  ...` Q +.@.#.` ` Q $.%.&.*.=.  ^ = -.    = = ;.>.,.* . [ . ' = = * .     ",
    "          . [ . * = = '.  = = =   Q = = = = %.  = = ).!.= -.~.  f f {.].,.* . [ . ' = = * .     ",
    "          . [ . * = = '.  = = =     U U ^.= %.  ^ /.(.' = -._.:.<.[.}.@.,.* . [ . ' = = * .     ",
    "          . [ . * = = '.  = = = @.|.1.1.2.= %.3.4.5.  = = -.  6.  7.8.@.,.* . [ . ' = = 9..     ",
    "          . [ . * = = '.  = = =   Q = = = = %.  = 0.  ' = -.  a.b.c.f @.,.* . [ . ' = = d..     ",
    "          . [ . * = = '.  = = =   0 ^ ^ ^ e.%.  = = f.  m -.  = g.h.= @.,.* . [ . ' = i.j.      ",
    "          . [ . * = = k.  = = = l.9 9 9   ' m.  = = n.o.z p.  = = = = l.X * . [ . ' = q..       ",
    "          . [ . * = = = = = = = = = = = = = = = = = = = = = = = = = = = = * . [ . ' r.s.        ",
    "          . 3 t.u.= = = = = = = = = = = = = = = = = = = = = = = = = = = = v.w.S . ' x..         ",
    "          . * y.z.A.^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ B.C.D.' . E.F.          ",
    "          . * = G.H.. . . . . . . . . . . . . . . . . . . . . . . . . . I.D.= ' . J..           ",
    "          . K.P P # $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ L.P P M.. .             ",
    "            . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                 ",
    "                                                                                                ",
    "                                                                                                ",
    "            . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .             ",
    "          . N.O.P.O.P.Q.R.S.P.O.P.O.P.O.T.U.T.U.T.,.^ ,.^ ,.^ V.^ ,.= D W ,.^ W.X..             ",
    "          Y.W Z.`. +e..+e.++D @+$.Z.`. +e.#+e.$+D @+$.Z.`.%+e.#+e.$+e.&+$.Z.D *+=+.             ",
    "        . -+D f e.m D `.= D e.D D f D m D `.= D e.D D f D m D `.= D e.D D f r.;+>+.             ",
    "        ,+`.'+)+!+~+{+= ]+f .+`.Z.)+^+~+{+= /+f .+`.Z.)+^+~+{+= /+f (+`.Z.f q.q.T .             ",
    "      . _+m f = D m ~+e.`.m f m f = D m ~+e.`.m f e.f = D m ~+e.`.m f m f :+<+i.T .             ",
    "    . [+~+}+)+|+~+1+g 2+g 3+`.}+)+|+~+1+g 4+= 3+`.}+)+|+~+1+g 4+= 3+~+5+e.6+7+= 8+.             ",
    "    ! 9+= ~+= T ' @ ' ,.' <.' <.' ' ' @ e.f = ~+= ~+= = = D = f = ~+= = 0+a+b+c+!               ",
    "  . d+m e+f+e.g+. . . . . . . . . . . . h+i+i+j+k+l+l+c m+l+l+n+o+e.e+p+q+r+s+!                 ",
    "  . t+* @ @ P S [ L S S S S S S S S S S z ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ P z u+v+w+                  ",
    "  . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .                     ",
    "                                                                                                "};
    xterm-353/icons/filled-xterm_16x16.xpm0000644000175100001440000000454212034404216016347 0ustar  tomusers/* XPM */
    static char * filled_xterm_16x16_xpm[] = {
    "16 16 110 2",
    "  	c None",
    ". 	c #BAA9A9",
    "+ 	c #C59C9C",
    "@ 	c #C49999",
    "# 	c #C6AAAA",
    "$ 	c #4D4242",
    "% 	c #F0E4E4",
    "& 	c #CEBABA",
    "* 	c #D5BEBE",
    "= 	c #C6B5B5",
    "- 	c #CEBEBE",
    "; 	c #796D6D",
    "> 	c #DEC5C5",
    ", 	c #B19B9B",
    "' 	c #C6B8B8",
    ") 	c #B19696",
    "! 	c #EBE5E5",
    "~ 	c #FFFFFF",
    "{ 	c #D6D6D6",
    "] 	c #D0BDBD",
    "^ 	c #FFF4F4",
    "/ 	c #FEFDFD",
    "( 	c #706969",
    "_ 	c #CCC3C3",
    ": 	c #FFF0F0",
    "< 	c #978989",
    "[ 	c #A9A5A5",
    "} 	c #A7A3A3",
    "| 	c #E3E1E1",
    "1 	c #DACBCB",
    "2 	c #DEDEDE",
    "3 	c #FFF8F8",
    "4 	c #FFF6F6",
    "5 	c #FFFCFC",
    "6 	c #FFFEFE",
    "7 	c #D2D2D2",
    "8 	c #9C9C9C",
    "9 	c #9B8787",
    "0 	c #B3A0A0",
    "a 	c #FFD5D5",
    "b 	c #D4C2C2",
    "c 	c #FFE7E7",
    "d 	c #7A6F6F",
    "e 	c #786F6F",
    "f 	c #C2C2C2",
    "g 	c #B4B4B4",
    "h 	c #FFE3E3",
    "i 	c #E1CECE",
    "j 	c #FED8D8",
    "k 	c #908888",
    "l 	c #878080",
    "m 	c #898383",
    "n 	c #F3ECEC",
    "o 	c #D8C2C2",
    "p 	c #FFFAFA",
    "q 	c #FFF2F2",
    "r 	c #FFF9F9",
    "s 	c #EFEFEF",
    "t 	c #FEFEFE",
    "u 	c #C8C3C3",
    "v 	c #D2BFBF",
    "w 	c #8A8383",
    "x 	c #FCE5E5",
    "y 	c #D9B6B6",
    "z 	c #DDBCBC",
    "A 	c #BCA0A0",
    "B 	c #F0D2D2",
    "C 	c #AB9C9C",
    "D 	c #000000",
    "E 	c #B0A2A2",
    "F 	c #AE9F9F",
    "G 	c #C6ABAB",
    "H 	c #B48E8E",
    "I 	c #C8ABAB",
    "J 	c #C39A9A",
    "K 	c #D0B2B2",
    "L 	c #C3A0A0",
    "M 	c #CFB2B2",
    "N 	c #C59999",
    "O 	c #CCC1C1",
    "P 	c #3C3535",
    "Q 	c #A39C9C",
    "R 	c #FAEDED",
    "S 	c #FEFCFC",
    "T 	c #F9F2F2",
    "U 	c #FEF7F7",
    "V 	c #FAEBEB",
    "W 	c #FEFAFA",
    "X 	c #F9F1F1",
    "Y 	c #FEF4F4",
    "Z 	c #FAEFEF",
    "` 	c #EBE0E0",
    " .	c #DFB9B9",
    "..	c #E8E3E3",
    "+.	c #BBB0B0",
    "@.	c #BBA9A9",
    "#.	c #CEC8C8",
    "$.	c #BCADAD",
    "%.	c #CDC8C8",
    "&.	c #C78D8D",
    "*.	c #E3B2B2",
    "=.	c #E3BCBC",
    "-.	c #BBAAAA",
    ";.	c #746C6C",
    ">.	c #858585",
    ",.	c #8A7F7F",
    "'.	c #977878",
    ").	c #A38686",
    "!.	c #A78686",
    "~.	c #201717",
    "    . + @ @ @ @ @ @ @ @ # $     ",
    "    % & * * * * * * * * = - ;   ",
    "    > , ' ) ! ~ ~ ~ ~ ~ { ] ^   ",
    "    > / ( _ ~ ~ ~ ~ ~ ~ { ] :   ",
    "    > ~ < [ ~ ~ ~ ~ ~ ~ { ] :   ",
    "    > } | 1 2 ~ ~ ~ ~ ~ { ] :   ",
    "    > ~ ~ 3 ~ 4 4 5 6 4 7 ] :   ",
    "    > 7 8 9 0 a b c d e f ] :   ",
    "    > ~ g h i j k c l m f ] n   ",
    "    o ~ ~ p ~ q 6 r s t u v w   ",
    "    x y z z z z z z A z B C     ",
    "                    D           ",
    "    E F G H I J K L M N O P     ",
    "  Q R S T U V W X Y Z U ` Q     ",
    "   ...+._ @.#.$.%.&.*.=.-.;.    ",
    "  >.>.>.,.'.).).).).).!.~.      "};
    xterm-353/icons/terminal_48x48.xpm0000644000175100001440000000503511766200770015610 0ustar  tomusers/* XPM */
    static char * terminal_48x48_xpm[] = {
    "48 48 2 1",
    " 	c #000000",
    ".	c #FFFFFF",
    "................................................",
    "......                                  ........",
    "..... ..................................  ......",
    "..... ...                            ... . .....",
    "..... .. ............................ .. .. ....",
    "..... . .............................. . ... ...",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . .... ..",
    "..... . .............................. . ... ...",
    "..... . .............................. . ... ...",
    "..... . .............................. . .. ....",
    "..... . .............................. . .. ....",
    "..... . .............................. . . .....",
    "..... .. ............................ .. . .....",
    "..... ...                            ...  ......",
    "..... ..................................  ......",
    "......                                  ........",
    "................................................",
    "................................................",
    "......                                    ......",
    "..... ..................................  ......",
    "..... . . . . . . . . . . . . . . . . ..  ......",
    ".... .................................. . ......",
    ".... . . . . . . . . . . . . . . . . .. . ......",
    "... .................................. .. ......",
    "... . . . . . . . . . . . . . . . . .. .. ......",
    ".. .................................. .. .......",
    ".. .  .                          .  . . ........",
    ". .................................. . .........",
    ".                                     ..........",
    "................................................"};
    xterm-353/icons/filled-xterm.svg0000644000175100001440000011565612034403736015514 0ustar  tomusers
    
    
    
      terminal
      
        
      
      
        
      
      
        
          
            image/svg+xml
            
            xterm
            
            
              
                Thomas E. Dickey
              
            
            
              
                MIT-X11
              
            
            XTerm icon, in SVG format.
            June 14, 2012
            http://invisible-island.net/xterm/
            http://invisible-island.net/xterm/xterm
          
          
            
            
            
            
            
          
        
      
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        X
        TERM
        
        
        
        
        
        
        
      
    
    xterm-353/icons/terminal_48x48.svg0000644000175100001440000005524011766323656015617 0ustar  tomusers
    
    
      terminal
      
        
      
      
        
      
      
        
          
            image/svg+xml
            
            terminal
            
            
              
                Thomas E. Dickey
              
            
            
              
                MIT-X11
              
            
            Translated from the X11 bitmaps/terminal file through stages to svg.
            June 14, 2012
            http://invisible-island.net/xterm/
            http://invisible-island.net/xterm/terminal_48x48
          
          
            
            
            
            
            
          
        
      
      
      
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
      
    
    xterm-353/icons/mini.xterm_48x48.xpm0000644000175100001440000002012012034362362016052 0ustar  tomusers/* XPM */
    static char * mini_xterm_48x48_xpm[] = {
    "48 48 213 2",
    "  	c None",
    ". 	c #FF0000",
    "+ 	c #FF5300",
    "@ 	c #FF5E00",
    "# 	c #FF4800",
    "$ 	c #FF4200",
    "% 	c #FF4000",
    "& 	c #FF4B00",
    "* 	c #FF5200",
    "= 	c #FF5400",
    "- 	c #FF3500",
    "; 	c #FF5100",
    "> 	c #FF5C00",
    ", 	c #FF3000",
    "' 	c #FF4500",
    ") 	c #FF2000",
    "! 	c #FF0300",
    "~ 	c #FF1600",
    "{ 	c #FF5D00",
    "] 	c #FF3800",
    "^ 	c #FF0200",
    "/ 	c #FF0900",
    "( 	c #FF2B00",
    "_ 	c #FF3300",
    ": 	c #FF1A00",
    "< 	c #FF1300",
    "[ 	c #FF1200",
    "} 	c #FF5700",
    "| 	c #4577BA",
    "1 	c #874E78",
    "2 	c #887577",
    "3 	c #887E77",
    "4 	c #887977",
    "5 	c #875078",
    "6 	c #566CA9",
    "7 	c #5E70A1",
    "8 	c #884E77",
    "9 	c #887677",
    "0 	c #7C5B83",
    "a 	c #795686",
    "b 	c #008DFE",
    "c 	c #0012F3",
    "d 	c #000BF2",
    "e 	c #008FFE",
    "f 	c #006CFA",
    "g 	c #0000F1",
    "h 	c #0001F1",
    "i 	c #0020F4",
    "j 	c #0040F6",
    "k 	c #0959F0",
    "l 	c #1158E8",
    "m 	c #1159E8",
    "n 	c #0058F9",
    "o 	c #001DF4",
    "p 	c #0023F4",
    "q 	c #005BFA",
    "r 	c #0060FA",
    "s 	c #0E58EB",
    "t 	c #0651F3",
    "u 	c #0033F5",
    "v 	c #000EF2",
    "w 	c #006EFA",
    "x 	c #0092FF",
    "y 	c #001FF4",
    "z 	c #000FF2",
    "A 	c #0C51EC",
    "B 	c #326AC9",
    "C 	c #7A6583",
    "D 	c #CA6234",
    "E 	c #FC5F03",
    "F 	c #FF5800",
    "G 	c #FF0800",
    "H 	c #F4060B",
    "I 	c #007CFB",
    "J 	c #0013F3",
    "K 	c #007EFB",
    "L 	c #FF1800",
    "M 	c #F3590C",
    "N 	c #AB6152",
    "O 	c #4F4EAD",
    "P 	c #175CE4",
    "Q 	c #0036F5",
    "R 	c #0022F4",
    "S 	c #0095FD",
    "T 	c #0084FD",
    "U 	c #0004F1",
    "V 	c #0051F8",
    "W 	c #345AC7",
    "X 	c #E61519",
    "Y 	c #FF5900",
    "Z 	c #FF4600",
    "` 	c #FF0100",
    " .	c #446EB9",
    "..	c #0034F6",
    "+.	c #0032F5",
    "@.	c #FF2200",
    "#.	c #006FFA",
    "$.	c #002DF5",
    "%.	c #0086FD",
    "&.	c #0046F7",
    "*.	c #0015F3",
    "=.	c #0076FC",
    "-.	c #FF0400",
    ";.	c #FF2300",
    ">.	c #FF2900",
    ",.	c #9E3E61",
    "'.	c #0039F6",
    ").	c #FF2A00",
    "!.	c #FF4300",
    "~.	c #0071FB",
    "{.	c #005EF9",
    "].	c #004DF7",
    "^.	c #008CFE",
    "/.	c #0008F2",
    "(.	c #001DF3",
    "_.	c #007DFB",
    ":.	c #FF4100",
    "<.	c #FF5B00",
    "[.	c #A3425C",
    "}.	c #994C66",
    "|.	c #FF1100",
    "1.	c #0072FB",
    "2.	c #000AF2",
    "3.	c #006EFC",
    "4.	c #0017F3",
    "5.	c #007FFB",
    "6.	c #FF0600",
    "7.	c #FF5600",
    "8.	c #A56A5A",
    "9.	c #A53B5A",
    "0.	c #FF4F00",
    "a.	c #0076FB",
    "b.	c #0076FA",
    "c.	c #0093FF",
    "d.	c #007DFC",
    "e.	c #FF1C00",
    "f.	c #A5765A",
    "g.	c #A55D5A",
    "h.	c #006FFB",
    "i.	c #002CF5",
    "j.	c #008AFD",
    "k.	c #006BF9",
    "l.	c #FF3A00",
    "m.	c #FF5000",
    "n.	c #007BFB",
    "o.	c #008BFD",
    "p.	c #A5755A",
    "q.	c #9A5565",
    "r.	c #A43A5B",
    "s.	c #FF4D00",
    "t.	c #80507F",
    "u.	c #FF0F00",
    "v.	c #7A5485",
    "w.	c #A5555A",
    "x.	c #FF0A00",
    "y.	c #A53D5A",
    "z.	c #A4515B",
    "A.	c #A5685A",
    "B.	c #A5735A",
    "C.	c #FF0700",
    "D.	c #FF2E00",
    "E.	c #FF1500",
    "F.	c #A3705C",
    "G.	c #FF0500",
    "H.	c #9A4965",
    "I.	c #FF0E00",
    "J.	c #FF3B00",
    "K.	c #FF2D00",
    "L.	c #A13C5E",
    "M.	c #FF4C00",
    "N.	c #62649D",
    "O.	c #FF0B00",
    "P.	c #FF4700",
    "Q.	c #FF1D00",
    "R.	c #A56D5A",
    "S.	c #FF2C00",
    "T.	c #A4465B",
    "U.	c #FF1400",
    "V.	c #A03E61",
    "W.	c #FF3100",
    "X.	c #FF1B00",
    "Y.	c #FF1000",
    "Z.	c #0029F5",
    "`.	c #0027F4",
    " +	c #4571BA",
    ".+	c #FF3900",
    "++	c #FF3200",
    "@+	c #008EFD",
    "#+	c #0019F3",
    "$+	c #0090FD",
    "%+	c #FF0D00",
    "&+	c #FF1E00",
    "*+	c #FF4E00",
    "=+	c #0088FC",
    "-+	c #0087FC",
    ";+	c #FF1900",
    ">+	c #0036F6",
    ",+	c #FF2100",
    "'+	c #0073FB",
    ")+	c #0062FA",
    "!+	c #001AF3",
    "~+	c #2463D8",
    "{+	c #3E58BE",
    "]+	c #2A7FD3",
    "^+	c #807B7F",
    "/+	c #008EFB",
    "(+	c #006AFA",
    "_+	c #004CF8",
    ":+	c #717B8D",
    "<+	c #EE0B11",
    "[+	c #F73E08",
    "}+	c #FF1F00",
    "|+	c #FF5500",
    "                                                                                                ",
    "                                                                                                ",
    "    . . . . . . . . . . . . . . . . . .                 . . . . . . . . . . . . . . . .         ",
    "    . + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ .                 . # @ @ @ @ @ @ @ @ @ @ @ @ $ .         ",
    "    . % & & & * @ @ @ @ @ = & & & & & .                 . - & & & & & ; @ > & & & & , .         ",
    "    . . . . . . * @ @ @ @ ; . . . . . .                 . . . . . . . ' @ ) . . . . . .         ",
    "              ! ~ { @ @ @ @ ] ^                                   / ( @ $ .                     ",
    "                ^ _ @ @ @ @ @ : !                               < [ > } ^ .                     ",
    "                | 1 2 3 3 3 3 4 5 6                           7 8 9 3 0 a                       ",
    "            b c d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d c e             ",
    "            f g g g g g g h i j k l m n o g g g g g g p q r s t u v g g g g g g g w             ",
    "          x y g g g g z A B C D E F G H I c g g g g J K   L / M N O P Q h g g g g R S           ",
    "          T g g g U V W X Y @ @ @ @ Z `  ...g g g g +.    ` ' @ @..     #.$.g g g g %.          ",
    "          &.g g *.=.    -.;.@ @ @ @ @ >.,.'.g g g g '.  / ).@ !..         ~.{.U g g ].          ",
    "        ^./.g (._.        ` :.@ @ @ @ <.[.'.g g g g '.}.|.<.} ^ .             1.2.g d e         ",
    "        3.g 4.5.            6.7.@ @ @ @ 8.'.g g g g '.9.0.@ [ .                 a./.g b.        ",
    "      c.R /.d.              -.e.@ @ @ @ f.'.g g g g '.g.@ - .                     h.h i.        ",
    "      j.k.%.                  ^ l.@ @ @ f.'.g g g g '.f.m.`                         n.f o.      ",
    "                                ! * @ @ f.'.g g g g '.p.G .                                     ",
    "                                ! ~ { @ f.'.g g g g '.q..                                       ",
    "                                  ^ _ @ f.'.g g g g '.r.                                        ",
    "                                    ^ s.f.'.g g g g '.t.                                        ",
    "                                    ^ u.p.'.g g g g '.v.                                        ",
    "                                      ^ w.'.g g g g '.r.                                        ",
    "                                      x.y.'.g g g g '.z.^                                       ",
    "                                      ` A.'.g g g g '.B.x..                                     ",
    "                                    C.D.f.'.g g g g '.f.# `                                     ",
    "                                  < E.{ F.'.g g g g '.f.@ ( ^                                   ",
    "                                : G.; @ H.'.g g g g '.f.@ <.I.^                                 ",
    "                                -.J.@ K.L.'.g g g g '.f.@ @ s.`                                 ",
    "                              I.) @ M.. N.'.g g g g '.f.@ @ @ _ ^                               ",
    "                            L O.F <.6..   '.g g g g '.f.@ @ @ { E.!                             ",
    "                            ^ P.@ Q..     '.g g g g '.R.@ @ @ @ * !                             ",
    "                          G S.@ % .       '.g g g g '.T.{ @ @ @ @ l.^                           ",
    "                        < U.> 7.^         ..g g g g u V.W.@ @ @ @ @ e.!                         ",
    "                      X.-.m.@ Y..         Z.g g g g `. +` M.@ @ @ @ 7.6.                        ",
    "                      -..+@ ++.         @+#+g g g g #+$+^ %+<.@ @ @ @ :.`                       ",
    "                    I.&+@ *+.           =+h g g g g h -+  ! >.@ @ @ @ @ ;.^                     ",
    "                  ;+x.} > C..           >+g g g g g g >+    ` Z @ @ @ @ Y / .                   ",
    "                  ` ' @ ,+.   %.1.'+)+!+g g g g g g g g #+)+~+{+]+^+@ @ @ P.`                   ",
    "                / ).@ !..   /+(+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+(+:+@ @ @ @ ).^                 ",
    "              I.[ > F . .                                       <+[+@ @ @ @ <.I.`               ",
    "    . . . . . . 0.@ }+. . . . . .                     . . . . . . . |+@ @ @ @ s.. . . . . .     ",
    "    O.@ @ @ @ @ @ @ @ @ @ @ @ @ ^                     ! $ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ $ .     ",
    "    . & & & & & & & & & & & & & .                     . , & & & & & & & & & & & & & & & , .     ",
    "    . . . . . . . . . . . . . . .                     . . . . . . . . . . . . . . . . . . .     ",
    "                                                                                                ",
    "                                                                                                "};
    xterm-353/icons/make-xpms0000755000175100001440000000140612034403520014201 0ustar  tomusers#!/bin/sh
    # $XTermId: make-xpms,v 1.6 2012/10/07 22:50:56 tom Exp $
    # some files are generated from other icons...
    for name in mini.xterm filled-xterm xterm xterm-color
    do
    	target=${name}.xpms
    	NAME=`echo "$target" | sed -e 's/[\.-]/_/g'`
    	LIST=
    	echo "** creating $target"
    	rm -f $target
    	echo "/* @XTermId@ */" | sed -e 's/@/$/g' >$target
    	echo "/* generated by $0 $* */" >>$target
    	echo "/* vile:xpmmode */" >>$target
    	for source in ${name}_*[0-9]x[1-9]*.xpm
    	do
    		echo ".. from $source"
    		BASE=`basename "$source" .xpm`
    		PART=`echo "$source" | sed -e 's/[\.-]/_/g'`
    		test -n "$LIST" && LIST="$LIST, "
    		LIST="$LIST
    	{ \"$BASE\", $PART }"
    		sed -e 's/char \*/const char * const/' $source >>$target
    	done
    	echo "static const XPM_DATA $NAME[] = {$LIST
    };" >>$target
    done
    xterm-353/icons/mini.xterm.xpms0000644000175100001440000003470312034364512015371 0ustar  tomusers/* $XTermId: mini.xterm.xpms,v 1.4 2012/10/07 20:42:50 tom Exp $ */
    /* generated by ./make-xpms  */
    /* vile:xpmmode */
    /* XPM */
    static const char * const mini_xterm_16x16_xpm[] = {
    "16 16 84 1",
    " 	c None",
    ".	c #FF3200",
    "+	c #FF3C00",
    "@	c #FF3F00",
    "#	c #FF3B00",
    "$	c #FF3800",
    "%	c #FF2000",
    "&	c #FF1100",
    "*	c #FF3D00",
    "=	c #FF3900",
    "-	c #FF2200",
    ";	c #FF0A00",
    ">	c #FF5D00",
    ",	c #FF1300",
    "'	c #FF0500",
    ")	c #D0412F",
    "!	c #DD6722",
    "~	c #DA3E25",
    "{	c #D84727",
    "]	c #D03C2F",
    "^	c #0023F3",
    "/	c #000BF2",
    "(	c #0E21E6",
    "_	c #4433B4",
    ":	c #352EC3",
    "<	c #0010F2",
    "[	c #0004F1",
    "}	c #2C33CB",
    "|	c #3E2ABA",
    "1	c #011EF3",
    "2	c #0012F3",
    "3	c #022DF5",
    "4	c #F2140D",
    "5	c #FF5E00",
    "6	c #052AF0",
    "7	c #0013F3",
    "8	c #DD4822",
    "9	c #002CF5",
    "0	c #004FF7",
    "a	c #003AF6",
    "b	c #1529E1",
    "c	c #D83827",
    "d	c #0037F7",
    "e	c #004CF8",
    "f	c #FF5900",
    "g	c #182EDE",
    "h	c #FF2100",
    "i	c #152CE1",
    "j	c #DD3B22",
    "k	c #FF2300",
    "l	c #FF2A00",
    "m	c #0C28E9",
    "n	c #E1571E",
    "o	c #FF2E00",
    "p	c #012AF4",
    "q	c #E1661E",
    "r	c #FF3600",
    "s	c #FF3500",
    "t	c #0028F4",
    "u	c #0011F2",
    "v	c #D64E29",
    "w	c #FF5C00",
    "x	c #FF2B00",
    "y	c #FF1D00",
    "z	c #FF2F00",
    "A	c #000EF2",
    "B	c #0003F1",
    "C	c #8C4072",
    "D	c #FF4C00",
    "E	c #FF2D00",
    "F	c #0360F6",
    "G	c #0031F6",
    "H	c #0016F3",
    "I	c #0827EE",
    "J	c #3D47BE",
    "K	c #E5631A",
    "L	c #FF4300",
    "M	c #FF3E00",
    "N	c #FF2400",
    "O	c #FF0700",
    "P	c #FF3400",
    "Q	c #FF5700",
    "R	c #FF5600",
    "S	c #FF3700",
    " .+@#$% &$$*=-  ",
    "  ;>#,    '+    ",
    "   )!~    {]    ",
    "  ^/(_:<[}|1/2  ",
    "  2345=678  97  ",
    " 0a  =>b7c   de ",
    "      fg7       ",
    "      hg7       ",
    "      $i7j      ",
    "     klm7no     ",
    "     # p7qr     ",
    "    sk tuvwx    ",
    "   yz  ABCfDE   ",
    "   = FGHHIJKr   ",
    " $LM$N  O$PQRS- ",
    "                "};
    /* XPM */
    static const char * const mini_xterm_32x32_xpm[] = {
    "32 32 143 2",
    "  	c None",
    ". 	c #FF0000",
    "+ 	c #FF1900",
    "@ 	c #FF1F00",
    "# 	c #FF0B00",
    "$ 	c #FF1D00",
    "% 	c #FF4A00",
    "& 	c #FF5100",
    "* 	c #FF5B00",
    "= 	c #FF5E00",
    "- 	c #FF5300",
    "; 	c #FF3600",
    "> 	c #FF0C00",
    ", 	c #FF5A00",
    "' 	c #FF5C00",
    ") 	c #FF0A00",
    "! 	c #FF0D00",
    "~ 	c #FF2E00",
    "{ 	c #FF5800",
    "] 	c #FF2700",
    "^ 	c #FF0500",
    "/ 	c #0073FB",
    "( 	c #0041F7",
    "_ 	c #0074FB",
    ": 	c #0059F9",
    "< 	c #0000F1",
    "[ 	c #0505EC",
    "} 	c #3A44BE",
    "| 	c #615A9A",
    "1 	c #784285",
    "2 	c #3466C8",
    "3 	c #004DF8",
    "4 	c #0053F8",
    "5 	c #006CF9",
    "6 	c #3C44BD",
    "7 	c #2729CF",
    "8 	c #002CF5",
    "9 	c #2D2EC9",
    "0 	c #8D6E71",
    "a 	c #E96416",
    "b 	c #FF4400",
    "c 	c #FF1800",
    "d 	c #0019F3",
    "e 	c #FF1400",
    "f 	c #D66729",
    "g 	c #73498A",
    "h 	c #091FEB",
    "i 	c #002CF4",
    "j 	c #006FFC",
    "k 	c #0002F1",
    "l 	c #0059F8",
    "m 	c #AD3252",
    "n 	c #FF1700",
    "o 	c #FF2B00",
    "p 	c #B84A47",
    "q 	c #0026F4",
    "r 	c #FF0700",
    "s 	c #FF1600",
    "t 	c #003FF6",
    "u 	c #0003F1",
    "v 	c #006FFA",
    "w 	c #0058F9",
    "x 	c #0055FA",
    "y 	c #FF3D00",
    "z 	c #C3363C",
    "A 	c #FF0400",
    "B 	c #FF3F00",
    "C 	c #FF1000",
    "D 	c #003DF6",
    "E 	c #005AF8",
    "F 	c #002AF4",
    "G 	c #FF0100",
    "H 	c #FF5600",
    "I 	c #C3643C",
    "J 	c #A73958",
    "K 	c #FF3100",
    "L 	c #0020F3",
    "M 	c #002DF5",
    "N 	c #0089FD",
    "O 	c #0022F4",
    "P 	c #0085FD",
    "Q 	c #C36E3C",
    "R 	c #BC3943",
    "S 	c #FF1300",
    "T 	c #007AFC",
    "U 	c #FF2200",
    "V 	c #C3693C",
    "W 	c #FF4600",
    "X 	c #C3563C",
    "Y 	c #FF1100",
    "Z 	c #BD6C42",
    "` 	c #C12F3E",
    " .	c #B13B4E",
    "..	c #C32F3C",
    "+.	c #C0283F",
    "@.	c #C34D3C",
    "#.	c #FF2400",
    "$.	c #BC3E43",
    "%.	c #C36D3C",
    "&.	c #FF3400",
    "*.	c #FF0800",
    "=.	c #C36B3C",
    "-.	c #FF4E00",
    ";.	c #C3523C",
    ">.	c #FF3E00",
    ",.	c #FF1C00",
    "'.	c #FF0200",
    ").	c #BF3240",
    "!.	c #FF1A00",
    "~.	c #B4624B",
    "{.	c #FF5900",
    "].	c #FF1200",
    "^.	c #B82E47",
    "/.	c #FF4800",
    "(.	c #FF3A00",
    "_.	c #001EF4",
    ":.	c #001DF4",
    "<.	c #7D4882",
    "[.	c #FF4F00",
    "}.	c #0076FB",
    "|.	c #000CF2",
    "1.	c #0276F9",
    "2.	c #FF3800",
    "3.	c #FF5D00",
    "4.	c #004CF7",
    "5.	c #004CF8",
    "6.	c #FB0104",
    "7.	c #FF5500",
    "8.	c #B53E4A",
    "9.	c #0055F8",
    "0.	c #0038F6",
    "a.	c #0028F4",
    "b.	c #0039F6",
    "c.	c #0254F6",
    "d.	c #C66E39",
    "e.	c #FF3500",
    "f.	c #248ADB",
    "g.	c #785587",
    "h.	c #DE3121",
    "i.	c #FF1E00",
    "j.	c #FF2800",
    "k.	c #FF5700",
    "l.	c #FF1B00",
    "                                                                ",
    "                                                                ",
    "  . + @ @ @ @ @ @ @ @ @ # $             . @ @ @ @ @ @ @ @ .     ",
    "  . % & & * = = = - & & ; @             > & & & , ' & & & )     ",
    "  . . . . ! = = = ~ . . .               . . . . { ] ^ . . .     ",
    "        / ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( _         ",
    "        : < < < [ } | 1 2 3 < < < < 4   5 6 7 < < < < :         ",
    "        8 < < 9 0 a = b c   d < < d       e f g h < < i         ",
    "      j k < l m n = = = o p q < < q     r { ] s   t < u v       ",
    "      w < x     . y = = ' z q < < q   A % B C       D < E       ",
    "      8 F         G H = = I q < < q J K & !           L M       ",
    "    N O P           r = = Q q < < q R ' S             T O N     ",
    "                    . U = Q q < < q V ] s                       ",
    "                      . W Q q < < q X Y                         ",
    "                        G Z q < < q `                           ",
    "                           .q < < q ..                          ",
    "                          +.q < < q @.#.                        ",
    "                          $.q < < q %.+ &.                      ",
    "                        *.=.q < < q Q - Y                       ",
    "                      A -.;.q < < q Q = >.,.                    ",
    "                    '.; -.).q < < q Q = = U ~                   ",
    "                    !., Y   q < < q ~.= = {.].                  ",
    "                  *., U     q < < q ^., = = /.s                 ",
    "                A -.(.].    _.< < :.<.C = = = ~ ]               ",
    "              '.; [.!     }.|.< < |.1.. 2.= = 3.s               ",
    "              !., Y       4.< < < < 5.  6.7.= = & ].            ",
    "            *., U 8.9.0.a.< < < < < < a.b.c.d.= = (.@           ",
    "          A -.e.#   f.                    g.h.= = = i.j.        ",
    "  . @ @ ,.y , Y ,.@ @ G               '.@ ,.].* = = k.l.@ @ .   ",
    "  . & & & & & & & & & )               ,.& & & & & & & & & & )   ",
    "  . . . . . . . . . . .               . . . . . . . . . . . .   ",
    "                                                                "};
    /* XPM */
    static const char * const mini_xterm_48x48_xpm[] = {
    "48 48 213 2",
    "  	c None",
    ". 	c #FF0000",
    "+ 	c #FF5300",
    "@ 	c #FF5E00",
    "# 	c #FF4800",
    "$ 	c #FF4200",
    "% 	c #FF4000",
    "& 	c #FF4B00",
    "* 	c #FF5200",
    "= 	c #FF5400",
    "- 	c #FF3500",
    "; 	c #FF5100",
    "> 	c #FF5C00",
    ", 	c #FF3000",
    "' 	c #FF4500",
    ") 	c #FF2000",
    "! 	c #FF0300",
    "~ 	c #FF1600",
    "{ 	c #FF5D00",
    "] 	c #FF3800",
    "^ 	c #FF0200",
    "/ 	c #FF0900",
    "( 	c #FF2B00",
    "_ 	c #FF3300",
    ": 	c #FF1A00",
    "< 	c #FF1300",
    "[ 	c #FF1200",
    "} 	c #FF5700",
    "| 	c #4577BA",
    "1 	c #874E78",
    "2 	c #887577",
    "3 	c #887E77",
    "4 	c #887977",
    "5 	c #875078",
    "6 	c #566CA9",
    "7 	c #5E70A1",
    "8 	c #884E77",
    "9 	c #887677",
    "0 	c #7C5B83",
    "a 	c #795686",
    "b 	c #008DFE",
    "c 	c #0012F3",
    "d 	c #000BF2",
    "e 	c #008FFE",
    "f 	c #006CFA",
    "g 	c #0000F1",
    "h 	c #0001F1",
    "i 	c #0020F4",
    "j 	c #0040F6",
    "k 	c #0959F0",
    "l 	c #1158E8",
    "m 	c #1159E8",
    "n 	c #0058F9",
    "o 	c #001DF4",
    "p 	c #0023F4",
    "q 	c #005BFA",
    "r 	c #0060FA",
    "s 	c #0E58EB",
    "t 	c #0651F3",
    "u 	c #0033F5",
    "v 	c #000EF2",
    "w 	c #006EFA",
    "x 	c #0092FF",
    "y 	c #001FF4",
    "z 	c #000FF2",
    "A 	c #0C51EC",
    "B 	c #326AC9",
    "C 	c #7A6583",
    "D 	c #CA6234",
    "E 	c #FC5F03",
    "F 	c #FF5800",
    "G 	c #FF0800",
    "H 	c #F4060B",
    "I 	c #007CFB",
    "J 	c #0013F3",
    "K 	c #007EFB",
    "L 	c #FF1800",
    "M 	c #F3590C",
    "N 	c #AB6152",
    "O 	c #4F4EAD",
    "P 	c #175CE4",
    "Q 	c #0036F5",
    "R 	c #0022F4",
    "S 	c #0095FD",
    "T 	c #0084FD",
    "U 	c #0004F1",
    "V 	c #0051F8",
    "W 	c #345AC7",
    "X 	c #E61519",
    "Y 	c #FF5900",
    "Z 	c #FF4600",
    "` 	c #FF0100",
    " .	c #446EB9",
    "..	c #0034F6",
    "+.	c #0032F5",
    "@.	c #FF2200",
    "#.	c #006FFA",
    "$.	c #002DF5",
    "%.	c #0086FD",
    "&.	c #0046F7",
    "*.	c #0015F3",
    "=.	c #0076FC",
    "-.	c #FF0400",
    ";.	c #FF2300",
    ">.	c #FF2900",
    ",.	c #9E3E61",
    "'.	c #0039F6",
    ").	c #FF2A00",
    "!.	c #FF4300",
    "~.	c #0071FB",
    "{.	c #005EF9",
    "].	c #004DF7",
    "^.	c #008CFE",
    "/.	c #0008F2",
    "(.	c #001DF3",
    "_.	c #007DFB",
    ":.	c #FF4100",
    "<.	c #FF5B00",
    "[.	c #A3425C",
    "}.	c #994C66",
    "|.	c #FF1100",
    "1.	c #0072FB",
    "2.	c #000AF2",
    "3.	c #006EFC",
    "4.	c #0017F3",
    "5.	c #007FFB",
    "6.	c #FF0600",
    "7.	c #FF5600",
    "8.	c #A56A5A",
    "9.	c #A53B5A",
    "0.	c #FF4F00",
    "a.	c #0076FB",
    "b.	c #0076FA",
    "c.	c #0093FF",
    "d.	c #007DFC",
    "e.	c #FF1C00",
    "f.	c #A5765A",
    "g.	c #A55D5A",
    "h.	c #006FFB",
    "i.	c #002CF5",
    "j.	c #008AFD",
    "k.	c #006BF9",
    "l.	c #FF3A00",
    "m.	c #FF5000",
    "n.	c #007BFB",
    "o.	c #008BFD",
    "p.	c #A5755A",
    "q.	c #9A5565",
    "r.	c #A43A5B",
    "s.	c #FF4D00",
    "t.	c #80507F",
    "u.	c #FF0F00",
    "v.	c #7A5485",
    "w.	c #A5555A",
    "x.	c #FF0A00",
    "y.	c #A53D5A",
    "z.	c #A4515B",
    "A.	c #A5685A",
    "B.	c #A5735A",
    "C.	c #FF0700",
    "D.	c #FF2E00",
    "E.	c #FF1500",
    "F.	c #A3705C",
    "G.	c #FF0500",
    "H.	c #9A4965",
    "I.	c #FF0E00",
    "J.	c #FF3B00",
    "K.	c #FF2D00",
    "L.	c #A13C5E",
    "M.	c #FF4C00",
    "N.	c #62649D",
    "O.	c #FF0B00",
    "P.	c #FF4700",
    "Q.	c #FF1D00",
    "R.	c #A56D5A",
    "S.	c #FF2C00",
    "T.	c #A4465B",
    "U.	c #FF1400",
    "V.	c #A03E61",
    "W.	c #FF3100",
    "X.	c #FF1B00",
    "Y.	c #FF1000",
    "Z.	c #0029F5",
    "`.	c #0027F4",
    " +	c #4571BA",
    ".+	c #FF3900",
    "++	c #FF3200",
    "@+	c #008EFD",
    "#+	c #0019F3",
    "$+	c #0090FD",
    "%+	c #FF0D00",
    "&+	c #FF1E00",
    "*+	c #FF4E00",
    "=+	c #0088FC",
    "-+	c #0087FC",
    ";+	c #FF1900",
    ">+	c #0036F6",
    ",+	c #FF2100",
    "'+	c #0073FB",
    ")+	c #0062FA",
    "!+	c #001AF3",
    "~+	c #2463D8",
    "{+	c #3E58BE",
    "]+	c #2A7FD3",
    "^+	c #807B7F",
    "/+	c #008EFB",
    "(+	c #006AFA",
    "_+	c #004CF8",
    ":+	c #717B8D",
    "<+	c #EE0B11",
    "[+	c #F73E08",
    "}+	c #FF1F00",
    "|+	c #FF5500",
    "                                                                                                ",
    "                                                                                                ",
    "    . . . . . . . . . . . . . . . . . .                 . . . . . . . . . . . . . . . .         ",
    "    . + @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ .                 . # @ @ @ @ @ @ @ @ @ @ @ @ $ .         ",
    "    . % & & & * @ @ @ @ @ = & & & & & .                 . - & & & & & ; @ > & & & & , .         ",
    "    . . . . . . * @ @ @ @ ; . . . . . .                 . . . . . . . ' @ ) . . . . . .         ",
    "              ! ~ { @ @ @ @ ] ^                                   / ( @ $ .                     ",
    "                ^ _ @ @ @ @ @ : !                               < [ > } ^ .                     ",
    "                | 1 2 3 3 3 3 4 5 6                           7 8 9 3 0 a                       ",
    "            b c d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d d c e             ",
    "            f g g g g g g h i j k l m n o g g g g g g p q r s t u v g g g g g g g w             ",
    "          x y g g g g z A B C D E F G H I c g g g g J K   L / M N O P Q h g g g g R S           ",
    "          T g g g U V W X Y @ @ @ @ Z `  ...g g g g +.    ` ' @ @..     #.$.g g g g %.          ",
    "          &.g g *.=.    -.;.@ @ @ @ @ >.,.'.g g g g '.  / ).@ !..         ~.{.U g g ].          ",
    "        ^./.g (._.        ` :.@ @ @ @ <.[.'.g g g g '.}.|.<.} ^ .             1.2.g d e         ",
    "        3.g 4.5.            6.7.@ @ @ @ 8.'.g g g g '.9.0.@ [ .                 a./.g b.        ",
    "      c.R /.d.              -.e.@ @ @ @ f.'.g g g g '.g.@ - .                     h.h i.        ",
    "      j.k.%.                  ^ l.@ @ @ f.'.g g g g '.f.m.`                         n.f o.      ",
    "                                ! * @ @ f.'.g g g g '.p.G .                                     ",
    "                                ! ~ { @ f.'.g g g g '.q..                                       ",
    "                                  ^ _ @ f.'.g g g g '.r.                                        ",
    "                                    ^ s.f.'.g g g g '.t.                                        ",
    "                                    ^ u.p.'.g g g g '.v.                                        ",
    "                                      ^ w.'.g g g g '.r.                                        ",
    "                                      x.y.'.g g g g '.z.^                                       ",
    "                                      ` A.'.g g g g '.B.x..                                     ",
    "                                    C.D.f.'.g g g g '.f.# `                                     ",
    "                                  < E.{ F.'.g g g g '.f.@ ( ^                                   ",
    "                                : G.; @ H.'.g g g g '.f.@ <.I.^                                 ",
    "                                -.J.@ K.L.'.g g g g '.f.@ @ s.`                                 ",
    "                              I.) @ M.. N.'.g g g g '.f.@ @ @ _ ^                               ",
    "                            L O.F <.6..   '.g g g g '.f.@ @ @ { E.!                             ",
    "                            ^ P.@ Q..     '.g g g g '.R.@ @ @ @ * !                             ",
    "                          G S.@ % .       '.g g g g '.T.{ @ @ @ @ l.^                           ",
    "                        < U.> 7.^         ..g g g g u V.W.@ @ @ @ @ e.!                         ",
    "                      X.-.m.@ Y..         Z.g g g g `. +` M.@ @ @ @ 7.6.                        ",
    "                      -..+@ ++.         @+#+g g g g #+$+^ %+<.@ @ @ @ :.`                       ",
    "                    I.&+@ *+.           =+h g g g g h -+  ! >.@ @ @ @ @ ;.^                     ",
    "                  ;+x.} > C..           >+g g g g g g >+    ` Z @ @ @ @ Y / .                   ",
    "                  ` ' @ ,+.   %.1.'+)+!+g g g g g g g g #+)+~+{+]+^+@ @ @ P.`                   ",
    "                / ).@ !..   /+(+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+(+:+@ @ @ @ ).^                 ",
    "              I.[ > F . .                                       <+[+@ @ @ @ <.I.`               ",
    "    . . . . . . 0.@ }+. . . . . .                     . . . . . . . |+@ @ @ @ s.. . . . . .     ",
    "    O.@ @ @ @ @ @ @ @ @ @ @ @ @ ^                     ! $ @ @ @ @ @ @ @ @ @ @ @ @ @ @ @ $ .     ",
    "    . & & & & & & & & & & & & & .                     . , & & & & & & & & & & & & & & & , .     ",
    "    . . . . . . . . . . . . . . .                     . . . . . . . . . . . . . . . . . . .     ",
    "                                                                                                ",
    "                                                                                                "};
    static const XPM_DATA mini_xterm_xpms[] = {
    	{ "mini.xterm_16x16", mini_xterm_16x16_xpm }, 
    	{ "mini.xterm_32x32", mini_xterm_32x32_xpm }, 
    	{ "mini.xterm_48x48", mini_xterm_48x48_xpm }
    };
    xterm-353/icons/xterm_48x48.xpm0000644000175100001440000000502712034404252015123 0ustar  tomusers/* XPM */
    static char * xterm_48x48_xpm[] = {
    "48 48 2 1",
    " 	c None",
    ".	c #000000",
    "                                                ",
    "      ..................................        ",
    "     .                                  ..      ",
    "     .   ............................   . .     ",
    "     .  .                            .  .  .    ",
    "     . .                              . .   .   ",
    "     . .                              . .    .  ",
    "     . . ...    ...                   . .    .  ",
    "     . .  .      .                    . .    .  ",
    "     . .   .    .                     . .    .  ",
    "     . .    .  .                      . .    .  ",
    "     . .     ..                       . .    .  ",
    "     . .     ..                       . .    .  ",
    "     . .    .  .                      . .    .  ",
    "     . .   .    .                     . .    .  ",
    "     . .  .      .                    . .    .  ",
    "     . . ...    ...                   . .    .  ",
    "     . .                              . .    .  ",
    "     . .                              . .    .  ",
    "     . .                              . .    .  ",
    "     . .                              . .    .  ",
    "     . . ..... .....  ....   .     .  . .    .  ",
    "     . .   .   .      .   .  ..   ..  . .    .  ",
    "     . .   .   .      .   .  ..   ..  . .    .  ",
    "     . .   .   .....  ....   . . . .  . .    .  ",
    "     . .   .   .      .  .   . ... .  . .   ..  ",
    "     . .   .   .      .   .  .  .  .  . .   .   ",
    "     . .   .   .....  .    . .     .  . .  ..   ",
    "     . .                              . .  .    ",
    "     . .                              . . ..    ",
    "     .  .                            .  . .     ",
    "     .   ............................   ...     ",
    "     .                                  ..      ",
    "      ..................................        ",
    "                                                ",
    "                                                ",
    "      ....................................      ",
    "     .                                  ..      ",
    "     . . . . . . . . . . . . . . . . . ...      ",
    "    .                                  . .      ",
    "    . . . . . . . . . . . . . . . . . .. .      ",
    "   .                                  .  .      ",
    "  .. . . . . . . . . . . . . . . . . ..  .      ",
    "  .                                  .  .       ",
    " .. .. .......................... .... .        ",
    " .                                  . .         ",
    " .....................................          ",
    "                                                "};
    xterm-353/XTerm.ad0000644000175100001440000002403513026632553012622 0ustar  tomusers! $XTermId: XTerm.ad,v 1.102 2016/12/22 02:07:39 tom Exp $
    ! -----------------------------------------------------------------------------
    ! this file is part of xterm
    !
    ! Copyright 1996-2011,2016 by Thomas E. Dickey
    ! 
    !                         All Rights Reserved
    ! 
    ! Permission is hereby granted, free of charge, to any person obtaining a
    ! copy of this software and associated documentation files (the
    ! "Software"), to deal in the Software without restriction, including
    ! without limitation the rights to use, copy, modify, merge, publish,
    ! distribute, sublicense, and/or sell copies of the Software, and to
    ! permit persons to whom the Software is furnished to do so, subject to
    ! the following conditions:
    ! 
    ! The above copyright notice and this permission notice shall be included
    ! in all copies or substantial portions of the Software.
    ! 
    ! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    ! OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    ! MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    ! IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
    ! CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    ! TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    ! SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    ! 
    ! Except as contained in this notice, the name(s) of the above copyright
    ! holders shall not be used in advertising or otherwise to promote the
    ! sale, use or other dealings in this Software without prior written
    ! authorization.
    ! -----------------------------------------------------------------------------
    
    *saveLines: 1024
    
    *SimpleMenu*BackingStore: NotUseful
    *SimpleMenu*menuLabel.font: -adobe-helvetica-bold-r-normal--*-120-*-*-*-*-iso8859-*
    *SimpleMenu*menuLabel.vertSpace: 	100
    *SimpleMenu*HorizontalMargins: 16
    *SimpleMenu*Sme.height:	16
    
    *SimpleMenu*Cursor: left_ptr
    
    *mainMenu.Label:  Main Options
    *mainMenu*toolbar*Label:  Toolbar
    *mainMenu*fullscreen*Label: Full Screen
    *mainMenu*securekbd*Label:  Secure Keyboard
    *mainMenu*allowsends*Label:  Allow SendEvents
    *mainMenu*redraw*Label:  Redraw Window
    *mainMenu*logging*Label:  Log to File
    *mainMenu*print-immediate*Label:  Print-All Immediately
    *mainMenu*print-on-error*Label:  Print-All on Error
    *mainMenu*print*Label:  Print Window
    *mainMenu*print-redir*Label:  Redirect to Printer
    *mainMenu*dump-html*Label:  XHTML Screen Dump
    *mainMenu*dump-svg*Label:  SVG Screen Dump
    *mainMenu*8-bit control*Label: 8-Bit Controls
    *mainMenu*backarrow key*Label: Backarrow Key (BS/DEL)
    *mainMenu*num-lock*Label: Alt/NumLock Modifiers
    *mainMenu*alt-esc*Label: Alt Sends Escape
    *mainMenu*meta-esc*Label: Meta Sends Escape
    *mainMenu*delete-is-del*Label: Delete is DEL
    *mainMenu*oldFunctionKeys*Label: Old Function-Keys
    *mainMenu*sunFunctionKeys*Label: Sun Function-Keys
    *mainMenu*sunKeyboard*Label: VT220 Keyboard
    *mainMenu*hpFunctionKeys*Label: HP Function-Keys
    *mainMenu*scoFunctionKeys*Label: SCO Function-Keys
    *mainMenu*tcapFunctionKeys*Label: Termcap Function-Keys
    *mainMenu*suspend*Label:  Send STOP Signal
    *mainMenu*continue*Label:  Send CONT Signal
    *mainMenu*interrupt*Label:  Send INT Signal
    *mainMenu*hangup*Label:  Send HUP Signal
    *mainMenu*terminate*Label:  Send TERM Signal
    *mainMenu*kill*Label:  Send KILL Signal
    *mainMenu*quit*Label:  Quit
    
    *vtMenu.Label:  VT Options
    *vtMenu*scrollbar*Label:  Enable Scrollbar
    *vtMenu*jumpscroll*Label:  Enable Jump Scroll
    *vtMenu*reversevideo*Label:  Enable Reverse Video
    *vtMenu*autowrap*Label:  Enable Auto Wraparound
    *vtMenu*reversewrap*Label:  Enable Reverse Wraparound
    *vtMenu*autolinefeed*Label:  Enable Auto Linefeed
    *vtMenu*appcursor*Label:  Enable Application Cursor Keys
    *vtMenu*appkeypad*Label:  Enable Application Keypad
    *vtMenu*scrollkey*Label:  Scroll to Bottom on Key Press
    *vtMenu*scrollttyoutput*Label:  Scroll to Bottom on Tty Output
    *vtMenu*allow132*Label: Allow 80/132 Column Switching
    *vtMenu*keepSelection*Label: Keep Selection
    *vtMenu*selectToClipboard*Label: Select to Clipboard
    *vtMenu*cursesemul*Label:  Enable Curses Emulation
    *vtMenu*visualbell*Label:  Enable Visual Bell
    *vtMenu*bellIsUrgent*Label:  Enable Bell Urgency
    *vtMenu*poponbell*Label:  Enable Pop on Bell
    *vtMenu*cursorblink*Label: Enable Blinking Cursor
    *vtMenu*titeInhibit*Label:  Enable Alternate Screen Switching
    *vtMenu*activeicon*Label: Enable Active Icon
    *vtMenu*softreset*Label:  Do Soft Reset
    *vtMenu*hardreset*Label:  Do Full Reset
    *vtMenu*clearsavedlines*Label:  Reset and Clear Saved Lines
    *vtMenu*tekshow*Label:  Show Tek Window
    *vtMenu*tekmode*Label:  Switch to Tek Mode
    *vtMenu*vthide*Label:  Hide VT Window
    *vtMenu*altscreen*Label:  Show Alternate Screen
    *vtMenu*sixelScrolling*Label:  Sixel Scrolling
    *vtMenu*privateColorRegisters*Label:  Private Color Registers
    
    *fontMenu.Label:  VT Fonts
    *fontMenu*fontdefault*Label:	Default
    *fontMenu*font1*Label:	Unreadable
    *VT100.font1:		nil2
    *IconFont:		nil2
    *fontMenu*font2*Label:	Tiny
    *VT100.font2:		5x7
    *fontMenu*font3*Label:	Small
    *VT100.font3:		6x10
    *fontMenu*font4*Label:	Medium
    *VT100.font4:		7x13
    *fontMenu*font5*Label:	Large
    *VT100.font5:		9x15
    *fontMenu*font6*Label:	Huge
    *VT100.font6:		10x20
    *fontMenu*fontescape*Label:	Escape Sequence
    *fontMenu*fontsel*Label:	Selection
    !fontescape and fontsel overridden by application
    *fontMenu*allow-bold-fonts*Label:  Bold Fonts
    *fontMenu*font-linedrawing*Label:  Line-Drawing Characters
    *fontMenu*font-doublesize*Label: Doublesized Characters
    *fontMenu*font-loadable*Label:	VT220 Soft Fonts
    *fontMenu*font-packed*Label:	Packed Font
    *fontMenu*render-font*Label:	TrueType Fonts
    *fontMenu*utf8-mode*Label:	UTF-8 Encoding
    *fontMenu*utf8-fonts*Label:	UTF-8 Fonts
    *fontMenu*utf8-title*Label:	UTF-8 Titles
    
    *fontMenu*allow-color-ops*Label:	Allow Color Ops
    *fontMenu*allow-font-ops*Label:	Allow Font Ops
    *fontMenu*allow-mouse-ops*Label:	Allow Mouse Ops
    *fontMenu*allow-tcap-ops*Label:	Allow Termcap Ops
    *fontMenu*allow-title-ops*Label:	Allow Title Ops
    *fontMenu*allow-window-ops*Label:	Allow Window Ops
    
    *VT100.utf8Fonts.font2:	-misc-fixed-medium-r-normal--8-80-75-75-c-50-iso10646-1
    *VT100.utf8Fonts.font:	-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1
    *VT100.utf8Fonts.font3:	-misc-fixed-medium-r-normal--14-130-75-75-c-70-iso10646-1
    *VT100.utf8Fonts.font4:	-misc-fixed-medium-r-normal--13-120-75-75-c-80-iso10646-1
    *VT100.utf8Fonts.font5:	-misc-fixed-medium-r-normal--18-120-100-100-c-90-iso10646-1
    *VT100.utf8Fonts.font6:	-misc-fixed-medium-r-normal--20-200-75-75-c-100-iso10646-1
    
    *tekMenu.Label:  Tek Options
    *tekMenu*tektextlarge*Label:  Large Characters
    *tekMenu*tektext2*Label:  #2 Size Characters
    *tekMenu*tektext3*Label:  #3 Size Characters
    *tekMenu*tektextsmall*Label:  Small Characters
    *tekMenu*tekpage*Label:  PAGE
    *tekMenu*tekreset*Label:  RESET
    *tekMenu*tekcopy*Label:  COPY
    *tekMenu*vtshow*Label:  Show VT Window
    *tekMenu*vtmode*Label:  Switch to VT Mode
    *tekMenu*tekhide*Label:  Hide Tek Window
    
    *tek4014*fontLarge: 9x15
    *tek4014*font2: 8x13
    *tek4014*font3: 6x13
    *tek4014*fontSmall: 6x10
    
    ! If xterm is built with a toolbar, the widget hierarchy looks like this,
    ! showing widget name / class names.  The complete menu hierarchy is built
    ! at startup because it is needed to make the layout work for the menubar:
    !
    !	xterm/XTerm
    !		form/Form
    !			menubar/Box
    !				mainMenuButton/MenuButton
    !					mainMenu/SimpleMenu
    !						menuLabel/SmeBSB
    !						toolbar/SmeBSB
    !						...
    !					vtMenu/SimpleMenu
    !						menuLabel/SmeBSB
    !						scrollbar/SmeBSB
    !						...
    !					fontMenu/SimpleMenu
    !						menuLabel/SmeBSB
    !						fontdefault/SmeBSB
    !						...
    !					tekMenu/SimpleMenu
    !						menuLabel/SmeBSB
    !						fontdefault/SmeBSB
    !						...
    !			vt100/VT100
    !			tektronix/TopLevelShell
    !				shellext/VendorShellExt
    !					tek4014/Tek4014
    !
    ! If built without a toolbar, the widget hierarchy is simpler, because there
    ! is no form, and the popup menu widgets are created only when they are first
    ! used.
    !
    !	xterm/XTerm
    !		shellext/VendorShellExt
    !			mainMenu/SimpleMenu
    !				menuLabel/SmeBSB
    !				...
    !			...
    !		vt100/VT100
    !		tektronix/TopLevelShell
    !			shellext/VendorShellExt
    !				tek4014/Tek4014
    !
    ! A more complete list of the widget/class names can be obtained using editres
    ! to dump a file.  Some widget names are not available until the corresponding
    ! menu has been created.
    
    ! These resources reduce space around the menubar, by eliminating padding in
    ! the enclosing form (Thickness) and the border of the Box which represents
    ! the menubar widget.
    *form.Thickness: 0
    *menubar.borderWidth: 0
    
    ! If we wanted to eliminate the border of the popup menus, we could do this
    ! instead, since they are children of the menubar:
    !*menubar*borderWidth: 0
    
    ! Eliminate the border of the buttons in the menubar, so the only line around
    ! the text is for the highlighted button:
    *MenuButton*borderWidth: 0
    
    ! Set a border for the menus to make them simpler to distinguish against the
    ! vt100 widget:
    *SimpleMenu*borderWidth: 2
    
    ! xterm can switch at runtime between bitmap (default) and TrueType fonts.
    ! The "faceSize" resource controls the size of the latter.  However, it was
    ! originally given with a size that makes the two types of fonts different
    ! sizes.  Uncomment this line to use the same size as "fixed".
    !*faceSize: 8
    
    ! Here is a pattern that is useful for double-clicking on a URL:
    !*charClass: 33:48,35:48,37-38:48,43-47:48,58:48,61:48,63-64:48,95:48,126:48
    !
    ! Alternatively,
    !*on2Clicks: regex [[:alpha:]]+://([[:alnum:]!#+,./=?@_~-]|(%[[:xdigit:]][[:xdigit:]]))+
    
    ! VT100s and similar terminals recognize escape sequences and control
    ! characters to which they reply to the host with other escape sequences,
    ! to provide information.  The "resize" program uses this feature.
    !
    ! In addition, xterm recognizes several escape sequences which can be used to
    ! set fonts, window properties, return settings via escape sequences.  Some
    ! find these useful; others are concerned with the possibility of unexpected
    ! inputs.
    !
    ! All of these features can be enabled or disabled via menus.
    !
    ! Depending on your environment, you may wish to disable those by default by
    ! uncommenting one or more of the resource settings below:
    !*allowFontOps: false
    !*allowTcapOps: false
    !*allowTitleOps: false
    !*allowWindowOps: false
    xterm-353/main.c0000644000175100001440000046054313610650260012347 0ustar  tomusers/* $XTermId: main.c,v 1.861 2020/01/18 18:38:40 tom Exp $ */
    
    /*
     * Copyright 2002-2019,2020 by Thomas E. Dickey
     *
     *                         All Rights Reserved
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     *
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * Except as contained in this notice, the name(s) of the above copyright
     * holders shall not be used in advertising or otherwise to promote the
     * sale, use or other dealings in this Software without prior written
     * authorization.
     *
     * Copyright 1987, 1988  X Consortium
     *
     * Permission to use, copy, modify, distribute, and sell this software and its
     * documentation for any purpose is hereby granted without fee, provided that
     * the above copyright notice appear in all copies and that both that
     * copyright notice and this permission notice appear in supporting
     * documentation.
     *
     * The above copyright notice and this permission notice shall be included in
     * all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     * OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * Except as contained in this notice, the name of the X Consortium shall not be
     * used in advertising or otherwise to promote the sale, use or other dealings
     * in this Software without prior written authorization from the X Consortium.
     *
     * Copyright 1987, 1988 by Digital Equipment Corporation, Maynard.
     *
     *                         All Rights Reserved
     *
     * Permission to use, copy, modify, and distribute this software and its
     * documentation for any purpose and without fee is hereby granted,
     * provided that the above copyright notice appear in all copies and that
     * both that copyright notice and this permission notice appear in
     * supporting documentation, and that the name of Digital not be used in
     * advertising or publicity pertaining to distribution of the software
     * without specific, written prior permission.
     *
     * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     * SOFTWARE.
     */
    
    /*
     *				 W A R N I N G
     *
     * If you think you know what all of this code is doing, you are
     * probably very mistaken.  There be serious and nasty dragons here.
     *
     * This client is *not* to be taken as an example of how to write X
     * Toolkit applications.  It is in need of a substantial rewrite,
     * ideally to create a generic tty widget with several different parsing
     * widgets so that you can plug 'em together any way you want.  Don't
     * hold your breath, though....
     */
    
    /* main.c */
    
    #define RES_OFFSET(field)	XtOffsetOf(XTERM_RESOURCE, field)
    
    #include 
    #include 
    #include 
    
    #include 
    #include 
    
    #if OPT_TOOLBAR
    
    #if defined(HAVE_LIB_XAW)
    #include 
    #elif defined(HAVE_LIB_XAW3D)
    #include 
    #elif defined(HAVE_LIB_XAW3DXFT)
    #include 
    #elif defined(HAVE_LIB_NEXTAW)
    #include 
    #elif defined(HAVE_LIB_XAWPLUS)
    #include 
    #endif
    
    #endif /* OPT_TOOLBAR */
    
    #include 
    #include 
    
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #if OPT_WIDE_CHARS
    #include 
    #endif
    
    #ifdef __osf__
    #define USE_SYSV_SIGNALS
    #define WTMP
    #include 		/* openpty() */
    #endif
    
    #ifdef __sgi
    #include 		/* initgroups() */
    #endif
    
    static void Syntax(char *) GCC_NORETURN;
    static void HsSysError(int) GCC_NORETURN;
    
    #if defined(__SCO__) || defined(SVR4) || defined(_POSIX_SOURCE) || ( defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 1) )
    #define USE_POSIX_SIGNALS
    #endif
    
    #if defined(SYSV) && !defined(SVR4) && !defined(ISC22) && !defined(ISC30)
    /* older SYSV systems cannot ignore SIGHUP.
       Shell hangs, or you get extra shells, or something like that */
    #define USE_SYSV_SIGHUP
    #endif
    
    #if defined(sony) && defined(bsd43) && !defined(KANJI)
    #define KANJI
    #endif
    
    #ifdef linux
    #define USE_SYSV_PGRP
    #define USE_SYSV_SIGNALS
    #define WTMP
    #ifdef __GLIBC__
    #if (__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1))
    #include 
    #endif
    #endif
    #endif
    
    #ifdef __MVS__
    #define USE_SYSV_PGRP
    #define USE_SYSV_SIGNALS
    #endif
    
    #ifdef __CYGWIN__
    #define WTMP
    #endif
    
    #ifdef __SCO__
    #ifndef _SVID3
    #define _SVID3
    #endif
    #endif
    
    #if defined(__GLIBC__) && !defined(linux)
    #define USE_SYSV_PGRP
    #define WTMP
    #endif
    
    #if defined(USE_TTY_GROUP) || defined(USE_UTMP_SETGID) || defined(HAVE_INITGROUPS)
    #include 
    #endif
    
    #ifndef TTY_GROUP_NAME
    #define TTY_GROUP_NAME "tty"
    #endif
    
    #include 
    
    #ifdef Lynx
    #ifndef BSDLY
    #define BSDLY	0
    #endif
    #ifndef VTDLY
    #define VTDLY	0
    #endif
    #ifndef FFDLY
    #define FFDLY	0
    #endif
    #endif
    
    #ifdef SYSV			/* { */
    
    #ifdef USE_USG_PTYS		/* AT&T SYSV has no ptyio.h */
    #include 	/* for I_PUSH */
    #include 		/* for POLLIN */
    #endif /* USE_USG_PTYS */
    
    #define USE_SYSV_SIGNALS
    #define	USE_SYSV_PGRP
    
    #if !defined(TIOCSWINSZ) || defined(__SCO__) || defined(__UNIXWARE__)
    #define USE_SYSV_ENVVARS	/* COLUMNS/LINES vs. TERMCAP */
    #endif
    
    /*
     * now get system-specific includes
     */
    #ifdef macII
    #include 
    #undef USE_SYSV_ENVVARS
    #undef FIOCLEX
    #undef FIONCLEX
    #define setpgrp2 setpgrp
    #include 
    #include 
    #endif
    
    #ifdef __hpux
    #include 
    #endif /* __hpux */
    
    #ifdef __osf__
    #undef  USE_SYSV_PGRP
    #define setpgrp setpgid
    #endif
    
    #ifdef __sgi
    #include 
    #endif /* __sgi */
    
    #ifdef sun
    #include 
    #endif
    
    #else /* } !SYSV { */ /* BSD systems */
    
    #ifdef __QNX__
    
    #ifndef __QNXNTO__
    #define ttyslot() 1
    #else
    #define USE_SYSV_PGRP
    extern __inline__
    int
    ttyslot(void)
    {
        return 1;			/* yuk */
    }
    #endif
    
    #else
    
    #if defined(__INTERIX) || defined(__APPLE__)
    #define setpgrp setpgid
    #endif
    
    #ifndef linux
    #ifndef VMS
    #ifndef USE_POSIX_TERMIOS
    #ifndef USE_ANY_SYSV_TERMIO
    #include 
    #endif
    #endif /* USE_POSIX_TERMIOS */
    #ifdef Lynx
    #include 
    #else
    #include 
    #endif
    #endif /* !VMS */
    #endif /* !linux */
    
    #endif /* __QNX__ */
    
    #endif /* } !SYSV */
    
    /* Xpoll.h and  on glibc 2.1 systems have colliding NBBY's */
    #if defined(__GLIBC__) && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 1)))
    #ifndef NOFILE
    #define NOFILE OPEN_MAX
    #endif
    #elif !(defined(VMS) || defined(WIN32) || defined(Lynx) || defined(__GNU__) || defined(__MVS__))
    #include 		/* for NOFILE */
    #endif
    
    #if defined(BSD) && (BSD >= 199103)
    #define WTMP
    #endif
    
    #include 
    
    #ifdef __hpux
    #include 
    #endif /* __hpux */
    
    #if defined(apollo) && (OSMAJORVERSION == 10) && (OSMINORVERSION < 4)
    #define ttyslot() 1
    #endif /* apollo */
    
    #if defined(UTMPX_FOR_UTMP)
    #define UTMP_STR utmpx
    #else
    #define UTMP_STR utmp
    #endif
    
    #if defined(USE_UTEMPTER)
    #include 
    #if 1
    #define UTEMPTER_ADD(pty,hostname,master_fd) utempter_add_record(master_fd, hostname)
    #define UTEMPTER_DEL()                       utempter_remove_added_record ()
    #else
    #define UTEMPTER_ADD(pty,hostname,master_fd) addToUtmp(pty, hostname, master_fd)
    #define UTEMPTER_DEL()                       removeFromUtmp()
    #endif
    #endif
    
    #if defined(I_FIND) && defined(I_PUSH)
    #define PUSH_FAILS(fd,name) ioctl(fd, I_FIND, name) == 0 \
    			 && ioctl(fd, I_PUSH, name) < 0
    #else
    #define PUSH_FAILS(fd,name) ioctl(fd, I_PUSH, name) < 0
    #endif
    
    #if defined(UTMPX_FOR_UTMP)
    
    #include 
    
    #define call_endutent  endutxent
    #define call_getutid   getutxid
    #define call_pututline pututxline
    #define call_setutent  setutxent
    #define call_updwtmp   updwtmpx
    
    #elif defined(HAVE_UTMP)
    
    #include 
    
    #if defined(_CRAY) && (OSMAJORVERSION < 8)
    extern struct utmp *getutid __((struct utmp * _Id));
    #endif
    
    #define call_endutent  endutent
    #define call_getutid   getutid
    #define call_pututline pututline
    #define call_setutent  setutent
    #define call_updwtmp   updwtmp
    
    #endif
    
    #if defined(USE_LASTLOG) && defined(HAVE_LASTLOG_H)
    #include 		/* caution: glibc includes utmp.h here */
    #endif
    
    #ifndef USE_LASTLOGX
    #if defined(_NETBSD_SOURCE) && defined(_PATH_LASTLOGX)
    #define USE_LASTLOGX 1
    #endif
    #endif
    
    #ifdef  PUCC_PTYD
    #include 
    #endif /* PUCC_PTYD */
    
    #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
    #include 		/* openpty() */
    #endif
    
    #if defined(__FreeBSD__) || defined(__DragonFly__)
    #include 		/* openpty() */
    #endif
    
    #if !defined(UTMP_FILENAME)
    #if defined(UTMP_FILE)
    #define UTMP_FILENAME UTMP_FILE
    #elif defined(_PATH_UTMP)
    #define UTMP_FILENAME _PATH_UTMP
    #else
    #define UTMP_FILENAME "/etc/utmp"
    #endif
    #endif
    
    #ifndef LASTLOG_FILENAME
    #ifdef _PATH_LASTLOG
    #define LASTLOG_FILENAME _PATH_LASTLOG
    #else
    #define LASTLOG_FILENAME "/usr/adm/lastlog"	/* only on BSD systems */
    #endif
    #endif
    
    #if !defined(WTMP_FILENAME)
    #if defined(WTMP_FILE)
    #define WTMP_FILENAME WTMP_FILE
    #elif defined(_PATH_WTMP)
    #define WTMP_FILENAME _PATH_WTMP
    #elif defined(SYSV)
    #define WTMP_FILENAME "/etc/wtmp"
    #else
    #define WTMP_FILENAME "/usr/adm/wtmp"
    #endif
    #endif
    
    #include 
    
    #if defined(__SCO__) || (defined(ISC) && !defined(_POSIX_SOURCE))
    #undef SIGTSTP			/* defined, but not the BSD way */
    #endif
    
    #ifdef SIGTSTP
    #include 
    #endif
    
    #if defined(__SCO__) || defined(__UNIXWARE__)
    #undef ECHOKE
    #undef ECHOCTL
    #endif
    
    #if defined(HAVE_SYS_TTYDEFAULTS_H) && !defined(CEOF)
    #include 
    #endif
    
    #ifdef X_NOT_POSIX
    extern long lseek();
    #if defined(USG) || defined(SVR4)
    extern unsigned sleep();
    #else
    extern void sleep();
    #endif
    extern char *ttyname();
    #endif
    
    #if defined(SYSV) && defined(DECL_PTSNAME)
    extern char *ptsname(int);
    #endif
    
    #ifndef VMS
    static void reapchild(int /* n */ );
    static int spawnXTerm(XtermWidget	/* xw */
    		      ,unsigned /* line_speed */ );
    static void remove_termcap_entry(char *, const char *);
    #ifdef USE_PTY_SEARCH
    static int pty_search(int * /* pty */ );
    #endif
    #endif /* ! VMS */
    
    static int get_pty(int *pty, char *from);
    static void resize_termcap(XtermWidget xw);
    static void set_owner(char *device, unsigned uid, unsigned gid, unsigned mode);
    
    static Bool added_utmp_entry = False;
    
    #ifdef HAVE_POSIX_SAVED_IDS
    static uid_t save_euid;
    static gid_t save_egid;
    #endif
    
    static uid_t save_ruid;
    static gid_t save_rgid;
    
    #if defined(USE_UTMP_SETGID)
    static int really_get_pty(int *pty, char *from);
    #endif
    
    #if defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER)
    static Bool xterm_exiting = False;
    #endif
    
    static char *explicit_shname = NULL;
    
    /*
    ** Ordinarily it should be okay to omit the assignment in the following
    ** statement. Apparently the c89 compiler on AIX 4.1.3 has a bug, or does
    ** it? Without the assignment though the compiler will init command_to_exec
    ** to 0xffffffff instead of NULL; and subsequent usage, e.g. in spawnXTerm() to
    ** SEGV.
    */
    static char **command_to_exec = NULL;
    
    #if OPT_LUIT_PROG
    static char **command_to_exec_with_luit = NULL;
    static unsigned command_length_with_luit = 0;
    #endif
    
    #define TERMCAP_ERASE "kb"
    #define VAL_INITIAL_ERASE A2E(8)
    
    /* choose a nice default value for speed - if we make it too low, users who
     * mistakenly use $TERM set to vt100 will get padding delays.  Setting it to a
     * higher value is not useful since legacy applications (termcap) that care
     * about padding generally store the code in a short, which does not have
     * enough bits for the extended values.
     */
    #ifdef B38400			/* everyone should define this */
    #define VAL_LINE_SPEED B38400
    #else /* ...but xterm's used this for a long time */
    #define VAL_LINE_SPEED B9600
    #endif
    
    /*
     * Allow use of system default characters if defined and reasonable.
     * These are based on the BSD ttydefaults.h
     */
    #ifndef CBRK
    #define CBRK     0xff		/* was 0 */
    #endif
    #ifndef CDISCARD
    #define CDISCARD CONTROL('O')
    #endif
    #ifndef CDSUSP
    #define CDSUSP   CONTROL('Y')
    #endif
    #ifndef CEOF
    #define CEOF     CONTROL('D')
    #endif
    #ifndef CEOL
    #define CEOL	 0xff		/* was 0 */
    #endif
    #ifndef CERASE
    #define CERASE   0177
    #endif
    #ifndef CERASE2
    #define	CERASE2  CONTROL('H')
    #endif
    #ifndef CFLUSH
    #define CFLUSH   CONTROL('O')
    #endif
    #ifndef CINTR
    #define CINTR    CONTROL('C')
    #endif
    #ifndef CKILL
    #define CKILL	 CONTROL('U')	/* was '@' */
    #endif
    #ifndef CLNEXT
    #define CLNEXT   CONTROL('V')
    #endif
    #ifndef CNUL
    #define CNUL     0
    #endif
    #ifndef CQUIT
    #define CQUIT    CONTROL('\\')
    #endif
    #ifndef CRPRNT
    #define CRPRNT   CONTROL('R')
    #endif
    #ifndef CREPRINT
    #define CREPRINT CRPRNT
    #endif
    #ifndef CSTART
    #define CSTART   CONTROL('Q')
    #endif
    #ifndef CSTATUS
    #define	CSTATUS  CONTROL('T')
    #endif
    #ifndef CSTOP
    #define CSTOP    CONTROL('S')
    #endif
    #ifndef CSUSP
    #define CSUSP    CONTROL('Z')
    #endif
    #ifndef CSWTCH
    #define CSWTCH   0
    #endif
    #ifndef CWERASE
    #define CWERASE  CONTROL('W')
    #endif
    
    #ifdef USE_ANY_SYSV_TERMIO
    #define TERMIO_STRUCT struct termio
    #define ttySetAttr(fd, datap) ioctl(fd, TCSETA, datap)
    #define ttyGetAttr(fd, datap) ioctl(fd, TCGETA, datap)
    #define ttyFlush(fd)          ioctl(fd, TCFLSH, 1)
    #elif defined(USE_POSIX_TERMIOS)
    #define TERMIO_STRUCT struct termios
    #define ttySetAttr(fd, datap) tcsetattr(fd, TCSANOW, datap)
    #define ttyGetAttr(fd, datap) tcgetattr(fd, datap)
    #define ttyFlush(fd)          tcflush(fd, TCOFLUSH)
    #endif /* USE_ANY_SYSV_TERMIO */
    
    #ifndef VMS
    #ifdef TERMIO_STRUCT
    /* The following structures are initialized in main() in order
    ** to eliminate any assumptions about the internal order of their
    ** contents.
    */
    static TERMIO_STRUCT d_tio;
    
    #ifndef ONLCR
    #define ONLCR 0
    #endif
    
    #ifndef OPOST
    #define OPOST 0
    #endif
    
    #define D_TIO_FLAGS (OPOST | ONLCR)
    
    #ifdef HAS_LTCHARS
    static struct ltchars d_ltc;
    #endif /* HAS_LTCHARS */
    
    #ifdef TIOCLSET
    static unsigned int d_lmode;
    #endif /* TIOCLSET */
    
    #else /* !TERMIO_STRUCT */
    
    #define D_SG_FLAGS (EVENP | ODDP | ECHO | CRMOD)
    
    static struct sgttyb d_sg =
    {
        0, 0, 0177, CKILL, (D_SG_FLAGS | XTABS)
    };
    static struct tchars d_tc =
    {
        CINTR, CQUIT, CSTART,
        CSTOP, CEOF, CBRK
    };
    static struct ltchars d_ltc =
    {
        CSUSP, CDSUSP, CRPRNT,
        CFLUSH, CWERASE, CLNEXT
    };
    static int d_disipline = NTTYDISC;
    static long int d_lmode = LCRTBS | LCRTERA | LCRTKIL | LCTLECH;
    #ifdef sony
    static long int d_jmode = KM_SYSSJIS | KM_ASCII;
    static struct jtchars d_jtc =
    {
        'J', 'B'
    };
    #endif /* sony */
    #endif /* TERMIO_STRUCT */
    #endif /* ! VMS */
    
    /*
     * SYSV has the termio.c_cc[V] and ltchars; BSD has tchars and ltchars;
     * SVR4 has only termio.c_cc, but it includes everything from ltchars.
     * POSIX termios has termios.c_cc, which is similar to SVR4.
     */
    #define TTYMODE(name) { name, sizeof(name)-1, 0, 0 }
    static Boolean override_tty_modes = False;
    /* *INDENT-OFF* */
    static struct {
        const char *name;
        size_t len;
        int set;
        int value;
    } ttyModes[] = {
        TTYMODE("intr"),		/* tchars.t_intrc ; VINTR */
    #define XTTYMODE_intr	0
        TTYMODE("quit"),		/* tchars.t_quitc ; VQUIT */
    #define XTTYMODE_quit	1
        TTYMODE("erase"),		/* sgttyb.sg_erase ; VERASE */
    #define XTTYMODE_erase	2
        TTYMODE("kill"),		/* sgttyb.sg_kill ; VKILL */
    #define XTTYMODE_kill	3
        TTYMODE("eof"),		/* tchars.t_eofc ; VEOF */
    #define XTTYMODE_eof	4
        TTYMODE("eol"),		/* VEOL */
    #define XTTYMODE_eol	5
        TTYMODE("swtch"),		/* VSWTCH */
    #define XTTYMODE_swtch	6
        TTYMODE("start"),		/* tchars.t_startc ; VSTART */
    #define XTTYMODE_start	7
        TTYMODE("stop"),		/* tchars.t_stopc ; VSTOP */
    #define XTTYMODE_stop	8
        TTYMODE("brk"),		/* tchars.t_brkc */
    #define XTTYMODE_brk	9
        TTYMODE("susp"),		/* ltchars.t_suspc ; VSUSP */
    #define XTTYMODE_susp	10
        TTYMODE("dsusp"),		/* ltchars.t_dsuspc ; VDSUSP */
    #define XTTYMODE_dsusp	11
        TTYMODE("rprnt"),		/* ltchars.t_rprntc ; VREPRINT */
    #define XTTYMODE_rprnt	12
        TTYMODE("flush"),		/* ltchars.t_flushc ; VDISCARD */
    #define XTTYMODE_flush	13
        TTYMODE("weras"),		/* ltchars.t_werasc ; VWERASE */
    #define XTTYMODE_weras	14
        TTYMODE("lnext"),		/* ltchars.t_lnextc ; VLNEXT */
    #define XTTYMODE_lnext	15
        TTYMODE("status"),		/* VSTATUS */
    #define XTTYMODE_status	16
        TTYMODE("erase2"),		/* VERASE2 */
    #define XTTYMODE_erase2	17
        TTYMODE("eol2"),		/* VEOL2 */
    #define XTTYMODE_eol2	18
        TTYMODE("tabs"),		/* TAB0 */
    #define XTTYMODE_tabs	19
        TTYMODE("-tabs"),		/* TAB3 */
    #define XTTYMODE__tabs	20
    };
    
    #ifndef TAB0
    #define TAB0 0
    #endif
    
    #ifndef TAB3
    #if defined(OXTABS)
    #define TAB3 OXTABS
    #elif defined(XTABS)
    #define TAB3 XTABS
    #endif
    #endif
    
    #ifndef TABDLY
    #define TABDLY (TAB0|TAB3)
    #endif
    
    #define isTtyMode(p,q) (ttyChars[p].myMode == q && ttyModes[q].set)
    
    #define isTabMode(n) \
    	(isTtyMode(n, XTTYMODE_tabs) || \
    	 isTtyMode(n, XTTYMODE__tabs))
    
    #define TMODE(ind,var) \
    	if (ttyModes[ind].set) \
    	    var = (cc_t) ttyModes[ind].value
    
    #define validTtyChar(data, n) \
    	    (ttyChars[n].sysMode >= 0 && \
    	     ttyChars[n].sysMode < (int) XtNumber(data.c_cc))
    
    static const struct {
        int sysMode;
        int myMode;
        int myDefault;
    } ttyChars[] = {
    #ifdef VINTR
        { VINTR,    XTTYMODE_intr,   CINTR },
    #endif
    #ifdef VQUIT
        { VQUIT,    XTTYMODE_quit,   CQUIT },
    #endif
    #ifdef VERASE
        { VERASE,   XTTYMODE_erase,  CERASE },
    #endif
    #ifdef VKILL
        { VKILL,    XTTYMODE_kill,   CKILL },
    #endif
    #ifdef VEOF
        { VEOF,     XTTYMODE_eof,    CEOF },
    #endif
    #ifdef VEOL
        { VEOL,     XTTYMODE_eol,    CEOL },
    #endif
    #ifdef VSWTCH
        { VSWTCH,   XTTYMODE_swtch,  CNUL },
    #endif
    #ifdef VSTART
        { VSTART,   XTTYMODE_start,  CSTART },
    #endif
    #ifdef VSTOP
        { VSTOP,    XTTYMODE_stop,   CSTOP },
    #endif
    #ifdef VSUSP
        { VSUSP,    XTTYMODE_susp,   CSUSP },
    #endif
    #ifdef VDSUSP
        { VDSUSP,   XTTYMODE_dsusp,  CDSUSP },
    #endif
    #ifdef VREPRINT
        { VREPRINT, XTTYMODE_rprnt,  CREPRINT },
    #endif
    #ifdef VDISCARD
        { VDISCARD, XTTYMODE_flush,  CDISCARD },
    #endif
    #ifdef VWERASE
        { VWERASE,  XTTYMODE_weras,  CWERASE },
    #endif
    #ifdef VLNEXT
        { VLNEXT,   XTTYMODE_lnext,  CLNEXT },
    #endif
    #ifdef VSTATUS
        { VSTATUS,  XTTYMODE_status, CSTATUS },
    #endif
    #ifdef VERASE2
        { VERASE2,  XTTYMODE_erase2, CERASE2 },
    #endif
    #ifdef VEOL2
        { VEOL2,    XTTYMODE_eol2,   CNUL },
    #endif
        { -1,       XTTYMODE_tabs,   TAB0 },
        { -1,       XTTYMODE__tabs,  TAB3 },
    };
    /* *INDENT-ON* */
    
    static int parse_tty_modes(char *s);
    
    #ifndef USE_UTEMPTER
    #ifdef USE_SYSV_UTMP
    #if (defined(AIXV3) && (OSMAJORVERSION < 4)) && !(defined(getutid))
    extern struct utmp *getutid();
    #endif /* AIXV3 */
    
    #else /* not USE_SYSV_UTMP */
    static char etc_utmp[] = UTMP_FILENAME;
    #endif /* USE_SYSV_UTMP */
    
    #if defined(USE_LASTLOG) && defined(USE_STRUCT_LASTLOG)
    static char etc_lastlog[] = LASTLOG_FILENAME;
    #else
    #undef USE_LASTLOG
    #endif
    
    #ifdef WTMP
    static char etc_wtmp[] = WTMP_FILENAME;
    #endif
    #endif /* !USE_UTEMPTER */
    
    /*
     * Some people with 4.3bsd /bin/login seem to like to use login -p -f user
     * to implement xterm -ls.  They can turn on USE_LOGIN_DASH_P and turn off
     * WTMP and USE_LASTLOG.
     */
    #ifdef USE_LOGIN_DASH_P
    #ifndef LOGIN_FILENAME
    #define LOGIN_FILENAME "/bin/login"
    #endif
    static char bin_login[] = LOGIN_FILENAME;
    #endif
    
    static char noPassedPty[2];
    static char *passedPty = noPassedPty;	/* name if pty if slave */
    
    #if defined(TIOCCONS) || defined(SRIOCSREDIR)
    static int Console;
    #include 	/* XmuGetHostname */
    #define MIT_CONSOLE_LEN	12
    #define MIT_CONSOLE "MIT_CONSOLE_"
    static char mit_console_name[255 + MIT_CONSOLE_LEN + 1] = MIT_CONSOLE;
    static Atom mit_console;
    #endif /* TIOCCONS */
    
    #ifndef USE_SYSV_UTMP
    static int tslot;
    #endif /* USE_SYSV_UTMP */
    static sigjmp_buf env;
    
    #define SetUtmpHost(dst, screen) \
    	{ \
    	    char host[sizeof(dst) + 1]; \
    	    strncpy(host, DisplayString(screen->display), sizeof(host) - 1); \
    	    host[sizeof(dst)] = '\0'; \
    	    TRACE(("DisplayString(%s)\n", host)); \
    	    if (!resource.utmpDisplayId) { \
    		char *endptr = strrchr(host, ':'); \
    		if (endptr) { \
    		    TRACE(("trimming display-id '%s'\n", host)); \
    		    *endptr = '\0'; \
    		} \
    	    } \
    	    copy_filled(dst, host, sizeof(dst)); \
    	}
    
    #ifdef HAVE_UTMP_UT_SYSLEN
    #  define SetUtmpSysLen(utmp) 			   \
    	{ \
    	    utmp.ut_host[sizeof(utmp.ut_host)-1] = '\0'; \
    	    utmp.ut_syslen = (short) ((int) strlen(utmp.ut_host) + 1); \
    	}
    #endif
    
    /* used by VT (charproc.c) */
    
    static XtResource application_resources[] =
    {
        Sres("iconGeometry", "IconGeometry", icon_geometry, NULL),
        Sres(XtNtitle, XtCTitle, title, NULL),
        Sres(XtNiconHint, XtCIconHint, icon_hint, NULL),
        Sres(XtNiconName, XtCIconName, icon_name, NULL),
        Sres("termName", "TermName", term_name, NULL),
        Sres("ttyModes", "TtyModes", tty_modes, NULL),
        Sres("validShells", "ValidShells", valid_shells, NULL),
        Bres("hold", "Hold", hold_screen, False),
        Bres("utmpInhibit", "UtmpInhibit", utmpInhibit, False),
        Bres("utmpDisplayId", "UtmpDisplayId", utmpDisplayId, True),
        Bres("messages", "Messages", messages, True),
        Ires("minBufSize", "MinBufSize", minBufSize, 4096),
        Ires("maxBufSize", "MaxBufSize", maxBufSize, 32768),
        Sres("menuLocale", "MenuLocale", menuLocale, DEF_MENU_LOCALE),
        Sres("omitTranslation", "OmitTranslation", omitTranslation, NULL),
        Sres("keyboardType", "KeyboardType", keyboardType, "unknown"),
    #if OPT_PRINT_ON_EXIT
        Ires("printModeImmediate", "PrintModeImmediate", printModeNow, 0),
        Ires("printOptsImmediate", "PrintOptsImmediate", printOptsNow, 9),
        Sres("printFileImmediate", "PrintFileImmediate", printFileNow, NULL),
        Ires("printModeOnXError", "PrintModeOnXError", printModeOnXError, 0),
        Ires("printOptsOnXError", "PrintOptsOnXError", printOptsOnXError, 9),
        Sres("printFileOnXError", "PrintFileOnXError", printFileOnXError, NULL),
    #endif
    #if OPT_SUNPC_KBD
        Bres("sunKeyboard", "SunKeyboard", sunKeyboard, False),
    #endif
    #if OPT_HP_FUNC_KEYS
        Bres("hpFunctionKeys", "HpFunctionKeys", hpFunctionKeys, False),
    #endif
    #if OPT_SCO_FUNC_KEYS
        Bres("scoFunctionKeys", "ScoFunctionKeys", scoFunctionKeys, False),
    #endif
    #if OPT_SUN_FUNC_KEYS
        Bres("sunFunctionKeys", "SunFunctionKeys", sunFunctionKeys, False),
    #endif
    #if OPT_TCAP_FKEYS
        Bres("tcapFunctionKeys", "TcapFunctionKeys", termcapKeys, False),
    #endif
    #if OPT_INITIAL_ERASE
        Bres("ptyInitialErase", "PtyInitialErase", ptyInitialErase, DEF_INITIAL_ERASE),
        Bres("backarrowKeyIsErase", "BackarrowKeyIsErase", backarrow_is_erase, DEF_BACKARO_ERASE),
    #endif
        Bres("useInsertMode", "UseInsertMode", useInsertMode, False),
    #if OPT_ZICONBEEP
        Ires("zIconBeep", "ZIconBeep", zIconBeep, 0),
        Sres("zIconTitleFormat", "ZIconTitleFormat", zIconFormat, "*** %s"),
    #endif
    #if OPT_PTY_HANDSHAKE
        Bres("waitForMap", "WaitForMap", wait_for_map, False),
        Bres("ptyHandshake", "PtyHandshake", ptyHandshake, True),
        Bres("ptySttySize", "PtySttySize", ptySttySize, DEF_PTY_STTY_SIZE),
    #endif
    #if OPT_REPORT_CCLASS
        Bres("reportCClass", "ReportCClass", reportCClass, False),
    #endif
    #if OPT_REPORT_COLORS
        Bres("reportColors", "ReportColors", reportColors, False),
    #endif
    #if OPT_REPORT_FONTS
        Bres("reportFonts", "ReportFonts", reportFonts, False),
    #endif
    #if OPT_REPORT_ICONS
        Bres("reportIcons", "ReportIcons", reportIcons, False),
    #endif
    #if OPT_XRES_QUERY
        Bres("reportXRes", "ReportXRes", reportXRes, False),
    #endif
    #if OPT_SAME_NAME
        Bres("sameName", "SameName", sameName, True),
    #endif
    #if OPT_SESSION_MGT
        Bres("sessionMgt", "SessionMgt", sessionMgt, True),
    #endif
    #if OPT_TOOLBAR
        Bres(XtNtoolBar, XtCToolBar, toolBar, True),
    #endif
    #if OPT_MAXIMIZE
        Bres(XtNmaximized, XtCMaximized, maximized, False),
        Sres(XtNfullscreen, XtCFullscreen, fullscreen_s, "off"),
    #endif
    #if USE_DOUBLE_BUFFER
        Bres(XtNbuffered, XtCBuffered, buffered, DEF_DOUBLE_BUFFER),
        Ires(XtNbufferedFPS, XtCBufferedFPS, buffered_fps, 40),
    #endif
    };
    
    static String fallback_resources[] =
    {
    #if OPT_TOOLBAR
        "*toolBar: false",
    #endif
        "*SimpleMenu*menuLabel.vertSpace: 100",
        "*SimpleMenu*HorizontalMargins: 16",
        "*SimpleMenu*Sme.height: 16",
        "*SimpleMenu*Cursor: left_ptr",
        "*mainMenu.Label:  Main Options (no app-defaults)",
        "*vtMenu.Label:  VT Options (no app-defaults)",
        "*fontMenu.Label:  VT Fonts (no app-defaults)",
    #if OPT_TEK4014
        "*tekMenu.Label:  Tek Options (no app-defaults)",
    #endif
        NULL
    };
    
    /* Command line options table.  Only resources are entered here...there is a
       pass over the remaining options after XrmParseCommand is let loose. */
    /* *INDENT-OFF* */
    #define DATA(option,pattern,type,value) { (char *) option, (char *) pattern, type, (XPointer) value }
    static XrmOptionDescRec optionDescList[] = {
    DATA("-geometry",	"*vt100.geometry",XrmoptionSepArg,	NULL),
    DATA("-132",		"*c132",	XrmoptionNoArg,		"on"),
    DATA("+132",		"*c132",	XrmoptionNoArg,		"off"),
    DATA("-ah",		"*alwaysHighlight", XrmoptionNoArg,	"on"),
    DATA("+ah",		"*alwaysHighlight", XrmoptionNoArg,	"off"),
    DATA("-aw",		"*autoWrap",	XrmoptionNoArg,		"on"),
    DATA("+aw",		"*autoWrap",	XrmoptionNoArg,		"off"),
    #ifndef NO_ACTIVE_ICON
    DATA("-ai",		"*activeIcon",	XrmoptionNoArg,		"off"),
    DATA("+ai",		"*activeIcon",	XrmoptionNoArg,		"on"),
    #endif /* NO_ACTIVE_ICON */
    DATA("-b",		"*internalBorder",XrmoptionSepArg,	NULL),
    DATA("-bc",		"*cursorBlink",	XrmoptionNoArg,		"on"),
    DATA("+bc",		"*cursorBlink",	XrmoptionNoArg,		"off"),
    DATA("-bcf",		"*cursorOffTime",XrmoptionSepArg,	NULL),
    DATA("-bcn",		"*cursorOnTime",XrmoptionSepArg,	NULL),
    DATA("-bdc",		"*colorBDMode",	XrmoptionNoArg,		"off"),
    DATA("+bdc",		"*colorBDMode",	XrmoptionNoArg,		"on"),
    DATA("-cb",		"*cutToBeginningOfLine", XrmoptionNoArg, "off"),
    DATA("+cb",		"*cutToBeginningOfLine", XrmoptionNoArg, "on"),
    DATA("-cc",		"*charClass",	XrmoptionSepArg,	NULL),
    DATA("-cm",		"*colorMode",	XrmoptionNoArg,		"off"),
    DATA("+cm",		"*colorMode",	XrmoptionNoArg,		"on"),
    DATA("-cn",		"*cutNewline",	XrmoptionNoArg,		"off"),
    DATA("+cn",		"*cutNewline",	XrmoptionNoArg,		"on"),
    DATA("-cr",		"*cursorColor",	XrmoptionSepArg,	NULL),
    DATA("-cu",		"*curses",	XrmoptionNoArg,		"on"),
    DATA("+cu",		"*curses",	XrmoptionNoArg,		"off"),
    DATA("-dc",		"*dynamicColors",XrmoptionNoArg,	"off"),
    DATA("+dc",		"*dynamicColors",XrmoptionNoArg,	"on"),
    DATA("-fb",		"*boldFont",	XrmoptionSepArg,	NULL),
    DATA("-fbb",		"*freeBoldBox", XrmoptionNoArg,		"off"),
    DATA("+fbb",		"*freeBoldBox", XrmoptionNoArg,		"on"),
    DATA("-fbx",		"*forceBoxChars", XrmoptionNoArg,	"off"),
    DATA("+fbx",		"*forceBoxChars", XrmoptionNoArg,	"on"),
    #ifndef NO_ACTIVE_ICON
    DATA("-fi",		"*iconFont",	XrmoptionSepArg,	NULL),
    #endif /* NO_ACTIVE_ICON */
    #if OPT_RENDERFONT
    DATA("-fa",		"*faceName",	XrmoptionSepArg,	NULL),
    DATA("-fd",		"*faceNameDoublesize", XrmoptionSepArg,	NULL),
    DATA("-fs",		"*faceSize",	XrmoptionSepArg,	NULL),
    #endif
    #if OPT_WIDE_ATTRS && OPT_ISO_COLORS
    DATA("-itc",		"*colorITMode",	XrmoptionNoArg,		"off"),
    DATA("+itc",		"*colorITMode",	XrmoptionNoArg,		"on"),
    #endif
    #if OPT_WIDE_CHARS
    DATA("-fw",		"*wideFont",	XrmoptionSepArg,	NULL),
    DATA("-fwb",		"*wideBoldFont", XrmoptionSepArg,	NULL),
    #endif
    #if OPT_INPUT_METHOD
    DATA("-fx",		"*ximFont",	XrmoptionSepArg,	NULL),
    #endif
    #if OPT_HIGHLIGHT_COLOR
    DATA("-hc",		"*highlightColor", XrmoptionSepArg,	NULL),
    DATA("-hm",		"*highlightColorMode", XrmoptionNoArg,	"on"),
    DATA("+hm",		"*highlightColorMode", XrmoptionNoArg,	"off"),
    DATA("-selfg",		"*highlightTextColor", XrmoptionSepArg,	NULL),
    DATA("-selbg",		"*highlightColor", XrmoptionSepArg,	NULL),
    #endif
    #if OPT_HP_FUNC_KEYS
    DATA("-hf",		"*hpFunctionKeys",XrmoptionNoArg,	"on"),
    DATA("+hf",		"*hpFunctionKeys",XrmoptionNoArg,	"off"),
    #endif
    DATA("-hold",		"*hold",	XrmoptionNoArg,		"on"),
    DATA("+hold",		"*hold",	XrmoptionNoArg,		"off"),
    #if OPT_INITIAL_ERASE
    DATA("-ie",		"*ptyInitialErase", XrmoptionNoArg,	"on"),
    DATA("+ie",		"*ptyInitialErase", XrmoptionNoArg,	"off"),
    #endif
    DATA("-j",		"*jumpScroll",	XrmoptionNoArg,		"on"),
    DATA("+j",		"*jumpScroll",	XrmoptionNoArg,		"off"),
    #if OPT_C1_PRINT
    DATA("-k8",		"*allowC1Printable", XrmoptionNoArg,	"on"),
    DATA("+k8",		"*allowC1Printable", XrmoptionNoArg,	"off"),
    #endif
    DATA("-kt",		"*keyboardType", XrmoptionSepArg,	NULL),
    /* parse logging options anyway for compatibility */
    DATA("-l",		"*logging",	XrmoptionNoArg,		"on"),
    DATA("+l",		"*logging",	XrmoptionNoArg,		"off"),
    DATA("-lf",		"*logFile",	XrmoptionSepArg,	NULL),
    DATA("-ls",		"*loginShell",	XrmoptionNoArg,		"on"),
    DATA("+ls",		"*loginShell",	XrmoptionNoArg,		"off"),
    DATA("-mb",		"*marginBell",	XrmoptionNoArg,		"on"),
    DATA("+mb",		"*marginBell",	XrmoptionNoArg,		"off"),
    DATA("-mc",		"*multiClickTime", XrmoptionSepArg,	NULL),
    DATA("-mesg",		"*messages",	XrmoptionNoArg,		"off"),
    DATA("+mesg",		"*messages",	XrmoptionNoArg,		"on"),
    DATA("-ms",		"*pointerColor",XrmoptionSepArg,	NULL),
    DATA("-nb",		"*nMarginBell",	XrmoptionSepArg,	NULL),
    DATA("-nul",		"*underLine",	XrmoptionNoArg,		"off"),
    DATA("+nul",		"*underLine",	XrmoptionNoArg,		"on"),
    DATA("-pc",		"*boldColors",	XrmoptionNoArg,		"on"),
    DATA("+pc",		"*boldColors",	XrmoptionNoArg,		"off"),
    DATA("-rw",		"*reverseWrap",	XrmoptionNoArg,		"on"),
    DATA("+rw",		"*reverseWrap",	XrmoptionNoArg,		"off"),
    DATA("-s",		"*multiScroll",	XrmoptionNoArg,		"on"),
    DATA("+s",		"*multiScroll",	XrmoptionNoArg,		"off"),
    DATA("-sb",		"*scrollBar",	XrmoptionNoArg,		"on"),
    DATA("+sb",		"*scrollBar",	XrmoptionNoArg,		"off"),
    #if OPT_REPORT_CCLASS
    DATA("-report-charclass","*reportCClass", XrmoptionNoArg,	"on"),
    #endif
    #if OPT_REPORT_COLORS
    DATA("-report-colors",	"*reportColors", XrmoptionNoArg,	"on"),
    #endif
    #if OPT_REPORT_ICONS
    DATA("-report-icons",	"*reportIcons",	XrmoptionNoArg,		"on"),
    #endif
    #if OPT_REPORT_FONTS
    DATA("-report-fonts",	"*reportFonts", XrmoptionNoArg,		"on"),
    #endif
    #if OPT_XRES_QUERY
    DATA("-report-xres",	"*reportXRes",	XrmoptionNoArg,		"on"),
    #endif
    #ifdef SCROLLBAR_RIGHT
    DATA("-leftbar",	"*rightScrollBar", XrmoptionNoArg,	"off"),
    DATA("-rightbar",	"*rightScrollBar", XrmoptionNoArg,	"on"),
    #endif
    DATA("-rvc",		"*colorRVMode",	XrmoptionNoArg,		"off"),
    DATA("+rvc",		"*colorRVMode",	XrmoptionNoArg,		"on"),
    DATA("-sf",		"*sunFunctionKeys", XrmoptionNoArg,	"on"),
    DATA("+sf",		"*sunFunctionKeys", XrmoptionNoArg,	"off"),
    DATA("-sh",		"*scaleHeight", XrmoptionSepArg,	NULL),
    DATA("-si",		"*scrollTtyOutput", XrmoptionNoArg,	"off"),
    DATA("+si",		"*scrollTtyOutput", XrmoptionNoArg,	"on"),
    DATA("-sk",		"*scrollKey",	XrmoptionNoArg,		"on"),
    DATA("+sk",		"*scrollKey",	XrmoptionNoArg,		"off"),
    DATA("-sl",		"*saveLines",	XrmoptionSepArg,	NULL),
    #if OPT_SUNPC_KBD
    DATA("-sp",		"*sunKeyboard", XrmoptionNoArg,		"on"),
    DATA("+sp",		"*sunKeyboard", XrmoptionNoArg,		"off"),
    #endif
    #if OPT_TEK4014
    DATA("-t",		"*tekStartup",	XrmoptionNoArg,		"on"),
    DATA("+t",		"*tekStartup",	XrmoptionNoArg,		"off"),
    #endif
    DATA("-ti",		"*decTerminalID",XrmoptionSepArg,	NULL),
    DATA("-tm",		"*ttyModes",	XrmoptionSepArg,	NULL),
    DATA("-tn",		"*termName",	XrmoptionSepArg,	NULL),
    #if OPT_WIDE_CHARS
    DATA("-u8",		"*utf8",	XrmoptionNoArg,		"2"),
    DATA("+u8",		"*utf8",	XrmoptionNoArg,		"0"),
    #endif
    #if OPT_LUIT_PROG
    DATA("-lc",		"*locale",	XrmoptionNoArg,		"on"),
    DATA("+lc",		"*locale",	XrmoptionNoArg,		"off"),
    DATA("-lcc",		"*localeFilter",XrmoptionSepArg,	NULL),
    DATA("-en",		"*locale",	XrmoptionSepArg,	NULL),
    #endif
    DATA("-uc",		"*cursorUnderLine", XrmoptionNoArg,	"on"),
    DATA("+uc",		"*cursorUnderLine", XrmoptionNoArg,	"off"),
    DATA("-ulc",		"*colorULMode",	XrmoptionNoArg,		"off"),
    DATA("+ulc",		"*colorULMode",	XrmoptionNoArg,		"on"),
    DATA("-ulit",       	"*italicULMode", XrmoptionNoArg,        "off"),
    DATA("+ulit",       	"*italicULMode", XrmoptionNoArg,        "on"),
    DATA("-ut",		"*utmpInhibit",	XrmoptionNoArg,		"on"),
    DATA("+ut",		"*utmpInhibit",	XrmoptionNoArg,		"off"),
    DATA("-im",		"*useInsertMode", XrmoptionNoArg,	"on"),
    DATA("+im",		"*useInsertMode", XrmoptionNoArg,	"off"),
    DATA("-vb",		"*visualBell",	XrmoptionNoArg,		"on"),
    DATA("+vb",		"*visualBell",	XrmoptionNoArg,		"off"),
    DATA("-pob",		"*popOnBell",	XrmoptionNoArg,		"on"),
    DATA("+pob",		"*popOnBell",	XrmoptionNoArg,		"off"),
    #if OPT_WIDE_CHARS
    DATA("-wc",		"*wideChars",	XrmoptionNoArg,		"on"),
    DATA("+wc",		"*wideChars",	XrmoptionNoArg,		"off"),
    DATA("-mk_width",	"*mkWidth",	XrmoptionNoArg,		"on"),
    DATA("+mk_width",	"*mkWidth",	XrmoptionNoArg,		"off"),
    DATA("-cjk_width",	"*cjkWidth",	XrmoptionNoArg,		"on"),
    DATA("+cjk_width",	"*cjkWidth",	XrmoptionNoArg,		"off"),
    #endif
    DATA("-wf",		"*waitForMap",	XrmoptionNoArg,		"on"),
    DATA("+wf",		"*waitForMap",	XrmoptionNoArg,		"off"),
    #if OPT_ZICONBEEP
    DATA("-ziconbeep",	"*zIconBeep",	XrmoptionSepArg,	NULL),
    #endif
    #if OPT_SAME_NAME
    DATA("-samename",	"*sameName",	XrmoptionNoArg,		"on"),
    DATA("+samename",	"*sameName",	XrmoptionNoArg,		"off"),
    #endif
    #if OPT_SESSION_MGT
    DATA("-sm",		"*sessionMgt",	XrmoptionNoArg,		"on"),
    DATA("+sm",		"*sessionMgt",	XrmoptionNoArg,		"off"),
    #endif
    #if OPT_TOOLBAR
    DATA("-tb",		"*"XtNtoolBar,	XrmoptionNoArg,		"on"),
    DATA("+tb",		"*"XtNtoolBar,	XrmoptionNoArg,		"off"),
    #endif
    #if OPT_MAXIMIZE
    DATA("-maximized",	"*maximized",	XrmoptionNoArg,		"on"),
    DATA("+maximized",	"*maximized",	XrmoptionNoArg,		"off"),
    DATA("-fullscreen",	"*fullscreen",	XrmoptionNoArg,		"on"),
    DATA("+fullscreen",	"*fullscreen",	XrmoptionNoArg,		"off"),
    #endif
    /* options that we process ourselves */
    DATA("-help",		NULL,		XrmoptionSkipNArgs,	NULL),
    DATA("-version",	NULL,		XrmoptionSkipNArgs,	NULL),
    DATA("-baudrate",	NULL,		XrmoptionSkipArg,	NULL),
    DATA("-class",		NULL,		XrmoptionSkipArg,	NULL),
    DATA("-e",		NULL,		XrmoptionSkipLine,	NULL),
    DATA("-into",		NULL,		XrmoptionSkipArg,	NULL),
    /* bogus old compatibility stuff for which there are
       standard XtOpenApplication options now */
    DATA("%",		"*tekGeometry",	XrmoptionStickyArg,	NULL),
    DATA("#",		".iconGeometry",XrmoptionStickyArg,	NULL),
    DATA("-T",		".title",	XrmoptionSepArg,	NULL),
    DATA("-n",		"*iconName",	XrmoptionSepArg,	NULL),
    DATA("-r",		"*reverseVideo",XrmoptionNoArg,		"on"),
    DATA("+r",		"*reverseVideo",XrmoptionNoArg,		"off"),
    DATA("-rv",		"*reverseVideo",XrmoptionNoArg,		"on"),
    DATA("+rv",		"*reverseVideo",XrmoptionNoArg,		"off"),
    DATA("-w",		".borderWidth", XrmoptionSepArg,	NULL),
    #undef DATA
    };
    
    static OptionHelp xtermOptions[] = {
    { "-version",              "print the version number" },
    { "-help",                 "print out this message" },
    { "-display displayname",  "X server to contact" },
    { "-geometry geom",        "size (in characters) and position" },
    { "-/+rv",                 "turn on/off reverse video" },
    { "-bg color",             "background color" },
    { "-fg color",             "foreground color" },
    { "-bd color",             "border color" },
    { "-bw number",            "border width in pixels" },
    { "-fn fontname",          "normal text font" },
    { "-fb fontname",          "bold text font" },
    { "-/+fbb",                "turn on/off normal/bold font comparison inhibit"},
    { "-/+fbx",                "turn off/on linedrawing characters"},
    #if OPT_RENDERFONT
    { "-fa pattern",           "FreeType font-selection pattern" },
    { "-fd pattern",           "FreeType Doublesize font-selection pattern" },
    { "-fs size",              "FreeType font-size" },
    #endif
    #if OPT_WIDE_CHARS
    { "-fw fontname",          "doublewidth text font" },
    { "-fwb fontname",         "doublewidth bold text font" },
    #endif
    #if OPT_INPUT_METHOD
    { "-fx fontname",          "XIM fontset" },
    #endif
    { "-iconic",               "start iconic" },
    { "-name string",          "client instance, icon, and title strings" },
    { "-baudrate rate",        "set line-speed (default 38400)" },
    { "-class string",         "class string (XTerm)" },
    { "-title string",         "title string" },
    { "-xrm resourcestring",   "additional resource specifications" },
    { "-/+132",                "turn on/off 80/132 column switching" },
    { "-/+ah",                 "turn on/off always highlight" },
    #ifndef NO_ACTIVE_ICON
    { "-/+ai",                 "turn off/on active icon" },
    { "-fi fontname",          "icon font for active icon" },
    #endif /* NO_ACTIVE_ICON */
    { "-b number",             "internal border in pixels" },
    { "-/+bc",                 "turn on/off text cursor blinking" },
    { "-bcf milliseconds",     "time text cursor is off when blinking"},
    { "-bcn milliseconds",     "time text cursor is on when blinking"},
    { "-/+bdc",                "turn off/on display of bold as color"},
    { "-/+cb",                 "turn on/off cut-to-beginning-of-line inhibit" },
    { "-cc classrange",        "specify additional character classes" },
    { "-/+cm",                 "turn off/on ANSI color mode" },
    { "-/+cn",                 "turn on/off cut newline inhibit" },
    { "-cr color",             "text cursor color" },
    { "-/+cu",                 "turn on/off curses emulation" },
    { "-/+dc",                 "turn off/on dynamic color selection" },
    #if OPT_HIGHLIGHT_COLOR
    { "-/+hm",                 "turn on/off selection-color override" },
    { "-selbg color",          "selection background color" },
    { "-selfg color",          "selection foreground color" },
    /* -hc is deprecated, not shown in help message */
    #endif
    #if OPT_HP_FUNC_KEYS
    { "-/+hf",                 "turn on/off HP Function Key escape codes" },
    #endif
    { "-/+hold",               "turn on/off logic that retains window after exit" },
    #if OPT_INITIAL_ERASE
    { "-/+ie",                 "turn on/off initialization of 'erase' from pty" },
    #endif
    { "-/+im",                 "use insert mode for TERMCAP" },
    { "-/+j",                  "turn on/off jump scroll" },
    #if OPT_C1_PRINT
    { "-/+k8",                 "turn on/off C1-printable classification"},
    #endif
    { "-kt keyboardtype",      "set keyboard type:" KEYBOARD_TYPES },
    #ifdef ALLOWLOGGING
    { "-/+l",                  "turn on/off logging" },
    { "-lf filename",          "logging filename (use '-' for standard out)" },
    #else
    { "-/+l",                  "turn on/off logging (not supported)" },
    { "-lf filename",          "logging filename (not supported)" },
    #endif
    { "-/+ls",                 "turn on/off login shell" },
    { "-/+mb",                 "turn on/off margin bell" },
    { "-mc milliseconds",      "multiclick time in milliseconds" },
    { "-/+mesg",               "forbid/allow messages" },
    { "-ms color",             "pointer color" },
    { "-nb number",            "margin bell in characters from right end" },
    { "-/+nul",                "turn off/on display of underlining" },
    { "-/+aw",                 "turn on/off auto wraparound" },
    { "-/+pc",                 "turn on/off PC-style bold colors" },
    { "-/+rw",                 "turn on/off reverse wraparound" },
    { "-/+s",                  "turn on/off multiscroll" },
    { "-/+sb",                 "turn on/off scrollbar" },
    #if OPT_REPORT_CCLASS
    {"-report-charclass",      "report \"charClass\" after initialization"},
    #endif
    #if OPT_REPORT_COLORS
    { "-report-colors",        "report colors as they are allocated" },
    #endif
    #if OPT_REPORT_FONTS
    { "-report-fonts",         "report fonts as loaded to stdout" },
    #endif
    #if OPT_REPORT_ICONS
    { "-report-icons",	   "report title/icon updates" },
    #endif
    #if OPT_XRES_QUERY
    { "-report-xres",          "report X resources for VT100 widget" },
    #endif
    #ifdef SCROLLBAR_RIGHT
    { "-rightbar",             "force scrollbar right (default left)" },
    { "-leftbar",              "force scrollbar left" },
    #endif
    { "-/+rvc",                "turn off/on display of reverse as color" },
    { "-/+sf",                 "turn on/off Sun Function Key escape codes" },
    { "-sh number",            "scale line-height values by the given number" },
    { "-/+si",                 "turn on/off scroll-on-tty-output inhibit" },
    { "-/+sk",                 "turn on/off scroll-on-keypress" },
    { "-sl number",            "number of scrolled lines to save" },
    #if OPT_SUNPC_KBD
    { "-/+sp",                 "turn on/off Sun/PC Function/Keypad mapping" },
    #endif
    #if OPT_TEK4014
    { "-/+t",                  "turn on/off Tek emulation window" },
    #endif
    #if OPT_TOOLBAR
    { "-/+tb",                 "turn on/off toolbar" },
    #endif
    { "-ti termid",            "terminal identifier" },
    { "-tm string",            "terminal mode keywords and characters" },
    { "-tn name",              "TERM environment variable name" },
    #if OPT_WIDE_CHARS
    { "-/+u8",                 "turn on/off UTF-8 mode (implies wide-characters)" },
    #endif
    #if OPT_LUIT_PROG
    { "-/+lc",                 "turn on/off locale mode using luit" },
    { "-lcc path",             "filename of locale converter (" DEFLOCALEFILTER ")" },
    /* -en is deprecated, not shown in help message */
    #endif
    { "-/+uc",                 "turn on/off underline cursor" },
    { "-/+ulc",                "turn off/on display of underline as color" },
    { "-/+ulit",               "turn off/on display of underline as italics" },
    #ifdef HAVE_UTMP
    { "-/+ut",                 "turn on/off utmp support" },
    #else
    { "-/+ut",                 "turn on/off utmp support (not available)" },
    #endif
    { "-/+vb",                 "turn on/off visual bell" },
    { "-/+pob",                "turn on/off pop on bell" },
    #if OPT_WIDE_ATTRS && OPT_ISO_COLORS
    { "-/+itc",                "turn off/on display of italic as color"},
    #endif
    #if OPT_WIDE_CHARS
    { "-/+wc",                 "turn on/off wide-character mode" },
    { "-/+mk_width",           "turn on/off simple width convention" },
    { "-/+cjk_width",          "turn on/off legacy CJK width convention" },
    #endif
    { "-/+wf",                 "turn on/off wait for map before command exec" },
    { "-e command args ...",   "command to execute" },
    #if OPT_TEK4014
    { "%geom",                 "Tek window geometry" },
    #endif
    { "#geom",                 "icon window geometry" },
    { "-T string",             "title name for window" },
    { "-n string",             "icon name for window" },
    #if defined(TIOCCONS) || defined(SRIOCSREDIR)
    { "-C",                    "intercept console messages" },
    #else
    { "-C",                    "intercept console messages (not supported)" },
    #endif
    { "-Sccn",                 "slave mode on \"ttycc\", file descriptor \"n\"" },
    { "-into windowId",        "use the window id given to -into as the parent window rather than the default root window" },
    #if OPT_ZICONBEEP
    { "-ziconbeep percent",    "beep and flag icon of window having hidden output" },
    #endif
    #if OPT_SAME_NAME
    { "-/+samename",           "turn on/off the no-flicker option for title and icon name" },
    #endif
    #if OPT_SESSION_MGT
    { "-/+sm",                 "turn on/off the session-management support" },
    #endif
    #if OPT_MAXIMIZE
    {"-/+maximized",           "turn on/off maxmize on startup" },
    {"-/+fullscreen",          "turn on/off fullscreen on startup" },
    #endif
    { NULL, NULL }};
    /* *INDENT-ON* */
    
    static const char *const message[] =
    {
        "Fonts should be fixed width and, if both normal and bold are specified, should",
        "have the same size.  If only a normal font is specified, it will be used for",
        "both normal and bold text (by doing overstriking).  The -e option, if given,",
        "must appear at the end of the command line, otherwise the user's default shell",
        "will be started.  Options that start with a plus sign (+) restore the default.",
        NULL};
    
    /*
     * Decode a key-definition.  This combines the termcap and ttyModes, for
     * comparison.  Note that octal escapes in ttyModes are done by the normal
     * resource translation.  Also, ttyModes allows '^-' as a synonym for disabled.
     */
    static int
    decode_keyvalue(char **ptr, int termcap)
    {
        char *string = *ptr;
        int value = -1;
    
        TRACE(("decode_keyvalue '%s'\n", string));
        if (*string == '^') {
    	switch (*++string) {
    	case '?':
    	    value = A2E(ANSI_DEL);
    	    break;
    	case '-':
    	    if (!termcap) {
    		errno = 0;
    #if defined(_POSIX_VDISABLE) && defined(HAVE_UNISTD_H)
    		value = _POSIX_VDISABLE;
    #endif
    #if defined(_PC_VDISABLE)
    		if (value == -1) {
    		    value = (int) fpathconf(0, _PC_VDISABLE);
    		    if (value == -1) {
    			if (errno != 0)
    			    break;	/* skip this (error) */
    			value = 0377;
    		    }
    		}
    #elif defined(VDISABLE)
    		if (value == -1)
    		    value = VDISABLE;
    #endif
    		break;
    	    }
    	    /* FALLTHRU */
    	default:
    	    value = CONTROL(*string);
    	    break;
    	}
    	++string;
        } else if (termcap && (*string == '\\')) {
    	char *s = (string + 1);
    	char *d;
    	int temp = (int) strtol(s, &d, 8);
    	if (PartS2L(s, d) && temp > 0) {
    	    value = temp;
    	    string = d;
    	}
        } else {
    	value = CharOf(*string);
    	++string;
        }
        *ptr = string;
        TRACE(("...decode_keyvalue %#x\n", value));
        return value;
    }
    
    static int
    matchArg(XrmOptionDescRec * table, const char *param)
    {
        int result = -1;
        int n;
        int ch;
    
        for (n = 0; (ch = table->option[n]) != '\0'; ++n) {
    	if (param[n] == ch) {
    	    result = n;
    	} else {
    	    if (param[n] != '\0')
    		result = -1;
    	    break;
    	}
        }
    
        return result;
    }
    
    /* return the number of argv[] entries which constitute arguments of option */
    static int
    countArg(XrmOptionDescRec * item)
    {
        int result = 0;
    
        switch (item->argKind) {
        case XrmoptionNoArg:
    	/* FALLTHRU */
        case XrmoptionIsArg:
    	/* FALLTHRU */
        case XrmoptionStickyArg:
    	break;
        case XrmoptionSepArg:
    	/* FALLTHRU */
        case XrmoptionResArg:
    	/* FALLTHRU */
        case XrmoptionSkipArg:
    	result = 1;
    	break;
        case XrmoptionSkipLine:
    	break;
        case XrmoptionSkipNArgs:
    	result = (int) (long) (item->value);
    	break;
        }
        return result;
    }
    
    #define isOption(string) (Boolean)((string)[0] == '-' || (string)[0] == '+')
    
    /*
     * Parse the argument list, more/less as XtInitialize, etc., would do, so we
     * can find our own "-help" and "-version" options reliably.  Improve on just
     * doing that, by detecting ambiguous options (things that happen to match the
     * abbreviated option we are examining), and making it smart enough to handle
     * "-d" as an abbreviation for "-display".  Doing this requires checking the
     * standard table (something that the X libraries should do).
     */
    static XrmOptionDescRec *
    parseArg(int *num, char **argv, char **valuep)
    {
        /* table adapted from XtInitialize, used here to improve abbreviations */
        /* *INDENT-OFF* */
    #define DATA(option,kind) { (char *) option, NULL, kind, (XtPointer) NULL }
        static XrmOptionDescRec opTable[] = {
    	DATA("+synchronous",	   XrmoptionNoArg),
    	DATA("-background",	   XrmoptionSepArg),
    	DATA("-bd",		   XrmoptionSepArg),
    	DATA("-bg",		   XrmoptionSepArg),
    	DATA("-bordercolor",	   XrmoptionSepArg),
    	DATA("-borderwidth",	   XrmoptionSepArg),
    	DATA("-bw",		   XrmoptionSepArg),
    	DATA("-display",	   XrmoptionSepArg),
    	DATA("-fg",		   XrmoptionSepArg),
    	DATA("-fn",		   XrmoptionSepArg),
    	DATA("-font",		   XrmoptionSepArg),
    	DATA("-foreground",	   XrmoptionSepArg),
    	DATA("-iconic",		   XrmoptionNoArg),
    	DATA("-name",		   XrmoptionSepArg),
    	DATA("-reverse",	   XrmoptionNoArg),
    	DATA("-selectionTimeout",  XrmoptionSepArg),
    	DATA("-synchronous",	   XrmoptionNoArg),
    	DATA("-title",		   XrmoptionSepArg),
    	DATA("-xnllanguage",	   XrmoptionSepArg),
    	DATA("-xrm",		   XrmoptionResArg),
    	DATA("-xtsessionID",	   XrmoptionSepArg),
    	/* These xterm options are processed after XtOpenApplication */
    #if defined(TIOCCONS) || defined(SRIOCSREDIR)
    	DATA("-C",		   XrmoptionNoArg),
    #endif /* TIOCCONS */
    	DATA("-S",		   XrmoptionStickyArg),
    	DATA("-D",		   XrmoptionNoArg),
        };
    #undef DATA
        /* *INDENT-ON* */
    
        XrmOptionDescRec *result = 0;
        Cardinal inlist;
        Cardinal limit = XtNumber(optionDescList) + XtNumber(opTable);
        int atbest = -1;
        int best = -1;
        int test;
        Boolean exact = False;
        int ambiguous1 = -1;
        int ambiguous2 = -1;
        char *option;
        char *value;
    
    #define ITEM(n) ((Cardinal)(n) < XtNumber(optionDescList) \
    		 ? &optionDescList[n] \
    		 : &opTable[(Cardinal)(n) - XtNumber(optionDescList)])
    
        if ((option = argv[*num]) != 0) {
    	Boolean need_value;
    	Boolean have_value = False;
    
    	TRACE(("parseArg %s\n", option));
    	if ((value = argv[(*num) + 1]) != 0) {
    	    have_value = (Boolean) !isOption(value);
    	}
    	for (inlist = 0; inlist < limit; ++inlist) {
    	    XrmOptionDescRec *check = ITEM(inlist);
    
    	    test = matchArg(check, option);
    	    if (test < 0)
    		continue;
    
    	    /* check for exact match */
    	    if ((test + 1) == (int) strlen(check->option)) {
    		if (check->argKind == XrmoptionStickyArg) {
    		    if (strlen(option) > strlen(check->option)) {
    			exact = True;
    			atbest = (int) inlist;
    			break;
    		    }
    		} else if ((test + 1) == (int) strlen(option)) {
    		    exact = True;
    		    atbest = (int) inlist;
    		    break;
    		}
    	    }
    
    	    need_value = (Boolean) (test > 0 && countArg(check) > 0);
    
    	    if (need_value && value != 0) {
    		;
    	    } else if (need_value ^ have_value) {
    		TRACE(("...skipping, need %d vs have %d\n", need_value, have_value));
    		continue;
    	    }
    
    	    /* special-case for our own options - always allow abbreviation */
    	    if (test > 0
    		&& ITEM(inlist)->argKind >= XrmoptionSkipArg) {
    		atbest = (int) inlist;
    		if (ITEM(inlist)->argKind == XrmoptionSkipNArgs) {
    		    /* in particular, silence a warning about ambiguity */
    		    exact = 1;
    		}
    		break;
    	    }
    	    if (test > best) {
    		best = test;
    		atbest = (int) inlist;
    	    } else if (test == best) {
    		if (atbest >= 0) {
    		    if (atbest > 0) {
    			ambiguous1 = (int) inlist;
    			ambiguous2 = (int) atbest;
    		    }
    		    atbest = -1;
    		}
    	    }
    	}
        }
    
        *valuep = 0;
        if (atbest >= 0) {
    	result = ITEM(atbest);
    	if (!exact) {
    	    if (ambiguous1 >= 0 && ambiguous2 >= 0) {
    		xtermWarning("ambiguous option \"%s\" vs \"%s\"\n",
    			     ITEM(ambiguous1)->option,
    			     ITEM(ambiguous2)->option);
    	    } else if (strlen(option) > strlen(result->option)) {
    		result = 0;
    	    }
    	}
    	if (result != 0) {
    	    TRACE(("...result %s\n", result->option));
    	    /* expand abbreviations */
    	    if (result->argKind != XrmoptionStickyArg) {
    		if (strcmp(argv[*num], result->option)) {
    		    argv[*num] = x_strdup(result->option);
    		}
    	    }
    
    	    /* adjust (*num) to skip option value */
    	    (*num) += countArg(result);
    	    TRACE(("...next %s\n", NonNull(argv[*num])));
    	    if (result->argKind == XrmoptionSkipArg) {
    		*valuep = argv[*num];
    		TRACE(("...parameter %s\n", NonNull(*valuep)));
    	    }
    	}
        }
    #undef ITEM
        return result;
    }
    
    static void
    Syntax(char *badOption)
    {
        OptionHelp *opt;
        OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList));
        int col;
    
        TRACE(("Syntax error at %s\n", badOption));
        xtermWarning("bad command line option \"%s\"\r\n\n", badOption);
    
        fprintf(stderr, "usage:  %s", ProgramName);
        col = 8 + (int) strlen(ProgramName);
        for (opt = list; opt->opt; opt++) {
    	int len = 3 + (int) strlen(opt->opt);	/* space [ string ] */
    	if (col + len > 79) {
    	    fprintf(stderr, "\r\n   ");		/* 3 spaces */
    	    col = 3;
    	}
    	fprintf(stderr, " [%s]", opt->opt);
    	col += len;
        }
    
        fprintf(stderr, "\r\n\nType %s -help for a full description.\r\n\n",
    	    ProgramName);
        exit(1);
    }
    
    static void
    Version(void)
    {
        printf("%s\n", xtermVersion());
        fflush(stdout);
    }
    
    static void
    Help(void)
    {
        OptionHelp *opt;
        OptionHelp *list = sortedOpts(xtermOptions, optionDescList, XtNumber(optionDescList));
        const char *const *cpp;
    
        printf("%s usage:\n    %s [-options ...] [-e command args]\n\n",
    	   xtermVersion(), ProgramName);
        printf("where options include:\n");
        for (opt = list; opt->opt; opt++) {
    	printf("    %-28s %s\n", opt->opt, opt->desc);
        }
    
        putchar('\n');
        for (cpp = message; *cpp; cpp++)
    	puts(*cpp);
        putchar('\n');
        fflush(stdout);
    }
    
    static void
    NeedParam(XrmOptionDescRec * option_ptr, const char *option_val)
    {
        if (IsEmpty(option_val)) {
    	xtermWarning("option %s requires a value\n", option_ptr->option);
    	exit(1);
        }
    }
    
    #if defined(TIOCCONS) || defined(SRIOCSREDIR)
    /* ARGSUSED */
    static Boolean
    ConvertConsoleSelection(Widget w GCC_UNUSED,
    			Atom *selection GCC_UNUSED,
    			Atom *target GCC_UNUSED,
    			Atom *type GCC_UNUSED,
    			XtPointer *value GCC_UNUSED,
    			unsigned long *length GCC_UNUSED,
    			int *format GCC_UNUSED)
    {
        /* we don't save console output, so can't offer it */
        return False;
    }
    #endif /* TIOCCONS */
    
    /*
     * DeleteWindow(): Action proc to implement ICCCM delete_window.
     */
    /* ARGSUSED */
    static void
    DeleteWindow(Widget w,
    	     XEvent *event GCC_UNUSED,
    	     String *params GCC_UNUSED,
    	     Cardinal *num_params GCC_UNUSED)
    {
    #if OPT_TEK4014
        if (w == toplevel) {
    	if (TEK4014_SHOWN(term))
    	    hide_vt_window();
    	else
    	    do_hangup(w, (XtPointer) 0, (XtPointer) 0);
        } else if (TScreenOf(term)->Vshow)
    	hide_tek_window();
        else
    #endif
    	do_hangup(w, (XtPointer) 0, (XtPointer) 0);
    }
    
    /* ARGSUSED */
    static void
    KeyboardMapping(Widget w GCC_UNUSED,
    		XEvent *event,
    		String *params GCC_UNUSED,
    		Cardinal *num_params GCC_UNUSED)
    {
        switch (event->type) {
        case MappingNotify:
    	XRefreshKeyboardMapping(&event->xmapping);
    	break;
        }
    }
    
    static XtActionsRec actionProcs[] =
    {
        {"DeleteWindow", DeleteWindow},
        {"KeyboardMapping", KeyboardMapping},
    };
    
    /*
     * Some platforms use names such as /dev/tty01, others /dev/pts/1.  Parse off
     * the "tty01" or "pts/1" portion, and return that for use as an identifier for
     * utmp.
     */
    static char *
    my_pty_name(char *device)
    {
        size_t len = strlen(device);
        Bool name = False;
    
        while (len != 0) {
    	int ch = device[len - 1];
    	if (isdigit(ch)) {
    	    len--;
    	} else if (ch == '/') {
    	    if (name)
    		break;
    	    len--;
    	} else if (isalpha(ch)) {
    	    name = True;
    	    len--;
    	} else {
    	    break;
    	}
        }
        TRACE(("my_pty_name(%s) -> '%s'\n", device, device + len));
        return device + len;
    }
    
    /*
     * If the name contains a '/', it is a "pts/1" case.  Otherwise, return the
     * last few characters for a utmp identifier.
     */
    static char *
    my_pty_id(char *device)
    {
        char *name = my_pty_name(device);
        char *leaf = x_basename(name);
    
        if (name == leaf) {		/* no '/' in the name */
    	int len = (int) strlen(leaf);
    	if (PTYCHARLEN < len)
    	    leaf = leaf + (len - PTYCHARLEN);
        }
        TRACE(("my_pty_id  (%s) -> '%s'\n", device, leaf));
        return leaf;
    }
    
    /*
     * Set the tty/pty identifier
     */
    static void
    set_pty_id(char *device, char *id)
    {
        char *name = my_pty_name(device);
        char *leaf = x_basename(name);
    
        if (name == leaf) {
    	strcpy(my_pty_id(device), id);
        } else {
    	strcpy(leaf, id);
        }
        TRACE(("set_pty_id(%s) -> '%s'\n", id, device));
    }
    
    /*
     * The original -S option accepts two characters to identify the pty, and a
     * file-descriptor (assumed to be nonzero).  That is not general enough, so we
     * check first if the option contains a '/' to delimit the two fields, and if
     * not, fall-thru to the original logic.
     */
    static Bool
    ParseSccn(char *option)
    {
        char *leaf = x_basename(option);
        Bool code = False;
    
        passedPty = x_strdup(option);
        if (leaf != option) {
    	if (leaf - option > 0
    	    && isdigit(CharOf(*leaf))
    	    && sscanf(leaf, "%d", &am_slave) == 1) {
    	    size_t len = (size_t) (leaf - option - 1);
    	    /*
    	     * If we have a slash, we only care about the part after the slash,
    	     * which is a file-descriptor.  The part before the slash can be
    	     * the /dev/pts/XXX value, but since we do not need to reopen it,
    	     * it is useful mainly for display in a "ps -ef".
    	     */
    	    passedPty[len] = 0;
    	    code = True;
    	}
        } else {
    	code = (sscanf(option, "%c%c%d",
    		       passedPty, passedPty + 1, &am_slave) == 3);
    	passedPty[2] = '\0';
        }
        TRACE(("ParseSccn(%s) = '%s' %d (%s)\n", option,
    	   passedPty, am_slave, code ? "OK" : "ERR"));
        return code;
    }
    
    #if defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER)
    /*
     * From "man utmp":
     * xterm and other terminal emulators directly create a USER_PROCESS record
     * and generate the ut_id by using the last two letters of /dev/ttyp%c or by
     * using p%d for /dev/pts/%d.  If they find a DEAD_PROCESS for this id, they
     * recycle it, otherwise they create a new entry.  If they can, they will mark
     * it as DEAD_PROCESS on exiting and it is advised that they null ut_line,
     * ut_time, ut_user and ut_host as well.
     *
     * Generally ut_id allows no more than 3 characters (plus null), even if the
     * pty implementation allows more than 3 digits.
     */
    static char *
    my_utmp_id(char *device)
    {
        typedef struct UTMP_STR UTMP_STRUCT;
    #define	UTIDSIZE	(sizeof(((UTMP_STRUCT *)NULL)->ut_id))
        static char result[UTIDSIZE + 1];
    
    #if defined(__SCO__) || defined(__UNIXWARE__)
        /*
         * Legend does not support old-style pty's, has no related compatibility
         * issues, and can use the available space in ut_id differently from the
         * default convention.
         *
         * This scheme is intended to avoid conflicts both with other users of
         * utmpx as well as between multiple xterms.  First, Legend uses all of the
         * characters of ut_id, and adds no terminating NUL is required (the
         * default scheme may add a trailing NUL).  Second, all xterm entries will
         * start with the letter 'x' followed by three digits, which will be the
         * last three digits of the device name, regardless of the format of the
         * device name, with leading 0's added where necessary.  For instance, an
         * xterm on /dev/pts/3 will have a ut_id of x003; an xterm on /dev/pts123
         * will have a ut_id of x123.  Under the other convention, /dev/pts/3 would
         * have a ut_id of p3 and /dev/pts123 would have a ut_id of p123.
         */
        int len, n;
    
        len = strlen(device);
        n = UTIDSIZE;
        result[n] = '\0';
        while ((n > 0) && (len > 0) && isdigit(device[len - 1]))
    	result[--n] = device[--len];
        while (n > 0)
    	result[--n] = '0';
        result[0] = 'x';
    #else
        char *name = my_pty_name(device);
        char *leaf = x_basename(name);
        size_t len = strlen(leaf);
    
        if ((UTIDSIZE - 1) < len)
    	leaf = leaf + (len - (UTIDSIZE - 1));
        sprintf(result, "p%s", leaf);
    #endif
    
        TRACE(("my_utmp_id (%s) -> '%s'\n", device, result));
        return result;
    }
    #endif /* USE_SYSV_UTMP */
    
    #ifdef USE_POSIX_SIGNALS
    
    typedef void (*sigfunc) (int);
    
    /* make sure we sure we ignore SIGCHLD for the cases parent
       has just been stopped and not actually killed */
    
    static sigfunc
    posix_signal(int signo, sigfunc func)
    {
        struct sigaction act, oact;
    
        act.sa_handler = func;
        sigemptyset(&act.sa_mask);
    #ifdef SA_RESTART
        act.sa_flags = SA_NOCLDSTOP | SA_RESTART;
    #else
        act.sa_flags = SA_NOCLDSTOP;
    #endif
        if (sigaction(signo, &act, &oact) < 0)
    	return (SIG_ERR);
        return (oact.sa_handler);
    }
    
    #endif /* USE_POSIX_SIGNALS */
    
    #if defined(DISABLE_SETUID) || defined(USE_UTMP_SETGID)
    static void
    disableSetUid(void)
    {
        TRACE(("process %d disableSetUid\n", (int) getpid()));
        if (setuid(save_ruid) == -1) {
    	xtermWarning("unable to reset uid\n");
    	exit(1);
        }
        TRACE_IDS;
    }
    #else
    #define disableSetUid()		/* nothing */
    #endif /* DISABLE_SETUID */
    
    #if defined(DISABLE_SETGID) || defined(USE_UTMP_SETGID)
    static void
    disableSetGid(void)
    {
        TRACE(("process %d disableSetGid\n", (int) getpid()));
        if (setegid(save_rgid) == -1) {
    	xtermWarning("unable to reset effective gid\n");
    	exit(1);
        }
        TRACE_IDS;
    }
    #else
    #define disableSetGid()		/* nothing */
    #endif /* DISABLE_SETGID */
    
    #if defined(HAVE_POSIX_SAVED_IDS)
    #if (!defined(USE_UTEMPTER) || !defined(DISABLE_SETGID))
    static void
    setEffectiveGroup(gid_t group)
    {
        TRACE(("process %d setEffectiveGroup(%d)\n", (int) getpid(), (int) group));
        if (setegid(group) == -1) {
    #ifdef __MVS__
    	if (!(errno == EMVSERR))	/* could happen if _BPX_SHAREAS=REUSE */
    #endif
    	{
    	    xtermPerror("setegid(%d)", (int) group);
    	}
        }
        TRACE_IDS;
    }
    #endif
    
    #if !defined(USE_UTMP_SETGID) && (!defined(USE_UTEMPTER) || !defined(DISABLE_SETUID))
    static void
    setEffectiveUser(uid_t user)
    {
        TRACE(("process %d setEffectiveUser(%d)\n", (int) getpid(), (int) user));
        if (seteuid(user) == -1) {
    #ifdef __MVS__
    	if (!(errno == EMVSERR))
    #endif
    	{
    	    xtermPerror("seteuid(%d)", (int) user);
    	}
        }
        TRACE_IDS;
    }
    #endif
    #endif /* HAVE_POSIX_SAVED_IDS */
    
    #if OPT_LUIT_PROG
    static Boolean
    complex_command(char **args)
    {
        Boolean result = False;
        if (x_countargv(args) == 1) {
    	char *check = xtermFindShell(args[0], False);
    	if (check == 0) {
    	    result = True;
    	} else {
    	    free(check);
    	}
        }
        return result;
    }
    #endif
    
    static unsigned
    lookup_baudrate(const char *value)
    {
        struct speed {
    	unsigned given_speed;	/* values for 'ospeed' */
    	unsigned actual_speed;	/* the actual speed */
        };
    
    #define DATA(number) { B##number, number }
    
        static struct speed const speeds[] =
        {
    	DATA(0),
    	DATA(50),
    	DATA(75),
    	DATA(110),
    	DATA(134),
    	DATA(150),
    	DATA(200),
    	DATA(300),
    	DATA(600),
    	DATA(1200),
    	DATA(1800),
    	DATA(2400),
    	DATA(4800),
    	DATA(9600),
    #ifdef B19200
    	DATA(19200),
    #elif defined(EXTA)
    	{EXTA, 19200},
    #endif
    #ifdef B28800
    	DATA(28800),
    #endif
    #ifdef B38400
    	DATA(38400),
    #elif defined(EXTB)
    	{EXTB, 38400},
    #endif
    #ifdef B57600
    	DATA(57600),
    #endif
    #ifdef B76800
    	DATA(76800),
    #endif
    #ifdef B115200
    	DATA(115200),
    #endif
    #ifdef B153600
    	DATA(153600),
    #endif
    #ifdef B230400
    	DATA(230400),
    #endif
    #ifdef B307200
    	DATA(307200),
    #endif
    #ifdef B460800
    	DATA(460800),
    #endif
    #ifdef B500000
    	DATA(500000),
    #endif
    #ifdef B576000
    	DATA(576000),
    #endif
    #ifdef B921600
    	DATA(921600),
    #endif
    #ifdef B1000000
    	DATA(1000000),
    #endif
    #ifdef B1152000
    	DATA(1152000),
    #endif
    #ifdef B1500000
    	DATA(1500000),
    #endif
    #ifdef B2000000
    	DATA(2000000),
    #endif
    #ifdef B2500000
    	DATA(2500000),
    #endif
    #ifdef B3000000
    	DATA(3000000),
    #endif
    #ifdef B3500000
    	DATA(3500000),
    #endif
    #ifdef B4000000
    	DATA(4000000),
    #endif
        };
    #undef DATA
        unsigned result = 0;
        long check;
        char *next;
        if (x_toupper(*value) == 'B')
    	value++;
        if (isdigit(CharOf(*value))) {
    	check = strtol(value, &next, 10);
    	if (FullS2L(value, next) && (check > 0)) {
    	    Cardinal n;
    	    for (n = 0; n < XtNumber(speeds); ++n) {
    		if (speeds[n].actual_speed == (unsigned) check) {
    		    result = speeds[n].given_speed;
    		    break;
    		}
    	    }
    	}
        }
        if (result == 0) {
    	fprintf(stderr, "unsupported value for baudrate: %s\n", value);
        }
        return result;
    }
    
    int
    main(int argc, char *argv[]ENVP_ARG)
    {
    #if OPT_MAXIMIZE
    #define DATA(name) { #name, es##name }
        static const FlagList tblFullscreen[] =
        {
    	DATA(Always),
    	DATA(Never)
        };
    #undef DATA
    #endif
    
        Widget form_top, menu_top;
        Dimension menu_high;
        TScreen *screen;
        int mode;
        char *my_class = x_strdup(DEFCLASS);
        unsigned line_speed = VAL_LINE_SPEED;
        Window winToEmbedInto = None;
    
        ProgramName = argv[0];
    
    #ifdef HAVE_POSIX_SAVED_IDS
        save_euid = geteuid();
        save_egid = getegid();
    #endif
    
        save_ruid = getuid();
        save_rgid = getgid();
    
    #if defined(DISABLE_SETUID) || defined(DISABLE_SETGID)
    #if defined(DISABLE_SETUID)
        disableSetUid();
    #endif
    #if defined(DISABLE_SETGID)
        disableSetGid();
    #endif
        TRACE_IDS;
    #endif
    
        /* extra length in case longer tty name like /dev/ttyq255 */
        ttydev = TypeMallocN(char, sizeof(TTYDEV) + 80);
    #ifdef USE_PTY_DEVICE
        ptydev = TypeMallocN(char, sizeof(PTYDEV) + 80);
        if (!ttydev || !ptydev)
    #else
        if (!ttydev)
    #endif
        {
    	xtermWarning("unable to allocate memory for ttydev or ptydev\n");
    	exit(1);
        }
        strcpy(ttydev, TTYDEV);
    #ifdef USE_PTY_DEVICE
        strcpy(ptydev, PTYDEV);
    #endif
    
    #if defined(USE_UTMP_SETGID)
        get_pty(NULL, NULL);
        disableSetUid();
        disableSetGid();
        TRACE_IDS;
    #define get_pty(pty, from) really_get_pty(pty, from)
    #endif
    
        /* Do these first, since we may not be able to open the display */
        TRACE_OPTS(xtermOptions, optionDescList, XtNumber(optionDescList));
        TRACE_ARGV("Before XtOpenApplication", argv);
        if (argc > 1) {
    	XrmOptionDescRec *option_ptr;
    	char *option_value;
    	int n;
    	Bool quit = False;
    
    	for (n = 1; n < argc; n++) {
    	    if ((option_ptr = parseArg(&n, argv, &option_value)) == 0) {
    		if (argv[n] == 0) {
    		    break;
    		} else if (isOption(argv[n])) {
    		    Syntax(argv[n]);
    		} else if (explicit_shname != 0) {
    		    xtermWarning("Explicit shell already was %s\n", explicit_shname);
    		    Syntax(argv[n]);
    		}
    		explicit_shname = xtermFindShell(argv[n], True);
    		if (explicit_shname == 0)
    		    exit(0);
    		TRACE(("...explicit shell %s\n", explicit_shname));
    	    } else if (!strcmp(option_ptr->option, "-e")) {
    		command_to_exec = (argv + n + 1);
    		if (!command_to_exec[0])
    		    Syntax(argv[n]);
    		break;
    	    } else if (!strcmp(option_ptr->option, "-version")) {
    		Version();
    		quit = True;
    	    } else if (!strcmp(option_ptr->option, "-help")) {
    		Help();
    		quit = True;
    	    } else if (!strcmp(option_ptr->option, "-baudrate")) {
    		NeedParam(option_ptr, option_value);
    		if ((line_speed = lookup_baudrate(option_value)) == 0) {
    		    Help();
    		    quit = True;
    		}
    	    } else if (!strcmp(option_ptr->option, "-class")) {
    		NeedParam(option_ptr, option_value);
    		free(my_class);
    		if ((my_class = x_strdup(option_value)) == 0) {
    		    Help();
    		    quit = True;
    		}
    	    } else if (!strcmp(option_ptr->option, "-into")) {
    		char *endPtr;
    		NeedParam(option_ptr, option_value);
    		winToEmbedInto = (Window) strtol(option_value, &endPtr, 0);
    		if (!FullS2L(option_value, endPtr)) {
    		    Help();
    		    quit = True;
    		}
    	    }
    	}
    	if (quit)
    	    exit(0);
    	/*
    	 * If there is anything left unparsed, and we're not using "-e",
    	 * then give up.
    	 */
    	if (n < argc && !command_to_exec) {
    	    Syntax(argv[n]);
    	}
        }
    
        /* This dumped core on HP-UX 9.05 with X11R5 */
    #if OPT_I18N_SUPPORT
        XtSetLanguageProc(NULL, NULL, NULL);
    #endif
    
    #ifdef TERMIO_STRUCT		/* { */
        /* Initialization is done here rather than above in order
         * to prevent any assumptions about the order of the contents
         * of the various terminal structures (which may change from
         * implementation to implementation).
         */
        memset(&d_tio, 0, sizeof(d_tio));
        d_tio.c_iflag = ICRNL | IXON;
        d_tio.c_oflag = TAB3 | D_TIO_FLAGS;
        {
    	Cardinal nn;
    
    	/* fill in default-values */
    	for (nn = 0; nn < XtNumber(ttyChars); ++nn) {
    	    if (validTtyChar(d_tio, nn)) {
    		d_tio.c_cc[ttyChars[nn].sysMode] =
    		    (cc_t) ttyChars[nn].myDefault;
    	    }
    	}
        }
    #if defined(macII) || defined(ATT) || defined(CRAY)	/* { */
        d_tio.c_cflag = line_speed | CS8 | CREAD | PARENB | HUPCL;
        d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;
    #ifdef ECHOKE
        d_tio.c_lflag |= ECHOKE | IEXTEN;
    #endif
    #ifdef ECHOCTL
        d_tio.c_lflag |= ECHOCTL | IEXTEN;
    #endif
    #ifndef USE_TERMIOS		/* { */
        d_tio.c_line = 0;
    #endif /* } */
    #ifdef HAS_LTCHARS		/* { */
        d_ltc.t_suspc = CSUSP;	/* t_suspc */
        d_ltc.t_dsuspc = CDSUSP;	/* t_dsuspc */
        d_ltc.t_rprntc = CRPRNT;
        d_ltc.t_flushc = CFLUSH;
        d_ltc.t_werasc = CWERASE;
        d_ltc.t_lnextc = CLNEXT;
    #endif /* } HAS_LTCHARS */
    #ifdef TIOCLSET			/* { */
        d_lmode = 0;
    #endif /* } TIOCLSET */
    #else /* }{ else !macII, ATT, CRAY */
    #ifndef USE_POSIX_TERMIOS
    #ifdef BAUD_0			/* { */
        d_tio.c_cflag = CS8 | CREAD | PARENB | HUPCL;
    #else /* }{ !BAUD_0 */
        d_tio.c_cflag = line_speed | CS8 | CREAD | PARENB | HUPCL;
    #endif /* } !BAUD_0 */
    #else /* USE_POSIX_TERMIOS */
        d_tio.c_cflag = CS8 | CREAD | PARENB | HUPCL;
        cfsetispeed(&d_tio, line_speed);
        cfsetospeed(&d_tio, line_speed);
    #endif
        d_tio.c_lflag = ISIG | ICANON | ECHO | ECHOE | ECHOK;
    #ifdef ECHOKE
        d_tio.c_lflag |= ECHOKE | IEXTEN;
    #endif
    #ifdef ECHOCTL
        d_tio.c_lflag |= ECHOCTL | IEXTEN;
    #endif
    #ifndef USE_POSIX_TERMIOS
    #ifdef NTTYDISC
        d_tio.c_line = NTTYDISC;
    #else
        d_tio.c_line = 0;
    #endif
    #endif /* USE_POSIX_TERMIOS */
    #ifdef __sgi
        d_tio.c_cflag &= ~(HUPCL | PARENB);
        d_tio.c_iflag |= BRKINT | ISTRIP | IGNPAR;
    #endif
    #ifdef __MVS__
        d_tio.c_cflag &= ~(HUPCL | PARENB);
    #endif
        {
    	Cardinal nn;
    	int i;
    
    	/* try to inherit tty settings */
    	for (i = 0; i <= 2; i++) {
    	    TERMIO_STRUCT deftio;
    	    if (ttyGetAttr(i, &deftio) == 0) {
    		for (nn = 0; nn < XtNumber(ttyChars); ++nn) {
    		    if (validTtyChar(d_tio, nn)) {
    			d_tio.c_cc[ttyChars[nn].sysMode] =
    			    deftio.c_cc[ttyChars[nn].sysMode];
    		    }
    		}
    		break;
    	    }
    	}
        }
    #if defined(USE_TERMIOS) || defined(USE_POSIX_TERMIOS)	/* { */
        d_tio.c_cc[VMIN] = 1;
        d_tio.c_cc[VTIME] = 0;
    #endif /* } */
    #ifdef HAS_LTCHARS		/* { */
        d_ltc.t_suspc = CharOf('\000');	/* t_suspc */
        d_ltc.t_dsuspc = CharOf('\000');	/* t_dsuspc */
        d_ltc.t_rprntc = CharOf('\377');	/* reserved... */
        d_ltc.t_flushc = CharOf('\377');
        d_ltc.t_werasc = CharOf('\377');
        d_ltc.t_lnextc = CharOf('\377');
    #endif /* } HAS_LTCHARS */
    
    #ifdef TIOCLSET			/* { */
        d_lmode = 0;
    #endif /* } TIOCLSET */
    #endif /* } macII, ATT, CRAY */
    #endif /* } TERMIO_STRUCT */
    
        /* Init the Toolkit. */
        {
    #if defined(HAVE_POSIX_SAVED_IDS) && !defined(USE_UTMP_SETGID) && !defined(USE_UTEMPTER)
    	setEffectiveGroup(save_rgid);
    	setEffectiveUser(save_ruid);
    	TRACE_IDS;
    #endif
    	toplevel = xtermOpenApplication(&app_con,
    					my_class,
    					optionDescList,
    					XtNumber(optionDescList),
    					&argc, argv,
    					fallback_resources,
    					sessionShellWidgetClass,
    					NULL, 0);
    
    	XtGetApplicationResources(toplevel, (XtPointer) &resource,
    				  application_resources,
    				  XtNumber(application_resources), NULL, 0);
    	TRACE_XRES();
    #if USE_DOUBLE_BUFFER
    	if (resource.buffered_fps <= 0)
    	    resource.buffered_fps = DEF_BUFFER_RATE;
    	if (resource.buffered_fps > 100)
    	    resource.buffered_fps = 100;
    #endif
    #if OPT_MAXIMIZE
    	resource.fullscreen = extendedBoolean(resource.fullscreen_s,
    					      tblFullscreen,
    					      esLAST);
    #endif
    	VTInitTranslations();
    #if OPT_PTY_HANDSHAKE
    	resource.wait_for_map0 = resource.wait_for_map;
    #endif
    
    #if defined(HAVE_POSIX_SAVED_IDS) && !defined(USE_UTMP_SETGID)
    #if !defined(DISABLE_SETUID) || !defined(DISABLE_SETGID)
    #if !defined(DISABLE_SETUID)
    	setEffectiveUser(save_euid);
    #endif
    #if !defined(DISABLE_SETGID)
    	setEffectiveGroup(save_egid);
    #endif
    	TRACE_IDS;
    #endif
    #endif
        }
    
        /*
         * ICCCM delete_window.
         */
        XtAppAddActions(app_con, actionProcs, XtNumber(actionProcs));
    
        /*
         * fill in terminal modes
         */
        if (resource.tty_modes) {
    	int n = parse_tty_modes(resource.tty_modes);
    	if (n < 0) {
    	    xtermWarning("bad tty modes \"%s\"\n", resource.tty_modes);
    	} else if (n > 0) {
    	    override_tty_modes = True;
    	}
        }
        initZIconBeep();
        hold_screen = resource.hold_screen ? 1 : 0;
        if (resource.icon_geometry != NULL) {
    	int scr, junk;
    	int ix, iy;
    	Arg args[2];
    
    	for (scr = 0;		/* yyuucchh */
    	     XtScreen(toplevel) != ScreenOfDisplay(XtDisplay(toplevel), scr);
    	     scr++) ;
    
    	args[0].name = XtNiconX;
    	args[1].name = XtNiconY;
    	XGeometry(XtDisplay(toplevel), scr, resource.icon_geometry, "",
    		  0, 0, 0, 0, 0, &ix, &iy, &junk, &junk);
    	args[0].value = (XtArgVal) ix;
    	args[1].value = (XtArgVal) iy;
    	XtSetValues(toplevel, args, 2);
        }
    
        XtSetValues(toplevel, ourTopLevelShellArgs,
    		number_ourTopLevelShellArgs);
    
    #if OPT_WIDE_CHARS
        /* seems as good a place as any */
        init_classtab();
    #endif
    
        /* Parse the rest of the command line */
        TRACE_ARGV("After XtOpenApplication", argv);
        for (argc--, argv++; argc > 0; argc--, argv++) {
    	if (!isOption(*argv)) {
    #ifdef VMS
    	    Syntax(*argv);
    #else
    	    if (argc > 1)
    		Syntax(*argv);
    	    continue;
    #endif
    	}
    
    	TRACE(("parsing %s\n", argv[0]));
    	switch (argv[0][1]) {
    	case 'C':
    #if defined(TIOCCONS) || defined(SRIOCSREDIR)
    #ifndef __sgi
    	    {
    		struct stat sbuf;
    
    		/* Must be owner and have read/write permission.
    		   xdm cooperates to give the console the right user. */
    		if (!stat("/dev/console", &sbuf) &&
    		    (sbuf.st_uid == save_ruid) &&
    		    !access("/dev/console", R_OK | W_OK)) {
    		    Console = True;
    		} else
    		    Console = False;
    	    }
    #else /* __sgi */
    	    Console = True;
    #endif /* __sgi */
    #endif /* TIOCCONS */
    	    continue;
    	case 'S':
    	    if (!ParseSccn(*argv + 2))
    		Syntax(*argv);
    	    continue;
    #ifdef DEBUG
    	case 'D':
    	    debug = True;
    	    continue;
    #endif /* DEBUG */
    	case 'b':
    	    if (strcmp(argv[0], "-baudrate"))
    		Syntax(*argv);
    	    argc--, argv++;
    	    continue;
    	case 'c':
    	    if (strcmp(argv[0], "-class"))
    		Syntax(*argv);
    	    argc--, argv++;
    	    continue;
    	case 'e':
    	    if (strcmp(argv[0], "-e"))
    		Syntax(*argv);
    	    command_to_exec = (argv + 1);
    	    break;
    	case 'i':
    	    if (strcmp(argv[0], "-into"))
    		Syntax(*argv);
    	    argc--, argv++;
    	    continue;
    
    	default:
    	    Syntax(*argv);
    	}
    	break;
        }
    
        SetupMenus(toplevel, &form_top, &menu_top, &menu_high);
    
        term = (XtermWidget) XtVaCreateManagedWidget("vt100", xtermWidgetClass,
    						 form_top,
    #if OPT_TOOLBAR
    						 XtNmenuBar, menu_top,
    						 XtNresizable, True,
    						 XtNfromVert, menu_top,
    						 XtNleft, XawChainLeft,
    						 XtNright, XawChainRight,
    						 XtNtop, XawChainTop,
    						 XtNbottom, XawChainBottom,
    						 XtNmenuHeight, menu_high,
    #endif
    						 (XtPointer) 0);
        decode_keyboard_type(term, &resource);
    
        screen = TScreenOf(term);
        screen->inhibit = 0;
    
    #ifdef ALLOWLOGGING
        if (term->misc.logInhibit)
    	screen->inhibit |= I_LOG;
    #endif
        if (term->misc.signalInhibit)
    	screen->inhibit |= I_SIGNAL;
    #if OPT_TEK4014
        if (term->misc.tekInhibit)
    	screen->inhibit |= I_TEK;
    #endif
    
        /*
         * We might start by showing the tek4014 window.
         */
    #if OPT_TEK4014
        if (screen->inhibit & I_TEK)
    	TEK4014_ACTIVE(term) = False;
    
        if (TEK4014_ACTIVE(term) && !TekInit())
    	SysError(ERROR_INIT);
    #endif
    
        /*
         * Start the toolbar at this point, after the first window has been setup.
         */
    #if OPT_TOOLBAR
        ShowToolbar(resource.toolBar);
    #endif
    
        xtermOpenSession();
    
        /*
         * Set title and icon name if not specified
         */
        if (command_to_exec) {
    	Arg args[2];
    
    	if (!resource.title) {
    	    if (command_to_exec) {
    		resource.title = x_basename(command_to_exec[0]);
    	    }			/* else not reached */
    	}
    
    	if (!resource.icon_name)
    	    resource.icon_name = resource.title;
    	XtSetArg(args[0], XtNtitle, resource.title);
    	XtSetArg(args[1], XtNiconName, resource.icon_name);
    
    	TRACE(("setting:\n\ttitle \"%s\"\n\ticon \"%s\"\n\thint \"%s\"\n\tbased on command \"%s\"\n",
    	       resource.title,
    	       resource.icon_name,
    	       NonNull(resource.icon_hint),
    	       *command_to_exec));
    
    	XtSetValues(toplevel, args, 2);
        }
    #if OPT_LUIT_PROG
        if (term->misc.callfilter) {
    	char **split_filter = x_splitargs(term->misc.localefilter);
    	unsigned count_split = x_countargv(split_filter);
    	unsigned count_exec = x_countargv(command_to_exec);
    	unsigned count_using = (unsigned) (term->misc.use_encoding ? 2 : 0);
    
    	command_to_exec_with_luit = TypeCallocN(char *,
    						  (count_split
    						   + count_exec
    						   + count_using
    						   + 8));
    	if (command_to_exec_with_luit == NULL)
    	    SysError(ERROR_LUMALLOC);
    
    	x_appendargv(command_to_exec_with_luit, split_filter);
    	if (count_using) {
    	    char *encoding_opt[4];
    	    encoding_opt[0] = x_strdup("-encoding");
    	    encoding_opt[1] = term->misc.locale_str;
    	    encoding_opt[2] = 0;
    	    x_appendargv(command_to_exec_with_luit, encoding_opt);
    	}
    	command_length_with_luit = x_countargv(command_to_exec_with_luit);
    	if (count_exec) {
    	    static char *fixup_shell[] =
    	    {(char *) "sh", (char *) "-c", 0};
    	    char *delimiter[2];
    	    delimiter[0] = x_strdup("--");
    	    delimiter[1] = 0;
    	    x_appendargv(command_to_exec_with_luit, delimiter);
    	    if (complex_command(command_to_exec)) {
    		x_appendargv(command_to_exec_with_luit, fixup_shell);
    	    }
    	    x_appendargv(command_to_exec_with_luit, command_to_exec);
    	}
    	TRACE_ARGV("luit command", command_to_exec_with_luit);
    	xtermSetenv("XTERM_FILTER", *command_to_exec_with_luit);
        }
    #endif
    
        if_DEBUG({
    	/* Set up stderr properly.  Opening this log file cannot be
    	   done securely by a privileged xterm process (although we try),
    	   so the debug feature is disabled by default. */
    	char dbglogfile[TIMESTAMP_LEN + 20];
    	int i = -1;
    	timestamp_filename(dbglogfile, "xterm.debug.log.");
    	if (creat_as(save_ruid, save_rgid, False, dbglogfile, 0600) > 0) {
    	    i = open(dbglogfile, O_WRONLY | O_TRUNC);
    	}
    	if (i >= 0) {
    	    dup2(i, 2);
    
    	    /* mark this file as close on exec */
    	    (void) fcntl(i, F_SETFD, 1);
    	}
        });
    
        spawnXTerm(term, line_speed);
    
    #ifndef VMS
        /* Child process is out there, let's catch its termination */
    
    #ifdef USE_POSIX_SIGNALS
        (void) posix_signal(SIGCHLD, reapchild);
    #else
        (void) signal(SIGCHLD, reapchild);
    #endif
        /* Realize procs have now been executed */
    
        if (am_slave >= 0) {	/* Write window id so master end can read and use */
    	char buf[80];
    
    	buf[0] = '\0';
    	sprintf(buf, "%lx\n", XtWindow(SHELL_OF(CURRENT_EMU())));
    	IGNORE_RC(write(screen->respond, buf, strlen(buf)));
        }
    #ifdef AIXV3
    #if (OSMAJORVERSION < 4)
        /* In AIXV3, xterms started from /dev/console have CLOCAL set.
         * This means we need to clear CLOCAL so that SIGHUP gets sent
         * to the slave-pty process when xterm exits.
         */
    
        {
    	TERMIO_STRUCT tio;
    
    	if (ttyGetAttr(screen->respond, &tio) == -1)
    	    SysError(ERROR_TIOCGETP);
    
    	tio.c_cflag &= ~(CLOCAL);
    
    	if (ttySetAttr(screen->respond, &tio) == -1)
    	    SysError(ERROR_TIOCSETP);
        }
    #endif
    #endif
    #if defined(USE_ANY_SYSV_TERMIO) || defined(__MVS__) || defined(__minix)
        if (0 > (mode = fcntl(screen->respond, F_GETFL, 0)))
    	SysError(ERROR_F_GETFL);
    #ifdef O_NDELAY
        mode |= O_NDELAY;
    #else
        mode |= O_NONBLOCK;
    #endif /* O_NDELAY */
        if (fcntl(screen->respond, F_SETFL, mode))
    	SysError(ERROR_F_SETFL);
    #else /* !USE_ANY_SYSV_TERMIO */
        mode = 1;
        if (ioctl(screen->respond, FIONBIO, (char *) &mode) == -1)
    	SysError(ERROR_FIONBIO);
    #endif /* USE_ANY_SYSV_TERMIO, etc */
    
        /* The erase character is used to delete the current completion */
    #if OPT_DABBREV
    #ifdef TERMIO_STRUCT
        screen->dabbrev_erase_char = d_tio.c_cc[VERASE];
    #else
        screen->dabbrev_erase_char = d_sg.sg_erase;
    #endif
        TRACE(("set dabbrev erase_char %#x\n", screen->dabbrev_erase_char));
    #endif
    
        FD_ZERO(&pty_mask);
        FD_ZERO(&X_mask);
        FD_ZERO(&Select_mask);
        FD_SET(screen->respond, &pty_mask);
        FD_SET(ConnectionNumber(screen->display), &X_mask);
        FD_SET(screen->respond, &Select_mask);
        FD_SET(ConnectionNumber(screen->display), &Select_mask);
        max_plus1 = ((screen->respond < ConnectionNumber(screen->display))
    		 ? (1 + ConnectionNumber(screen->display))
    		 : (1 + screen->respond));
    
    #endif /* !VMS */
        if_DEBUG({
    	TRACE(("debugging on pid %d\n", (int) getpid()));
        });
        XSetErrorHandler(xerror);
        XSetIOErrorHandler(xioerror);
    #if OPT_SESSION_MGT
        IceSetIOErrorHandler(ice_error);
    #endif
    
        initPtyData(&VTbuffer);
    #ifdef ALLOWLOGGING
        if (term->misc.log_on) {
    	StartLog(term);
        }
    #endif
    
        xtermEmbedWindow(winToEmbedInto);
    #if OPT_COLOR_RES
        TRACE(("checking reverseVideo before rv %s fg %s, bg %s\n",
    	   term->misc.re_verse0 ? "reverse" : "normal",
    	   NonNull(TScreenOf(term)->Tcolors[TEXT_FG].resource),
    	   NonNull(TScreenOf(term)->Tcolors[TEXT_BG].resource)));
    
        if (term->misc.re_verse0) {
    	if (isDefaultForeground(TScreenOf(term)->Tcolors[TEXT_FG].resource)
    	    && isDefaultBackground(TScreenOf(term)->Tcolors[TEXT_BG].resource)) {
    	    TScreenOf(term)->Tcolors[TEXT_FG].resource = x_strdup(XtDefaultBackground);
    	    TScreenOf(term)->Tcolors[TEXT_BG].resource = x_strdup(XtDefaultForeground);
    	} else {
    	    ReverseVideo(term);
    	}
    	term->misc.re_verse = True;
    	update_reversevideo();
    	TRACE(("updated  reverseVideo after  rv %s fg %s, bg %s\n",
    	       term->misc.re_verse ? "reverse" : "normal",
    	       NonNull(TScreenOf(term)->Tcolors[TEXT_FG].resource),
    	       NonNull(TScreenOf(term)->Tcolors[TEXT_BG].resource)));
        }
    #endif /* OPT_COLOR_RES */
    
    #if OPT_MAXIMIZE
        if (resource.maximized)
    	RequestMaximize(term, True);
    #endif
        for (;;) {
    #if OPT_TEK4014
    	if (TEK4014_ACTIVE(term))
    	    TekRun();
    	else
    #endif
    	    VTRun(term);
        }
    }
    
    #if defined(__osf__) || (defined(__GLIBC__) && !defined(USE_USG_PTYS)) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)
    #define USE_OPENPTY 1
    static int opened_tty = -1;
    #endif
    
    /*
     * This function opens up a pty master and stuffs its value into pty.
     *
     * If it finds one, it returns a value of 0.  If it does not find one,
     * it returns a value of !0.  This routine is designed to be re-entrant,
     * so that if a pty master is found and later, we find that the slave
     * has problems, we can re-enter this function and get another one.
     */
    static int
    get_pty(int *pty, char *from GCC_UNUSED)
    {
        int result = 1;
    
    #if defined(USE_OPENPTY)
        result = openpty(pty, &opened_tty, ttydev, NULL, NULL);
        if (opened_tty >= 0) {
    	close(opened_tty);
    	opened_tty = -1;
        }
    #elif defined(HAVE_POSIX_OPENPT) && defined(HAVE_PTSNAME) && defined(HAVE_GRANTPT_PTY_ISATTY)
        if ((*pty = posix_openpt(O_RDWR)) >= 0) {
    	char *name = ptsname(*pty);
    	if (name != 0) {
    	    strcpy(ttydev, name);
    	    result = 0;
    	}
        }
    #ifdef USE_PTY_SEARCH
        if (result) {
    	result = pty_search(pty);
        }
    #endif
    #elif defined(PUCC_PTYD)
        result = ((*pty = openrpty(ttydev, ptydev,
    			       (resource.utmpInhibit ? OPTY_NOP : OPTY_LOGIN),
    			       save_ruid, from)) < 0);
    #elif defined(__QNXNTO__)
        result = pty_search(pty);
    #else
    #if defined(USE_USG_PTYS) || defined(__CYGWIN__)
    #if defined(__MVS__)
        result = pty_search(pty);
    #else
        result = ((*pty = open("/dev/ptmx", O_RDWR)) < 0);
    #endif
    #if defined(SVR4) || defined(__SCO__)
        if (!result)
    	strcpy(ttydev, ptsname(*pty));
    #endif
    
    #elif defined(AIXV3)
    
        if ((*pty = open("/dev/ptc", O_RDWR)) >= 0) {
    	strcpy(ttydev, ttyname(*pty));
    	result = 0;
        }
    #elif defined(__convex__)
    
        char *pty_name;
        extern char *getpty(void);
    
        while ((pty_name = getpty()) != NULL) {
    	if ((*pty = open(pty_name, O_RDWR)) >= 0) {
    	    strcpy(ptydev, pty_name);
    	    strcpy(ttydev, pty_name);
    	    *x_basename(ttydev) = 't';
    	    result = 0;
    	    break;
    	}
        }
    
    #elif defined(sequent)
    
        result = ((*pty = getpseudotty(&ttydev, &ptydev)) < 0);
    
    #elif defined(__sgi) && (OSMAJORVERSION >= 4)
    
        char *tty_name;
    
        tty_name = _getpty(pty, O_RDWR, 0622, 0);
        if (tty_name != 0) {
    	strcpy(ttydev, tty_name);
    	result = 0;
        }
    #elif (defined(__sgi) && (OSMAJORVERSION < 4)) || (defined(umips) && defined (SYSTYPE_SYSV))
    
        struct stat fstat_buf;
    
        *pty = open("/dev/ptc", O_RDWR);
        if (*pty >= 0 && (fstat(*pty, &fstat_buf)) >= 0) {
    	result = 0;
    	sprintf(ttydev, "/dev/ttyq%d", minor(fstat_buf.st_rdev));
        }
    #elif defined(__hpux)
    
        /*
         * Use the clone device if it works, otherwise use pty_search logic.
         */
        if ((*pty = open("/dev/ptym/clone", O_RDWR)) >= 0) {
    	char *name = ptsname(*pty);
    	if (name != 0) {
    	    strcpy(ttydev, name);
    	    result = 0;
    	} else {		/* permissions, or other unexpected problem */
    	    close(*pty);
    	    *pty = -1;
    	    result = pty_search(pty);
    	}
        } else {
    	result = pty_search(pty);
        }
    
    #else
    
        result = pty_search(pty);
    
    #endif
    #endif
    
        TRACE(("get_pty(ttydev=%s, ptydev=%s) %s fd=%d\n",
    	   ttydev != 0 ? ttydev : "?",
    	   ptydev != 0 ? ptydev : "?",
    	   result ? "FAIL" : "OK",
    	   pty != 0 ? *pty : -1));
        return result;
    }
    
    static void
    set_pty_permissions(uid_t uid, unsigned gid, unsigned mode)
    {
    #ifdef USE_TTY_GROUP
        struct group *ttygrp;
    
        if ((ttygrp = getgrnam(TTY_GROUP_NAME)) != 0) {
    	gid = (unsigned) ttygrp->gr_gid;
    	mode &= 0660U;
        }
        endgrent();
    #endif /* USE_TTY_GROUP */
    
        TRACE_IDS;
        set_owner(ttydev, (unsigned) uid, gid, mode);
    }
    
    #ifdef get_pty			/* USE_UTMP_SETGID */
    #undef get_pty
    /*
     * Call the real get_pty() before relinquishing root-setuid, caching the
     * result.
     */
    static int
    get_pty(int *pty, char *from)
    {
        static int m_pty = -1;
        int result = -1;
    
        if (pty == NULL) {
    	result = really_get_pty(&m_pty, from);
    
    	seteuid(0);
    	set_pty_permissions(save_ruid, save_rgid, 0600U);
    	seteuid(save_ruid);
    	TRACE_IDS;
    
        } else if (m_pty != -1) {
    	*pty = m_pty;
    	result = 0;
        } else {
    	result = -1;
        }
        TRACE(("get_pty(ttydev=%s, ptydev=%s) %s fd=%d (utmp setgid)\n",
    	   ttydev != 0 ? ttydev : "?",
    	   ptydev != 0 ? ptydev : "?",
    	   result ? "FAIL" : "OK",
    	   pty != 0 ? *pty : -1));
    #ifdef USE_OPENPTY
        if (opened_tty >= 0) {
    	close(opened_tty);
    	opened_tty = -1;
        }
    #endif
        return result;
    }
    #endif
    
    /*
     * Called from get_pty to iterate over likely pseudo terminals
     * we might allocate.  Used on those systems that do not have
     * a functional interface for allocating a pty.
     * Returns 0 if found a pty, 1 if fails.
     */
    #ifdef USE_PTY_SEARCH
    static int
    pty_search(int *pty)
    {
        static int devindex = 0, letter = 0;
    
    #if defined(CRAY) || defined(__MVS__)
        while (devindex < MAXPTTYS) {
    	sprintf(ttydev, TTYFORMAT, devindex);
    	sprintf(ptydev, PTYFORMAT, devindex);
    	devindex++;
    
    	TRACE(("pty_search(ttydev=%s, ptydev=%s)\n", ttydev, ptydev));
    	if ((*pty = open(ptydev, O_RDWR)) >= 0) {
    	    return 0;
    	}
        }
    #else /* CRAY || __MVS__ */
        while (PTYCHAR1[letter]) {
    	ttydev[strlen(ttydev) - 2] =
    	    ptydev[strlen(ptydev) - 2] = PTYCHAR1[letter];
    
    	while (PTYCHAR2[devindex]) {
    	    ttydev[strlen(ttydev) - 1] =
    		ptydev[strlen(ptydev) - 1] = PTYCHAR2[devindex];
    	    devindex++;
    
    	    TRACE(("pty_search(ttydev=%s, ptydev=%s)\n", ttydev, ptydev));
    	    if ((*pty = open(ptydev, O_RDWR)) >= 0) {
    #ifdef sun
    		/* Need to check the process group of the pty.
    		 * If it exists, then the slave pty is in use,
    		 * and we need to get another one.
    		 */
    		int pgrp_rtn;
    		if (ioctl(*pty, TIOCGPGRP, &pgrp_rtn) == 0 || errno != EIO) {
    		    close(*pty);
    		    continue;
    		}
    #endif /* sun */
    		return 0;
    	    }
    	}
    	devindex = 0;
    	letter++;
        }
    #endif /* CRAY else */
        /*
         * We were unable to allocate a pty master!  Return an error
         * condition and let our caller terminate cleanly.
         */
        return 1;
    }
    #endif /* USE_PTY_SEARCH */
    
    /*
     * The only difference in /etc/termcap between 4014 and 4015 is that
     * the latter has support for switching character sets.  We support the
     * 4015 protocol, but ignore the character switches.  Therefore, we
     * choose 4014 over 4015.
     *
     * Features of the 4014 over the 4012: larger (19") screen, 12-bit
     * graphics addressing (compatible with 4012 10-bit addressing),
     * special point plot mode, incremental plot mode (not implemented in
     * later Tektronix terminals), and 4 character sizes.
     * All of these are supported by xterm.
     */
    
    #if OPT_TEK4014
    static const char *const tekterm[] =
    {
        "tek4014",
        "tek4015",			/* 4014 with APL character set support */
        "tek4012",			/* 4010 with lower case */
        "tek4013",			/* 4012 with APL character set support */
        "tek4010",			/* small screen, upper-case only */
        "dumb",
        0
    };
    #endif
    
    /* The VT102 is a VT100 with the Advanced Video Option included standard.
     * It also adds Escape sequences for insert/delete character/line.
     * The VT220 adds 8-bit character sets, selective erase.
     * The VT320 adds a 25th status line, terminal state interrogation.
     * The VT420 has up to 48 lines on the screen.
     */
    
    static const char *const vtterm[] =
    {
    #ifdef USE_X11TERM
        "x11term",			/* for people who want special term name */
    #endif
        DFT_TERMTYPE,		/* for people who want special term name */
        "xterm",			/* the preferred name, should be fastest */
        "vt102",
        "vt100",
        "ansi",
        "dumb",
        0
    };
    
    /* ARGSUSED */
    static void
    hungtty(int i GCC_UNUSED)
    {
        DEBUG_MSG("handle:hungtty\n");
        siglongjmp(env, 1);
    }
    
    #if OPT_PTY_HANDSHAKE
    #define NO_FDS {-1, -1}
    
    static int cp_pipe[2] = NO_FDS;	/* this pipe is used for child to parent transfer */
    static int pc_pipe[2] = NO_FDS;	/* this pipe is used for parent to child transfer */
    
    typedef enum {			/* c == child, p == parent                        */
        PTY_BAD,			/* c->p: can't open pty slave for some reason     */
        PTY_FATALERROR,		/* c->p: we had a fatal error with the pty        */
        PTY_GOOD,			/* c->p: we have a good pty, let's go on          */
        PTY_NEW,			/* p->c: here is a new pty slave, try this        */
        PTY_NOMORE,			/* p->c; no more pty's, terminate                 */
        UTMP_ADDED,			/* c->p: utmp entry has been added                */
        UTMP_TTYSLOT,		/* c->p: here is my ttyslot                       */
        PTY_EXEC			/* p->c: window has been mapped the first time    */
    } status_t;
    
    #define HANDSHAKE_LEN	1024
    
    typedef struct {
        status_t status;
        int error;
        int fatal_error;
        int tty_slot;
        int rows;
        int cols;
        char buffer[HANDSHAKE_LEN];
    } handshake_t;
    
    /* the buffer is large enough that we can always have a trailing null */
    #define copy_handshake(dst, src) \
    	strncpy(dst.buffer, src, (size_t)HANDSHAKE_LEN - 1)[HANDSHAKE_LEN - 1] = '\0'
    
    #if OPT_TRACE
    static void
    trace_handshake(const char *tag, handshake_t * data)
    {
        const char *status = "?";
        switch (data->status) {
        case PTY_BAD:
    	status = "PTY_BAD";
    	break;
        case PTY_FATALERROR:
    	status = "PTY_FATALERROR";
    	break;
        case PTY_GOOD:
    	status = "PTY_GOOD";
    	break;
        case PTY_NEW:
    	status = "PTY_NEW";
    	break;
        case PTY_NOMORE:
    	status = "PTY_NOMORE";
    	break;
        case UTMP_ADDED:
    	status = "UTMP_ADDED";
    	break;
        case UTMP_TTYSLOT:
    	status = "UTMP_TTYSLOT";
    	break;
        case PTY_EXEC:
    	status = "PTY_EXEC";
    	break;
        }
        TRACE(("handshake %s %s errno=%d, error=%d device \"%s\"\n",
    	   tag,
    	   status,
    	   data->error,
    	   data->fatal_error,
    	   data->buffer));
    }
    #define TRACE_HANDSHAKE(tag, data) trace_handshake(tag, data)
    #else
    #define TRACE_HANDSHAKE(tag, data)	/* nothing */
    #endif
    
    /* HsSysError()
     *
     * This routine does the equivalent of a SysError but it handshakes
     * over the errno and error exit to the master process so that it can
     * display our error message and exit with our exit code so that the
     * user can see it.
     */
    
    static void
    HsSysError(int error)
    {
        handshake_t handshake;
    
        memset(&handshake, 0, sizeof(handshake));
        handshake.status = PTY_FATALERROR;
        handshake.error = errno;
        handshake.fatal_error = error;
        copy_handshake(handshake, ttydev);
    
        if (resource.ptyHandshake && (cp_pipe[1] >= 0)) {
    	TRACE(("HsSysError errno=%d, error=%d device \"%s\"\n",
    	       handshake.error,
    	       handshake.fatal_error,
    	       handshake.buffer));
    	TRACE_HANDSHAKE("writing", &handshake);
    	IGNORE_RC(write(cp_pipe[1],
    			(const char *) &handshake,
    			sizeof(handshake)));
        } else {
    	xtermWarning("fatal pty error errno=%d, error=%d device \"%s\"\n",
    		     handshake.error,
    		     handshake.fatal_error,
    		     handshake.buffer);
    	fprintf(stderr, "%s\n", SysErrorMsg(handshake.error));
    	fprintf(stderr, "Reason: %s\n", SysReasonMsg(handshake.fatal_error));
        }
        exit(error);
    }
    
    void
    first_map_occurred(void)
    {
        if (resource.wait_for_map) {
    	if (pc_pipe[1] >= 0) {
    	    handshake_t handshake;
    	    TScreen *screen = TScreenOf(term);
    
    	    memset(&handshake, 0, sizeof(handshake));
    	    handshake.status = PTY_EXEC;
    	    handshake.rows = screen->max_row;
    	    handshake.cols = screen->max_col;
    
    	    TRACE(("first_map_occurred: %dx%d\n", MaxRows(screen), MaxCols(screen)));
    	    TRACE_HANDSHAKE("writing", &handshake);
    	    IGNORE_RC(write(pc_pipe[1],
    			    (const char *) &handshake,
    			    sizeof(handshake)));
    	    close(cp_pipe[0]);
    	    close(pc_pipe[1]);
    	}
    	resource.wait_for_map = False;
        }
    }
    #else
    /*
     * temporary hack to get xterm working on att ptys
     */
    static void
    HsSysError(int error)
    {
        xtermWarning("fatal pty error %d (errno=%d) on tty %s\n",
    		 error, errno, ttydev);
        exit(error);
    }
    #endif /* OPT_PTY_HANDSHAKE else !OPT_PTY_HANDSHAKE */
    
    #ifndef VMS
    static void
    set_owner(char *device, unsigned uid, unsigned gid, unsigned mode)
    {
        int why;
    
        TRACE_IDS;
        TRACE(("set_owner(%s, uid=%d, gid=%d, mode=%#o\n",
    	   device, (int) uid, (int) gid, (unsigned) mode));
    
        if (chown(device, (uid_t) uid, (gid_t) gid) < 0) {
    	why = errno;
    	if (why != ENOENT
    	    && save_ruid == 0) {
    	    xtermPerror("Cannot chown %s to %ld,%ld",
    			device, (long) uid, (long) gid);
    	}
    	TRACE(("...chown failed: %s\n", strerror(why)));
        } else if (chmod(device, (mode_t) mode) < 0) {
    	why = errno;
    	if (why != ENOENT) {
    	    struct stat sb;
    	    if (stat(device, &sb) < 0) {
    		xtermPerror("Cannot chmod %s to %03o",
    			    device, (unsigned) mode);
    	    } else if (mode != (sb.st_mode & 0777U)) {
    		xtermPerror("Cannot chmod %s to %03lo currently %03lo",
    			    device,
    			    (unsigned long) mode,
    			    (unsigned long) (sb.st_mode & 0777U));
    		TRACE(("...stat uid=%d, gid=%d, mode=%#o\n",
    		       (int) sb.st_uid, (int) sb.st_gid, (unsigned) sb.st_mode));
    	    }
    	}
    	TRACE(("...chmod failed: %s\n", strerror(why)));
        }
    }
    
    /*
     * utmp data may not be null-terminated; even if it is, there may be garbage
     * after the null.  This fills the unused part of the result with nulls.
     */
    static void
    copy_filled(char *target, const char *source, size_t len)
    {
        size_t used = 0;
        while (used < len) {
    	if ((target[used] = source[used]) == 0)
    	    break;
    	++used;
        }
        while (used < len) {
    	target[used++] = '\0';
        }
    }
    
    #if defined(HAVE_UTMP) && defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER)
    /*
     * getutid() only looks at ut_type and ut_id.
     * But we'll also check ut_line in find_utmp().
     */
    static void
    init_utmp(int type, struct UTMP_STR *tofind)
    {
        memset(tofind, 0, sizeof(*tofind));
        tofind->ut_type = (short) type;
        copy_filled(tofind->ut_id, my_utmp_id(ttydev), sizeof(tofind->ut_id));
        copy_filled(tofind->ut_line, my_pty_name(ttydev), sizeof(tofind->ut_line));
    }
    
    /*
     * We could use getutline() if we didn't support old systems.
     */
    static struct UTMP_STR *
    find_utmp(struct UTMP_STR *tofind)
    {
        struct UTMP_STR *result;
        struct UTMP_STR limited;
        struct UTMP_STR working;
    
        for (;;) {
    	memset(&working, 0, sizeof(working));
    	working.ut_type = tofind->ut_type;
    	copy_filled(working.ut_id, tofind->ut_id, sizeof(tofind->ut_id));
    #if defined(__digital__) && defined(__unix__) && (defined(OSMAJORVERSION) && OSMAJORVERSION < 5)
    	working.ut_type = 0;
    #endif
    	if ((result = call_getutid(&working)) == 0)
    	    break;
    	copy_filled(limited.ut_line, result->ut_line, sizeof(result->ut_line));
    	if (!memcmp(limited.ut_line, tofind->ut_line, sizeof(limited.ut_line)))
    	    break;
    	/*
    	 * Solaris, IRIX64 and HPUX manpages say to fill the static area
    	 * pointed to by the return-value to zeros if searching for multiple
    	 * occurrences.  Otherwise it will continue to return the same value.
    	 */
    	memset(result, 0, sizeof(*result));
        }
        return result;
    }
    #endif /* HAVE_UTMP... */
    
    #define close_fd(fd) close(fd), fd = -1
    
    #if defined(TIOCNOTTY) && (!defined(__GLIBC__) || (__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))
    #define USE_NO_DEV_TTY 1
    #else
    #define USE_NO_DEV_TTY 0
    #endif
    
    static int
    same_leaf(char *a, char *b)
    {
        char *p = x_basename(a);
        char *q = x_basename(b);
        return !strcmp(p, q);
    }
    
    /*
     * "good enough" (inode wouldn't port to Cygwin)
     */
    static int
    same_file(const char *a, const char *b)
    {
        struct stat asb;
        struct stat bsb;
        int result = 0;
    
        if ((stat(a, &asb) == 0)
    	&& (stat(b, &bsb) == 0)
    	&& ((asb.st_mode & S_IFMT) == S_IFREG)
    	&& ((bsb.st_mode & S_IFMT) == S_IFREG)
    	&& (asb.st_mtime == bsb.st_mtime)
    	&& (asb.st_size == bsb.st_size)) {
    	result = 1;
        }
        return result;
    }
    
    static int
    findValidShell(const char *haystack, const char *needle)
    {
        int result = -1;
        int count = -1;
        const char *s, *t;
        size_t have;
        size_t want = strlen(needle);
    
        TRACE(("findValidShell:\n%s\n", NonNull(haystack)));
    
        for (s = t = haystack; (s != 0) && (*s != '\0'); s = t) {
    	++count;
    	if ((t = strchr(s, '\n')) == 0) {
    	    t = s + strlen(s);
    	}
    	have = (size_t) (t - s);
    
    	if ((have >= want) && (*s != '#')) {
    	    char *p = malloc(have + 1);
    
    	    if (p != 0) {
    		char *q;
    
    		memcpy(p, s, have);
    		p[have] = '\0';
    		if ((q = x_strtrim(p)) != 0) {
    		    TRACE(("...test %s\n", q));
    		    if (!strcmp(q, needle)) {
    			result = count;
    		    } else if (same_leaf(q, (char *) needle) &&
    			       same_file(q, needle)) {
    			result = count;
    		    }
    		    free(q);
    		}
    		free(p);
    	    }
    	    if (result >= 0)
    		break;
    	}
    	while (*t == '\n') {
    	    ++t;
    	}
        }
        return result;
    }
    
    static int
    ourValidShell(const char *pathname)
    {
        return findValidShell(x_strtrim(resource.valid_shells), pathname);
    }
    
    #if defined(HAVE_GETUSERSHELL) && defined(HAVE_ENDUSERSHELL)
    static Boolean
    validShell(const char *pathname)
    {
        int result = -1;
    
        if (validProgram(pathname)) {
    	char *q;
    	int count = -1;
    
    	TRACE(("validShell:getusershell\n"));
    	while ((q = getusershell()) != 0) {
    	    ++count;
    	    TRACE(("...test \"%s\"\n", q));
    	    if (!strcmp(q, pathname)) {
    		result = count;
    		break;
    	    }
    	}
    	endusershell();
    
    	if (result < 0)
    	    result = ourValidShell(pathname);
        }
    
        TRACE(("validShell %s ->%d\n", NonNull(pathname), result));
        return (result >= 0);
    }
    #else
    /*
     * Only set $SHELL for paths found in the standard location.
     */
    static Boolean
    validShell(const char *pathname)
    {
        int result = -1;
        const char *ok_shells = "/etc/shells";
        char *blob;
        struct stat sb;
        size_t rc;
        FILE *fp;
    
        if (validProgram(pathname)) {
    
    	TRACE(("validShell:%s\n", ok_shells));
    
    	if (stat(ok_shells, &sb) == 0
    	    && (sb.st_mode & S_IFMT) == S_IFREG
    	    && ((size_t) sb.st_size > 0)
    	    && ((size_t) sb.st_size < (((size_t) ~0) - 2))
    	    && (blob = calloc((size_t) sb.st_size + 2, sizeof(char))) != 0) {
    
    	    if ((fp = fopen(ok_shells, "r")) != 0) {
    		rc = fread(blob, sizeof(char), (size_t) sb.st_size, fp);
    		fclose(fp);
    
    		if (rc == (size_t) sb.st_size) {
    		    blob[rc] = '\0';
    		    result = findValidShell(blob, pathname);
    		}
    	    }
    	    free(blob);
    	}
    	if (result < 0)
    	    result = ourValidShell(pathname);
        }
        TRACE(("validShell %s ->%d\n", NonNull(pathname), result));
        return (result > 0);
    }
    #endif
    
    static char *
    resetShell(char *oldPath)
    {
        char *newPath = x_strdup("/bin/sh");
        char *envPath = getenv("SHELL");
        if (oldPath != 0)
    	free(oldPath);
        if (!IsEmpty(envPath))
    	xtermSetenv("SHELL", newPath);
        return newPath;
    }
    
    /*
     *  Inits pty and tty and forks a login process.
     *  Does not close fd Xsocket.
     *  If slave, the pty named in passedPty is already open for use
     */
    static int
    spawnXTerm(XtermWidget xw, unsigned line_speed)
    {
        TScreen *screen = TScreenOf(xw);
        Cardinal nn;
    #if OPT_PTY_HANDSHAKE
        Bool got_handshake_size = False;
        handshake_t handshake;
        int done;
    #endif
    #if OPT_INITIAL_ERASE
        int initial_erase = VAL_INITIAL_ERASE;
        Bool setInitialErase;
    #endif
        int rc = 0;
        int ttyfd = -1;
        Bool ok_termcap;
        char *newtc;
    
    #ifdef TERMIO_STRUCT
        TERMIO_STRUCT tio;
    #ifdef __MVS__
        TERMIO_STRUCT gio;
    #endif /* __MVS__ */
    #ifdef TIOCLSET
        unsigned lmode;
    #endif /* TIOCLSET */
    #ifdef HAS_LTCHARS
        struct ltchars ltc;
    #endif /* HAS_LTCHARS */
    #else /* !TERMIO_STRUCT */
        int ldisc = 0;
        int discipline;
        unsigned lmode;
        struct tchars tc;
        struct ltchars ltc;
        struct sgttyb sg;
    #ifdef sony
        int jmode;
        struct jtchars jtc;
    #endif /* sony */
    #endif /* TERMIO_STRUCT */
    
        char *shell_path = 0;
        char *shname, *shname_minus;
        int i;
    #if USE_NO_DEV_TTY
        int no_dev_tty = False;
    #endif
        const char *const *envnew;	/* new environment */
        char buf[64];
        char *TermName = NULL;
    #ifdef TTYSIZE_STRUCT
        TTYSIZE_STRUCT ts;
    #endif
        struct passwd pw;
        char *login_name = NULL;
    #ifndef USE_UTEMPTER
    #ifdef HAVE_UTMP
        struct UTMP_STR utmp;
    #ifdef USE_SYSV_UTMP
        struct UTMP_STR *utret = NULL;
    #endif
    #ifdef USE_LASTLOG
        struct lastlog lastlog;
    #endif
    #ifdef USE_LASTLOGX
        struct lastlogx lastlogx;
    #endif /* USE_LASTLOG */
    #endif /* HAVE_UTMP */
    #endif /* !USE_UTEMPTER */
    
    #if OPT_TRACE
        unsigned long xterm_parent = (unsigned long) getpid();
    #endif
    
        /* Noisy compilers (suppress some unused-variable warnings) */
        (void) rc;
    #if defined(HAVE_UTMP) && defined(USE_SYSV_UTMP) && !defined(USE_UTEMPTER)
        (void) utret;
    #endif
    
        screen->uid = save_ruid;
        screen->gid = save_rgid;
    
    #ifdef SIGTTOU
        /* so that TIOCSWINSZ || TIOCSIZE doesn't block */
        signal(SIGTTOU, SIG_IGN);
    #endif
    
    #if OPT_PTY_HANDSHAKE
        memset(&handshake, 0, sizeof(handshake));
    #endif
    
        if (am_slave >= 0) {
    	screen->respond = am_slave;
    	set_pty_id(ttydev, passedPty);
    #ifdef USE_PTY_DEVICE
    	set_pty_id(ptydev, passedPty);
    #endif
    	if (xtermResetIds(screen) < 0)
    	    exit(1);
        } else {
    	Bool tty_got_hung;
    
    	/*
    	 * Sometimes /dev/tty hangs on open (as in the case of a pty
    	 * that has gone away).  Simply make up some reasonable
    	 * defaults.
    	 */
    
    	if (!sigsetjmp(env, 1)) {
    	    signal(SIGALRM, hungtty);
    	    alarm(2);		/* alarm(1) might return too soon */
    	    ttyfd = open("/dev/tty", O_RDWR);
    	    alarm(0);
    	    tty_got_hung = False;
    	} else {
    	    tty_got_hung = True;
    	    ttyfd = -1;
    	    errno = ENXIO;
    	}
    	shell_path = 0;
    	memset(&pw, 0, sizeof(pw));
    #if OPT_PTY_HANDSHAKE
    	got_handshake_size = False;
    #endif /* OPT_PTY_HANDSHAKE */
    #if OPT_INITIAL_ERASE
    	initial_erase = VAL_INITIAL_ERASE;
    #endif
    	signal(SIGALRM, SIG_DFL);
    
    	/*
    	 * Check results and ignore current control terminal if
    	 * necessary.  ENXIO is what is normally returned if there is
    	 * no controlling terminal, but some systems (e.g. SunOS 4.0)
    	 * seem to return EIO.  Solaris 2.3 is said to return EINVAL.
    	 * Cygwin returns ENOENT.  FreeBSD can return ENOENT, especially
    	 * if xterm is run within a jail.
    	 */
    #if USE_NO_DEV_TTY
    	no_dev_tty = False;
    #endif
    	if (ttyfd < 0) {
    	    if (tty_got_hung || errno == ENXIO || errno == EIO ||
    		errno == ENOENT ||
    #ifdef ENODEV
    		errno == ENODEV ||
    #endif
    		errno == EINVAL || errno == ENOTTY || errno == EACCES) {
    #if USE_NO_DEV_TTY
    		no_dev_tty = True;
    #endif
    #ifdef HAS_LTCHARS
    		ltc = d_ltc;
    #endif /* HAS_LTCHARS */
    #ifdef TIOCLSET
    		lmode = d_lmode;
    #endif /* TIOCLSET */
    #ifdef TERMIO_STRUCT
    		tio = d_tio;
    #else /* !TERMIO_STRUCT */
    		sg = d_sg;
    		tc = d_tc;
    		discipline = d_disipline;
    #ifdef sony
    		jmode = d_jmode;
    		jtc = d_jtc;
    #endif /* sony */
    #endif /* TERMIO_STRUCT */
    	    } else {
    		SysError(ERROR_OPDEVTTY);
    	    }
    	} else {
    
    	    /* Get a copy of the current terminal's state,
    	     * if we can.  Some systems (e.g., SVR4 and MacII)
    	     * may not have a controlling terminal at this point
    	     * if started directly from xdm or xinit,
    	     * in which case we just use the defaults as above.
    	     */
    #ifdef HAS_LTCHARS
    	    if (ioctl(ttyfd, TIOCGLTC, <c) == -1)
    		ltc = d_ltc;
    #endif /* HAS_LTCHARS */
    #ifdef TIOCLSET
    	    if (ioctl(ttyfd, TIOCLGET, &lmode) == -1)
    		lmode = d_lmode;
    #endif /* TIOCLSET */
    #ifdef TERMIO_STRUCT
    	    rc = ttyGetAttr(ttyfd, &tio);
    	    if (rc == -1)
    		tio = d_tio;
    #else /* !TERMIO_STRUCT */
    	    rc = ioctl(ttyfd, TIOCGETP, (char *) &sg);
    	    if (rc == -1)
    		sg = d_sg;
    	    if (ioctl(ttyfd, TIOCGETC, (char *) &tc) == -1)
    		tc = d_tc;
    	    if (ioctl(ttyfd, TIOCGETD, (char *) &discipline) == -1)
    		discipline = d_disipline;
    #ifdef sony
    	    if (ioctl(ttyfd, TIOCKGET, (char *) &jmode) == -1)
    		jmode = d_jmode;
    	    if (ioctl(ttyfd, TIOCKGETC, (char *) &jtc) == -1)
    		jtc = d_jtc;
    #endif /* sony */
    #endif /* TERMIO_STRUCT */
    
    	    /*
    	     * If ptyInitialErase is set, we want to get the pty's
    	     * erase value.  Just in case that will fail, first get
    	     * the value from /dev/tty, so we will have something
    	     * at least.
    	     */
    #if OPT_INITIAL_ERASE
    	    if (resource.ptyInitialErase) {
    #ifdef TERMIO_STRUCT
    		initial_erase = tio.c_cc[VERASE];
    #else /* !TERMIO_STRUCT */
    		initial_erase = sg.sg_erase;
    #endif /* TERMIO_STRUCT */
    		TRACE(("%s initial_erase:%d (from /dev/tty)\n",
    		       rc == 0 ? "OK" : "FAIL",
    		       initial_erase));
    	    }
    #endif
    #ifdef __MVS__
    	    if (ttyGetAttr(ttyfd, &gio) == 0) {
    		gio.c_cflag &= ~(HUPCL | PARENB);
    		ttySetAttr(ttyfd, &gio);
    	    }
    #endif /* __MVS__ */
    
    	    close_fd(ttyfd);
    	}
    
    	if (get_pty(&screen->respond, XDisplayString(screen->display))) {
    	    SysError(ERROR_PTYS);
    	}
    	TRACE_GET_TTYSIZE(screen->respond, "after get_pty");
    #if OPT_INITIAL_ERASE
    	if (resource.ptyInitialErase) {
    #ifdef TERMIO_STRUCT
    	    TERMIO_STRUCT my_tio;
    	    rc = ttyGetAttr(screen->respond, &my_tio);
    	    if (rc == 0)
    		initial_erase = my_tio.c_cc[VERASE];
    #else /* !TERMIO_STRUCT */
    	    struct sgttyb my_sg;
    	    rc = ioctl(screen->respond, TIOCGETP, (char *) &my_sg);
    	    if (rc == 0)
    		initial_erase = my_sg.sg_erase;
    #endif /* TERMIO_STRUCT */
    	    TRACE(("%s initial_erase:%d (from pty)\n",
    		   (rc == 0) ? "OK" : "FAIL",
    		   initial_erase));
    	}
    #endif /* OPT_INITIAL_ERASE */
        }
    
        /* avoid double MapWindow requests */
        XtSetMappedWhenManaged(SHELL_OF(CURRENT_EMU()), False);
    
        wm_delete_window = XInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW",
    				   False);
    
        if (!TEK4014_ACTIVE(xw))
    	VTInit(xw);		/* realize now so know window size for tty driver */
    #if defined(TIOCCONS) || defined(SRIOCSREDIR)
        if (Console) {
    	/*
    	 * Inform any running xconsole program
    	 * that we are going to steal the console.
    	 */
    	XmuGetHostname(mit_console_name + MIT_CONSOLE_LEN, 255);
    	mit_console = XInternAtom(screen->display, mit_console_name, False);
    	/* the user told us to be the console, so we can use CurrentTime */
    	XtOwnSelection(SHELL_OF(CURRENT_EMU()),
    		       mit_console, CurrentTime,
    		       ConvertConsoleSelection, NULL, NULL);
        }
    #endif
    #if OPT_TEK4014
        if (TEK4014_ACTIVE(xw)) {
    	envnew = tekterm;
        } else
    #endif
        {
    	envnew = vtterm;
        }
    
        /*
         * This used to exit if no termcap entry was found for the specified
         * terminal name.  That's a little unfriendly, so instead we'll allow
         * the program to proceed (but not to set $TERMCAP) if the termcap
         * entry is not found.
         */
        ok_termcap = True;
        if (!get_termcap(xw, TermName = resource.term_name)) {
    	const char *last = NULL;
    	char *next;
    
    	TermName = x_strdup(*envnew);
    	ok_termcap = False;
    	while (*envnew != NULL) {
    	    if (last == NULL || strcmp(last, *envnew)) {
    		next = x_strdup(*envnew);
    		if (get_termcap(xw, next)) {
    		    free(TermName);
    		    TermName = next;
    		    ok_termcap = True + 1;
    		    break;
    		} else {
    		    free(next);
    		}
    	    }
    	    last = *envnew;
    	    envnew++;
    	}
        }
        if (ok_termcap) {
    	resource.term_name = x_strdup(TermName);
    	resize_termcap(xw);
        }
    
        /*
         * Check if ptyInitialErase is not set.  If so, we rely on the termcap
         * (or terminfo) to tell us what the erase mode should be set to.
         */
    #if OPT_INITIAL_ERASE
        TRACE(("resource ptyInitialErase is %sset\n",
    	   resource.ptyInitialErase ? "" : "not "));
        setInitialErase = False;
        if (override_tty_modes && ttyModes[XTTYMODE_erase].set) {
    	initial_erase = ttyModes[XTTYMODE_erase].value;
    	setInitialErase = True;
        } else if (resource.ptyInitialErase) {
    	/* EMPTY */ ;
        } else if (ok_termcap) {
    	char *s = get_tcap_erase(xw);
    	TRACE(("...extracting initial_erase value from termcap\n"));
    	if (s != 0) {
    	    char *save = s;
    	    initial_erase = decode_keyvalue(&s, True);
    	    setInitialErase = True;
    	    free(save);
    	}
        }
        TRACE(("...initial_erase:%d\n", initial_erase));
    
        TRACE(("resource backarrowKeyIsErase is %sset\n",
    	   resource.backarrow_is_erase ? "" : "not "));
        if (resource.backarrow_is_erase) {	/* see input.c */
    	if (initial_erase == ANSI_DEL) {
    	    UIntClr(xw->keyboard.flags, MODE_DECBKM);
    	} else {
    	    xw->keyboard.flags |= MODE_DECBKM;
    	    xw->keyboard.reset_DECBKM = 1;
    	}
    	TRACE(("...sets DECBKM %s\n",
    	       (xw->keyboard.flags & MODE_DECBKM) ? "on" : "off"));
        } else {
    	xw->keyboard.reset_DECBKM = 2;
        }
    #endif /* OPT_INITIAL_ERASE */
    
    #ifdef TTYSIZE_STRUCT
        /* tell tty how big window is */
    #if OPT_TEK4014
        if (TEK4014_ACTIVE(xw)) {
    	setup_winsize(ts, TDefaultRows, TDefaultCols,
    		      TFullHeight(TekScreenOf(tekWidget)),
    		      TFullWidth(TekScreenOf(tekWidget)));
        } else
    #endif
        {
    	setup_winsize(ts, MaxRows(screen), MaxCols(screen),
    		      FullHeight(screen), FullWidth(screen));
        }
        TRACE_RC(i, SET_TTYSIZE(screen->respond, ts));
        TRACE(("spawn SET_TTYSIZE %dx%d return %d\n",
    	   TTYSIZE_ROWS(ts),
    	   TTYSIZE_COLS(ts), i));
    #endif /* TTYSIZE_STRUCT */
    
    #if !defined(USE_OPENPTY)
    #if defined(USE_USG_PTYS) || defined(HAVE_POSIX_OPENPT)
        /*
         * utempter checks the ownership of the device; some implementations
         * set ownership in grantpt - do this first.
         */
        grantpt(screen->respond);
    #endif
    #if !defined(USE_USG_PTYS) && defined(HAVE_POSIX_OPENPT)
        unlockpt(screen->respond);
        TRACE_GET_TTYSIZE(screen->respond, "after unlockpt");
    #endif
    #endif /* !USE_OPENPTY */
    
        added_utmp_entry = False;
    #if defined(USE_UTEMPTER)
    #undef UTMP
        if ((xw->misc.login_shell || !command_to_exec) && !resource.utmpInhibit) {
    	struct UTMP_STR dummy;
    
    	/* Note: utempter may trim it anyway */
    	SetUtmpHost(dummy.ut_host, screen);
    	TRACE(("...calling addToUtmp(pty=%s, hostname=%s, master_fd=%d)\n",
    	       ttydev, dummy.ut_host, screen->respond));
    	UTEMPTER_ADD(ttydev, dummy.ut_host, screen->respond);
    	added_utmp_entry = True;
        }
    #endif
    
        if (am_slave < 0) {
    #if OPT_PTY_HANDSHAKE
    	if (resource.ptyHandshake && (pipe(pc_pipe) || pipe(cp_pipe)))
    	    SysError(ERROR_FORK);
    #endif
    	TRACE(("Forking...\n"));
    	if ((screen->pid = fork()) == -1)
    	    SysError(ERROR_FORK);
    
    	if (screen->pid == 0) {
    #ifdef USE_USG_PTYS
    	    int ptyfd = -1;
    	    char *pty_name;
    #endif
    	    /*
    	     * now in child process
    	     */
    #if defined(_POSIX_SOURCE) || defined(SVR4) || defined(__convex__) || defined(__SCO__) || defined(__QNX__)
    	    int pgrp = setsid();	/* variable may not be used... */
    #else
    	    int pgrp = getpid();
    #endif
    	    TRACE_CHILD
    
    #ifdef USE_USG_PTYS
    #ifdef HAVE_SETPGID
    		setpgid(0, 0);
    #else
    		setpgrp();
    #endif
    	    unlockpt(screen->respond);
    	    TRACE_GET_TTYSIZE(screen->respond, "after unlockpt");
    	    if ((pty_name = ptsname(screen->respond)) == 0) {
    		SysError(ERROR_PTSNAME);
    	    } else if ((ptyfd = open(pty_name, O_RDWR)) < 0) {
    		SysError(ERROR_OPPTSNAME);
    	    }
    #ifdef I_PUSH
    	    else if (PUSH_FAILS(ptyfd, "ptem")) {
    		SysError(ERROR_PTEM);
    	    }
    #if !defined(SVR4) && !(defined(SYSV) && defined(i386))
    	    else if (!x_getenv("CONSEM")
    		     && PUSH_FAILS(ptyfd, "consem")) {
    		SysError(ERROR_CONSEM);
    	    }
    #endif /* !SVR4 */
    	    else if (PUSH_FAILS(ptyfd, "ldterm")) {
    		SysError(ERROR_LDTERM);
    	    }
    #ifdef SVR4			/* from Sony */
    	    else if (PUSH_FAILS(ptyfd, "ttcompat")) {
    		SysError(ERROR_TTCOMPAT);
    	    }
    #endif /* SVR4 */
    #endif /* I_PUSH */
    	    ttyfd = ptyfd;
    #ifndef __MVS__
    	    close_fd(screen->respond);
    #endif /* __MVS__ */
    
    #ifdef TTYSIZE_STRUCT
    	    /* tell tty how big window is */
    #if OPT_TEK4014
    	    if (TEK4014_ACTIVE(xw)) {
    		setup_winsize(ts, TDefaultRows, TDefaultCols,
    			      TFullHeight(TekScreenOf(tekWidget)),
    			      TFullWidth(TekScreenOf(tekWidget)));
    	    } else
    #endif /* OPT_TEK4014 */
    	    {
    		setup_winsize(ts, MaxRows(screen), MaxCols(screen),
    			      FullHeight(screen), FullWidth(screen));
    	    }
    	    trace_winsize(ts, "initial tty size");
    #endif /* TTYSIZE_STRUCT */
    
    #endif /* USE_USG_PTYS */
    
    	    (void) pgrp;	/* not all branches use this variable */
    
    #if OPT_PTY_HANDSHAKE		/* warning, goes for a long ways */
    	    if (resource.ptyHandshake) {
    		char *ptr;
    
    		/* close parent's sides of the pipes */
    		close(cp_pipe[0]);
    		close(pc_pipe[1]);
    
    		/* Make sure that our sides of the pipes are not in the
    		 * 0, 1, 2 range so that we don't fight with stdin, out
    		 * or err.
    		 */
    		if (cp_pipe[1] <= 2) {
    		    if ((i = fcntl(cp_pipe[1], F_DUPFD, 3)) >= 0) {
    			IGNORE_RC(close(cp_pipe[1]));
    			cp_pipe[1] = i;
    		    }
    		}
    		if (pc_pipe[0] <= 2) {
    		    if ((i = fcntl(pc_pipe[0], F_DUPFD, 3)) >= 0) {
    			IGNORE_RC(close(pc_pipe[0]));
    			pc_pipe[0] = i;
    		    }
    		}
    
    		/* we don't need the socket, or the pty master anymore */
    		close(ConnectionNumber(screen->display));
    #ifndef __MVS__
    		if (screen->respond >= 0)
    		    close(screen->respond);
    #endif /* __MVS__ */
    
    		/* Now is the time to set up our process group and
    		 * open up the pty slave.
    		 */
    #ifdef USE_SYSV_PGRP
    #if defined(CRAY) && (OSMAJORVERSION > 5)
    		IGNORE_RC(setsid());
    #else
    		IGNORE_RC(setpgrp());
    #endif
    #endif /* USE_SYSV_PGRP */
    
    #if defined(__QNX__) && !defined(__QNXNTO__)
    		qsetlogin(getlogin(), ttydev);
    #endif
    		if (ttyfd >= 0) {
    #ifdef __MVS__
    		    if (ttyGetAttr(ttyfd, &gio) == 0) {
    			gio.c_cflag &= ~(HUPCL | PARENB);
    			ttySetAttr(ttyfd, &gio);
    		    }
    #else /* !__MVS__ */
    		    close_fd(ttyfd);
    #endif /* __MVS__ */
    		}
    
    		for (;;) {
    #if USE_NO_DEV_TTY
    		    if (!no_dev_tty
    			&& (ttyfd = open("/dev/tty", O_RDWR)) >= 0) {
    			ioctl(ttyfd, TIOCNOTTY, (char *) NULL);
    			close_fd(ttyfd);
    		    }
    #endif /* USE_NO_DEV_TTY */
    #ifdef CSRG_BASED
    		    IGNORE_RC(revoke(ttydev));
    #endif
    		    if ((ttyfd = open(ttydev, O_RDWR)) >= 0) {
    			TRACE_GET_TTYSIZE(ttyfd, "after open");
    			TRACE_RC(i, SET_TTYSIZE(ttyfd, ts));
    			TRACE_GET_TTYSIZE(ttyfd, "after SET_TTYSIZE fixup");
    #if defined(CRAY) && defined(TCSETCTTY)
    			/* make /dev/tty work */
    			ioctl(ttyfd, TCSETCTTY, 0);
    #endif
    #if ((defined(__GLIBC__) && defined(__FreeBSD_kernel__)) || defined(__GNU__)) && defined(TIOCSCTTY)
    			/* make /dev/tty work */
    			ioctl(ttyfd, TIOCSCTTY, 0);
    #endif
    #ifdef USE_SYSV_PGRP
    			/* We need to make sure that we are actually
    			 * the process group leader for the pty.  If
    			 * we are, then we should now be able to open
    			 * /dev/tty.
    			 */
    			if ((i = open("/dev/tty", O_RDWR)) >= 0) {
    			    /* success! */
    			    close(i);
    			    break;
    			}
    #else /* USE_SYSV_PGRP */
    			break;
    #endif /* USE_SYSV_PGRP */
    		    }
    		    perror("open ttydev");
    #ifdef TIOCSCTTY
    		    ioctl(ttyfd, TIOCSCTTY, 0);
    #endif
    		    /* let our master know that the open failed */
    		    handshake.status = PTY_BAD;
    		    handshake.error = errno;
    		    copy_handshake(handshake, ttydev);
    		    TRACE_HANDSHAKE("writing", &handshake);
    		    IGNORE_RC(write(cp_pipe[1],
    				    (const char *) &handshake,
    				    sizeof(handshake)));
    
    		    /* get reply from parent */
    		    i = (int) read(pc_pipe[0], (char *) &handshake,
    				   sizeof(handshake));
    		    if (i <= 0) {
    			/* parent terminated */
    			exit(1);
    		    }
    
    		    if (handshake.status == PTY_NOMORE) {
    			/* No more ptys, let's shutdown. */
    			exit(1);
    		    }
    
    		    /* We have a new pty to try */
    		    if (ttyfd >= 0)
    			close(ttyfd);
    		    free(ttydev);
    		    handshake.buffer[HANDSHAKE_LEN - 1] = '\0';
    		    ttydev = x_strdup(handshake.buffer);
    		}
    
    		/* use the same tty name that everyone else will use
    		 * (from ttyname)
    		 */
    		if ((ptr = ttyname(ttyfd)) != 0) {
    		    free(ttydev);
    		    ttydev = x_strdup(ptr);
    		}
    	    }
    #endif /* OPT_PTY_HANDSHAKE -- from near fork */
    
    	    set_pty_permissions(screen->uid,
    				(unsigned) screen->gid,
    				(resource.messages
    				 ? 0622U
    				 : 0600U));
    
    	    /*
    	     * set up the tty modes
    	     */
    	    {
    #ifdef TERMIO_STRUCT
    #if defined(umips) || defined(CRAY) || defined(linux)
    		/* If the control tty had its modes screwed around with,
    		   eg. by lineedit in the shell, or emacs, etc. then tio
    		   will have bad values.  Let's just get termio from the
    		   new tty and tailor it.  */
    		if (ttyGetAttr(ttyfd, &tio) == -1)
    		    SysError(ERROR_TIOCGETP);
    		tio.c_lflag |= ECHOE;
    #endif /* umips */
    		/* Now is also the time to change the modes of the
    		 * child pty.
    		 */
    		/* input: nl->nl, don't ignore cr, cr->nl */
    		UIntClr(tio.c_iflag, (INLCR | IGNCR));
    		tio.c_iflag |= ICRNL;
    #if OPT_WIDE_CHARS && defined(IUTF8)
    #if OPT_LUIT_PROG
    		if (command_to_exec_with_luit == 0)
    #endif
    		    if (screen->utf8_mode)
    			tio.c_iflag |= IUTF8;
    #endif
    		/* output: cr->cr, nl is not return, no delays, ln->cr/nl */
    #ifndef USE_POSIX_TERMIOS
    		UIntClr(tio.c_oflag,
    			(OCRNL
    			 | ONLRET
    			 | NLDLY
    			 | CRDLY
    			 | TABDLY
    			 | BSDLY
    			 | VTDLY
    			 | FFDLY));
    #endif /* USE_POSIX_TERMIOS */
    		tio.c_oflag |= D_TIO_FLAGS;
    #ifndef USE_POSIX_TERMIOS
    # if defined(Lynx) && !defined(CBAUD)
    #  define CBAUD V_CBAUD
    # endif
    		UIntClr(tio.c_cflag, CBAUD);
    #ifdef BAUD_0
    		/* baud rate is 0 (don't care) */
    #elif defined(HAVE_TERMIO_C_ISPEED)
    		tio.c_ispeed = tio.c_ospeed = line_speed;
    #else /* !BAUD_0 */
    		tio.c_cflag |= line_speed;
    #endif /* !BAUD_0 */
    #else /* USE_POSIX_TERMIOS */
    		cfsetispeed(&tio, line_speed);
    		cfsetospeed(&tio, line_speed);
    #ifdef __MVS__
    		/* turn off bits that can't be set from the slave side */
    		tio.c_cflag &= ~(PACKET | PKT3270 | PTU3270 | PKTXTND);
    #endif /* __MVS__ */
    		/* Clear CLOCAL so that SIGHUP is sent to us
    		   when the xterm ends */
    		tio.c_cflag &= (unsigned) ~CLOCAL;
    #endif /* USE_POSIX_TERMIOS */
    		/* enable signals, canonical processing (erase, kill, etc),
    		 * echo
    		 */
    		tio.c_lflag |= ISIG | ICANON | ECHO | ECHOE | ECHOK;
    #ifdef ECHOKE
    		tio.c_lflag |= ECHOKE | IEXTEN;
    #endif
    #ifdef ECHOCTL
    		tio.c_lflag |= ECHOCTL | IEXTEN;
    #endif
    		for (nn = 0; nn < XtNumber(ttyChars); ++nn) {
    		    if (validTtyChar(tio, nn)) {
    			int sysMode = ttyChars[nn].sysMode;
    #ifdef __MVS__
    			if (tio.c_cc[sysMode] != 0) {
    			    switch (sysMode) {
    			    case VEOL:
    			    case VEOF:
    				continue;
    			    }
    			}
    #endif
    			tio.c_cc[sysMode] = (cc_t) ttyChars[nn].myDefault;
    		    }
    		}
    
    		if (override_tty_modes) {
    		    TRACE(("applying termios ttyModes\n"));
    		    for (nn = 0; nn < XtNumber(ttyChars); ++nn) {
    			if (validTtyChar(tio, nn)) {
    			    TMODE(ttyChars[nn].myMode,
    				  tio.c_cc[ttyChars[nn].sysMode]);
    			} else if (isTabMode(nn)) {
    			    unsigned tmp = (unsigned) tio.c_oflag;
    			    tmp = tmp & (unsigned) ~TABDLY;
    			    tmp |= (unsigned) ttyModes[ttyChars[nn].myMode].value;
    			    tio.c_oflag = tmp;
    			}
    		    }
    #ifdef HAS_LTCHARS
    		    /* both SYSV and BSD have ltchars */
    		    TMODE(XTTYMODE_susp, ltc.t_suspc);
    		    TMODE(XTTYMODE_dsusp, ltc.t_dsuspc);
    		    TMODE(XTTYMODE_rprnt, ltc.t_rprntc);
    		    TMODE(XTTYMODE_flush, ltc.t_flushc);
    		    TMODE(XTTYMODE_weras, ltc.t_werasc);
    		    TMODE(XTTYMODE_lnext, ltc.t_lnextc);
    #endif
    		}
    #ifdef HAS_LTCHARS
    #ifdef __hpux
    		/* ioctl chokes when the "reserved" process group controls
    		 * are not set to _POSIX_VDISABLE */
    		ltc.t_rprntc = _POSIX_VDISABLE;
    		ltc.t_rprntc = _POSIX_VDISABLE;
    		ltc.t_flushc = _POSIX_VDISABLE;
    		ltc.t_werasc = _POSIX_VDISABLE;
    		ltc.t_lnextc = _POSIX_VDISABLE;
    #endif /* __hpux */
    		if (ioctl(ttyfd, TIOCSLTC, <c) == -1)
    		    HsSysError(ERROR_TIOCSETC);
    #endif /* HAS_LTCHARS */
    #ifdef TIOCLSET
    		if (ioctl(ttyfd, TIOCLSET, (char *) &lmode) == -1)
    		    HsSysError(ERROR_TIOCLSET);
    #endif /* TIOCLSET */
    		if (ttySetAttr(ttyfd, &tio) == -1)
    		    HsSysError(ERROR_TIOCSETP);
    
    		/* ignore errors here - some platforms don't work */
    		UIntClr(tio.c_cflag, CSIZE);
    		if (screen->input_eight_bits)
    		    tio.c_cflag |= CS8;
    		else
    		    tio.c_cflag |= CS7;
    		(void) ttySetAttr(ttyfd, &tio);
    
    #else /* !TERMIO_STRUCT */
    		sg.sg_flags &= ~(ALLDELAY | XTABS | CBREAK | RAW);
    		sg.sg_flags |= ECHO | CRMOD;
    		/* make sure speed is set on pty so that editors work right */
    		sg.sg_ispeed = line_speed;
    		sg.sg_ospeed = line_speed;
    		/* reset t_brkc to default value */
    		tc.t_brkc = -1;
    #ifdef LPASS8
    		if (screen->input_eight_bits)
    		    lmode |= LPASS8;
    		else
    		    lmode &= ~(LPASS8);
    #endif
    #ifdef sony
    		jmode &= ~KM_KANJI;
    #endif /* sony */
    
    		ltc = d_ltc;
    
    		if (override_tty_modes) {
    		    TRACE(("applying sgtty ttyModes\n"));
    		    TMODE(XTTYMODE_intr, tc.t_intrc);
    		    TMODE(XTTYMODE_quit, tc.t_quitc);
    		    TMODE(XTTYMODE_erase, sg.sg_erase);
    		    TMODE(XTTYMODE_kill, sg.sg_kill);
    		    TMODE(XTTYMODE_eof, tc.t_eofc);
    		    TMODE(XTTYMODE_start, tc.t_startc);
    		    TMODE(XTTYMODE_stop, tc.t_stopc);
    		    TMODE(XTTYMODE_brk, tc.t_brkc);
    		    /* both SYSV and BSD have ltchars */
    		    TMODE(XTTYMODE_susp, ltc.t_suspc);
    		    TMODE(XTTYMODE_dsusp, ltc.t_dsuspc);
    		    TMODE(XTTYMODE_rprnt, ltc.t_rprntc);
    		    TMODE(XTTYMODE_flush, ltc.t_flushc);
    		    TMODE(XTTYMODE_weras, ltc.t_werasc);
    		    TMODE(XTTYMODE_lnext, ltc.t_lnextc);
    		    if (ttyModes[XTTYMODE_tabs].set
    			|| ttyModes[XTTYMODE__tabs].set) {
    			sg.sg_flags &= ~XTABS;
    			if (ttyModes[XTTYMODE__tabs].set.set)
    			    sg.sg_flags |= XTABS;
    		    }
    		}
    
    		if (ioctl(ttyfd, TIOCSETP, (char *) &sg) == -1)
    		    HsSysError(ERROR_TIOCSETP);
    		if (ioctl(ttyfd, TIOCSETC, (char *) &tc) == -1)
    		    HsSysError(ERROR_TIOCSETC);
    		if (ioctl(ttyfd, TIOCSETD, (char *) &discipline) == -1)
    		    HsSysError(ERROR_TIOCSETD);
    		if (ioctl(ttyfd, TIOCSLTC, (char *) <c) == -1)
    		    HsSysError(ERROR_TIOCSLTC);
    		if (ioctl(ttyfd, TIOCLSET, (char *) &lmode) == -1)
    		    HsSysError(ERROR_TIOCLSET);
    #ifdef sony
    		if (ioctl(ttyfd, TIOCKSET, (char *) &jmode) == -1)
    		    HsSysError(ERROR_TIOCKSET);
    		if (ioctl(ttyfd, TIOCKSETC, (char *) &jtc) == -1)
    		    HsSysError(ERROR_TIOCKSETC);
    #endif /* sony */
    #endif /* TERMIO_STRUCT */
    #if defined(TIOCCONS) || defined(SRIOCSREDIR)
    		if (Console) {
    #ifdef TIOCCONS
    		    int on = 1;
    		    if (ioctl(ttyfd, TIOCCONS, (char *) &on) == -1)
    			xtermPerror("cannot open console");
    #endif
    #ifdef SRIOCSREDIR
    		    int fd = open("/dev/console", O_RDWR);
    		    if (fd == -1 || ioctl(fd, SRIOCSREDIR, ttyfd) == -1)
    			xtermPerror("cannot open console");
    		    IGNORE_RC(close(fd));
    #endif
    		}
    #endif /* TIOCCONS */
    	    }
    
    	    signal(SIGCHLD, SIG_DFL);
    #ifdef USE_SYSV_SIGHUP
    	    /* watch out for extra shells (I don't understand either) */
    	    signal(SIGHUP, SIG_DFL);
    #else
    	    signal(SIGHUP, SIG_IGN);
    #endif
    	    /* restore various signals to their defaults */
    	    signal(SIGINT, SIG_DFL);
    	    signal(SIGQUIT, SIG_DFL);
    	    signal(SIGTERM, SIG_DFL);
    
    	    /*
    	     * If we're not asked to let the parent process set the terminal's
    	     * erase mode, or if we had the ttyModes erase resource, then set
    	     * the terminal's erase mode from our best guess.
    	     */
    #if OPT_INITIAL_ERASE
    	    TRACE(("check if we should set erase to %d:%s\n\tptyInitialErase:%d,\n\toveride_tty_modes:%d,\n\tXTTYMODE_erase:%d\n",
    		   initial_erase,
    		   setInitialErase ? "YES" : "NO",
    		   resource.ptyInitialErase,
    		   override_tty_modes,
    		   ttyModes[XTTYMODE_erase].set));
    	    if (setInitialErase) {
    #if OPT_TRACE
    		int old_erase;
    #endif
    #ifdef TERMIO_STRUCT
    		if (ttyGetAttr(ttyfd, &tio) == -1)
    		    tio = d_tio;
    #if OPT_TRACE
    		old_erase = tio.c_cc[VERASE];
    #endif
    		tio.c_cc[VERASE] = (cc_t) initial_erase;
    		TRACE_RC(rc, ttySetAttr(ttyfd, &tio));
    #else /* !TERMIO_STRUCT */
    		if (ioctl(ttyfd, TIOCGETP, (char *) &sg) == -1)
    		    sg = d_sg;
    #if OPT_TRACE
    		old_erase = sg.sg_erase;
    #endif
    		sg.sg_erase = initial_erase;
    		rc = ioctl(ttyfd, TIOCSETP, (char *) &sg);
    #endif /* TERMIO_STRUCT */
    		TRACE(("%s setting erase to %d (was %d)\n",
    		       rc ? "FAIL" : "OK", initial_erase, old_erase));
    	    }
    #endif
    
    	    xtermCopyEnv(environ);
    
    	    /*
    	     * standards.freedesktop.org/startup-notification-spec/
    	     * notes that this variable is used when a "reliable" mechanism is
    	     * not available; in practice it must be unset to avoid confusing
    	     * GTK applications.
    	     */
    	    xtermUnsetenv("DESKTOP_STARTUP_ID");
    	    /*
    	     * We set this temporarily to work around poor design of Xcursor.
    	     * Unset it here to avoid confusion.
    	     */
    	    xtermUnsetenv("XCURSOR_PATH");
    
    	    xtermSetenv("TERM", resource.term_name);
    	    if (!resource.term_name)
    		*get_tcap_buffer(xw) = 0;
    
    	    sprintf(buf, "%lu",
    		    ((unsigned long) XtWindow(SHELL_OF(CURRENT_EMU()))));
    	    xtermSetenv("WINDOWID", buf);
    
    	    /* put the display into the environment of the shell */
    	    xtermSetenv("DISPLAY", XDisplayString(screen->display));
    
    	    xtermSetenv("XTERM_VERSION", xtermVersion());
    	    xtermSetenv("XTERM_LOCALE", xtermEnvLocale());
    
    	    /*
    	     * For debugging only, add environment variables that can be used
    	     * in scripts to selectively kill xterm's parent or child
    	     * processes.
    	     */
    #if OPT_TRACE
    	    sprintf(buf, "%lu", (unsigned long) xterm_parent);
    	    xtermSetenv("XTERM_PARENT", buf);
    	    sprintf(buf, "%lu", (unsigned long) getpid());
    	    xtermSetenv("XTERM_CHILD", buf);
    #endif
    
    	    signal(SIGTERM, SIG_DFL);
    
    	    /* this is the time to go and set up stdin, out, and err
    	     */
    	    {
    #if defined(CRAY) && (OSMAJORVERSION >= 6)
    		close_fd(ttyfd);
    
    		IGNORE_RC(close(0));
    
    		if (open("/dev/tty", O_RDWR)) {
    		    SysError(ERROR_OPDEVTTY);
    		}
    		IGNORE_RC(close(1));
    		IGNORE_RC(close(2));
    		dup(0);
    		dup(0);
    #else
    		/* dup the tty */
    		for (i = 0; i <= 2; i++)
    		    if (i != ttyfd) {
    			IGNORE_RC(close(i));
    			IGNORE_RC(dup(ttyfd));
    		    }
    #ifndef ATT
    		/* and close the tty */
    		if (ttyfd > 2)
    		    close_fd(ttyfd);
    #endif
    #endif /* CRAY */
    	    }
    
    #if !defined(USE_SYSV_PGRP)
    #ifdef TIOCSCTTY
    	    setsid();
    	    ioctl(0, TIOCSCTTY, 0);
    #endif
    	    ioctl(0, TIOCSPGRP, (char *) &pgrp);
    	    setpgrp(0, 0);
    	    close(open(ttydev, O_WRONLY));
    	    setpgrp(0, pgrp);
    #if defined(__QNX__)
    	    tcsetpgrp(0, pgrp /*setsid() */ );
    #endif
    #endif /* !USE_SYSV_PGRP */
    
    #ifdef Lynx
    	    {
    		TERMIO_STRUCT t;
    		if (ttyGetAttr(0, &t) >= 0) {
    		    /* this gets lost somewhere on our way... */
    		    t.c_oflag |= OPOST;
    		    ttySetAttr(0, &t);
    		}
    	    }
    #endif
    
    #ifdef HAVE_UTMP
    	    login_name = NULL;
    	    if (x_getpwuid(screen->uid, &pw)) {
    		login_name = x_getlogin(screen->uid, &pw);
    	    }
    	    if (login_name != NULL) {
    		xtermSetenv("LOGNAME", login_name);	/* for POSIX */
    	    }
    #ifndef USE_UTEMPTER
    #ifdef USE_UTMP_SETGID
    	    setEffectiveGroup(save_egid);
    	    TRACE_IDS;
    #endif
    #ifdef USE_SYSV_UTMP
    	    /* Set up our utmp entry now.  We need to do it here
    	     * for the following reasons:
    	     *   - It needs to have our correct process id (for
    	     *     login).
    	     *   - If our parent was to set it after the fork(),
    	     *     it might make it out before we need it.
    	     *   - We need to do it before we go and change our
    	     *     user and group id's.
    	     */
    	    (void) call_setutent();
    	    init_utmp(DEAD_PROCESS, &utmp);
    
    	    /* position to entry in utmp file */
    	    /* Test return value: beware of entries left behind: PSz 9 Mar 00 */
    	    utret = find_utmp(&utmp);
    	    if (utret == 0) {
    		(void) call_setutent();
    		init_utmp(USER_PROCESS, &utmp);
    		utret = find_utmp(&utmp);
    		if (utret == 0) {
    		    (void) call_setutent();
    		}
    	    }
    #if OPT_TRACE
    	    if (!utret)
    		TRACE(("getutid: NULL\n"));
    	    else
    		TRACE(("getutid: pid=%d type=%d user=%s line=%.*s id=%.*s\n",
    		       (int) utret->ut_pid, utret->ut_type, utret->ut_user,
    		       (int) sizeof(utret->ut_line), utret->ut_line,
    		       (int) sizeof(utret->ut_id), utret->ut_id));
    #endif
    
    	    /* set up the new entry */
    	    utmp.ut_type = USER_PROCESS;
    #ifdef HAVE_UTMP_UT_XSTATUS
    	    utmp.ut_xstatus = 2;
    #endif
    	    copy_filled(utmp.ut_user,
    			(login_name != NULL) ? login_name : "????",
    			sizeof(utmp.ut_user));
    	    /* why are we copying this string again?  (see above) */
    	    copy_filled(utmp.ut_id, my_utmp_id(ttydev), sizeof(utmp.ut_id));
    	    copy_filled(utmp.ut_line,
    			my_pty_name(ttydev), sizeof(utmp.ut_line));
    
    #ifdef HAVE_UTMP_UT_HOST
    	    SetUtmpHost(utmp.ut_host, screen);
    #endif
    #ifdef HAVE_UTMP_UT_SYSLEN
    	    SetUtmpSysLen(utmp);
    #endif
    
    	    copy_filled(utmp.ut_name,
    			(login_name) ? login_name : "????",
    			sizeof(utmp.ut_name));
    
    	    utmp.ut_pid = getpid();
    #if defined(HAVE_UTMP_UT_XTIME)
    #if defined(HAVE_UTMP_UT_SESSION)
    	    utmp.ut_session = getsid(0);
    #endif
    	    utmp.ut_xtime = time((time_t *) 0);
    	    utmp.ut_tv.tv_usec = 0;
    #else
    	    utmp.ut_time = time((time_t *) 0);
    #endif
    
    	    /* write out the entry */
    	    if (!resource.utmpInhibit) {
    		errno = 0;
    		call_pututline(&utmp);
    		TRACE(("pututline: id %.*s, line %.*s, pid %ld, errno %d %s\n",
    		       (int) sizeof(utmp.ut_id), utmp.ut_id,
    		       (int) sizeof(utmp.ut_line), utmp.ut_line,
    		       (long) utmp.ut_pid,
    		       errno, (errno != 0) ? strerror(errno) : ""));
    	    }
    #ifdef WTMP
    #if defined(WTMPX_FILE) && (defined(SVR4) || defined(__SCO__))
    	    if (xw->misc.login_shell)
    		updwtmpx(WTMPX_FILE, &utmp);
    #elif defined(linux) && defined(__GLIBC__) && (__GLIBC__ >= 2) && !(defined(__powerpc__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0))
    	    if (xw->misc.login_shell)
    		call_updwtmp(etc_wtmp, &utmp);
    #else
    	    if (xw->misc.login_shell &&
    		(i = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) {
    		IGNORE_RC(write(i, (char *) &utmp, sizeof(utmp)));
    		close(i);
    	    }
    #endif
    #endif
    	    /* close the file */
    	    (void) call_endutent();
    
    #else /* USE_SYSV_UTMP */
    	    /* We can now get our ttyslot!  We can also set the initial
    	     * utmp entry.
    	     */
    	    tslot = ttyslot();
    	    added_utmp_entry = False;
    	    {
    		if (tslot > 0 && OkPasswd(&pw) && !resource.utmpInhibit &&
    		    (i = open(etc_utmp, O_WRONLY)) >= 0) {
    		    memset(&utmp, 0, sizeof(utmp));
    		    copy_filled(utmp.ut_line,
    				my_pty_name(ttydev),
    				sizeof(utmp.ut_line));
    		    copy_filled(utmp.ut_name, login_name,
    				sizeof(utmp.ut_name));
    #ifdef HAVE_UTMP_UT_HOST
    		    SetUtmpHost(utmp.ut_host, screen);
    #endif
    #ifdef HAVE_UTMP_UT_SYSLEN
    		    SetUtmpSysLen(utmp);
    #endif
    
    		    utmp.ut_time = time((time_t *) 0);
    		    lseek(i, (long) (tslot * sizeof(utmp)), 0);
    		    IGNORE_RC(write(i, (char *) &utmp, sizeof(utmp)));
    		    close(i);
    		    added_utmp_entry = True;
    #if defined(WTMP)
    		    if (xw->misc.login_shell &&
    			(i = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) {
    			int status;
    			status = write(i, (char *) &utmp, sizeof(utmp));
    			status = close(i);
    		    }
    #elif defined(MNX_LASTLOG)
    		    if (xw->misc.login_shell &&
    			(i = open(_U_LASTLOG, O_WRONLY)) >= 0) {
    			lseek(i, (long) (screen->uid *
    					 sizeof(utmp)), 0);
    			IGNORE_RC(write(i, (char *) &utmp, sizeof(utmp)));
    			close(i);
    		    }
    #endif /* WTMP or MNX_LASTLOG */
    		} else
    		    tslot = -tslot;
    	    }
    
    	    /* Let's pass our ttyslot to our parent so that it can
    	     * clean up after us.
    	     */
    #if OPT_PTY_HANDSHAKE
    	    if (resource.ptyHandshake) {
    		handshake.tty_slot = tslot;
    	    }
    #endif /* OPT_PTY_HANDSHAKE */
    #endif /* USE_SYSV_UTMP */
    
    #ifdef USE_LASTLOGX
    	    if (xw->misc.login_shell) {
    		memset(&lastlogx, 0, sizeof(lastlogx));
    		copy_filled(lastlogx.ll_line,
    			    my_pty_name(ttydev),
    			    sizeof(lastlogx.ll_line));
    		X_GETTIMEOFDAY(&lastlogx.ll_tv);
    		SetUtmpHost(lastlogx.ll_host, screen);
    		updlastlogx(_PATH_LASTLOGX, screen->uid, &lastlogx);
    	    }
    #endif
    
    #ifdef USE_LASTLOG
    	    if (xw->misc.login_shell &&
    		(i = open(etc_lastlog, O_WRONLY)) >= 0) {
    		size_t size = sizeof(struct lastlog);
    		off_t offset = (off_t) ((size_t) screen->uid * size);
    
    		memset(&lastlog, 0, size);
    		copy_filled(lastlog.ll_line,
    			    my_pty_name(ttydev),
    			    sizeof(lastlog.ll_line));
    		SetUtmpHost(lastlog.ll_host, screen);
    		lastlog.ll_time = time((time_t *) 0);
    		if (lseek(i, offset, 0) != (off_t) (-1)) {
    		    IGNORE_RC(write(i, (char *) &lastlog, size));
    		}
    		close(i);
    	    }
    #endif /* USE_LASTLOG */
    
    #if defined(USE_UTMP_SETGID)
    	    disableSetGid();
    	    TRACE_IDS;
    #endif
    
    #if OPT_PTY_HANDSHAKE
    	    /* Let our parent know that we set up our utmp entry
    	     * so that it can clean up after us.
    	     */
    	    if (resource.ptyHandshake) {
    		handshake.status = UTMP_ADDED;
    		handshake.error = 0;
    		copy_handshake(handshake, ttydev);
    		TRACE_HANDSHAKE("writing", &handshake);
    		IGNORE_RC(write(cp_pipe[1], (char *) &handshake, sizeof(handshake)));
    	    }
    #endif /* OPT_PTY_HANDSHAKE */
    #endif /* USE_UTEMPTER */
    #endif /* HAVE_UTMP */
    
    	    IGNORE_RC(setgid(screen->gid));
    	    TRACE_IDS;
    #ifdef HAVE_INITGROUPS
    	    if (geteuid() == 0 && OkPasswd(&pw)) {
    		if (initgroups(login_name, pw.pw_gid)) {
    		    perror("initgroups failed");
    		    SysError(ERROR_INIGROUPS);
    		}
    	    }
    #endif
    	    if (setuid(screen->uid)) {
    		SysError(ERROR_SETUID);
    	    }
    	    TRACE_IDS;
    #if OPT_PTY_HANDSHAKE
    	    if (resource.ptyHandshake) {
    		/* mark the pipes as close on exec */
    		(void) fcntl(cp_pipe[1], F_SETFD, 1);
    		(void) fcntl(pc_pipe[0], F_SETFD, 1);
    
    		/* We are at the point where we are going to
    		 * exec our shell (or whatever).  Let our parent
    		 * know we arrived safely.
    		 */
    		handshake.status = PTY_GOOD;
    		handshake.error = 0;
    		copy_handshake(handshake, ttydev);
    		TRACE_HANDSHAKE("writing", &handshake);
    		IGNORE_RC(write(cp_pipe[1],
    				(const char *) &handshake,
    				sizeof(handshake)));
    
    		if (resource.wait_for_map) {
    		    i = (int) read(pc_pipe[0], (char *) &handshake,
    				   sizeof(handshake));
    		    if (i != sizeof(handshake) ||
    			handshake.status != PTY_EXEC) {
    			/* some very bad problem occurred */
    			exit(ERROR_PTY_EXEC);
    		    }
    		    if (handshake.rows > 0 && handshake.cols > 0) {
    			TRACE(("handshake read ttysize: %dx%d\n",
    			       handshake.rows, handshake.cols));
    			set_max_row(screen, handshake.rows);
    			set_max_col(screen, handshake.cols);
    #ifdef TTYSIZE_STRUCT
    			got_handshake_size = True;
    			setup_winsize(ts, MaxRows(screen), MaxCols(screen),
    				      FullHeight(screen), FullWidth(screen));
    			trace_winsize(ts, "got handshake");
    #endif /* TTYSIZE_STRUCT */
    		    }
    		}
    	    }
    #endif /* OPT_PTY_HANDSHAKE */
    
    #ifdef USE_SYSV_ENVVARS
    	    {
    		char numbuf[12];
    		sprintf(numbuf, "%d", MaxCols(screen));
    		xtermSetenv("COLUMNS", numbuf);
    		sprintf(numbuf, "%d", MaxRows(screen));
    		xtermSetenv("LINES", numbuf);
    	    }
    #ifdef HAVE_UTMP
    	    if (OkPasswd(&pw)) {	/* SVR4 doesn't provide these */
    		if (!x_getenv("HOME"))
    		    xtermSetenv("HOME", pw.pw_dir);
    		if (!x_getenv("SHELL"))
    		    xtermSetenv("SHELL", pw.pw_shell);
    	    }
    #endif /* HAVE_UTMP */
    #else /* USE_SYSV_ENVVARS */
    	    if (*(newtc = get_tcap_buffer(xw)) != '\0') {
    		resize_termcap(xw);
    		if (xw->misc.titeInhibit && !xw->misc.tiXtraScroll) {
    		    remove_termcap_entry(newtc, "ti=");
    		    remove_termcap_entry(newtc, "te=");
    		}
    		/*
    		 * work around broken termcap entries */
    		if (resource.useInsertMode) {
    		    remove_termcap_entry(newtc, "ic=");
    		    /* don't get duplicates */
    		    remove_termcap_entry(newtc, "im=");
    		    remove_termcap_entry(newtc, "ei=");
    		    remove_termcap_entry(newtc, "mi");
    		    if (*newtc)
    			strcat(newtc, ":im=\\E[4h:ei=\\E[4l:mi:");
    		}
    		if (*newtc) {
    #if OPT_INITIAL_ERASE
    		    unsigned len;
    		    remove_termcap_entry(newtc, TERMCAP_ERASE "=");
    		    len = (unsigned) strlen(newtc);
    		    if (len != 0 && newtc[len - 1] == ':')
    			len--;
    		    sprintf(newtc + len, ":%s=\\%03o:",
    			    TERMCAP_ERASE,
    			    CharOf(initial_erase));
    #endif
    		    xtermSetenv("TERMCAP", newtc);
    		}
    	    }
    #endif /* USE_SYSV_ENVVARS */
    #ifdef OWN_TERMINFO_ENV
    	    xtermSetenv("TERMINFO", OWN_TERMINFO_DIR);
    #endif
    
    #if OPT_PTY_HANDSHAKE
    	    /*
    	     * Need to reset after all the ioctl bashing we did above.
    	     *
    	     * If we expect the waitForMap logic to set the handshake-size,
    	     * use that to prevent races.
    	     */
    	    TRACE(("should we reset screensize after pty-handshake?\n"));
    	    TRACE(("... ptyHandshake      :%d\n", resource.ptyHandshake));
    	    TRACE(("... ptySttySize       :%d\n", resource.ptySttySize));
    	    TRACE(("... got_handshake_size:%d\n", got_handshake_size));
    	    TRACE(("... wait_for_map0     :%d\n", resource.wait_for_map0));
    	    if (resource.ptyHandshake
    		&& resource.ptySttySize
    		&& (got_handshake_size || !resource.wait_for_map0)) {
    #ifdef TTYSIZE_STRUCT
    		TRACE_RC(i, SET_TTYSIZE(0, ts));
    		trace_winsize(ts, "ptyHandshake SET_TTYSIZE");
    #endif /* TTYSIZE_STRUCT */
    	    }
    #endif /* OPT_PTY_HANDSHAKE */
    	    signal(SIGHUP, SIG_DFL);
    
    	    /*
    	     * If we have an explicit shell to run, make that set $SHELL.
    	     * Next, allow an existing setting of $SHELL, for absolute paths.
    	     * Otherwise, if $SHELL is not set, determine it from the user's
    	     * password information, if possible.
    	     *
    	     * Incidentally, our setting of $SHELL tells luit to use that
    	     * program rather than choosing between $SHELL and "/bin/sh".
    	     */
    	    if (validShell(explicit_shname)) {
    		xtermSetenv("SHELL", explicit_shname);
    	    } else if (validProgram(shell_path = x_getenv("SHELL"))) {
    		if (!validShell(shell_path)) {
    		    xtermUnsetenv("SHELL");
    		}
    	    } else if ((!OkPasswd(&pw) && !x_getpwuid(screen->uid, &pw))
    		       || *(shell_path = x_strdup(pw.pw_shell)) == 0) {
    		shell_path = resetShell(shell_path);
    	    } else if (validShell(shell_path)) {
    		xtermSetenv("SHELL", shell_path);
    	    } else {
    		shell_path = resetShell(shell_path);
    	    }
    
    	    /*
    	     * Set $XTERM_SHELL, which is not necessarily a valid shell, but
    	     * is executable.
    	     */
    	    if (validProgram(explicit_shname)) {
    		shell_path = explicit_shname;
    	    } else if (shell_path == 0) {
    		/* this could happen if the explicit shname lost a race */
    		shell_path = resetShell(shell_path);
    	    }
    	    xtermSetenv("XTERM_SHELL", shell_path);
    
    	    shname = x_basename(shell_path);
    	    TRACE(("shell path '%s' leaf '%s'\n", shell_path, shname));
    
    #if OPT_LUIT_PROG
    	    /*
    	     * Use two copies of command_to_exec, in case luit is not actually
    	     * there, or refuses to run.  In that case we will fall-through to
    	     * to command that the user gave anyway.
    	     */
    	    if (command_to_exec_with_luit && command_to_exec) {
    		char *myShell = xtermFindShell(*command_to_exec_with_luit, False);
    		xtermSetenv("XTERM_SHELL", myShell);
    		free(myShell);
    		TRACE_ARGV("spawning luit command", command_to_exec_with_luit);
    		execvp(*command_to_exec_with_luit, command_to_exec_with_luit);
    		xtermPerror("Can't execvp %s", *command_to_exec_with_luit);
    		xtermWarning("cannot support your locale.\n");
    	    }
    #endif
    	    if (command_to_exec) {
    		char *myShell = xtermFindShell(*command_to_exec, False);
    		xtermSetenv("XTERM_SHELL", myShell);
    		free(myShell);
    		TRACE_ARGV("spawning command", command_to_exec);
    		execvp(*command_to_exec, command_to_exec);
    		if (command_to_exec[1] == 0)
    		    execlp(shell_path, shname, "-c", command_to_exec[0],
    			   (void *) 0);
    		xtermPerror("Can't execvp %s", *command_to_exec);
    	    }
    #ifdef USE_SYSV_SIGHUP
    	    /* fix pts sh hanging around */
    	    signal(SIGHUP, SIG_DFL);
    #endif
    
    	    if ((shname_minus = TextAlloc(strlen(shname) + 1)) != 0) {
    		(void) strcpy(shname_minus, "-");
    		(void) strcat(shname_minus, shname);
    	    } else {
    		static char default_minus[] = "-sh";
    		shname_minus = default_minus;
    	    }
    #ifndef TERMIO_STRUCT
    	    ldisc = (!XStrCmp("csh", shname + strlen(shname) - 3)
    		     ? NTTYDISC
    		     : 0);
    	    ioctl(0, TIOCSETD, (char *) &ldisc);
    #endif /* !TERMIO_STRUCT */
    
    #ifdef USE_LOGIN_DASH_P
    	    if (xw->misc.login_shell && OkPasswd(&pw) && added_utmp_entry)
    		execl(bin_login, "login", "-p", "-f", login_name, (void *) 0);
    #endif
    
    #if OPT_LUIT_PROG
    	    if (command_to_exec_with_luit) {
    		if (xw->misc.login_shell) {
    		    char *params[4];
    		    params[0] = x_strdup("-argv0");
    		    params[1] = shname_minus;
    		    params[2] = NULL;
    		    x_appendargv(command_to_exec_with_luit
    				 + command_length_with_luit,
    				 params);
    		}
    		TRACE_ARGV("final luit command", command_to_exec_with_luit);
    		execvp(*command_to_exec_with_luit, command_to_exec_with_luit);
    		/* Exec failed. */
    		xtermPerror("Can't execvp %s", *command_to_exec_with_luit);
    	    }
    #endif
    	    execlp(shell_path,
    		   (xw->misc.login_shell ? shname_minus : shname),
    		   (void *) 0);
    
    	    /* Exec failed. */
    	    xtermPerror("Could not exec %s", shell_path);
    	    IGNORE_RC(sleep(5));
    	    free(shell_path);
    	    exit(ERROR_EXEC);
    	}
    	/* end if in child after fork */
    #if OPT_PTY_HANDSHAKE
    	if (resource.ptyHandshake) {
    	    /* Parent process.  Let's handle handshaked requests to our
    	     * child process.
    	     */
    
    	    /* close childs's sides of the pipes */
    	    close(cp_pipe[1]);
    	    close(pc_pipe[0]);
    
    	    for (done = 0; !done;) {
    		if (read(cp_pipe[0],
    			 (char *) &handshake,
    			 sizeof(handshake)) <= 0) {
    		    /* Our child is done talking to us.  If it terminated
    		     * due to an error, we will catch the death of child
    		     * and clean up.
    		     */
    		    break;
    		}
    
    		TRACE_HANDSHAKE("read", &handshake);
    		switch (handshake.status) {
    		case PTY_GOOD:
    		    /* Success!  Let's free up resources and
    		     * continue.
    		     */
    		    done = 1;
    		    break;
    
    		case PTY_BAD:
    		    /* The open of the pty failed!  Let's get
    		     * another one.
    		     */
    		    IGNORE_RC(close(screen->respond));
    		    if (get_pty(&screen->respond, XDisplayString(screen->display))) {
    			/* no more ptys! */
    			xtermPerror("child process can find no available ptys");
    			handshake.status = PTY_NOMORE;
    			TRACE_HANDSHAKE("writing", &handshake);
    			IGNORE_RC(write(pc_pipe[1],
    					(const char *) &handshake,
    					sizeof(handshake)));
    			exit(ERROR_PTYS);
    		    }
    		    handshake.status = PTY_NEW;
    		    copy_handshake(handshake, ttydev);
    		    TRACE_HANDSHAKE("writing", &handshake);
    		    IGNORE_RC(write(pc_pipe[1],
    				    (const char *) &handshake,
    				    sizeof(handshake)));
    		    break;
    
    		case PTY_FATALERROR:
    		    errno = handshake.error;
    		    close(cp_pipe[0]);
    		    close(pc_pipe[1]);
    		    SysError(handshake.fatal_error);
    		    /*NOTREACHED */
    
    		case UTMP_ADDED:
    		    /* The utmp entry was set by our slave.  Remember
    		     * this so that we can reset it later.
    		     */
    		    added_utmp_entry = True;
    #ifndef	USE_SYSV_UTMP
    		    tslot = handshake.tty_slot;
    #endif /* USE_SYSV_UTMP */
    		    free(ttydev);
    		    handshake.buffer[HANDSHAKE_LEN - 1] = '\0';
    		    ttydev = x_strdup(handshake.buffer);
    		    break;
    		case PTY_NEW:
    		case PTY_NOMORE:
    		case UTMP_TTYSLOT:
    		case PTY_EXEC:
    		default:
    		    xtermWarning("unexpected handshake status %d\n",
    				 (int) handshake.status);
    		}
    	    }
    	    /* close our sides of the pipes */
    	    if (!resource.wait_for_map) {
    		close(cp_pipe[0]);
    		close(pc_pipe[1]);
    	    }
    	}
    #endif /* OPT_PTY_HANDSHAKE */
        }
    
        /* end if no slave */
        /*
         * still in parent (xterm process)
         */
    #ifdef USE_SYSV_SIGHUP
        /* hung sh problem? */
        signal(SIGHUP, SIG_DFL);
    #else
        signal(SIGHUP, SIG_IGN);
    #endif
    
    /*
     * Unfortunately, System V seems to have trouble divorcing the child process
     * from the process group of xterm.  This is a problem because hitting the
     * INTR or QUIT characters on the keyboard will cause xterm to go away if we
     * don't ignore the signals.  This is annoying.
     */
    
    #if defined(USE_SYSV_SIGNALS) && !defined(SIGTSTP)
        signal(SIGINT, SIG_IGN);
    
    #ifndef SYSV
        /* hung shell problem */
        signal(SIGQUIT, SIG_IGN);
    #endif
        signal(SIGTERM, SIG_IGN);
    #elif defined(SYSV) || defined(__osf__)
        /* if we were spawned by a jobcontrol smart shell (like ksh or csh),
         * then our pgrp and pid will be the same.  If we were spawned by
         * a jobcontrol dumb shell (like /bin/sh), then we will be in our
         * parent's pgrp, and we must ignore keyboard signals, or we will
         * tank on everything.
         */
        if (getpid() == getpgrp()) {
    	(void) signal(SIGINT, Exit);
    	(void) signal(SIGQUIT, Exit);
    	(void) signal(SIGTERM, Exit);
        } else {
    	(void) signal(SIGINT, SIG_IGN);
    	(void) signal(SIGQUIT, SIG_IGN);
    	(void) signal(SIGTERM, SIG_IGN);
        }
        (void) signal(SIGPIPE, Exit);
    #else /* SYSV */
        signal(SIGINT, Exit);
        signal(SIGQUIT, Exit);
        signal(SIGTERM, Exit);
        signal(SIGPIPE, Exit);
    #endif /* USE_SYSV_SIGNALS and not SIGTSTP */
    #ifdef NO_LEAKS
        if (ok_termcap != True)
    	free(TermName);
    #endif
    
        return 0;
    }				/* end spawnXTerm */
    
    void
    Exit(int n)
    {
        XtermWidget xw = term;
        TScreen *screen = TScreenOf(xw);
    
    #ifdef USE_UTEMPTER
        DEBUG_MSG("handle:Exit USE_UTEMPTER\n");
        if (!resource.utmpInhibit && added_utmp_entry) {
    	TRACE(("...calling removeFromUtmp\n"));
    	UTEMPTER_DEL();
        }
    #elif defined(HAVE_UTMP)
    #ifdef USE_SYSV_UTMP
        struct UTMP_STR utmp;
        struct UTMP_STR *utptr;
    
        DEBUG_MSG("handle:Exit USE_SYSV_UTMP\n");
        /* don't do this more than once */
        if (xterm_exiting) {
    	exit(n);
        }
        xterm_exiting = True;
    
    #ifdef PUCC_PTYD
        closepty(ttydev, ptydev, (resource.utmpInhibit ? OPTY_NOP : OPTY_LOGIN), screen->respond);
    #endif /* PUCC_PTYD */
    
        /* cleanup the utmp entry we forged earlier */
        if (!resource.utmpInhibit
    #if OPT_PTY_HANDSHAKE		/* without handshake, no way to know */
    	&& (resource.ptyHandshake && added_utmp_entry)
    #endif /* OPT_PTY_HANDSHAKE */
    	) {
    #if defined(USE_UTMP_SETGID)
    	setEffectiveGroup(save_egid);
    	TRACE_IDS;
    #endif
    	init_utmp(USER_PROCESS, &utmp);
    	(void) call_setutent();
    
    	/*
    	 * We could use getutline() if we didn't support old systems.
    	 */
    	while ((utptr = find_utmp(&utmp)) != 0) {
    	    if (utptr->ut_pid == screen->pid) {
    		utptr->ut_type = DEAD_PROCESS;
    #if defined(HAVE_UTMP_UT_XTIME)
    #if defined(HAVE_UTMP_UT_SESSION)
    		utptr->ut_session = getsid(0);
    #endif
    		utptr->ut_xtime = time((time_t *) 0);
    		utptr->ut_tv.tv_usec = 0;
    #else
    		*utptr->ut_user = 0;
    		utptr->ut_time = time((time_t *) 0);
    #endif
    		(void) call_pututline(utptr);
    #ifdef WTMP
    #if defined(WTMPX_FILE) && (defined(SVR4) || defined(__SCO__))
    		if (xw->misc.login_shell)
    		    updwtmpx(WTMPX_FILE, utptr);
    #elif defined(linux) && defined(__GLIBC__) && (__GLIBC__ >= 2) && !(defined(__powerpc__) && (__GLIBC__ == 2) && (__GLIBC_MINOR__ == 0))
    		copy_filled(utmp.ut_line, utptr->ut_line, sizeof(utmp.ut_line));
    		if (xw->misc.login_shell)
    		    call_updwtmp(etc_wtmp, utptr);
    #else
    		/* set wtmp entry if wtmp file exists */
    		if (xw->misc.login_shell) {
    		    int fd;
    		    if ((fd = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) {
    			IGNORE_RC(write(fd, utptr, sizeof(*utptr)));
    			close(fd);
    		    }
    		}
    #endif
    #endif
    		break;
    	    }
    	    memset(utptr, 0, sizeof(*utptr));	/* keep searching */
    	}
    	(void) call_endutent();
    #ifdef USE_UTMP_SETGID
    	disableSetGid();
    	TRACE_IDS;
    #endif
        }
    #else /* not USE_SYSV_UTMP */
        int wfd;
        struct utmp utmp;
    
        DEBUG_MSG("handle:Exit !USE_SYSV_UTMP\n");
        if (!resource.utmpInhibit && added_utmp_entry &&
    	(am_slave < 0 && tslot > 0)) {
    #if defined(USE_UTMP_SETGID)
    	setEffectiveGroup(save_egid);
    	TRACE_IDS;
    #endif
    	if ((wfd = open(etc_utmp, O_WRONLY)) >= 0) {
    	    memset(&utmp, 0, sizeof(utmp));
    	    lseek(wfd, (long) (tslot * sizeof(utmp)), 0);
    	    IGNORE_RC(write(wfd, (char *) &utmp, sizeof(utmp)));
    	    close(wfd);
    	}
    #ifdef WTMP
    	if (xw->misc.login_shell &&
    	    (wfd = open(etc_wtmp, O_WRONLY | O_APPEND)) >= 0) {
    	    copy_filled(utmp.ut_line,
    			my_pty_name(ttydev),
    			sizeof(utmp.ut_line));
    	    utmp.ut_time = time((time_t *) 0);
    	    IGNORE_RC(write(wfd, (char *) &utmp, sizeof(utmp)));
    	    close(wfd);
    	}
    #endif /* WTMP */
    #ifdef USE_UTMP_SETGID
    	disableSetGid();
    	TRACE_IDS;
    #endif
        }
    #endif /* USE_SYSV_UTMP */
    #endif /* HAVE_UTMP */
    
        cleanup_colored_cursor();
    
        /*
         * Flush pending data before releasing ownership, so nobody else can write
         * in the middle of the data.
         */
        ttyFlush(screen->respond);
    
    #ifdef USE_PTY_SEARCH
        if (am_slave < 0) {
    	TRACE_IDS;
    	/* restore ownership of tty and pty */
    	set_owner(ttydev, 0, 0, 0666U);
    #if (defined(USE_PTY_DEVICE) && !defined(__sgi) && !defined(__hpux))
    	set_owner(ptydev, 0, 0, 0666U);
    #endif
        }
    #endif
    
        /*
         * Close after releasing ownership to avoid race condition: other programs
         * grabbing it, and *then* having us release ownership....
         */
        close(screen->respond);	/* close explicitly to avoid race with slave side */
    #ifdef ALLOWLOGGING
        if (screen->logging)
    	CloseLog(xw);
    #endif
    
        xtermPrintOnXError(xw, n);
    
    #ifdef NO_LEAKS
        if (n == 0) {
    	Display *dpy = TScreenOf(xw)->display;
    
    	TRACE(("Freeing memory leaks\n"));
    
    	if (toplevel) {
    	    XtDestroyWidget(toplevel);
    	    TRACE(("destroyed top-level widget\n"));
    	}
    	sortedOpts(0, 0, 0);
    	noleaks_charproc();
    	noleaks_ptydata();
    #if OPT_GRAPHICS
    	noleaks_graphics();
    #endif
    #if OPT_WIDE_CHARS
    	noleaks_CharacterClass();
    #endif
    	/* XrmSetDatabase(dpy, 0); increases leaks ;-) */
    	XtCloseDisplay(dpy);
    	XtDestroyApplicationContext(app_con);
    	xtermCloseSession();
    	TRACE(("closed display\n"));
    
    	TRACE_CLOSE();
        }
    #endif
    
        exit(n);
    }
    
    /* ARGSUSED */
    static void
    resize_termcap(XtermWidget xw)
    {
        char *newtc = get_tcap_buffer(xw);
    
    #ifndef USE_SYSV_ENVVARS
        if (!TEK4014_ACTIVE(xw) && *newtc) {
    	TScreen *screen = TScreenOf(xw);
    	char *ptr1, *ptr2;
    	size_t i;
    	int li_first = 0;
    	char *temp;
    	char oldtc[TERMCAP_SIZE];
    
    	strcpy(oldtc, newtc);
    	TRACE(("resize %s\n", oldtc));
    	if ((ptr1 = x_strindex(oldtc, "co#")) == NULL) {
    	    strcat(oldtc, "co#80:");
    	    ptr1 = x_strindex(oldtc, "co#");
    	}
    	if ((ptr2 = x_strindex(oldtc, "li#")) == NULL) {
    	    strcat(oldtc, "li#24:");
    	    ptr2 = x_strindex(oldtc, "li#");
    	}
    	if (ptr1 > ptr2) {
    	    li_first++;
    	    temp = ptr1;
    	    ptr1 = ptr2;
    	    ptr2 = temp;
    	}
    	ptr1 += 3;
    	ptr2 += 3;
    	strncpy(newtc, oldtc, i = (size_t) (ptr1 - oldtc));
    	temp = newtc + i;
    	sprintf(temp, "%d", (li_first
    			     ? MaxRows(screen)
    			     : MaxCols(screen)));
    	temp += strlen(temp);
    	if ((ptr1 = strchr(ptr1, ':')) != 0 && (ptr1 < ptr2)) {
    	    strncpy(temp, ptr1, i = (size_t) (ptr2 - ptr1));
    	    temp += i;
    	    sprintf(temp, "%d", (li_first
    				 ? MaxCols(screen)
    				 : MaxRows(screen)));
    	    if ((ptr2 = strchr(ptr2, ':')) != 0) {
    		strcat(temp, ptr2);
    	    }
    	}
    	TRACE(("   ==> %s\n", newtc));
    	TRACE(("   new size %dx%d\n", MaxRows(screen), MaxCols(screen)));
        }
    #endif /* USE_SYSV_ENVVARS */
    }
    
    #endif /* ! VMS */
    
    /*
     * Does a non-blocking wait for a child process.  If the system
     * doesn't support non-blocking wait, do nothing.
     * Returns the pid of the child, or 0 or -1 if none or error.
     */
    int
    nonblocking_wait(void)
    {
    #ifdef USE_POSIX_WAIT
        pid_t pid;
    
        pid = waitpid(-1, NULL, WNOHANG);
    #elif defined(USE_SYSV_SIGNALS) && (defined(CRAY) || !defined(SIGTSTP))
        /* cannot do non-blocking wait */
        int pid = 0;
    #else /* defined(USE_SYSV_SIGNALS) && (defined(CRAY) || !defined(SIGTSTP)) */
    #if defined(Lynx)
        int status;
    #else
        union wait status;
    #endif
        int pid;
    
        pid = wait3(&status, WNOHANG, (struct rusage *) NULL);
    #endif /* USE_POSIX_WAIT else */
        return pid;
    }
    
    #ifndef VMS
    
    /* ARGSUSED */
    static void
    reapchild(int n GCC_UNUSED)
    {
        int olderrno = errno;
        int pid;
    
        DEBUG_MSG("handle:reapchild\n");
    
        pid = wait(NULL);
    
    #ifdef USE_SYSV_SIGNALS
        /* cannot re-enable signal before waiting for child
         * because then SVR4 loops.  Sigh.  HP-UX 9.01 too.
         */
        (void) signal(SIGCHLD, reapchild);
    #endif
    
        do {
    	if (pid == TScreenOf(term)->pid) {
    	    DEBUG_MSG("Exiting\n");
    	    if (hold_screen)
    		caught_intr = True;
    	    else
    		need_cleanup = True;
    	}
        } while ((pid = nonblocking_wait()) > 0);
    
        errno = olderrno;
    }
    #endif /* !VMS */
    
    static void
    remove_termcap_entry(char *buf, const char *str)
    {
        char *base = buf;
        char *first = base;
        int count = 0;
        size_t len = strlen(str);
    
        TRACE(("*** remove_termcap_entry('%s', '%s')\n", str, buf));
    
        while (*buf != 0) {
    	if (!count && !strncmp(buf, str, len)) {
    	    while (*buf != 0) {
    		if (*buf == '\\')
    		    buf++;
    		else if (*buf == ':')
    		    break;
    		if (*buf != 0)
    		    buf++;
    	    }
    	    while ((*first++ = *buf++) != 0) {
    		;
    	    }
    	    TRACE(("...removed_termcap_entry('%s', '%s')\n", str, base));
    	    return;
    	} else if (*buf == '\\') {
    	    buf++;
    	} else if (*buf == ':') {
    	    first = buf;
    	    count = 0;
    	} else if (!isspace(CharOf(*buf))) {
    	    count++;
    	}
    	if (*buf != 0)
    	    buf++;
        }
        TRACE(("...cannot remove\n"));
    }
    
    /*
     * parse_tty_modes accepts lines of the following form:
     *
     *         [SETTING] ...
     *
     * where setting consists of the words in the ttyModes[] array followed by a
     * character or ^char.
     */
    static int
    parse_tty_modes(char *s)
    {
        int c;
        Cardinal j, k;
        int count = 0;
        Boolean found;
    
        TRACE(("parse_tty_modes\n"));
        for (;;) {
    	size_t len;
    
    	while (*s && isspace(CharOf(*s))) {
    	    s++;
    	}
    	if (!*s) {
    	    return count;
    	}
    
    	for (len = 0; s[len] && !isspace(CharOf(s[len])); ++len) {
    	    ;
    	}
    	found = False;
    	for (j = 0; j < XtNumber(ttyModes); ++j) {
    	    if (len == ttyModes[j].len
    		&& strncmp(s,
    			   ttyModes[j].name,
    			   ttyModes[j].len) == 0) {
    		found = True;
    		break;
    	    }
    	}
    	if (!found) {
    	    return -1;
    	}
    
    	s += ttyModes[j].len;
    	while (*s && isspace(CharOf(*s))) {
    	    s++;
    	}
    
    	/* check if this needs a parameter */
    	found = False;
    	for (k = 0, c = 0; k < XtNumber(ttyChars); ++k) {
    	    if ((int) j == ttyChars[k].myMode) {
    		if (ttyChars[k].sysMode < 0) {
    		    found = True;
    		    c = ttyChars[k].myDefault;
    		}
    		break;
    	    }
    	}
    
    	if (!found) {
    	    if (!*s
    		|| (c = decode_keyvalue(&s, False)) == -1) {
    		return -1;
    	    }
    	}
    	ttyModes[j].value = c;
    	ttyModes[j].set = 1;
    	count++;
    	TRACE(("...parsed #%d: %s=%#x\n", count, ttyModes[j].name, c));
        }
    }
    
    #ifndef VMS			/* don't use pipes on OpenVMS */
    int
    GetBytesAvailable(int fd)
    {
    #if defined(FIONREAD)
        int arg;
        ioctl(fd, FIONREAD, (char *) &arg);
        return (int) arg;
    #elif defined(__CYGWIN__)
        fd_set set;
        struct timeval select_timeout =
        {0, 0};
    
        FD_ZERO(&set);
        FD_SET(fd, &set);
        if (Select(fd + 1, &set, NULL, NULL, &select_timeout) > 0)
    	return 1;
        else
    	return 0;
    #elif defined(FIORDCK)
        return (ioctl(fd, FIORDCHK, NULL));
    #else /* !FIORDCK */
        struct pollfd pollfds[1];
    
        pollfds[0].fd = fd;
        pollfds[0].events = POLLIN;
        return poll(pollfds, 1, 0);
    #endif
    }
    #endif /* !VMS */
    
    /* Utility function to try to hide system differences from
       everybody who used to call killpg() */
    
    int
    kill_process_group(int pid, int sig)
    {
        TRACE(("kill_process_group(pid=%d, sig=%d)\n", pid, sig));
    #if defined(SVR4) || defined(SYSV) || !defined(X_NOT_POSIX)
        return kill(-pid, sig);
    #else
        return killpg(pid, sig);
    #endif
    }
    
    #if OPT_EBCDIC
    int
    A2E(int x)
    {
        char c;
        c = x;
        __atoe_l(&c, 1);
        return c;
    }
    
    int
    E2A(int x)
    {
        char c;
        c = x;
        __etoa_l(&c, 1);
        return c;
    }
    #endif
    
    #if defined(__QNX__) && !defined(__QNXNTO__)
    #include 
    #include 
    #include 
    #include 
    #include 
    
    struct _proc_session ps;
    struct _proc_session_reply rps;
    
    int
    qsetlogin(char *login, char *ttyname)
    {
        int v = getsid(getpid());
    
        memset(&ps, 0, sizeof(ps));
        memset(&rps, 0, sizeof(rps));
    
        ps.type = _PROC_SESSION;
        ps.subtype = _PROC_SUB_ACTION1;
        ps.sid = v;
        strcpy(ps.name, login);
    
        Send(1, &ps, &rps, sizeof(ps), sizeof(rps));
    
        if (rps.status < 0)
    	return (rps.status);
    
        ps.type = _PROC_SESSION;
        ps.subtype = _PROC_SUB_ACTION2;
        ps.sid = v;
        sprintf(ps.name, "//%d%s", getnid(), ttyname);
        Send(1, &ps, &rps, sizeof(ps), sizeof(rps));
    
        return (rps.status);
    }
    #endif
    
    #ifdef __minix
    int
    setpgrp(void)
    {
        return 0;
    }
    
    void
    _longjmp(jmp_buf _env, int _val)
    {
        longjmp(_env, _val);
    }
    #endif
    xterm-353/MANIFEST0000644000175100001440000003313513610624747012414 0ustar  tomusersMANIFEST for xterm-353, version xterm-353
    --------------------------------------------------------------------------------
    MANIFEST                        this file
    256colres.h                     resource-definitions for 256-color mode
    256colres.pl                    script to generate 256colres.h
    88colres.h                      resource definitions for 88-color mode
    88colres.pl                     script to generate 88colres.h
    AAA_README_VMS.txt              note for VMS port of 'xterm'
    COPYING                         license for this program
    INSTALL                         configure script: options and related install instructions
    Imakefile                       imake template for Makefile
    KOI8RXTerm.ad                   resources for koi8rxterm
    Makefile.in                     configure script template for Makefile
    README                          overview & caveats for 'xterm'
    README.i18n                     i18n readme:
    README.os390                    overview for os390 (EBCDIC) port of 'xterm'
    THANKS                          list of direct contributors
    TekPrsTbl.c                     Tek4014 parser state tables
    Tekparse.def                    template for generating Tekparse.h
    Tekparse.h                      Tek4014 parser-state definitions
    Tekproc.c                       Tek4014 parser-state functions
    Tests                           Useful tests for xterm-developers
    UXTerm.ad                       alternate resources for UTF-8
    VTPrsTbl.c                      VT100 parser state tables
    VTparse.def                     template for generating VTparse.h
    VTparse.h                       VT100 parser-state definitions
    XTerm-col.ad                    color resource definitions for XTerm class
    XTerm.ad                        resource definitions for XTerm class
    aclocal.m4                      configure script: custom macros
    button.c                        mouse button and selection processing
    cachedGCs.c                     maintain cache of GC's
    charclass.c                     compact character-class module
    charclass.h                     interface of charclass.c
    charproc.c                      VT100 parser functions
    charsets.c                      module to translate character-sets
    config.guess                    configure script: guess the system type
    config.sub                      configure script: validate system type
    configure                       generated
    configure.in                    template for generating configure script
    ctlseqs.ms                      documentation: Xterm Control Sequences
    ctlseqs.txt                     generated rendition of ctlseqs.ms
    cursor.c                        VT100 low-level cursor movement
    data.c                          global data declarations
    data.h                          global data external-definitions
    df-install.in                   utility script for desktop-files
    doublechr.c                     VT100 double-size character support
    error.h                         error-code definitions for 'xterm'
    fontutils.c                     xterm functions for (re)loading fonts
    fontutils.h                     interface of fontutils.c
    gen-charsets.pl                 script to convert codepages into code
    gen-pc-fkeys.pl                 script to generate extended function-key terminfo
    graphics.c                      graphics support functions for 'xterm'
    graphics.h                      interface of graphics.c
    graphics_regis.c                support for ReGIS
    graphics_regis.h                interface of graphics_regis.c
    graphics_sixel.c                support for Sixels
    graphics_sixel.h                interface of graphics_sixel.c
    html.c                          format HTML-screendumps
    input.c                         VT100 key-symbol and function-key translation
    install-sh                      install-script (needed by configure)
    keysym2ucs.c                    lookup-table for UTF-8 to keysyms
    keysym2ucs.h                    interface of keysym2ucs.c
    koi8rxterm                      KOI-8 wrapper from Debian (originally me)
    koi8rxterm.man                  manpage for koi8rxterm
    linedata.c                      manage all line-data for VT100 widget
    link_axp.com                    build-script for VMS port of xterm
    main.c                          main program of 'xterm'
    main.h                          default definitions for 'xterm'
    make.com                        build-script for VMS port of 'xterm'
    menu.c                          popup/pulldown menus for 'xterm'
    menu.h                          interface of menu.c
    minstall.in                     script for installing manpages
    misc.c                          miscellaneous utility functions for 'xterm'
    plink.sh                        script to prune unneeded libraries from link
    precompose.c                    table of precompose sequences
    precompose.h                    interface of precompose.c
    print.c                         VT100+ print support functions
    ptydata.c                       functions to manipulate data read from pty
    ptyx.h                          structure-definitions for 'xterm'
    resize.c                        program to compute/modify xterm's window size
    resize.man                      manual page for 'resize'
    run-tic.sh                      run tic, filtering out harmless messages
    screen.c                        VT100 screen update functions
    scrollback.c                    manage scrollback (a big FIFO)
    scrollbar.c                     VT100 scrollbar support functions
    sinstall.sh                     install setuid if existing program was
    svg.c                           format SVG-screendumps
    tabs.c                          VT100 tabstop support-functions
    termcap                         termcap entries for 'xterm'
    terminfo                        terminfo entries for 'xterm'
    testxmc.c                       testing: xmc/magic-cookies
    trace.c                         debugging trace functions for 'xterm'
    trace.h                         interface of trace.c
    util.c                          miscellaneous utility functions for 'xterm'
    uxterm                          wrapper script to make unicode-xterm
    uxterm.desktop                  sample desktop file for uxterm
    uxterm.man                      manpage for uxterm, from Debian
    version.c                       xterm package version, used also in resize
    version.h                       version of xterm
    vms.c                           VMS version of xterm's spawn(), etc.
    vms.h                           system headers and definitions for vms.c
    wcwidth.c                       wide-character utility functions
    wcwidth.h                       interface of wcwidth.c
    xcharmouse.h                    Jason Bacon's mouse-defs, cleaned up a little
    xstrings.c                      a few common string functions
    xstrings.h                      interface of xstrings.c
    xterm.appdata.xml               sample "appdata.xml" file
    xterm.dat                       application defaults for VMS port of 'xterm'
    xterm.desktop                   sample desktop file for xterm.
    xterm.h                         common includes, definitions and prototypes for 'xterm'
    xterm.log.html                  changelog for xterm
    xterm.man                       manual page for 'xterm'
    xterm_axp.opt                   linker options file for VMS port of 'xterm'
    xterm_io.h                      split-out definitions of termio/termios/sgtty and winsize from main.c, os2main.c, screen.c and resize.c
    xtermcap.c                      termcap-related functions.
    xtermcap.h                      interface of xtermcap.c
    xtermcfg.hin                    configure script: template for xtermcfg.h
    xutf8.c                         JC's cleanup of UTF8
    xutf8.h                         JC's cleanup of UTF8
    icons                           subdirectory
    icons/filled-xterm.png          filled-xterm variants
    icons/filled-xterm.svg          filled-xterm variants
    icons/filled-xterm.xpms         filled-xterm variants
    icons/filled-xterm_16x16.xpm    filled-xterm variants
    icons/filled-xterm_32x32.xpm    filled-xterm variants
    icons/filled-xterm_48x48.xpm    filled-xterm variants
    icons/make-xpms                 script to make combined xpm-icons
    icons/mini.xterm.svg            svg format for mini-icon
    icons/mini.xterm.xpms           collection of mini-icons
    icons/mini.xterm_16x16.png      mini-icon 16x16 png
    icons/mini.xterm_16x16.xpm      mini-icon 16x16 pixmap
    icons/mini.xterm_256x256.png    mini-icon 256x256 png
    icons/mini.xterm_32x32.png      mini-icon 32x32 png
    icons/mini.xterm_32x32.xpm      mini-icon 32x32 pixmap
    icons/mini.xterm_48x48.png      mini-icon 48x48 png
    icons/mini.xterm_48x48.xpm      mini-icon 48x48 pixmap
    icons/terminal_48x48.svg        svg-format of "terminal"
    icons/terminal_48x48.xpm        xpm-format of "terminal"
    icons/xterm-color.png           xterm-color 48x48, in png-format
    icons/xterm-color.svg           xterm-color icon
    icons/xterm-color.xpms          collection of color icons
    icons/xterm-color_16x16.xpm     16x16 color icon
    icons/xterm-color_32x32.xpm     32x32 color icon
    icons/xterm-color_48x48.xpm     48x48 color icon
    icons/xterm.png                 xterm 48x48, in png-format
    icons/xterm.svg                 xterm icon
    icons/xterm.xpms                collection of icons
    icons/xterm_16x16.xpm           normal icon 16x16 pixmap
    icons/xterm_32x32.xpm           32x32 monochrome icon
    icons/xterm_48x48.xpm           48x48 monochrome icon
    package/debian                  subdirectory
    package/debian/changelog        build-script
    package/debian/color.sed        build-script
    package/debian/compat           build-script
    package/debian/control          build-script
    package/debian/copyright        build-script
    package/debian/postinst         post-install script for update-alternatives
    package/debian/prerm            pre-remove script for update-alternatives
    package/debian/rules            build-script
    package/debian/source           subdirectory
    package/debian/source/format    build-script
    package/debian                  subdirectory
    package/debian/watch            build-script
    package/debian/xterm-dev.docs   build-script
    package/debian/xterm-dev.lintian-overrides  ignore useless warnings from lintian
    package/debian/xterm-dev.menu   Debian menu-file for xterm-dev package.
    package/debian/xterm-xres.sed   build-script
    package/freebsd                 subdirectory
    package/freebsd/Makefile        build-script
    package/freebsd/distinfo        generated sums
    package/freebsd/pkg-descr       build-script
    package/freebsd/pkg-message     build-script
    package/freebsd/pkg-message.wchar  build-script
    package/freebsd/pkg-plist       build-script
    package/pkgsrc                  subdirectory
    package/pkgsrc/DESCR            build-script
    package/pkgsrc/Makefile         build-script
    package/pkgsrc/PLIST            build-script
    package/pkgsrc/distinfo         build-script
    package/pkgsrc/options.mk       build-script
    package                         subdirectory
    package/xterm.spec              build-script
    tektests                        subdirectory
    tektests/aitest.tek             tek4014 demo: draw a globe
    tektests/dmerc.tek              tek4014 demo: draws a Mercator projection with orbit
    tektests/fotest.tek             tek4014 demo: draw a scatterplot on log scale
    tektests/imtest.tek             tek4014 demo: draw a test pattern
    tektests/imtesth.tek            tek4014 demo: draw a test pattern
    tektests/ocpred.tek             tek4014 demo: an occultation prediction
    tektests/usmap.tek              tek4014 demo: a US map
    unicode                         subdirectory
    unicode/README                  description of files in ./unicode
    unicode/convmap.pl              perl script for generating the lookup table for UTF-8 to keysym
    unicode/keysym.map              keysym mapping from UTF-8
    unicode/make-precompose.sh      make precompose.c
    unicode/precompose.c.head       header of precompose.c
    unicode/precompose.c.tail       tail of precompose.c
    vttests                         subdirectory
    vttests/16colors.sh             test-script to show 16-colors
    vttests/256colors.pl            script to illustrate 256-colors
    vttests/256colors2.pl           fancy test-script for 256-colors
    vttests/88colors.pl             sample script showing 88-colors
    vttests/88colors2.pl            sample script showing 88-colors
    vttests/8colors.sh              test-script to illustrate 8-colors
    vttests/acolors.sh              demonstrate changing the ANSI colors
    vttests/closest-rgb.pl          demo of color-distances
    vttests/doublechars.sh          test script to demonstrate doublesize chars
    vttests/dynamic.pl              demo for dynamic colors
    vttests/dynamic.sh              script to illustrate the dynamic colors control sequence
    vttests/dynamic2.sh             complete example of dynamic colors
    vttests/fonts.sh                script to demonstrate font-switching sequences
    vttests/modify-keys.pl          illustrate modifyOtherKeys with a table
    vttests/mouse-codes             demo script for mouse-codes
    vttests/other-sgr.sh            demonstrate non-VTxx SGRs
    vttests/paste64.pl              script to test base64-selection option
    vttests/print-vt-chars.pl       demo-script
    vttests/query-color.pl          demonstrate OSC 4
    vttests/query-dynamic.pl        demonstrate OSC 10 to OSC 19
    vttests/query-fonts.pl          script to demo/test font-querying
    vttests/query-status.pl         query DECRQSS status
    vttests/query-xres.pl           test/demo for DCS+Q
    vttests/report-sgr.pl           demonstrate report-sgr
    vttests/resize.pl               translated resize.sh to perl since it is easy to test, and I needed
    vttests/resize.sh               script to demonstrate resizing
    vttests/sgrPushPop.pl           demonstrate xterm SGR push/pop
    vttests/sgrPushPop2.pl          demonstrate xterm SGR push/pop for colors
    vttests/tcapquery.pl            script to test tcap-query option
    vttests/title.sh                test-script to show title of xterm in action
    xterm-353/resize.man0000644000175100001440000001717513426674314013267 0ustar  tomusers.\" $XTermId: resize.man,v 1.37 2019/02/07 00:16:12 tom Exp $
    .\"
    .\" Copyright 1998-2017,2019 by Thomas E. Dickey
    .\"
    .\"                         All Rights Reserved
    .\"
    .\" Permission is hereby granted, free of charge, to any person obtaining a
    .\" copy of this software and associated documentation files (the
    .\" "Software"), to deal in the Software without restriction, including
    .\" without limitation the rights to use, copy, modify, merge, publish,
    .\" distribute, sublicense, and/or sell copies of the Software, and to
    .\" permit persons to whom the Software is furnished to do so, subject to
    .\" the following conditions:
    .\"
    .\" The above copyright notice and this permission notice shall be included
    .\" in all copies or substantial portions of the Software.
    .\"
    .\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    .\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    .\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    .\" IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
    .\" CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    .\" TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    .\" SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    .\"
    .\" Except as contained in this notice, the name(s) of the above copyright
    .\" holders shall not be used in advertising or otherwise to promote the
    .\" sale, use or other dealings in this Software without prior written
    .\" authorization.
    .\"
    .\" updated by Thomas E. Dickey for XFree86, 1998-2006.
    .\"
    .ds N Resize
    .ds n resize
    .\"
    .\" Bulleted paragraph
    .de bP
    .ie n  .IP \(bu 4
    .el    .IP \(bu 2
    ..
    .\" Escape single quotes in literal strings from groff's Unicode transform.
    .ie \n(.g .ds AQ \(aq
    .el       .ds AQ '
    .ie \n(.g .ds `` \(lq
    .el       .ds `` ``
    .ie \n(.g .ds '' \(rq
    .el       .ds '' ''
    .TH RESIZE 1 "__app_date__" "__app_version__" "X Window System"
    .SH NAME
    resize \- set environment and terminal settings to current xterm window size
    .SH SYNOPSIS
    .B \*n
    [ \fB\-v\fP | \fB\-u\fP | \fB\-c\fP ] [ \fB\-s\fP [ \fIrow col\fP ] ]
    .SH DESCRIPTION
    .I \*N
    prints a shell command for setting the appropriate environment variables
    to indicate the current size of \fIxterm\fP window from which the command
    is run.
    .PP
    .I \*N
    determines the command through several steps:
    .bP
    first, it finds the name of the user's shell program.
    It uses the \fBSHELL\fP variable if set,
    otherwise it uses the user's data from /etc/passwd.
    .bP
    then it decides whether to use Bourne shell syntax or C-Shell syntax.
    It uses a built-in table of known shells,
    which can be overridden by the \fB\-u\fP and \fB\-c\fP options.
    .bP
    then \fI\*n\fP asks the operating system for the terminal settings.
    This is the same information which can be manipulated using \fIstty\fP.
    .bP
    then \fI\*n\fP asks the terminal for its size in characters.
    Depending on whether the "\fB\-s\fP option is given,
    \fI\*n\fP uses a different escape sequence to ask for this information.
    .bP
    at this point, \fI\*n\fP attempts to update the terminal settings
    to reflect the terminal window's size in pixels:
    .RS
    .bP
    if the \fB\-s\fP option is used,
    \fI\*n\fP then asks the terminal for its size in pixels.
    .bP
    otherwise,
    \fI\*n\fP asks the operating system for the information
    and updates that after ensuring that the window's dimensions are
    a multiple of the character height and width.
    .bP
    in either case, the updated terminal settings are done
    using a different system call than used for \fIstty\fP.
    .RE
    .bP
    then \fI\*n\fP updates the terminal settings to reflect any altered
    values such as its size in rows or columns.
    This affects the values shown by \fIstty\fP.
    .bP
    finally, \fI\*n\fP generates shell commands for setting the
    environment variables,
    and writes that to the standard output.
    .SH EXAMPLES
    For \fI\*n\fP's output to take effect,
    \fI\*n\fP must either be evaluated
    as part of the command line (usually done with a shell alias or function) or
    else redirected to a file which can then be read in.
    From the C shell (usually
    known as \fI/bin/csh\fP), the following alias could be defined in the
    user's \fI.cshrc\fP:
    .sp
    .nf
            %  alias rs \*(AQset noglob; eval \fC\`\fP\*n\fC\`\fP\*(AQ
    .fi
    .sp
    After resizing the window, the user would type:
    .sp
    .nf
            %  rs
    .fi
    .sp
    Users of versions of the Bourne shell (usually known as \fI/bin/sh\fP) that
    don't have command
    functions will need to send the output to a temporary file and then read it back
    in with the \*(``.\*('' command:
    .sp
    .nf
            $  \*n > /tmp/out
            $  .\0/tmp/out
    .fi
    .SH OPTIONS
    The following options may be used with \fI\*n\fP:
    .TP 8
    .B \-c
    This option indicates that C shell commands should be generated even if the
    user's current shell does not appear to use C shell syntax.
    .TP 8
    .B \-s \fR[\fIrows columns\fP]
    This option indicates that Sun console escape sequences will be used
    instead of the VT100-style \fIxterm\fP escape codes.
    If \fIrows\fP and
    \fIcolumns\fP are given,
    \fI\*n\fP will ask the \fIxterm\fP to resize itself using those values.
    .IP
    Both of the escape sequences used for this option
    (first to obtain the window size and
    second to modify it)
    are subject to \fIxterm\fP's \fBallowWindowOps\fP resource setting.
    The window manager may also choose to disallow the change.
    .IP
    The VT100-style escape sequence used to determine the
    screen size always works for VT100-compatible terminals.
    VT100s have no corresponding way to modify the screensize.
    .TP 8
    .B \-u
    This option indicates that Bourne shell commands should be generated even if
    the user's current shell does not appear to use Bourne shell syntax.
    .TP 8
    .B \-v
    This causes \fI\*n\fP to print a version number to the standard output,
    and then exit.
    .PP
    Note that the Sun console escape sequences are recognized
    by XFree86 \fIxterm\fP and
    by \fIdtterm\fP.
    The \fI\*n\fP program may be installed as \fIsunsize\fP,
    which causes makes it assume the \fB\-s\fP option.
    .PP
    The \fIrows\fP and
    \fIcolumns\fP arguments must appear last; though they are normally
    associated with the \fB\-s\fP option, they are parsed separately.
    .SH FILES
    .TP 15
    /etc/termcap
    for the base termcap entry to modify.
    .TP 15
    ~/.cshrc
    user's alias for the command.
    .SH ENVIRONMENT
    .TP 15
    SHELL
    Unless overridden by the \fB\-c\fP option,
    \fI\*n\fP determines the user's current shell by
    .RS
    .bP
    first checking if \fB$SHELL\fP
    is set, and using that,
    .bP
    otherwise \fI\*n\fP looks in the password file
    (/etc/passwd).
    .RE
    .IP
    Generally Bourne-shell variants (including \fIksh\fP)
    do not modify \fB$SHELL\fP,
    so it is possible for \fI\*n\fP to be confused if one runs
    \fI\*n\fP from a Bourne shell spawned from a C shell.
    .IP
    After determining the user's shell, \fI\*n\fP  checks the shell's name
    against a table of known shell names.
    If it does not find the name in its table, \fI\*n\fP will use
    C shell syntax for the generated commands to set environment variables.
    .TP 15
    TERM
    .IR \*N 's
    generated shell command
    sets this to "__default_termname__" if not already set.
    .TP 15
    TERMCAP
    .IR \*N 's
    generated shell command
    sets this variable on systems using termcap,
    e.g., when \fI\*n\fP is linked with the \fItermcap\fP library
    rather than a \fIterminfo\fP library.
    The latter does not provide the complete text for a termcap entry.
    .TP 15
    COLUMNS, LINES
    .IR \*N 's
    generated shell command
    sets these variables on systems using terminfo.
    Many applications (including the curses library) 
    use those variables when set to override their screensize.
    .SH "SEE ALSO"
    use_env(3x)
    .br
    csh(1), stty(1), tset(1)
    .br
    xterm(__mansuffix__)
    .SH AUTHORS
    Mark Vandevoorde (MIT-Athena), Edward Moy (Berkeley)
    .br
    Thomas Dickey (invisible-island.net).
    .br
    Copyright (c) 1984, 1985 by X Consortium
    .br
    See
    .IR X (__miscmansuffix__)
    for a complete copyright notice.
    xterm-353/precompose.h0000644000175100001440000000040407152532744013600 0ustar  tomusers/* $XFree86: xc/programs/xterm/precompose.h,v 1.1 2000/08/26 04:33:54 dawes Exp $ */
    
    #ifndef PRECOMPOSE_H
    #define PRECOMPOSE_H
    
    int do_precomposition(int base, int comb);
    
    /* returns unicode value if a canonical composition exists,
       otherwise -1 */
    
    #endif
    xterm-353/configure.in0000644000175100001440000011415413606425327013573 0ustar  tomusersdnl $XTermId: configure.in,v 1.368 2020/01/11 20:06:47 tom Exp $
    dnl
    dnl -----------------------------------------------------------------------------
    dnl this file is part of xterm
    dnl
    dnl Copyright 1997-2019,2020 by Thomas E. Dickey
    dnl
    dnl                         All Rights Reserved
    dnl
    dnl Permission is hereby granted, free of charge, to any person obtaining a
    dnl copy of this software and associated documentation files (the
    dnl "Software"), to deal in the Software without restriction, including
    dnl without limitation the rights to use, copy, modify, merge, publish,
    dnl distribute, sublicense, and/or sell copies of the Software, and to
    dnl permit persons to whom the Software is furnished to do so, subject to
    dnl the following conditions:
    dnl
    dnl The above copyright notice and this permission notice shall be included
    dnl in all copies or substantial portions of the Software.
    dnl
    dnl THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    dnl OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    dnl MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    dnl IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
    dnl CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    dnl TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    dnl SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    dnl
    dnl Except as contained in this notice, the name(s) of the above copyright
    dnl holders shall not be used in advertising or otherwise to promote the
    dnl sale, use or other dealings in this Software without prior written
    dnl authorization.
    dnl ---------------------------------------------------------------------------
    dnl Process this file with autoconf to produce a configure script.
    dnl
    AC_PREREQ(2.52.20200111)
    AC_INIT
    AC_CONFIG_SRCDIR([charproc.c])
    AC_CONFIG_HEADER(xtermcfg.h:xtermcfg.hin)
    CF_CHECK_CACHE
    
    ###	checks for alternative programs
    
    dnl Only add to this case statement when a system has a compiler that is not
    dnl detected by AC_PROG_CC.
    case "$host_os" in
    (openedition)	: ${CFLAGS="-O2 -Wc,dll -Wl,EDIT=NO"}
    		: ${CPPFLAGS="-D_ALL_SOURCE"}
    		: ${LIBS="/usr/lib/Xaw.x /usr/lib/SM.x /usr/lib/ICE.x /usr/lib/X11.x"}
    		: ${CC=c89};;
    (darwin*)
    		: ${LDFLAGS}="${LDFLAGS} -Wl,-bind_at_load";;
    esac
    
    CF_PROG_CC
    AC_PROG_CPP
    AC_PROG_AWK
    AC_PROG_INSTALL
    AC_PROG_LN_S
    AC_ARG_PROGRAM
    CF_PROG_LINT
    
    ###	checks for compiler characteristics
    CF_XOPEN_SOURCE(700)
    CF_SIGWINCH
    
    ###	checks for header files
    AC_CHECK_HEADERS( \
    ncurses/curses.h \
    ncurses/term.h \
    stdlib.h \
    sys/ptem.h sys/ttydefaults.h \
    term.h \
    termios.h \
    unistd.h \
    wchar.h \
    )
    AC_HEADER_TIME
    AM_LANGINFO_CODESET
    
    ###	checks for typedefs
    CF_SIG_ATOMIC_T
    AC_CHECK_TYPE(time_t, long)
    CF_TYPE_CC_T
    AC_TYPE_MODE_T
    AC_TYPE_PID_T
    AC_TYPE_UID_T
    AC_TYPE_OFF_T
    
    ###	checks for library functions
    AC_CHECK_FUNCS( \
    	gethostname \
    	getusershell \
    	endusershell \
    	getlogin \
    	initgroups \
    	mkdtemp \
    	putenv \
    	unsetenv \
    	sched_yield \
    	setpgid \
    	strftime \
    	tcgetattr \
    	waitpid \
    	wcswidth \
    	wcwidth )
    CF_UTMP
    CF_STRUCT_LASTLOG
    CF_POSIX_SAVED_IDS
    
    CF_HELP_MESSAGE(Compile/Install Options:)
    CF_FUNC_TGETENT
    
    CF_WITH_APP_CLASS(XTerm)
    CF_WITH_APP_DEFAULTS
    CF_WITH_ICON_NAME(mini.xterm)
    CF_WITH_ICON_SYMLINK(xterm)
    
    # Install all icons except for the overused "terminal".
    cf_cv_icon_list=
    for my_item in $srcdir/icons/*.svg
    do
    	test -f "$my_item" || continue
    	cf_icon_name=`echo $my_item |sed -e "s,.svg,," -e "s,^$srcdir/,,"`
    	case $cf_icon_name in
    	(*_48x48)
    		continue
    		;;
    	esac
    	CF_VERBOSE(adding $cf_icon_name to icon-list)
    	cf_cv_icon_list="$cf_cv_icon_list $cf_icon_name"
    	if test -f "${cf_icon_name}_48x48.png"
    	then
    		CF_VERBOSE(adding ${cf_icon_name}_48x48 to icon-list)
    		cf_cv_icon_list="$cf_cv_icon_list ${cf_icon_name}_48x48"
    	fi
    done
    CF_WITH_ICON_THEME([$cf_cv_icon_list],,,icons/${ICON_NAME}_48x48)
    
    CF_DISABLE_DESKTOP(xterm)
    CF_WITH_DESKTOP_CATEGORY(xterm,
    	[*rxvt*|*konsole|*[[Tt]]erminal],
    	[System|TerminalEmulator|*])
    
    AC_MSG_CHECKING(for install-permissions reference)
    AC_ARG_WITH(reference,
    	[  --with-reference=XXX    program to use as permissions-reference],
    	[with_reference=$withval],
    	[with_reference=xterm])
    AC_MSG_RESULT($with_reference)
    
    with_full_paths=yes
    CF_PATH_PROG(XTERM_PATH,$with_reference)
    
    # If any of --program-prefix, --program-suffix or --program-transform-name is
    # given, accept an option tell the makefile to create a symbolic link, e.g.,
    # to "xterm" on install.
    XTERM_SYMLINK=NONE
    AC_SUBST(XTERM_SYMLINK)
    if test "$program_transform_name" != "'s,,,'" ; then
    cf_name=`echo "$program_transform_name" | sed -e '[s,\\$\\$,$,g]'`
    cf_name=`echo xterm |sed -e "$cf_name"`
    AC_MSG_CHECKING(for symbolic link to create to $cf_name)
    AC_ARG_WITH(xterm-symlink,
    	[  --with-xterm-symlink=XXX make symbolic link to installed xterm],
    	[with_symlink=$withval],
    	[with_symlink=xterm])
    AC_MSG_RESULT($with_symlink)
    test "$with_symlink" = yes && with_symlink=xterm
    test -n "$with_symlink" && \
    	test "$with_symlink" != no && \
    	test "$with_symlink" != $cf_name && \
    	XTERM_SYMLINK="$with_symlink"
    fi
    
    AC_MSG_CHECKING(if you want to disable openpty)
    CF_ARG_DISABLE(openpty,
    	[  --disable-openpty       disable openpty, prefer other interfaces],
    	[disable_openpty=yes],
    	[disable_openpty=no],
    	no)
    AC_MSG_RESULT($disable_openpty)
    
    AC_MSG_CHECKING(if you want to disable setuid)
    CF_ARG_DISABLE(setuid,
    	[  --disable-setuid        disable setuid in xterm, do not install setuid/setgid],
    	[disable_setuid=yes],
    	[disable_setuid=no],
    	no)
    AC_MSG_RESULT($disable_setuid)
    
    AC_MSG_CHECKING(if you want to disable setgid)
    CF_ARG_DISABLE(setgid,
    	[  --disable-setgid        disable setgid in xterm, do not install setuid/setgid],
    	[disable_setgid=yes],
    	[disable_setgid=no],
    	no)
    AC_MSG_RESULT($disable_setgid)
    
    AC_MSG_CHECKING(if you want to run xterm setuid to a given user)
    AC_ARG_WITH(setuid,
    	[  --with-setuid=XXX       use the given setuid user],
    	[use_given_setuid=$withval],
    	[use_given_setuid=no])
    AC_MSG_RESULT($use_given_setuid)
    
    if test "$use_given_setuid" != no ; then
    	if test "$use_given_setuid" = yes ; then
    		cf_cv_given_setuid=root
    	else
    		cf_cv_given_setuid=$use_given_setuid
    	fi
    	# inherit SINSTALL_OPTS from environment to allow packager to customize it.
    	SINSTALL_OPTS="$SINSTALL_OPTS u+s -u $cf_cv_given_setuid"
    fi
    
    AC_MSG_CHECKING(if you want to run xterm setgid to match utmp/utmpx file)
    AC_ARG_WITH(utmp-setgid,
    	[  --with-utmp-setgid=XXX  use setgid to match utmp/utmpx file],
    	[use_utmp_setgid=$withval],
    	[use_utmp_setgid=no])
    AC_MSG_RESULT($use_utmp_setgid)
    
    if test "$use_utmp_setgid" != no ; then
    	if test "$use_utmp_setgid" = yes ; then
    		CF_UTMP_GROUP
    	else
    		cf_cv_utmp_group=$use_utmp_setgid
    	fi
    	if test "$cf_cv_posix_saved_ids" != yes ; then
    		AC_MSG_ERROR(Your system does not support POSIX saved-ids)
    	fi
    	AC_DEFINE(USE_UTMP_SETGID,1,[Define to 1 if we should use setgid to access utmp/utmpx])
    	SINSTALL_OPTS="$SINSTALL_OPTS g+s -g $cf_cv_utmp_group"
    fi
    
    AC_SUBST(SINSTALL_OPTS)
    
    AC_MSG_CHECKING(if you want to link with utempter)
    AC_ARG_WITH(utempter,
    	[  --with-utempter         use utempter library for access to utmp],
    	[use_utempter=$withval],
    	[use_utempter=no])
    AC_MSG_RESULT($use_utempter)
    
    if test "$use_utempter" = yes ; then
    	CF_UTEMPTER
    	test "$cf_cv_have_utempter" != yes && use_utempter=no
    else
    	use_utempter=no
    fi
    
    # Some configurations permit (or require) either setuid or setgid mode.
    # Let the user decide.
    if test "$use_utempter" = yes ; then
    	if test "${enable_setuid+set}" != set ; then
    		disable_setuid=yes
    		CF_VERBOSE([No --disable-setuid option given, force to yes])
    	fi
    fi
    
    ###	checks for external data
    CF_ERRNO
    CF_TTY_GROUP
    
    ###	checks for system services and user specified options
    
    AC_PATH_XTRA
    CF_POSIX_WAIT
    CF_SYSV
    CF_SVR4
    CF_X_TOOLKIT
    
    AC_CHECK_HEADERS( \
    	X11/DECkeysym.h \
    	X11/Sunkeysym.h \
    	X11/XF86keysym.h \
    	X11/XKBlib.h \
    	X11/TranslateI.h \
    	X11/Xpoll.h \
    	X11/extensions/XKB.h \
    	)
    
    CF_WITH_XPM
    CF_WITH_XINERAMA
    CF_X_ATHENA
    CF_TYPE_FD_MASK
    CF_TERMIO_C_ISPEED
    CF_TERMIOS_TYPES
    
    # If we notice Xcursor, there is a workaround needed.
    AC_CHECK_LIB(Xcursor, XcursorGetTheme,[AC_DEFINE(HAVE_LIB_XCURSOR,1,[Define to 1 if we have the Xcursor library])])
    
    LIBS="$LIBS $X_EXTRA_LIBS"
    
    CF_FUNC_GRANTPT
    CF_XKB_QUERY_EXTENSION
    CF_XKB_KEYCODE_TO_KEYSYM
    CF_XKB_BELL_EXT
    
    AC_CHECK_FUNCS(Xutf8LookupString, [],[
    	EXTRAHDRS="$EXTRAHDRS xutf8.h"
    	EXTRASRCS="$EXTRASRCS xutf8.c"
    	EXTRAOBJS="$EXTRAOBJS xutf8.o"
    ])
    
    CF_WITH_IMAKE_CFLAGS($(MAIN_DEFINES) $(VENDORMANDEFS))
    CF_WITH_MAN2HTML
    
    # If we have already established that there is a full termcap implementation,
    # suppress the definitions for terminfo that we make have imported from the
    # imake-file.
    if test "x$cf_cv_lib_tgetent" != xno || test "x$cf_cv_lib_part_tgetent" != xno ; then
    	case "$IMAKE_CFLAGS" in
    	(*-DUSE_TERMINFO\ -DHAVE_TIGETSTR*)
    		CF_UNDO_CFLAGS(IMAKE_CFLAGS,terminfo,[-DUSE_TERMINFO[[ 	]]*-DHAVE_TIGETSTR[[ 	]]*])
    		CF_UNDO_CFLAGS(CPPFLAGS,terminfo,[-DUSE_TERMINFO[[ 	]]*-DHAVE_TIGETSTR[[ 	]]*])
    		;;
    	esac
    fi
    
    CF_HELP_MESSAGE(Terminal Configuration:)
    
    AC_MSG_CHECKING(for default terminal-id)
    AC_ARG_WITH(terminal-id,
    	[  --with-terminal-id=V    set default decTerminalID (default: vt420)],
    	[default_termid=$withval],
    	[default_termid=vt420])
    AC_MSG_RESULT($default_termid)
    case $default_termid in
    (vt*)	default_termid=`echo $default_termid | sed -e 's/^..//'`
    	;;
    esac
    AC_DEFINE_UNQUOTED(DFT_DECID,"$default_termid",[default terminal-id])
    AC_SUBST(default_termid)
    
    AC_MSG_CHECKING(for default terminal-type)
    AC_ARG_WITH(terminal-type,
    	[  --with-terminal-type=T  set default $TERM (default: xterm)],
    	[default_TERM=$withval],
    	[default_TERM=xterm])
    AC_MSG_RESULT($default_TERM)
    AC_DEFINE_UNQUOTED(DFT_TERMTYPE,"$default_TERM",[default terminal-type])
    AC_SUBST(default_TERM)
    
    ###############################################################################
    AC_MSG_CHECKING(if backarrow-key should be BS)
    CF_ARG_DISABLE(backarrow-key,
    	[  --enable-backarrow-key  set default backarrowKey resource (default: true)],
    	[backarrow_is_bs=$enableval],
    	[backarrow_is_bs=yes])
    CF_XBOOL_RESULT(DEF_BACKARO_BS,backarrow_is_bs,[Define to 1 if backarrow-key should be BS])
    
    AC_MSG_CHECKING(if backarrow-key should be treated as erase)
    CF_ARG_ENABLE(backarrow-is-erase,
    	[  --enable-backarrow-is-erase set default backarrowKeyIsErase resource (default: false)],
    	[backarrow_is_erase=$enableval],
    	[backarrow_is_erase=no])
    CF_XBOOL_RESULT(DEF_BACKARO_ERASE,backarrow_is_erase,[Define to 1 if backarrow-key should be treated as erase])
    
    AC_MSG_CHECKING(for default backspace/DEL setting)
    AC_ARG_ENABLE(delete-is-del,
    	[  --enable-delete-is-del  set default deleteIsDEL resource (default: maybe)],
    	[delete_is_del=$enableval],
    	[delete_is_del=maybe])
    CF_XBOOL_RESULT(DEFDELETE_DEL,delete_is_del,[Define to 1 if default backspace/DEL setting is DEL])
    
    AC_MSG_CHECKING(for default pty initial erase setting)
    AC_ARG_ENABLE(pty-erase,
    	[  --enable-pty-erase      set default ptyInitialErase resource (default: maybe)],
    	[initial_erase=$enableval],
    	[initial_erase=False])
    CF_XBOOL_RESULT(DEF_INITIAL_ERASE,initial_erase,[Define to 1 if default pty initial erase setting is TRUE])
    
    AC_MSG_CHECKING(if alt should send ESC)
    CF_ARG_ENABLE(alt-sends-esc,
    	[  --enable-alt-sends-esc  set default altSendsEscape resource (default: no)],
    	[alt_sends_esc=$enableval],
    	[alt_sends_esc=no])
    CF_XBOOL_RESULT(DEF_ALT_SENDS_ESC,alt_sends_esc,[Define to 1 if alt should send ESC])
    
    AC_MSG_CHECKING(if meta should send ESC)
    CF_ARG_ENABLE(meta-sends-esc,
    	[  --enable-meta-sends-esc set default metaSendsEscape resource (default: no)],
    	[meta_sends_esc=$enableval],
    	[meta_sends_esc=no])
    CF_XBOOL_RESULT(DEF_META_SENDS_ESC,meta_sends_esc,[Define to 1 if meta should send ESC])
    
    ###############################################################################
    AC_CHECK_PROG(cf_tic_prog,tic,yes,no)
    if test "$cf_tic_prog" = yes ; then
    	if test -n "$TERMINFO"
    	then
    		case "$TERMINFO" in
    		(/*)
    			test -d "$TERMINFO" || unset TERMINFO
    			;;
    		(*)
    			unset TERMINFO
    			;;
    		esac
    	fi
    	AC_MSG_CHECKING(for private terminfo-directory)
    	AC_ARG_WITH(own-terminfo,
    		[  --with-own-terminfo=P   set default $TERMINFO (default: from environment)],
    		[TERMINFO_DIR=$withval],
    		[TERMINFO_DIR=${TERMINFO-none}])
    	AC_MSG_RESULT($TERMINFO_DIR)
    	if test "$TERMINFO_DIR" = yes ; then
    		AC_MSG_WARN(no value given)
    	elif test "$TERMINFO_DIR" != none ; then
    		if test -d $TERMINFO_DIR ; then
    			AC_DEFINE_UNQUOTED(OWN_TERMINFO_DIR,"$TERMINFO_DIR",[Define to override default TERMINFO value])
    			AC_MSG_CHECKING(if \$TERMINFO should also be set)
    			AC_ARG_ENABLE(env-terminfo,
    				[  --enable-env-terminfo   setenv $TERMINFO if --with-own-terminfo gives value],
    				[cf_env_terminfo=yes],
    				[cf_env_terminfo=no])
    			AC_MSG_RESULT($cf_env_terminfo)
    			test $cf_env_terminfo = yes &&
    			AC_DEFINE(OWN_TERMINFO_ENV,1,[Define to 1 to enable setenv of $TERMINFO value])
    		else
    			AC_MSG_WARN(not a directory)
    		fi
    	elif test "$prefix" != NONE ; then
    		TERMINFO_DIR='${prefix}/lib/terminfo'
    	elif test -d /usr/lib/terminfo ; then
    		TERMINFO_DIR=/usr/lib/terminfo
    	else
    		TERMINFO_DIR=
    	fi
    	SET_TERMINFO=
    	if test -n "$TERMINFO_DIR" ; then
    		TERMINFO_DIR='$(DESTDIR)'$TERMINFO_DIR
    		SET_TERMINFO='TERMINFO=$(TERMINFO_DIR)'
    	fi
    	no_ticprog=
    else
    	no_ticprog="#"
    	TERMINFO_DIR=
    	SET_TERMINFO=
    fi
    AC_SUBST(no_ticprog)
    AC_SUBST(TERMINFO_DIR)
    AC_SUBST(SET_TERMINFO)
    
    ###############################################################################
    CF_HELP_MESSAGE(Optional Features:)
    
    AC_MSG_CHECKING(if you want active-icons)
    CF_ARG_DISABLE(active-icon,
    	[  --disable-active-icon   disable X11R6.3 active-icon feature],
    	[enable_active_icon=no],
    	[enable_active_icon=yes])
    AC_MSG_RESULT($enable_active_icon)
    if test "$enable_active_icon" = no ; then
    	AC_DEFINE(NO_ACTIVE_ICON,1,[Define to 1 to disable X11R6.3 active-icon feature])
    fi
    
    AC_MSG_CHECKING(if you want ANSI color)
    CF_ARG_DISABLE(ansi-color,
    	[  --disable-ansi-color    disable ANSI color],
    	[enable_ansi_color=no],
    	[enable_ansi_color=yes])
    AC_MSG_RESULT($enable_ansi_color)
    test "$enable_ansi_color" = no && AC_DEFINE(OPT_ISO_COLORS,0,[Define to 0 to disable ANSI color])
    
    if test "$enable_ansi_color" = yes ; then
    
    	AC_MSG_CHECKING(if you want 16 colors like aixterm)
    	CF_ARG_DISABLE(16-color,
    		[  --disable-16-color      disable 16-color support],
    		[enable_16_color=no],
    		[enable_16_color=yes])
    	AC_MSG_RESULT($enable_16_color)
    	test "$enable_16_color" = no && AC_DEFINE(OPT_AIX_COLORS,0,[Define to 0 to disable 16-color support])
    
    	AC_MSG_CHECKING(if you want 256 colors)
    	CF_ARG_DISABLE(256-color,
    		[  --disable-256-color     disable 256-color support],
    		[enable_256_color=no],
    		[enable_256_color=yes])
    	AC_MSG_RESULT($enable_256_color)
    
    	if test "$enable_256_color" = yes ; then
    
    		CHARPROC_DEPS="$CHARPROC_DEPS 256colres.h"
    		EXTRAHDRS="$EXTRAHDRS 256colres.h"
    		AC_DEFINE(OPT_256_COLORS,1,[Define to 1 to enable 256-color support])
    
    		AC_MSG_CHECKING(if you want direct-color support)
    		CF_ARG_DISABLE(direct-color,
    			[  --disable-direct-color  disable direct-color support],
    			[enable_direct_color=no],
    			[enable_direct_color=yes])
    		AC_MSG_RESULT($enable_direct_color)
    		if test "$enable_direct_color" = yes ; then
    			AC_DEFINE(OPT_DIRECT_COLOR,1,[Define to 1 to enable direct-color support])
    		fi
    
    	else
    
    		AC_MSG_CHECKING(if you want 88 colors)
    		CF_ARG_DISABLE(88-color,
    			[  --disable-88-color      disable 88-color support],
    			[enable_88_color=no],
    			[enable_88_color=yes])
    		AC_MSG_RESULT($enable_88_color)
    		if test "$enable_88_color" = yes ; then
    			CHARPROC_DEPS="$CHARPROC_DEPS 88colres.h"
    			EXTRAHDRS="$EXTRAHDRS 88colres.h"
    			AC_DEFINE(OPT_88_COLORS,1,[Define to 1 to enable 88-color support])
    		fi
    
    	fi
    
    fi
    
    AC_MSG_CHECKING(if you want blinking cursor)
    CF_ARG_DISABLE(blink-cursor,
    	[  --disable-blink-cursor  disable support for blinking cursor],
    	[enable_blink_curs=no],
    	[enable_blink_curs=yes])
    AC_MSG_RESULT($enable_blink_curs)
    test "$enable_blink_curs" = no && AC_DEFINE(OPT_BLINK_CURS,0,[Define to 0 to disable support for blinking cursor])
    
    AC_MSG_CHECKING(if you want to ignore Linux's broken palette-strings)
    
    case $host_os in
    (linux*)
    	assume_broken_osc=yes ;;
    (*)
    	assume_broken_osc=no ;;
    esac
    
    CF_ARG_OPTION(broken-osc,
    	[  --enable-broken-osc     allow broken Linux OSC-strings],
    	[enable_broken_osc=$enableval],
    	[enable_broken_osc=$enableval],
    	[$assume_broken_osc])
    AC_MSG_RESULT($enable_broken_osc)
    if test "$enable_broken_osc" = yes ; then
    	AC_DEFINE(OPT_BROKEN_OSC,1,[Define to 1 to allow broken Linux OSC-strings])
    else
    	AC_DEFINE(OPT_BROKEN_OSC,0,[Define to 0 to allow broken Linux OSC-strings])
    fi
    
    AC_MSG_CHECKING(if you want to allow broken string-terminators)
    CF_ARG_ENABLE(broken-st,
    	[  --disable-broken-st     disallow broken string-terminators],
    	[enable_broken_st=no],
    	[enable_broken_st=yes])
    AC_MSG_RESULT($enable_broken_st)
    test "$enable_broken_st" = no && AC_DEFINE(OPT_BROKEN_ST,0,[Define to 0 to disallow broken string-terminators])
    
    AC_MSG_CHECKING(if you want to compile-in icon data)
    CF_ARG_ENABLE(builtin-xpms,
    	[  --enable-builtin-xpms   compile-in icon data],
    	[enable_builtin_xpms=yes],
    	[enable_builtin_xpms=no])
    AC_MSG_RESULT($enable_builtin_xpms)
    test "$enable_builtin_xpms" = yes && AC_DEFINE(OPT_BUILTIN_XPMS,1,[Define to 1 to compile-in icon data])
    
    AC_MSG_CHECKING(if you want printable 128-159)
    CF_ARG_DISABLE(c1-print,
    	[  --disable-c1-print      disallow -k8 option for printable 128-159],
    	[enable_c1_print=no],
    	[enable_c1_print=yes])
    AC_MSG_RESULT($enable_c1_print)
    test "$enable_c1_print" = no && AC_DEFINE(OPT_C1_PRINT,0,[Define to 0 to disallow -k8 option for printable 128-159])
    
    if test "$enable_ansi_color" = yes ; then
    
    	AC_MSG_CHECKING(if you want bold colors mapped like IBM PC)
    	CF_ARG_DISABLE(bold-color,
    		[  --disable-bold-color    disable PC-style mapping of bold colors],
    		[enable_pc_color=no],
    		[enable_pc_color=yes])
    	AC_MSG_RESULT($enable_pc_color)
    	test "$enable_pc_color" = no && AC_DEFINE(OPT_PC_COLORS,0,[Define to 0 to disable PC-style mapping of bold colors])
    
    	AC_MSG_CHECKING(if you want separate color-classes)
    	CF_ARG_DISABLE(color-class,
    		[  --disable-color-class   disable separate color class resources],
    		[enable_color_class=no],
    		[enable_color_class=yes])
    	AC_MSG_RESULT($enable_color_class)
    	test "$enable_color_class" = no && AC_DEFINE(OPT_COLOR_CLASS,0,[Define to 0 to disable separate color class resources])
    
    	AC_MSG_CHECKING(if you want color-mode enabled by default)
    	CF_ARG_DISABLE(color-mode,
    		[  --disable-color-mode    disable default colorMode resource],
    		[default_colormode=no],
    		[default_colormode=yes])
    	AC_MSG_RESULT($default_colormode)
    	test "$default_colormode" = no && AC_DEFINE(DFT_COLORMODE,0,[Define to 0 if you want color-mode enabled by default])
    
    fi
    
    AC_MSG_CHECKING(if you want support for color highlighting)
    CF_ARG_DISABLE(highlighting,
    	[  --disable-highlighting  disable support for color highlighting],
    	[default_highlight=no],
    	[default_highlight=yes])
    AC_MSG_RESULT($default_highlight)
    test "$default_highlight" = no && AC_DEFINE(OPT_HIGHLIGHT_COLOR,0,[Define to 1 if you want support for color highlighting])
    
    AC_MSG_CHECKING(if you want support for doublesize characters)
    CF_ARG_DISABLE(doublechars,
    	[  --disable-doublechars   disable support for double-size chars],
    	[enable_doublechars=no],
    	[enable_doublechars=yes])
    AC_MSG_RESULT($enable_doublechars)
    test "$enable_doublechars" = no && AC_DEFINE(OPT_DEC_CHRSET,0,[Define to 0 to disable support for double-size chars])
    
    AC_MSG_CHECKING(if you want fallback-support for box characters)
    CF_ARG_DISABLE(boxchars,
    	[  --disable-boxchars      disable fallback-support for box chars],
    	[enable_boxchars=no],
    	[enable_boxchars=yes])
    AC_MSG_RESULT($enable_boxchars)
    test "$enable_boxchars" = no && AC_DEFINE(OPT_BOX_CHARS,0,[Define to 0 to disable fallback-support for box chars])
    
    AC_MSG_CHECKING(if you want to allow spawning new xterms)
    CF_ARG_ENABLE(exec-xterm,
    	[  --enable-exec-xterm     enable "spawn-new-terminal" action],
    	[enable_exec_xterm=yes],
    	[enable_exec_xterm=no])
    AC_MSG_RESULT($enable_exec_xterm)
    if test "$enable_exec_xterm" = yes ; then
    	CF_PROCFS_CWD
    	if test "$cf_cv_procfs_cwd" = no ; then
    		AC_MSG_WARN(no suitable proc filesystem found)
    	else
    		AC_DEFINE_UNQUOTED(PROCFS_ROOT,"$cf_cv_procfs_cwd",[This is defined via the --enable-exec-xterm option])
    		AC_DEFINE(OPT_EXEC_XTERM,1,[Define to 1 to enable "spawn-new-terminal" action])
    	fi
    fi
    
    CF_X_EXT
    CF_X_EXT_DOUBLE_BUFFER
    double_buffer=False
    if test "$cf_x_ext_double_buffer" = yes ; then
    	AC_MSG_CHECKING(if you want to enable double-buffering in default resources)
    	CF_ARG_ENABLE(double-buffer,
    		[  --enable-double-buffer  enable double-buffering in default resources],
    		[enable_double_bfr=yes],
    		[enable_double_bfr=no])
    	AC_MSG_RESULT($enable_double_bfr)
    	if test "$enable_double_bfr" = yes ; then
    		AC_DEFINE(OPT_DOUBLE_BUFFER,1,[Define to 1 to enable double-buffering in default resources])
    		double_buffer=True
    	fi
    fi
    AC_SUBST(double_buffer)
    
    AC_MSG_CHECKING(if you want to use FreeType library)
    CF_ARG_DISABLE(freetype,
    	[  --disable-freetype      disable freetype library-support],
    	[enable_freetype=no],
    	[enable_freetype=yes])
    AC_MSG_RESULT($enable_freetype)
    if test "$enable_freetype" = yes ; then
    	CF_X_FONTCONFIG
    else
    	CPPFLAGS=`echo "$CPPFLAGS" | sed -e s/-DXRENDERFONT//`
    fi
    
    AC_MSG_CHECKING(if you want support for HP-style function keys)
    CF_ARG_ENABLE(hp-fkeys,
    	[  --enable-hp-fkeys       enable support for HP-style function keys],
    	[enable_hp_fkeys=yes],
    	[enable_hp_fkeys=no])
    AC_MSG_RESULT($enable_hp_fkeys)
    if test "$enable_hp_fkeys" = yes ; then
    	AC_DEFINE(OPT_HP_FUNC_KEYS,1,[Define to 1 to enable support for HP-style function keys])
    fi
    
    AC_MSG_CHECKING(if you want support for SCO-style function keys)
    CF_ARG_ENABLE(sco-fkeys,
    	[  --enable-sco-fkeys      enable support for SCO-style function keys],
    	[enable_sco_fkeys=yes],
    	[enable_sco_fkeys=no])
    AC_MSG_RESULT($enable_sco_fkeys)
    if test "$enable_sco_fkeys" = yes ; then
    	AC_DEFINE(OPT_SCO_FUNC_KEYS,1,[Define to 1 to enable support for SCO-style function keys])
    fi
    
    AC_MSG_CHECKING(if you want support for Sun-style function keys)
    CF_ARG_DISABLE(sun-fkeys,
    	[  --disable-sun-fkeys     disable support for Sun-style function keys],
    	[enable_sun_fkeys=no],
    	[enable_sun_fkeys=yes])
    AC_MSG_RESULT($enable_sun_fkeys)
    if test "$enable_sun_fkeys" = no ; then
    	AC_DEFINE(OPT_SUN_FUNC_KEYS,0,[Define to 0 to disable support for Sun-style function keys])
    fi
    
    AC_MSG_CHECKING(if you want saved-lines stored as a FIFO)
    CF_ARG_DISABLE(fifo-lines,
    	[  --disable-fifo-lines    disable FIFO-storage for saved-lines],
    	[enable_fifo_lines=no],
    	[enable_fifo_lines=yes])
    AC_MSG_RESULT($enable_fifo_lines)
    if test "$enable_fifo_lines" = yes ; then
    	AC_DEFINE(OPT_FIFO_LINES,1,[Define to 1 to disable FIFO-storage for saved-lines])
    fi
    
    AC_MSG_CHECKING(if you want support for internationalization)
    CF_ARG_DISABLE(i18n,
    	[  --disable-i18n          disable internationalization],
    	[enable_i18n=no],
    	[enable_i18n=yes])
    AC_MSG_RESULT($enable_i18n)
    if test "$enable_i18n" = no ; then
    	AC_DEFINE(OPT_I18N_SUPPORT,0,[Define to 0 to disable internationalization])
    fi
    
    AC_MSG_CHECKING(if you want support for initial-erase setup)
    CF_ARG_DISABLE(initial-erase,
    	[  --disable-initial-erase disable setup for stty erase],
    	[enable_ie=no],
    	[enable_ie=yes])
    AC_MSG_RESULT($enable_ie)
    if test "$enable_ie" = no ; then
    	AC_DEFINE(OPT_INITIAL_ERASE,0,[Define to 0 to disable setup for stty erase])
    fi
    
    AC_MSG_CHECKING(if you want support for input-method)
    CF_ARG_DISABLE(input-method,
    	[  --disable-input-method  disable input-method],
    	[enable_ximp=no],
    	[enable_ximp=$enable_i18n])
    AC_MSG_RESULT($enable_ximp)
    CF_INPUT_METHOD
    test "$cf_cv_input_method" = no && enable_ximp=no
    if test "$enable_ximp" != no ; then
    	if test "$enable_i18n" = no ; then
    		AC_MSG_WARN(input-methor relies upon internationalization)
    		enable_ximp=no
    	fi
    fi
    if test "$enable_ximp" = no ; then
    	AC_DEFINE(OPT_INPUT_METHOD,0,[Define to 0 to disable input-method])
    fi
    
    AC_MSG_CHECKING(if you want support for load-vt-fonts)
    CF_ARG_ENABLE(load-vt-fonts,
    	[  --enable-load-vt-fonts  enable load-vt-fonts() action],
    	[enable_load_vt_fonts=yes],
    	[enable_load_vt_fonts=no])
    AC_MSG_RESULT($enable_load_vt_fonts)
    if test "$enable_load_vt_fonts" = yes ; then
    	AC_DEFINE(OPT_LOAD_VTFONTS,1,[Define to 1 to enable load-vt-fonts() action])
    fi
    
    AC_MSG_CHECKING(if you want support for logging)
    CF_ARG_ENABLE(logging,
    	[  --enable-logging        enable logging],
    	[enable_logging=yes],
    	[enable_logging=no])
    AC_MSG_RESULT($enable_logging)
    if test "$enable_logging" = yes ; then
    	AC_DEFINE(ALLOWLOGGING,1,[if you want support for logging])
    	AC_MSG_CHECKING(if you want to allow logging via a pipe)
    	CF_ARG_ENABLE(logfile-exec,
    		[  --enable-logfile-exec   enable exec'd logfile filter],
    		[enable_log_exec=yes],
    		[enable_log_exec=no])
    	AC_MSG_RESULT($enable_log_exec)
    	if test "$enable_log_exec" = yes ; then
    		AC_DEFINE(ALLOWLOGFILEEXEC,1,[if you want to allow logging via a pipe])
    	fi
    fi
    
    AC_MSG_CHECKING(if you want support for iconify/maximize translations)
    CF_ARG_DISABLE(maximize,
    	[  --disable-maximize      disable actions for iconify/deiconify/maximize/restore],
    	[enable_maximize=no],
    	[enable_maximize=yes])
    AC_MSG_RESULT($enable_maximize)
    test "$enable_maximize" = no && AC_DEFINE(OPT_MAXIMIZE,0,[Define to 0 to disable actions for iconify/deiconify/maximize/restore])
    
    AC_MSG_CHECKING(if you want NumLock to override keyboard tables)
    CF_ARG_DISABLE(num-lock,
    	[  --disable-num-lock      disable NumLock keypad support],
    	[enable_numlock=no],
    	[enable_numlock=yes])
    AC_MSG_RESULT($enable_numlock)
    test "$enable_numlock" = no && AC_DEFINE(OPT_NUM_LOCK,0,[Define to 0 to disable NumLock keypad support])
    
    AC_MSG_CHECKING(if you want support for get/set of base64 selection data)
    
    CF_ARG_DISABLE(paste64,
    	[  --disable-paste64       disable get/set base64 selection data],
    	[enable_paste64=no],
    	[enable_paste64=yes])
    AC_MSG_RESULT($enable_paste64)
    if test "$enable_paste64" = yes ; then
    	AC_DEFINE(OPT_PASTE64,1,[Define to 1 to disable get/set base64 selection data])
    else
    	AC_DEFINE(OPT_PASTE64,0,[Define to 0 to disable get/set base64 selection data])
    fi
    
    AC_MSG_CHECKING(if you want support for pty-handshaking)
    
    CF_ARG_DISABLE(pty-handshake,
    	[  --disable-pty-handshake disable pty-handshake support],
    	[enable_pty_handshake=no],
    	[enable_pty_handshake=yes])
    AC_MSG_RESULT($enable_pty_handshake)
    if test "$enable_pty_handshake" = yes ; then
    	AC_DEFINE(OPT_PTY_HANDSHAKE,1,[Define to 1 to disable pty-handshake support])
    else
    	AC_DEFINE(OPT_PTY_HANDSHAKE,0,[Define to 0 to disable pty-handshake support])
    fi
    
    AC_MSG_CHECKING(if you want support for mouse in readline applications)
    CF_ARG_ENABLE(readline-mouse,
    	[  --enable-readline-mouse enable support for mouse in readline applications],
    	[enable_readline_mouse=yes],
    	[enable_readline_mouse=no])
    AC_MSG_RESULT($enable_readline_mouse)
    if test "$enable_readline_mouse" = yes ; then
    	AC_DEFINE(OPT_READLINE,1,[Define to 1 to enable support for mouse in readline applications])
    fi
    
    AC_MSG_CHECKING(if you want support for regular-expression selections)
    CF_ARG_DISABLE(regex,
    	[  --disable-regex         disable regular-expression selections],
    	[enable_regex=no],
    	[enable_regex=yes])
    AC_MSG_RESULT($enable_regex)
    if test "$enable_regex" = yes ; then
    	CF_WITH_PCRE2
    	if test "$with_pcre2" = no ; then
    		CF_WITH_PCRE
    		if test "$with_pcre" = no ; then
    			CF_REGEX
    			if test "X$cf_cv_regex_hdrs" != "Xregex.h" ; then
    				AC_MSG_ERROR([Only POSIX, PCRE, or PCRE2 regular expressions are supported])
    			fi
    		fi
    	fi
    	AC_DEFINE(OPT_SELECT_REGEX,1,[Define to 1 to enable regular-expression selections])
    fi
    
    AC_MSG_CHECKING(if you want support for right-scrollbar)
    CF_ARG_DISABLE(rightbar,
    	[  --disable-rightbar      disable right-scrollbar support],
    	[enable_rightbar=no],
    	[enable_rightbar=yes])
    AC_MSG_RESULT($enable_rightbar)
    if test "$enable_rightbar" = yes ; then
    	AC_DEFINE(SCROLLBAR_RIGHT,1,[Define to 1 to enable right-scrollbar support])
    fi
    
    AC_MSG_CHECKING(if you want check for redundant name-change)
    CF_ARG_DISABLE(samename,
    	[  --disable-samename      disable check for redundant name-change],
    	[enable_samename=no],
    	[enable_samename=yes])
    AC_MSG_RESULT($enable_samename)
    test "$enable_samename" = no && AC_DEFINE(OPT_SAME_NAME,0,[Define to 0 to disable check for redundant name-change])
    
    AC_MSG_CHECKING(if you want support for selection-actions)
    CF_ARG_DISABLE(selection-ops,
    	[  --disable-selection-ops disable selection-action operations],
    	[enable_selection_ops=no],
    	[enable_selection_ops=yes])
    AC_MSG_RESULT($enable_selection_ops)
    test "$enable_selection_ops" = no && AC_DEFINE(OPT_SELECTION_OPS,0,[Define to 0 disable selection-action operations])
    
    AC_MSG_CHECKING(if you want support for session management)
    CF_ARG_DISABLE(session-mgt,
    	[  --disable-session-mgt   disable support for session management],
    	[enable_session_mgt=no],
    	[enable_session_mgt=yes])
    AC_MSG_RESULT($enable_session_mgt)
    test "$enable_session_mgt" = no && AC_DEFINE(OPT_SESSION_MGT,0,[Define to 0 to disable support for session management])
    
    AC_MSG_CHECKING(if you want to use termcap function-keys)
    CF_ARG_DISABLE(tcap-fkeys,
    	[  --disable-tcap-fkeys    disable termcap function-keys support],
    	[enable_tcap_fkeys=no],
    	[enable_tcap_fkeys=yes])
    AC_MSG_RESULT($enable_tcap_fkeys)
    test "$enable_tcap_fkeys" = yes && AC_DEFINE(OPT_TCAP_FKEYS,1,[Define to 1 to disable termcap function-keys support])
    
    AC_MSG_CHECKING(if you want to use termcap-query/report)
    CF_ARG_DISABLE(tcap-query,
    	[  --disable-tcap-query    disable compiled-in termcap-query support],
    	[enable_tcap_query=no],
    	[enable_tcap_query=yes])
    AC_MSG_RESULT($enable_tcap_query)
    test "$enable_tcap_query" = yes && AC_DEFINE(OPT_TCAP_QUERY,1,[Define to 1 to disable compiled-in termcap-query support])
    
    AC_MSG_CHECKING(if you want support for tek4014)
    CF_ARG_DISABLE(tek4014,
    	[  --disable-tek4014       disable tek4014 emulation],
    	[enable_tek4014=no],
    	[enable_tek4014=yes])
    AC_MSG_RESULT($enable_tek4014)
    if test "$enable_tek4014" = no ; then
    	AC_DEFINE(OPT_TEK4014,0,[Define to 0 to disable tek4014 emulation])
    else
    	EXTRAHDRS="$EXTRAHDRS Tekparse.h"
    	EXTRASRCS="$EXTRASRCS TekPrsTbl.c Tekproc.c"
    	EXTRAOBJS="$EXTRAOBJS TekPrsTbl.o Tekproc.o"
    fi
    
    AC_MSG_CHECKING(if you want pulldown menus with a toolbar)
    CF_ARG_ENABLE(toolbar,
    	[  --enable-toolbar        compile-in toolbar for pulldown menus],
    	[enable_toolbar=yes],
    	[enable_toolbar=no])
    AC_MSG_RESULT($enable_toolbar)
    if test "$enable_toolbar" = yes ; then
    	AC_DEFINE(OPT_TOOLBAR,1,[Define to 1 to compile-in toolbar for pulldown menus])
    fi
    
    AC_MSG_CHECKING(if you want VT52 emulation)
    CF_ARG_DISABLE(vt52,
    	[  --disable-vt52          disable VT52 emulation],
    	[enable_vt52=no],
    	[enable_vt52=yes])
    AC_MSG_RESULT($enable_vt52)
    test "$enable_vt52" = no && AC_DEFINE(OPT_VT52_MODE,0,[Define to 0 to disable VT52 emulation])
    
    AC_MSG_CHECKING(if you want wide-attribute support)
    CF_ARG_DISABLE(wide-attrs,
    	[  --disable-wide-attrs    disable wide-attribute support],
    	[enable_wattr=no],
    	[enable_wattr=yes])
    AC_MSG_RESULT($enable_wattr)
    
    if test x$enable_wattr = xno && test x$enable_direct_color = xyes ; then
    	AC_MSG_WARN(overriding wide-attributes to support direct color)
    	enable_wattr=yes
    fi
    
    AC_MSG_CHECKING(if you want wide-character support)
    CF_ARG_DISABLE(wide-chars,
    	[  --disable-wide-chars    disable wide-character support],
    	[enable_wchar=no],
    	[enable_wchar=yes])
    AC_MSG_RESULT($enable_wchar)
    test "x$enable_wattr" = xno && AC_DEFINE(OPT_WIDE_ATTRS,0,[Define to 0 to disable rarely-used SGR features])
    
    AC_MSG_CHECKING(if you want only 16-bit character support)
    CF_ARG_ENABLE(16bit-chars,
    	[  --enable-16bit-chars    enable 16-bit character support],
    	[enable_16bit_chars=yes],
    	[enable_16bit_chars=no])
    AC_MSG_RESULT($enable_16bit_chars)
    
    if test "$enable_16bit_chars" = yes ; then
    	AC_DEFINE(OPT_WIDER_ICHAR,0,[Define to 0 to enable 16-bit character support])
    	enable_wchar=yes
    fi
    
    if test "$enable_wchar" = yes ; then
    
    AC_MSG_CHECKING(if you want to use mini-luit/Latin9 built-in support)
    CF_ARG_ENABLE(mini-luit,
    	[  --enable-mini-luit      enable mini-luit (built-in Latin9 support)],
    	[enable_mini_luit=yes],
    	[enable_mini_luit=no])
    AC_MSG_RESULT($enable_mini_luit)
    if test "$enable_mini_luit" = yes ; then
    	AC_DEFINE(OPT_MINI_LUIT,1,[Define to 1 to enable mini-luit (built-in Latin9 support)])
    fi
    
    AC_MSG_CHECKING(if you want to use luit)
    CF_ARG_DISABLE(luit,
    	[  --disable-luit          enable luit filter (Unicode translation)],
    	[enable_luit=no],
    	[enable_luit=yes])
    AC_MSG_RESULT($enable_luit)
    if test "$enable_luit" = yes ; then
    	AC_DEFINE(OPT_LUIT_PROG,1,[Define to 1 to enable luit filter (Unicode translation)])
    	CF_PATH_PROG(LUIT,xterm-filter,bluit luit)
    fi
    
    	AC_DEFINE(OPT_WIDE_CHARS,1,[Define to 1 to enable wide-character support])
    	EXTRAHDRS="$EXTRAHDRS charclass.h precompose.h wcwidth.h"
    	EXTRASRCS="$EXTRASRCS charclass.c precompose.c wcwidth.c"
    	EXTRAOBJS="$EXTRAOBJS charclass.o precompose.o wcwidth.o"
    fi
    
    AC_MSG_CHECKING(if you want dynamic-abbreviation support)
    CF_ARG_ENABLE(dabbrev,
    	[  --enable-dabbrev        enable dynamic-abbreviation support],
    	[enable_dabbrev=yes],
    	[enable_dabbrev=no])
    AC_MSG_RESULT($enable_dabbrev)
    if test "$enable_dabbrev" = yes ; then
    	AC_DEFINE(OPT_DABBREV,1,[Define to 1 to enable dynamic-abbreviation support])
    fi
    
    AC_MSG_CHECKING(if you want DECterm Locator support)
    CF_ARG_ENABLE(dec-locator,
    	[  --enable-dec-locator    enable DECterm Locator support],
    	[enable_dec_locator=yes],
    	[enable_dec_locator=no])
    AC_MSG_RESULT($enable_dec_locator)
    if test "$enable_dec_locator" = yes ; then
    	AC_DEFINE(OPT_DEC_LOCATOR,1,[Define to 1 to enable DECterm Locator support])
    fi
    
    AC_MSG_CHECKING(if you want XHTML and SVG screen dump support)
    CF_ARG_DISABLE(screen-dumps,
    	[  --disable-screen-dumps  disable XHTML and SVG screen dumps],
    	[enable_screen_dumps=no],
    	[enable_screen_dumps=yes])
    AC_MSG_RESULT($enable_screen_dumps)
    if test "$enable_screen_dumps" = yes ; then
    	EXTRASRCS="$EXTRASRCS html.c svg.c"
    	EXTRAOBJS="$EXTRAOBJS html.o svg.o"
    else
    	AC_DEFINE(OPT_SCREEN_DUMPS,0,[Define to 0 to disable XHTML and SVG screen dump support])
    fi
    
    AC_MSG_CHECKING(if you want ReGIS graphics support)
    CF_ARG_ENABLE(regis-graphics,
    	[  --enable-regis-graphics enable ReGIS graphics support],
    	[enable_regis_graphics=yes],
    	[enable_regis_graphics=no])
    AC_MSG_RESULT($enable_regis_graphics)
    if test "$enable_regis_graphics" = yes ; then
    	AC_DEFINE(OPT_REGIS_GRAPHICS,1,[Define to 1 to enable ReGIS graphics support])
    	EXTRAHDRS="$EXTRAHDRS graphics_regis.h"
    	EXTRASRCS="$EXTRASRCS graphics_regis.c"
    	EXTRAOBJS="$EXTRAOBJS graphics_regis.o"
    	CF_MATH_LIB
    fi
    
    AC_MSG_CHECKING(if you want sixel graphics support)
    CF_ARG_ENABLE(sixel-graphics,
    	[  --enable-sixel-graphics enable sixel graphics support],
    	[enable_sixel_graphics=yes],
    	[enable_sixel_graphics=no])
    AC_MSG_RESULT($enable_sixel_graphics)
    if test "$enable_sixel_graphics" = yes ; then
    	AC_DEFINE(OPT_SIXEL_GRAPHICS,1,[Define to 1 to enable sixel graphics support])
    	EXTRAHDRS="$EXTRAHDRS graphics_sixel.h"
    	EXTRASRCS="$EXTRASRCS graphics_sixel.c"
    	EXTRAOBJS="$EXTRAOBJS graphics_sixel.o"
    fi
    
    if test "$enable_regis_graphics" = yes || test "$enable_sixel_graphics" = yes ; then
    	AC_DEFINE(OPT_GRAPHICS,1,[Defined to 1 to if any graphics mode is enabled])
    	EXTRAHDRS="$EXTRAHDRS graphics.h"
    	EXTRASRCS="$EXTRASRCS graphics.c"
    	EXTRAOBJS="$EXTRAOBJS graphics.o"
    fi
    
    AC_MSG_CHECKING(if you want VT420 rectangle support)
    CF_ARG_DISABLE(rectangles,
    	[  --disable-rectangles    disable VT420 rectangle support],
    	[enable_rectangles=no],
    	[enable_rectangles=yes])
    AC_MSG_RESULT($enable_rectangles)
    if test "$enable_rectangles" = yes ; then
    	AC_DEFINE(OPT_DEC_RECTOPS,1,[Define to 1 to disable VT420 rectangle support])
    fi
    
    AC_MSG_CHECKING(if you want -ziconbeep option)
    CF_ARG_DISABLE(ziconbeep,
    	[  --disable-ziconbeep     disable -ziconbeep option],
    	[enable_ziconbeep=no],
    	[enable_ziconbeep=yes])
    AC_MSG_RESULT($enable_ziconbeep)
    test "$enable_ziconbeep" = no && AC_DEFINE(OPT_ZICONBEEP,0,[Define to 0 to disable -ziconbeep option])
    
    ###############################################################################
    CF_HELP_MESSAGE(Testing/development Options:)
    
    AC_MSG_CHECKING(if you want debugging traces)
    CF_ARG_ENABLE(trace,
    	[  --enable-trace          test: set to enable debugging traces],
    	[enable_trace=yes],
    	[enable_trace=no])
    AC_MSG_RESULT($enable_trace)
    if test "$enable_trace" = yes ; then
    	AC_DEFINE(OPT_TRACE,1,[Define to 1 to enable debugging traces])
    	EXTRASRCS="$EXTRASRCS trace.c"
    	EXTRAOBJS="$EXTRAOBJS trace.o"
    fi
    
    CF_DISABLE_LEAKS
    CF_DISABLE_ECHO
    
    AC_MSG_CHECKING(if you want magic cookie emulation)
    CF_ARG_ENABLE(xmc-glitch,
    	[  --enable-xmc-glitch     test: enable xmc magic-cookie emulation],
    	[enable_xmc=yes],
    	[enable_xmc=no])
    AC_MSG_RESULT($enable_xmc)
    if test "$enable_xmc" = yes ; then
    	AC_DEFINE(OPT_XMC_GLITCH,1,[Define to 1 to enable xmc magic-cookie emulation])
    	EXTRASRCS="$EXTRASRCS testxmc.c"
    	EXTRAOBJS="$EXTRAOBJS testxmc.o"
    fi
    
    dnl FIXME - extra test needed to make tcap-fkeys work on HPUX
    AC_CHECK_FUNCS(tigetstr)
    
    dnl only check for ncurses' use_extended_names if really not using termcap
    if test -n "$cf_cv_lib_part_tgetent"; then
        AC_CHECK_FUNCS(use_extended_names)
    fi
    
    if test -n "$GCC" ; then
    AC_MSG_CHECKING(if you want to turn on gcc warnings)
    CF_ARG_ENABLE(warnings,
    	[  --enable-warnings       test: turn on GCC compiler warnings],
    	[with_warnings=yes],
    	[with_warnings=no])
    AC_MSG_RESULT($with_warnings)
    if test "$with_warnings" = yes
    then
    	CF_GCC_ATTRIBUTES
    	CF_GCC_WARNINGS(Wdeclaration-after-statement Wextra Wno-unknown-pragmas Wswitch-enum Wno-cast-qual)
    fi
    fi
    
    AC_SUBST(EXTRA_CFLAGS)
    AC_SUBST(CHARPROC_DEPS)
    AC_SUBST(EXTRAHDRS)
    AC_SUBST(EXTRASRCS)
    AC_SUBST(EXTRAOBJS)
    
    test "$disable_setuid" = yes && AC_DEFINE(DISABLE_SETUID,1,[Define to 1 if you want to disable setuid])
    test "$disable_setgid" = yes && AC_DEFINE(DISABLE_SETGID,1,[Define to 1 if you want to disable setgid])
    
    if test $disable_setuid = yes ; then
    	MAY_SETUID="#"
    	NOT_SETUID=
    elif test $disable_setgid = yes ; then
    	MAY_SETUID="#"
    	NOT_SETUID=
    else
    	MAY_SETUID=
    	NOT_SETUID="#"
    fi
    
    AC_SUBST(MAY_SETUID)
    AC_SUBST(NOT_SETUID)
    
    ###	remove from CPPFLAGS the optional features we define in xtermcfg.h
    ###	or other conflicting symbols that may be defined via imake:
    for cf_def in \
    	__STDC__ \
    	ALLOWLOGGING \
    	ALLOWLOGFILEEXEC \
    	OPT_LUIT_PROG \
    	OPT_WIDE_CHARS \
    	SCROLLBAR_RIGHT \
    	USE_TTY_GROUP \
    	USE_UTEMPTER \
    	XRENDERFONT
    do
    	CPPFLAGS=`echo "$CPPFLAGS" | sed -e s/-D$cf_def//`
    done
    
    CF_MAKE_TAGS
    CF_DISABLE_RPATH_HACK
    
    # Force plink.sh to not trim pcre's libraries, which have the same symbol
    # names as the system regexp.
    if test "$with_pcre" != no
    then
    	LIBS=`echo "$LIBS" | sed -e 's/-lpcre/-kpcre/g'`
    fi
    
    ###	output xtermcfg.h, etc
    AC_CONFIG_FILES([Makefile df-install minstall:minstall.in])
    AC_OUTPUT
    xterm-353/charclass.h0000644000175100001440000000104213610647225013363 0ustar  tomusers/* $XTermId: charclass.h,v 1.8 2020/01/18 18:29:41 tom Exp $ */
    
    /* $XFree86: xc/programs/xterm/charclass.h,v 1.3 2006/02/13 01:14:58 dickey Exp $ */
    
    #ifndef CHARCLASS_H
    #define CHARCLASS_H
    
    extern void init_classtab(void);
    /* initialise the table. needs calling before either of the 
       others. */
    
    extern int SetCharacterClassRange(int low, int high, int value);
    extern int CharacterClass(int c);
    
    #if OPT_REPORT_CCLASS
    extern void report_wide_char_class(void);
    #endif
    
    #ifdef NO_LEAKS
    extern void noleaks_CharacterClass(void);
    #endif
    
    #endif
    xterm-353/config.guess0000755000175100001440000013647113577276335013622 0ustar  tomusers#! /bin/sh
    # Attempt to guess a canonical system name.
    #   Copyright 1992-2019 Free Software Foundation, Inc.
    
    timestamp='2019-12-21'
    
    # This file is free software; you can redistribute it and/or modify it
    # under the terms of the GNU General Public License as published by
    # the Free Software Foundation; either version 3 of the License, or
    # (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful, but
    # WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    # General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program; if not, see .
    #
    # As a special exception to the GNU General Public License, if you
    # distribute this file as part of a program that contains a
    # configuration script generated by Autoconf, you may include it under
    # the same distribution terms that you use for the rest of that
    # program.  This Exception is an additional permission under section 7
    # of the GNU General Public License, version 3 ("GPLv3").
    #
    # Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
    #
    # You can get the latest version of this script from:
    # https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
    #
    # Please send patches to .
    
    
    me=`echo "$0" | sed -e 's,.*/,,'`
    
    usage="\
    Usage: $0 [OPTION]
    
    Output the configuration name of the system \`$me' is run on.
    
    Options:
      -h, --help         print this help, then exit
      -t, --time-stamp   print date of last modification, then exit
      -v, --version      print version number, then exit
    
    Report bugs and patches to ."
    
    version="\
    GNU config.guess ($timestamp)
    
    Originally written by Per Bothner.
    Copyright 1992-2019 Free Software Foundation, Inc.
    
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
    
    help="
    Try \`$me --help' for more information."
    
    # Parse command line
    while test $# -gt 0 ; do
      case $1 in
        --time-stamp | --time* | -t )
           echo "$timestamp" ; exit ;;
        --version | -v )
           echo "$version" ; exit ;;
        --help | --h* | -h )
           echo "$usage"; exit ;;
        -- )     # Stop option processing
           shift; break ;;
        - )	# Use stdin as input.
           break ;;
        -* )
           echo "$me: invalid option $1$help" >&2
           exit 1 ;;
        * )
           break ;;
      esac
    done
    
    if test $# != 0; then
      echo "$me: too many arguments$help" >&2
      exit 1
    fi
    
    # CC_FOR_BUILD -- compiler used by this script. Note that the use of a
    # compiler to aid in system detection is discouraged as it requires
    # temporary files to be created and, as you can see below, it is a
    # headache to deal with in a portable fashion.
    
    # Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
    # use `HOST_CC' if defined, but it is deprecated.
    
    # Portable tmp directory creation inspired by the Autoconf team.
    
    tmp=
    # shellcheck disable=SC2172
    trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
    
    set_cc_for_build() {
        # prevent multiple calls if $tmp is already set
        test "$tmp" && return 0
        : "${TMPDIR=/tmp}"
        # shellcheck disable=SC2039
        { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
    	{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
    	{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
    	{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
        dummy=$tmp/dummy
        case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
    	,,)    echo "int x;" > "$dummy.c"
    	       for driver in cc gcc c89 c99 ; do
    		   if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
    		       CC_FOR_BUILD="$driver"
    		       break
    		   fi
    	       done
    	       if test x"$CC_FOR_BUILD" = x ; then
    		   CC_FOR_BUILD=no_compiler_found
    	       fi
    	       ;;
    	,,*)   CC_FOR_BUILD=$CC ;;
    	,*,*)  CC_FOR_BUILD=$HOST_CC ;;
        esac
    }
    
    # This is needed to find uname on a Pyramid OSx when run in the BSD universe.
    # (ghazi@noc.rutgers.edu 1994-08-24)
    if test -f /.attbin/uname ; then
    	PATH=$PATH:/.attbin ; export PATH
    fi
    
    UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
    UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
    UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
    UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
    
    case "$UNAME_SYSTEM" in
    Linux|GNU|GNU/*)
    	# If the system lacks a compiler, then just pick glibc.
    	# We could probably try harder.
    	LIBC=gnu
    
    	set_cc_for_build
    	cat <<-EOF > "$dummy.c"
    	#include 
    	#if defined(__UCLIBC__)
    	LIBC=uclibc
    	#elif defined(__dietlibc__)
    	LIBC=dietlibc
    	#else
    	LIBC=gnu
    	#endif
    	EOF
    	eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"
    
    	# If ldd exists, use it to detect musl libc.
    	if command -v ldd >/dev/null && \
    		ldd --version 2>&1 | grep -q ^musl
    	then
    	    LIBC=musl
    	fi
    	;;
    esac
    
    # Note: order is significant - the case branches are not exclusive.
    
    case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
        *:NetBSD:*:*)
    	# NetBSD (nbsd) targets should (where applicable) match one or
    	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
    	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
    	# switched to ELF, *-*-netbsd* would select the old
    	# object file format.  This provides both forward
    	# compatibility and a consistent mechanism for selecting the
    	# object file format.
    	#
    	# Note: NetBSD doesn't particularly care about the vendor
    	# portion of the name.  We always set it to "unknown".
    	sysctl="sysctl -n hw.machine_arch"
    	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
    	    "/sbin/$sysctl" 2>/dev/null || \
    	    "/usr/sbin/$sysctl" 2>/dev/null || \
    	    echo unknown)`
    	case "$UNAME_MACHINE_ARCH" in
    	    armeb) machine=armeb-unknown ;;
    	    arm*) machine=arm-unknown ;;
    	    sh3el) machine=shl-unknown ;;
    	    sh3eb) machine=sh-unknown ;;
    	    sh5el) machine=sh5le-unknown ;;
    	    earmv*)
    		arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
    		endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
    		machine="${arch}${endian}"-unknown
    		;;
    	    *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
    	esac
    	# The Operating System including object format, if it has switched
    	# to ELF recently (or will in the future) and ABI.
    	case "$UNAME_MACHINE_ARCH" in
    	    earm*)
    		os=netbsdelf
    		;;
    	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
    		set_cc_for_build
    		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
    			| grep -q __ELF__
    		then
    		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
    		    # Return netbsd for either.  FIX?
    		    os=netbsd
    		else
    		    os=netbsdelf
    		fi
    		;;
    	    *)
    		os=netbsd
    		;;
    	esac
    	# Determine ABI tags.
    	case "$UNAME_MACHINE_ARCH" in
    	    earm*)
    		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
    		abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
    		;;
    	esac
    	# The OS release
    	# Debian GNU/NetBSD machines have a different userland, and
    	# thus, need a distinct triplet. However, they do not need
    	# kernel version information, so it can be replaced with a
    	# suitable tag, in the style of linux-gnu.
    	case "$UNAME_VERSION" in
    	    Debian*)
    		release='-gnu'
    		;;
    	    *)
    		release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
    		;;
    	esac
    	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
    	# contains redundant information, the shorter form:
    	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
    	echo "$machine-${os}${release}${abi-}"
    	exit ;;
        *:Bitrig:*:*)
    	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
    	echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
    	exit ;;
        *:OpenBSD:*:*)
    	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
    	echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
    	exit ;;
        *:LibertyBSD:*:*)
    	UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
    	echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
    	exit ;;
        *:MidnightBSD:*:*)
    	echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
    	exit ;;
        *:ekkoBSD:*:*)
    	echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
    	exit ;;
        *:SolidBSD:*:*)
    	echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
    	exit ;;
        *:OS108:*:*)
    	echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE"
    	exit ;;
        macppc:MirBSD:*:*)
    	echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
    	exit ;;
        *:MirBSD:*:*)
    	echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
    	exit ;;
        *:Sortix:*:*)
    	echo "$UNAME_MACHINE"-unknown-sortix
    	exit ;;
        *:Twizzler:*:*)
    	echo "$UNAME_MACHINE"-unknown-twizzler
    	exit ;;
        *:Redox:*:*)
    	echo "$UNAME_MACHINE"-unknown-redox
    	exit ;;
        mips:OSF1:*.*)
    	echo mips-dec-osf1
    	exit ;;
        alpha:OSF1:*:*)
    	case $UNAME_RELEASE in
    	*4.0)
    		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
    		;;
    	*5.*)
    		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
    		;;
    	esac
    	# According to Compaq, /usr/sbin/psrinfo has been available on
    	# OSF/1 and Tru64 systems produced since 1995.  I hope that
    	# covers most systems running today.  This code pipes the CPU
    	# types through head -n 1, so we only detect the type of CPU 0.
    	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
    	case "$ALPHA_CPU_TYPE" in
    	    "EV4 (21064)")
    		UNAME_MACHINE=alpha ;;
    	    "EV4.5 (21064)")
    		UNAME_MACHINE=alpha ;;
    	    "LCA4 (21066/21068)")
    		UNAME_MACHINE=alpha ;;
    	    "EV5 (21164)")
    		UNAME_MACHINE=alphaev5 ;;
    	    "EV5.6 (21164A)")
    		UNAME_MACHINE=alphaev56 ;;
    	    "EV5.6 (21164PC)")
    		UNAME_MACHINE=alphapca56 ;;
    	    "EV5.7 (21164PC)")
    		UNAME_MACHINE=alphapca57 ;;
    	    "EV6 (21264)")
    		UNAME_MACHINE=alphaev6 ;;
    	    "EV6.7 (21264A)")
    		UNAME_MACHINE=alphaev67 ;;
    	    "EV6.8CB (21264C)")
    		UNAME_MACHINE=alphaev68 ;;
    	    "EV6.8AL (21264B)")
    		UNAME_MACHINE=alphaev68 ;;
    	    "EV6.8CX (21264D)")
    		UNAME_MACHINE=alphaev68 ;;
    	    "EV6.9A (21264/EV69A)")
    		UNAME_MACHINE=alphaev69 ;;
    	    "EV7 (21364)")
    		UNAME_MACHINE=alphaev7 ;;
    	    "EV7.9 (21364A)")
    		UNAME_MACHINE=alphaev79 ;;
    	esac
    	# A Pn.n version is a patched version.
    	# A Vn.n version is a released version.
    	# A Tn.n version is a released field test version.
    	# A Xn.n version is an unreleased experimental baselevel.
    	# 1.2 uses "1.2" for uname -r.
    	echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
    	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
    	exitcode=$?
    	trap '' 0
    	exit $exitcode ;;
        Amiga*:UNIX_System_V:4.0:*)
    	echo m68k-unknown-sysv4
    	exit ;;
        *:[Aa]miga[Oo][Ss]:*:*)
    	echo "$UNAME_MACHINE"-unknown-amigaos
    	exit ;;
        *:[Mm]orph[Oo][Ss]:*:*)
    	echo "$UNAME_MACHINE"-unknown-morphos
    	exit ;;
        *:OS/390:*:*)
    	echo i370-ibm-openedition
    	exit ;;
        *:z/VM:*:*)
    	echo s390-ibm-zvmoe
    	exit ;;
        *:OS400:*:*)
    	echo powerpc-ibm-os400
    	exit ;;
        arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
    	echo arm-acorn-riscix"$UNAME_RELEASE"
    	exit ;;
        arm*:riscos:*:*|arm*:RISCOS:*:*)
    	echo arm-unknown-riscos
    	exit ;;
        SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
    	echo hppa1.1-hitachi-hiuxmpp
    	exit ;;
        Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
    	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
    	if test "`(/bin/universe) 2>/dev/null`" = att ; then
    		echo pyramid-pyramid-sysv3
    	else
    		echo pyramid-pyramid-bsd
    	fi
    	exit ;;
        NILE*:*:*:dcosx)
    	echo pyramid-pyramid-svr4
    	exit ;;
        DRS?6000:unix:4.0:6*)
    	echo sparc-icl-nx6
    	exit ;;
        DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
    	case `/usr/bin/uname -p` in
    	    sparc) echo sparc-icl-nx7; exit ;;
    	esac ;;
        s390x:SunOS:*:*)
    	echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
    	exit ;;
        sun4H:SunOS:5.*:*)
    	echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
    	exit ;;
        sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
    	echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
    	exit ;;
        i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
    	echo i386-pc-auroraux"$UNAME_RELEASE"
    	exit ;;
        i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
    	set_cc_for_build
    	SUN_ARCH=i386
    	# If there is a compiler, see if it is configured for 64-bit objects.
    	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
    	# This test works for both compilers.
    	if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
    	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
    		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
    		grep IS_64BIT_ARCH >/dev/null
    	    then
    		SUN_ARCH=x86_64
    	    fi
    	fi
    	echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
    	exit ;;
        sun4*:SunOS:6*:*)
    	# According to config.sub, this is the proper way to canonicalize
    	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
    	# it's likely to be more like Solaris than SunOS4.
    	echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
    	exit ;;
        sun4*:SunOS:*:*)
    	case "`/usr/bin/arch -k`" in
    	    Series*|S4*)
    		UNAME_RELEASE=`uname -v`
    		;;
    	esac
    	# Japanese Language versions have a version number like `4.1.3-JL'.
    	echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
    	exit ;;
        sun3*:SunOS:*:*)
    	echo m68k-sun-sunos"$UNAME_RELEASE"
    	exit ;;
        sun*:*:4.2BSD:*)
    	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
    	test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
    	case "`/bin/arch`" in
    	    sun3)
    		echo m68k-sun-sunos"$UNAME_RELEASE"
    		;;
    	    sun4)
    		echo sparc-sun-sunos"$UNAME_RELEASE"
    		;;
    	esac
    	exit ;;
        aushp:SunOS:*:*)
    	echo sparc-auspex-sunos"$UNAME_RELEASE"
    	exit ;;
        # The situation for MiNT is a little confusing.  The machine name
        # can be virtually everything (everything which is not
        # "atarist" or "atariste" at least should have a processor
        # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
        # to the lowercase version "mint" (or "freemint").  Finally
        # the system name "TOS" denotes a system which is actually not
        # MiNT.  But MiNT is downward compatible to TOS, so this should
        # be no problem.
        atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
    	echo m68k-atari-mint"$UNAME_RELEASE"
    	exit ;;
        atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
    	echo m68k-atari-mint"$UNAME_RELEASE"
    	exit ;;
        *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
    	echo m68k-atari-mint"$UNAME_RELEASE"
    	exit ;;
        milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
    	echo m68k-milan-mint"$UNAME_RELEASE"
    	exit ;;
        hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
    	echo m68k-hades-mint"$UNAME_RELEASE"
    	exit ;;
        *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
    	echo m68k-unknown-mint"$UNAME_RELEASE"
    	exit ;;
        m68k:machten:*:*)
    	echo m68k-apple-machten"$UNAME_RELEASE"
    	exit ;;
        powerpc:machten:*:*)
    	echo powerpc-apple-machten"$UNAME_RELEASE"
    	exit ;;
        RISC*:Mach:*:*)
    	echo mips-dec-mach_bsd4.3
    	exit ;;
        RISC*:ULTRIX:*:*)
    	echo mips-dec-ultrix"$UNAME_RELEASE"
    	exit ;;
        VAX*:ULTRIX*:*:*)
    	echo vax-dec-ultrix"$UNAME_RELEASE"
    	exit ;;
        2020:CLIX:*:* | 2430:CLIX:*:*)
    	echo clipper-intergraph-clix"$UNAME_RELEASE"
    	exit ;;
        mips:*:*:UMIPS | mips:*:*:RISCos)
    	set_cc_for_build
    	sed 's/^	//' << EOF > "$dummy.c"
    #ifdef __cplusplus
    #include   /* for printf() prototype */
    	int main (int argc, char *argv[]) {
    #else
    	int main (argc, argv) int argc; char *argv[]; {
    #endif
    	#if defined (host_mips) && defined (MIPSEB)
    	#if defined (SYSTYPE_SYSV)
    	  printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
    	#endif
    	#if defined (SYSTYPE_SVR4)
    	  printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
    	#endif
    	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
    	  printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
    	#endif
    	#endif
    	  exit (-1);
    	}
    EOF
    	$CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
    	  dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
    	  SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
    	    { echo "$SYSTEM_NAME"; exit; }
    	echo mips-mips-riscos"$UNAME_RELEASE"
    	exit ;;
        Motorola:PowerMAX_OS:*:*)
    	echo powerpc-motorola-powermax
    	exit ;;
        Motorola:*:4.3:PL8-*)
    	echo powerpc-harris-powermax
    	exit ;;
        Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
    	echo powerpc-harris-powermax
    	exit ;;
        Night_Hawk:Power_UNIX:*:*)
    	echo powerpc-harris-powerunix
    	exit ;;
        m88k:CX/UX:7*:*)
    	echo m88k-harris-cxux7
    	exit ;;
        m88k:*:4*:R4*)
    	echo m88k-motorola-sysv4
    	exit ;;
        m88k:*:3*:R3*)
    	echo m88k-motorola-sysv3
    	exit ;;
        AViiON:dgux:*:*)
    	# DG/UX returns AViiON for all architectures
    	UNAME_PROCESSOR=`/usr/bin/uname -p`
    	if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
    	then
    	    if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
    	       [ "$TARGET_BINARY_INTERFACE"x = x ]
    	    then
    		echo m88k-dg-dgux"$UNAME_RELEASE"
    	    else
    		echo m88k-dg-dguxbcs"$UNAME_RELEASE"
    	    fi
    	else
    	    echo i586-dg-dgux"$UNAME_RELEASE"
    	fi
    	exit ;;
        M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
    	echo m88k-dolphin-sysv3
    	exit ;;
        M88*:*:R3*:*)
    	# Delta 88k system running SVR3
    	echo m88k-motorola-sysv3
    	exit ;;
        XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
    	echo m88k-tektronix-sysv3
    	exit ;;
        Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
    	echo m68k-tektronix-bsd
    	exit ;;
        *:IRIX*:*:*)
    	echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
    	exit ;;
        ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
    	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
    	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
        i*86:AIX:*:*)
    	echo i386-ibm-aix
    	exit ;;
        ia64:AIX:*:*)
    	if [ -x /usr/bin/oslevel ] ; then
    		IBM_REV=`/usr/bin/oslevel`
    	else
    		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
    	fi
    	echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
    	exit ;;
        *:AIX:2:3)
    	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
    		set_cc_for_build
    		sed 's/^		//' << EOF > "$dummy.c"
    		#include 
    
    		main()
    			{
    			if (!__power_pc())
    				exit(1);
    			puts("powerpc-ibm-aix3.2.5");
    			exit(0);
    			}
    EOF
    		if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
    		then
    			echo "$SYSTEM_NAME"
    		else
    			echo rs6000-ibm-aix3.2.5
    		fi
    	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
    		echo rs6000-ibm-aix3.2.4
    	else
    		echo rs6000-ibm-aix3.2
    	fi
    	exit ;;
        *:AIX:*:[4567])
    	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
    	if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
    		IBM_ARCH=rs6000
    	else
    		IBM_ARCH=powerpc
    	fi
    	if [ -x /usr/bin/lslpp ] ; then
    		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
    			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
    	else
    		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
    	fi
    	echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
    	exit ;;
        *:AIX:*:*)
    	echo rs6000-ibm-aix
    	exit ;;
        ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
    	echo romp-ibm-bsd4.4
    	exit ;;
        ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
    	echo romp-ibm-bsd"$UNAME_RELEASE"   # 4.3 with uname added to
    	exit ;;                             # report: romp-ibm BSD 4.3
        *:BOSX:*:*)
    	echo rs6000-bull-bosx
    	exit ;;
        DPX/2?00:B.O.S.:*:*)
    	echo m68k-bull-sysv3
    	exit ;;
        9000/[34]??:4.3bsd:1.*:*)
    	echo m68k-hp-bsd
    	exit ;;
        hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
    	echo m68k-hp-bsd4.4
    	exit ;;
        9000/[34678]??:HP-UX:*:*)
    	HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
    	case "$UNAME_MACHINE" in
    	    9000/31?)            HP_ARCH=m68000 ;;
    	    9000/[34]??)         HP_ARCH=m68k ;;
    	    9000/[678][0-9][0-9])
    		if [ -x /usr/bin/getconf ]; then
    		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
    		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
    		    case "$sc_cpu_version" in
    		      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
    		      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
    		      532)                      # CPU_PA_RISC2_0
    			case "$sc_kernel_bits" in
    			  32) HP_ARCH=hppa2.0n ;;
    			  64) HP_ARCH=hppa2.0w ;;
    			  '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20
    			esac ;;
    		    esac
    		fi
    		if [ "$HP_ARCH" = "" ]; then
    		    set_cc_for_build
    		    sed 's/^		//' << EOF > "$dummy.c"
    
    		#define _HPUX_SOURCE
    		#include 
    		#include 
    
    		int main ()
    		{
    		#if defined(_SC_KERNEL_BITS)
    		    long bits = sysconf(_SC_KERNEL_BITS);
    		#endif
    		    long cpu  = sysconf (_SC_CPU_VERSION);
    
    		    switch (cpu)
    			{
    			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
    			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
    			case CPU_PA_RISC2_0:
    		#if defined(_SC_KERNEL_BITS)
    			    switch (bits)
    				{
    				case 64: puts ("hppa2.0w"); break;
    				case 32: puts ("hppa2.0n"); break;
    				default: puts ("hppa2.0"); break;
    				} break;
    		#else  /* !defined(_SC_KERNEL_BITS) */
    			    puts ("hppa2.0"); break;
    		#endif
    			default: puts ("hppa1.0"); break;
    			}
    		    exit (0);
    		}
    EOF
    		    (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
    		    test -z "$HP_ARCH" && HP_ARCH=hppa
    		fi ;;
    	esac
    	if [ "$HP_ARCH" = hppa2.0w ]
    	then
    	    set_cc_for_build
    
    	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
    	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
    	    # generating 64-bit code.  GNU and HP use different nomenclature:
    	    #
    	    # $ CC_FOR_BUILD=cc ./config.guess
    	    # => hppa2.0w-hp-hpux11.23
    	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
    	    # => hppa64-hp-hpux11.23
    
    	    if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
    		grep -q __LP64__
    	    then
    		HP_ARCH=hppa2.0w
    	    else
    		HP_ARCH=hppa64
    	    fi
    	fi
    	echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
    	exit ;;
        ia64:HP-UX:*:*)
    	HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
    	echo ia64-hp-hpux"$HPUX_REV"
    	exit ;;
        3050*:HI-UX:*:*)
    	set_cc_for_build
    	sed 's/^	//' << EOF > "$dummy.c"
    	#include 
    	int
    	main ()
    	{
    	  long cpu = sysconf (_SC_CPU_VERSION);
    	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
    	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
    	     results, however.  */
    	  if (CPU_IS_PA_RISC (cpu))
    	    {
    	      switch (cpu)
    		{
    		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
    		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
    		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
    		  default: puts ("hppa-hitachi-hiuxwe2"); break;
    		}
    	    }
    	  else if (CPU_IS_HP_MC68K (cpu))
    	    puts ("m68k-hitachi-hiuxwe2");
    	  else puts ("unknown-hitachi-hiuxwe2");
    	  exit (0);
    	}
    EOF
    	$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
    		{ echo "$SYSTEM_NAME"; exit; }
    	echo unknown-hitachi-hiuxwe2
    	exit ;;
        9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
    	echo hppa1.1-hp-bsd
    	exit ;;
        9000/8??:4.3bsd:*:*)
    	echo hppa1.0-hp-bsd
    	exit ;;
        *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
    	echo hppa1.0-hp-mpeix
    	exit ;;
        hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
    	echo hppa1.1-hp-osf
    	exit ;;
        hp8??:OSF1:*:*)
    	echo hppa1.0-hp-osf
    	exit ;;
        i*86:OSF1:*:*)
    	if [ -x /usr/sbin/sysversion ] ; then
    	    echo "$UNAME_MACHINE"-unknown-osf1mk
    	else
    	    echo "$UNAME_MACHINE"-unknown-osf1
    	fi
    	exit ;;
        parisc*:Lites*:*:*)
    	echo hppa1.1-hp-lites
    	exit ;;
        C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
    	echo c1-convex-bsd
    	exit ;;
        C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
    	if getsysinfo -f scalar_acc
    	then echo c32-convex-bsd
    	else echo c2-convex-bsd
    	fi
    	exit ;;
        C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
    	echo c34-convex-bsd
    	exit ;;
        C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
    	echo c38-convex-bsd
    	exit ;;
        C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
    	echo c4-convex-bsd
    	exit ;;
        CRAY*Y-MP:*:*:*)
    	echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
    	exit ;;
        CRAY*[A-Z]90:*:*:*)
    	echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
    	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
    	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
    	      -e 's/\.[^.]*$/.X/'
    	exit ;;
        CRAY*TS:*:*:*)
    	echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
    	exit ;;
        CRAY*T3E:*:*:*)
    	echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
    	exit ;;
        CRAY*SV1:*:*:*)
    	echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
    	exit ;;
        *:UNICOS/mp:*:*)
    	echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
    	exit ;;
        F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
    	FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
    	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
    	FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
    	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
    	exit ;;
        5000:UNIX_System_V:4.*:*)
    	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
    	FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
    	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
    	exit ;;
        i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
    	echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
    	exit ;;
        sparc*:BSD/OS:*:*)
    	echo sparc-unknown-bsdi"$UNAME_RELEASE"
    	exit ;;
        *:BSD/OS:*:*)
    	echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
    	exit ;;
        arm:FreeBSD:*:*)
    	UNAME_PROCESSOR=`uname -p`
    	set_cc_for_build
    	if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
    	    | grep -q __ARM_PCS_VFP
    	then
    	    echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabi
    	else
    	    echo "${UNAME_PROCESSOR}"-unknown-freebsd"`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`"-gnueabihf
    	fi
    	exit ;;
        *:FreeBSD:*:*)
    	UNAME_PROCESSOR=`/usr/bin/uname -p`
    	case "$UNAME_PROCESSOR" in
    	    amd64)
    		UNAME_PROCESSOR=x86_64 ;;
    	    i386)
    		UNAME_PROCESSOR=i586 ;;
    	esac
    	echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
    	exit ;;
        i*:CYGWIN*:*)
    	echo "$UNAME_MACHINE"-pc-cygwin
    	exit ;;
        *:MINGW64*:*)
    	echo "$UNAME_MACHINE"-pc-mingw64
    	exit ;;
        *:MINGW*:*)
    	echo "$UNAME_MACHINE"-pc-mingw32
    	exit ;;
        *:MSYS*:*)
    	echo "$UNAME_MACHINE"-pc-msys
    	exit ;;
        i*:PW*:*)
    	echo "$UNAME_MACHINE"-pc-pw32
    	exit ;;
        *:Interix*:*)
    	case "$UNAME_MACHINE" in
    	    x86)
    		echo i586-pc-interix"$UNAME_RELEASE"
    		exit ;;
    	    authenticamd | genuineintel | EM64T)
    		echo x86_64-unknown-interix"$UNAME_RELEASE"
    		exit ;;
    	    IA64)
    		echo ia64-unknown-interix"$UNAME_RELEASE"
    		exit ;;
    	esac ;;
        i*:UWIN*:*)
    	echo "$UNAME_MACHINE"-pc-uwin
    	exit ;;
        amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
    	echo x86_64-pc-cygwin
    	exit ;;
        prep*:SunOS:5.*:*)
    	echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
    	exit ;;
        *:GNU:*:*)
    	# the GNU system
    	echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`"
    	exit ;;
        *:GNU/*:*:*)
    	# other systems with GNU libc and userland
    	echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
    	exit ;;
        *:Minix:*:*)
    	echo "$UNAME_MACHINE"-unknown-minix
    	exit ;;
        aarch64:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        aarch64_be:Linux:*:*)
    	UNAME_MACHINE=aarch64_be
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        alpha:Linux:*:*)
    	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null` in
    	  EV5)   UNAME_MACHINE=alphaev5 ;;
    	  EV56)  UNAME_MACHINE=alphaev56 ;;
    	  PCA56) UNAME_MACHINE=alphapca56 ;;
    	  PCA57) UNAME_MACHINE=alphapca56 ;;
    	  EV6)   UNAME_MACHINE=alphaev6 ;;
    	  EV67)  UNAME_MACHINE=alphaev67 ;;
    	  EV68*) UNAME_MACHINE=alphaev68 ;;
    	esac
    	objdump --private-headers /bin/sh | grep -q ld.so.1
    	if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        arc:Linux:*:* | arceb:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        arm*:Linux:*:*)
    	set_cc_for_build
    	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
    	    | grep -q __ARM_EABI__
    	then
    	    echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	else
    	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
    		| grep -q __ARM_PCS_VFP
    	    then
    		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
    	    else
    		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
    	    fi
    	fi
    	exit ;;
        avr32*:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        cris:Linux:*:*)
    	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
    	exit ;;
        crisv32:Linux:*:*)
    	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
    	exit ;;
        e2k:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        frv:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        hexagon:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        i*86:Linux:*:*)
    	echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
    	exit ;;
        ia64:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        k1om:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        m32r*:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        m68*:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        mips:Linux:*:* | mips64:Linux:*:*)
    	set_cc_for_build
    	IS_GLIBC=0
    	test x"${LIBC}" = xgnu && IS_GLIBC=1
    	sed 's/^	//' << EOF > "$dummy.c"
    	#undef CPU
    	#undef mips
    	#undef mipsel
    	#undef mips64
    	#undef mips64el
    	#if ${IS_GLIBC} && defined(_ABI64)
    	LIBCABI=gnuabi64
    	#else
    	#if ${IS_GLIBC} && defined(_ABIN32)
    	LIBCABI=gnuabin32
    	#else
    	LIBCABI=${LIBC}
    	#endif
    	#endif
    
    	#if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
    	CPU=mipsisa64r6
    	#else
    	#if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
    	CPU=mipsisa32r6
    	#else
    	#if defined(__mips64)
    	CPU=mips64
    	#else
    	CPU=mips
    	#endif
    	#endif
    	#endif
    
    	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
    	MIPS_ENDIAN=el
    	#else
    	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
    	MIPS_ENDIAN=
    	#else
    	MIPS_ENDIAN=
    	#endif
    	#endif
    EOF
    	eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI'`"
    	test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
    	;;
        mips64el:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        openrisc*:Linux:*:*)
    	echo or1k-unknown-linux-"$LIBC"
    	exit ;;
        or32:Linux:*:* | or1k*:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        padre:Linux:*:*)
    	echo sparc-unknown-linux-"$LIBC"
    	exit ;;
        parisc64:Linux:*:* | hppa64:Linux:*:*)
    	echo hppa64-unknown-linux-"$LIBC"
    	exit ;;
        parisc:Linux:*:* | hppa:Linux:*:*)
    	# Look for CPU level
    	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
    	  PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
    	  PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
    	  *)    echo hppa-unknown-linux-"$LIBC" ;;
    	esac
    	exit ;;
        ppc64:Linux:*:*)
    	echo powerpc64-unknown-linux-"$LIBC"
    	exit ;;
        ppc:Linux:*:*)
    	echo powerpc-unknown-linux-"$LIBC"
    	exit ;;
        ppc64le:Linux:*:*)
    	echo powerpc64le-unknown-linux-"$LIBC"
    	exit ;;
        ppcle:Linux:*:*)
    	echo powerpcle-unknown-linux-"$LIBC"
    	exit ;;
        riscv32:Linux:*:* | riscv64:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        s390:Linux:*:* | s390x:Linux:*:*)
    	echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
    	exit ;;
        sh64*:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        sh*:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        sparc:Linux:*:* | sparc64:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        tile*:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        vax:Linux:*:*)
    	echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
    	exit ;;
        x86_64:Linux:*:*)
    	echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
    	exit ;;
        xtensa*:Linux:*:*)
    	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
    	exit ;;
        i*86:DYNIX/ptx:4*:*)
    	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
    	# earlier versions are messed up and put the nodename in both
    	# sysname and nodename.
    	echo i386-sequent-sysv4
    	exit ;;
        i*86:UNIX_SV:4.2MP:2.*)
    	# Unixware is an offshoot of SVR4, but it has its own version
    	# number series starting with 2...
    	# I am not positive that other SVR4 systems won't match this,
    	# I just have to hope.  -- rms.
    	# Use sysv4.2uw... so that sysv4* matches it.
    	echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
    	exit ;;
        i*86:OS/2:*:*)
    	# If we were able to find `uname', then EMX Unix compatibility
    	# is probably installed.
    	echo "$UNAME_MACHINE"-pc-os2-emx
    	exit ;;
        i*86:XTS-300:*:STOP)
    	echo "$UNAME_MACHINE"-unknown-stop
    	exit ;;
        i*86:atheos:*:*)
    	echo "$UNAME_MACHINE"-unknown-atheos
    	exit ;;
        i*86:syllable:*:*)
    	echo "$UNAME_MACHINE"-pc-syllable
    	exit ;;
        i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
    	echo i386-unknown-lynxos"$UNAME_RELEASE"
    	exit ;;
        i*86:*DOS:*:*)
    	echo "$UNAME_MACHINE"-pc-msdosdjgpp
    	exit ;;
        i*86:*:4.*:*)
    	UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
    	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
    		echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
    	else
    		echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
    	fi
    	exit ;;
        i*86:*:5:[678]*)
    	# UnixWare 7.x, OpenUNIX and OpenServer 6.
    	case `/bin/uname -X | grep "^Machine"` in
    	    *486*)	     UNAME_MACHINE=i486 ;;
    	    *Pentium)	     UNAME_MACHINE=i586 ;;
    	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
    	esac
    	echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}"
    	exit ;;
        i*86:*:3.2:*)
    	if test -f /usr/options/cb.name; then
    		UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then
    		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
    		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
    		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
    			&& UNAME_MACHINE=i586
    		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
    			&& UNAME_MACHINE=i686
    		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
    			&& UNAME_MACHINE=i686
    		echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
    	else
    		echo "$UNAME_MACHINE"-pc-sysv32
    	fi
    	exit ;;
        pc:*:*:*)
    	# Left here for compatibility:
    	# uname -m prints for DJGPP always 'pc', but it prints nothing about
    	# the processor, so we play safe by assuming i586.
    	# Note: whatever this is, it MUST be the same as what config.sub
    	# prints for the "djgpp" host, or else GDB configure will decide that
    	# this is a cross-build.
    	echo i586-pc-msdosdjgpp
    	exit ;;
        Intel:Mach:3*:*)
    	echo i386-pc-mach3
    	exit ;;
        paragon:*:*:*)
    	echo i860-intel-osf1
    	exit ;;
        i860:*:4.*:*) # i860-SVR4
    	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
    	  echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
    	else # Add other i860-SVR4 vendors below as they are discovered.
    	  echo i860-unknown-sysv"$UNAME_RELEASE"  # Unknown i860-SVR4
    	fi
    	exit ;;
        mini*:CTIX:SYS*5:*)
    	# "miniframe"
    	echo m68010-convergent-sysv
    	exit ;;
        mc68k:UNIX:SYSTEM5:3.51m)
    	echo m68k-convergent-sysv
    	exit ;;
        M680?0:D-NIX:5.3:*)
    	echo m68k-diab-dnix
    	exit ;;
        M68*:*:R3V[5678]*:*)
    	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
        3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
    	OS_REL=''
    	test -r /etc/.relid \
    	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
    	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
    	  && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
    	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
    	  && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
        3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
    	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
    	  && { echo i486-ncr-sysv4; exit; } ;;
        NCR*:*:4.2:* | MPRAS*:*:4.2:*)
    	OS_REL='.3'
    	test -r /etc/.relid \
    	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
    	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
    	    && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
    	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
    	    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
    	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
    	    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
        m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
    	echo m68k-unknown-lynxos"$UNAME_RELEASE"
    	exit ;;
        mc68030:UNIX_System_V:4.*:*)
    	echo m68k-atari-sysv4
    	exit ;;
        TSUNAMI:LynxOS:2.*:*)
    	echo sparc-unknown-lynxos"$UNAME_RELEASE"
    	exit ;;
        rs6000:LynxOS:2.*:*)
    	echo rs6000-unknown-lynxos"$UNAME_RELEASE"
    	exit ;;
        PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
    	echo powerpc-unknown-lynxos"$UNAME_RELEASE"
    	exit ;;
        SM[BE]S:UNIX_SV:*:*)
    	echo mips-dde-sysv"$UNAME_RELEASE"
    	exit ;;
        RM*:ReliantUNIX-*:*:*)
    	echo mips-sni-sysv4
    	exit ;;
        RM*:SINIX-*:*:*)
    	echo mips-sni-sysv4
    	exit ;;
        *:SINIX-*:*:*)
    	if uname -p 2>/dev/null >/dev/null ; then
    		UNAME_MACHINE=`(uname -p) 2>/dev/null`
    		echo "$UNAME_MACHINE"-sni-sysv4
    	else
    		echo ns32k-sni-sysv
    	fi
    	exit ;;
        PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
    			# says 
    	echo i586-unisys-sysv4
    	exit ;;
        *:UNIX_System_V:4*:FTX*)
    	# From Gerald Hewes .
    	# How about differentiating between stratus architectures? -djm
    	echo hppa1.1-stratus-sysv4
    	exit ;;
        *:*:*:FTX*)
    	# From seanf@swdc.stratus.com.
    	echo i860-stratus-sysv4
    	exit ;;
        i*86:VOS:*:*)
    	# From Paul.Green@stratus.com.
    	echo "$UNAME_MACHINE"-stratus-vos
    	exit ;;
        *:VOS:*:*)
    	# From Paul.Green@stratus.com.
    	echo hppa1.1-stratus-vos
    	exit ;;
        mc68*:A/UX:*:*)
    	echo m68k-apple-aux"$UNAME_RELEASE"
    	exit ;;
        news*:NEWS-OS:6*:*)
    	echo mips-sony-newsos6
    	exit ;;
        R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
    	if [ -d /usr/nec ]; then
    		echo mips-nec-sysv"$UNAME_RELEASE"
    	else
    		echo mips-unknown-sysv"$UNAME_RELEASE"
    	fi
    	exit ;;
        BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
    	echo powerpc-be-beos
    	exit ;;
        BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
    	echo powerpc-apple-beos
    	exit ;;
        BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
    	echo i586-pc-beos
    	exit ;;
        BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
    	echo i586-pc-haiku
    	exit ;;
        x86_64:Haiku:*:*)
    	echo x86_64-unknown-haiku
    	exit ;;
        SX-4:SUPER-UX:*:*)
    	echo sx4-nec-superux"$UNAME_RELEASE"
    	exit ;;
        SX-5:SUPER-UX:*:*)
    	echo sx5-nec-superux"$UNAME_RELEASE"
    	exit ;;
        SX-6:SUPER-UX:*:*)
    	echo sx6-nec-superux"$UNAME_RELEASE"
    	exit ;;
        SX-7:SUPER-UX:*:*)
    	echo sx7-nec-superux"$UNAME_RELEASE"
    	exit ;;
        SX-8:SUPER-UX:*:*)
    	echo sx8-nec-superux"$UNAME_RELEASE"
    	exit ;;
        SX-8R:SUPER-UX:*:*)
    	echo sx8r-nec-superux"$UNAME_RELEASE"
    	exit ;;
        SX-ACE:SUPER-UX:*:*)
    	echo sxace-nec-superux"$UNAME_RELEASE"
    	exit ;;
        Power*:Rhapsody:*:*)
    	echo powerpc-apple-rhapsody"$UNAME_RELEASE"
    	exit ;;
        *:Rhapsody:*:*)
    	echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
    	exit ;;
        *:Darwin:*:*)
    	UNAME_PROCESSOR=`uname -p`
    	case $UNAME_PROCESSOR in
    	    unknown) UNAME_PROCESSOR=powerpc ;;
    	esac
    	if command -v xcode-select > /dev/null 2> /dev/null && \
    		! xcode-select --print-path > /dev/null 2> /dev/null ; then
    	    # Avoid executing cc if there is no toolchain installed as
    	    # cc will be a stub that puts up a graphical alert
    	    # prompting the user to install developer tools.
    	    CC_FOR_BUILD=no_compiler_found
    	else
    	    set_cc_for_build
    	fi
    	if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
    	    if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
    		   (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
    		   grep IS_64BIT_ARCH >/dev/null
    	    then
    		case $UNAME_PROCESSOR in
    		    i386) UNAME_PROCESSOR=x86_64 ;;
    		    powerpc) UNAME_PROCESSOR=powerpc64 ;;
    		esac
    	    fi
    	    # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
    	    if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
    		   (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
    		   grep IS_PPC >/dev/null
    	    then
    		UNAME_PROCESSOR=powerpc
    	    fi
    	elif test "$UNAME_PROCESSOR" = i386 ; then
    	    # uname -m returns i386 or x86_64
    	    UNAME_PROCESSOR=$UNAME_MACHINE
    	fi
    	echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
    	exit ;;
        *:procnto*:*:* | *:QNX:[0123456789]*:*)
    	UNAME_PROCESSOR=`uname -p`
    	if test "$UNAME_PROCESSOR" = x86; then
    		UNAME_PROCESSOR=i386
    		UNAME_MACHINE=pc
    	fi
    	echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
    	exit ;;
        *:QNX:*:4*)
    	echo i386-pc-qnx
    	exit ;;
        NEO-*:NONSTOP_KERNEL:*:*)
    	echo neo-tandem-nsk"$UNAME_RELEASE"
    	exit ;;
        NSE-*:NONSTOP_KERNEL:*:*)
    	echo nse-tandem-nsk"$UNAME_RELEASE"
    	exit ;;
        NSR-*:NONSTOP_KERNEL:*:*)
    	echo nsr-tandem-nsk"$UNAME_RELEASE"
    	exit ;;
        NSV-*:NONSTOP_KERNEL:*:*)
    	echo nsv-tandem-nsk"$UNAME_RELEASE"
    	exit ;;
        NSX-*:NONSTOP_KERNEL:*:*)
    	echo nsx-tandem-nsk"$UNAME_RELEASE"
    	exit ;;
        *:NonStop-UX:*:*)
    	echo mips-compaq-nonstopux
    	exit ;;
        BS2000:POSIX*:*:*)
    	echo bs2000-siemens-sysv
    	exit ;;
        DS/*:UNIX_System_V:*:*)
    	echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
    	exit ;;
        *:Plan9:*:*)
    	# "uname -m" is not consistent, so use $cputype instead. 386
    	# is converted to i386 for consistency with other x86
    	# operating systems.
    	# shellcheck disable=SC2154
    	if test "$cputype" = 386; then
    	    UNAME_MACHINE=i386
    	else
    	    UNAME_MACHINE="$cputype"
    	fi
    	echo "$UNAME_MACHINE"-unknown-plan9
    	exit ;;
        *:TOPS-10:*:*)
    	echo pdp10-unknown-tops10
    	exit ;;
        *:TENEX:*:*)
    	echo pdp10-unknown-tenex
    	exit ;;
        KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
    	echo pdp10-dec-tops20
    	exit ;;
        XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
    	echo pdp10-xkl-tops20
    	exit ;;
        *:TOPS-20:*:*)
    	echo pdp10-unknown-tops20
    	exit ;;
        *:ITS:*:*)
    	echo pdp10-unknown-its
    	exit ;;
        SEI:*:*:SEIUX)
    	echo mips-sei-seiux"$UNAME_RELEASE"
    	exit ;;
        *:DragonFly:*:*)
    	echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
    	exit ;;
        *:*VMS:*:*)
    	UNAME_MACHINE=`(uname -p) 2>/dev/null`
    	case "$UNAME_MACHINE" in
    	    A*) echo alpha-dec-vms ; exit ;;
    	    I*) echo ia64-dec-vms ; exit ;;
    	    V*) echo vax-dec-vms ; exit ;;
    	esac ;;
        *:XENIX:*:SysV)
    	echo i386-pc-xenix
    	exit ;;
        i*86:skyos:*:*)
    	echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
    	exit ;;
        i*86:rdos:*:*)
    	echo "$UNAME_MACHINE"-pc-rdos
    	exit ;;
        i*86:AROS:*:*)
    	echo "$UNAME_MACHINE"-pc-aros
    	exit ;;
        x86_64:VMkernel:*:*)
    	echo "$UNAME_MACHINE"-unknown-esx
    	exit ;;
        amd64:Isilon\ OneFS:*:*)
    	echo x86_64-unknown-onefs
    	exit ;;
        *:Unleashed:*:*)
    	echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE"
    	exit ;;
    esac
    
    # No uname command or uname output not recognized.
    set_cc_for_build
    cat > "$dummy.c" <
    #include 
    #endif
    #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
    #if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
    #include 
    #if defined(_SIZE_T_) || defined(SIGLOST)
    #include 
    #endif
    #endif
    #endif
    main ()
    {
    #if defined (sony)
    #if defined (MIPSEB)
      /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
         I don't know....  */
      printf ("mips-sony-bsd\n"); exit (0);
    #else
    #include 
      printf ("m68k-sony-newsos%s\n",
    #ifdef NEWSOS4
      "4"
    #else
      ""
    #endif
      ); exit (0);
    #endif
    #endif
    
    #if defined (NeXT)
    #if !defined (__ARCHITECTURE__)
    #define __ARCHITECTURE__ "m68k"
    #endif
      int version;
      version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`;
      if (version < 4)
        printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
      else
        printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
      exit (0);
    #endif
    
    #if defined (MULTIMAX) || defined (n16)
    #if defined (UMAXV)
      printf ("ns32k-encore-sysv\n"); exit (0);
    #else
    #if defined (CMU)
      printf ("ns32k-encore-mach\n"); exit (0);
    #else
      printf ("ns32k-encore-bsd\n"); exit (0);
    #endif
    #endif
    #endif
    
    #if defined (__386BSD__)
      printf ("i386-pc-bsd\n"); exit (0);
    #endif
    
    #if defined (sequent)
    #if defined (i386)
      printf ("i386-sequent-dynix\n"); exit (0);
    #endif
    #if defined (ns32000)
      printf ("ns32k-sequent-dynix\n"); exit (0);
    #endif
    #endif
    
    #if defined (_SEQUENT_)
      struct utsname un;
    
      uname(&un);
      if (strncmp(un.version, "V2", 2) == 0) {
        printf ("i386-sequent-ptx2\n"); exit (0);
      }
      if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
        printf ("i386-sequent-ptx1\n"); exit (0);
      }
      printf ("i386-sequent-ptx\n"); exit (0);
    #endif
    
    #if defined (vax)
    #if !defined (ultrix)
    #include 
    #if defined (BSD)
    #if BSD == 43
      printf ("vax-dec-bsd4.3\n"); exit (0);
    #else
    #if BSD == 199006
      printf ("vax-dec-bsd4.3reno\n"); exit (0);
    #else
      printf ("vax-dec-bsd\n"); exit (0);
    #endif
    #endif
    #else
      printf ("vax-dec-bsd\n"); exit (0);
    #endif
    #else
    #if defined(_SIZE_T_) || defined(SIGLOST)
      struct utsname un;
      uname (&un);
      printf ("vax-dec-ultrix%s\n", un.release); exit (0);
    #else
      printf ("vax-dec-ultrix\n"); exit (0);
    #endif
    #endif
    #endif
    #if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
    #if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
    #if defined(_SIZE_T_) || defined(SIGLOST)
      struct utsname *un;
      uname (&un);
      printf ("mips-dec-ultrix%s\n", un.release); exit (0);
    #else
      printf ("mips-dec-ultrix\n"); exit (0);
    #endif
    #endif
    #endif
    
    #if defined (alliant) && defined (i860)
      printf ("i860-alliant-bsd\n"); exit (0);
    #endif
    
      exit (1);
    }
    EOF
    
    $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=`$dummy` &&
    	{ echo "$SYSTEM_NAME"; exit; }
    
    # Apollos put the system type in the environment.
    test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
    
    echo "$0: unable to guess system type" >&2
    
    case "$UNAME_MACHINE:$UNAME_SYSTEM" in
        mips:Linux | mips64:Linux)
    	# If we got here on MIPS GNU/Linux, output extra information.
    	cat >&2 <&2 </dev/null || echo unknown`
    uname -r = `(uname -r) 2>/dev/null || echo unknown`
    uname -s = `(uname -s) 2>/dev/null || echo unknown`
    uname -v = `(uname -v) 2>/dev/null || echo unknown`
    
    /usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
    /bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
    
    hostinfo               = `(hostinfo) 2>/dev/null`
    /bin/universe          = `(/bin/universe) 2>/dev/null`
    /usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
    /bin/arch              = `(/bin/arch) 2>/dev/null`
    /usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
    /usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
    
    UNAME_MACHINE = "$UNAME_MACHINE"
    UNAME_RELEASE = "$UNAME_RELEASE"
    UNAME_SYSTEM  = "$UNAME_SYSTEM"
    UNAME_VERSION = "$UNAME_VERSION"
    EOF
    
    exit 1
    
    # Local variables:
    # eval: (add-hook 'before-save-hook 'time-stamp)
    # time-stamp-start: "timestamp='"
    # time-stamp-format: "%:y-%02m-%02d"
    # time-stamp-end: "'"
    # End:
    xterm-353/256colres.h0000644000175100001440000003702310633366147013157 0ustar  tomusers/*
     * This header file was generated by ./256colres.pl
     */
    /* $XTermId: 256colres.h,v 1.11 2007/06/12 00:44:23 tom Exp $ */
    
    #ifndef included_256colres_h
    #define included_256colres_h
    
    COLOR_RES("16",	screen.Acolors[16],	DFT_COLOR("rgb:00/00/00")),
    COLOR_RES("17",	screen.Acolors[17],	DFT_COLOR("rgb:00/00/5f")),
    COLOR_RES("18",	screen.Acolors[18],	DFT_COLOR("rgb:00/00/87")),
    COLOR_RES("19",	screen.Acolors[19],	DFT_COLOR("rgb:00/00/af")),
    COLOR_RES("20",	screen.Acolors[20],	DFT_COLOR("rgb:00/00/d7")),
    COLOR_RES("21",	screen.Acolors[21],	DFT_COLOR("rgb:00/00/ff")),
    COLOR_RES("22",	screen.Acolors[22],	DFT_COLOR("rgb:00/5f/00")),
    COLOR_RES("23",	screen.Acolors[23],	DFT_COLOR("rgb:00/5f/5f")),
    COLOR_RES("24",	screen.Acolors[24],	DFT_COLOR("rgb:00/5f/87")),
    COLOR_RES("25",	screen.Acolors[25],	DFT_COLOR("rgb:00/5f/af")),
    COLOR_RES("26",	screen.Acolors[26],	DFT_COLOR("rgb:00/5f/d7")),
    COLOR_RES("27",	screen.Acolors[27],	DFT_COLOR("rgb:00/5f/ff")),
    COLOR_RES("28",	screen.Acolors[28],	DFT_COLOR("rgb:00/87/00")),
    COLOR_RES("29",	screen.Acolors[29],	DFT_COLOR("rgb:00/87/5f")),
    COLOR_RES("30",	screen.Acolors[30],	DFT_COLOR("rgb:00/87/87")),
    COLOR_RES("31",	screen.Acolors[31],	DFT_COLOR("rgb:00/87/af")),
    COLOR_RES("32",	screen.Acolors[32],	DFT_COLOR("rgb:00/87/d7")),
    COLOR_RES("33",	screen.Acolors[33],	DFT_COLOR("rgb:00/87/ff")),
    COLOR_RES("34",	screen.Acolors[34],	DFT_COLOR("rgb:00/af/00")),
    COLOR_RES("35",	screen.Acolors[35],	DFT_COLOR("rgb:00/af/5f")),
    COLOR_RES("36",	screen.Acolors[36],	DFT_COLOR("rgb:00/af/87")),
    COLOR_RES("37",	screen.Acolors[37],	DFT_COLOR("rgb:00/af/af")),
    COLOR_RES("38",	screen.Acolors[38],	DFT_COLOR("rgb:00/af/d7")),
    COLOR_RES("39",	screen.Acolors[39],	DFT_COLOR("rgb:00/af/ff")),
    COLOR_RES("40",	screen.Acolors[40],	DFT_COLOR("rgb:00/d7/00")),
    COLOR_RES("41",	screen.Acolors[41],	DFT_COLOR("rgb:00/d7/5f")),
    COLOR_RES("42",	screen.Acolors[42],	DFT_COLOR("rgb:00/d7/87")),
    COLOR_RES("43",	screen.Acolors[43],	DFT_COLOR("rgb:00/d7/af")),
    COLOR_RES("44",	screen.Acolors[44],	DFT_COLOR("rgb:00/d7/d7")),
    COLOR_RES("45",	screen.Acolors[45],	DFT_COLOR("rgb:00/d7/ff")),
    COLOR_RES("46",	screen.Acolors[46],	DFT_COLOR("rgb:00/ff/00")),
    COLOR_RES("47",	screen.Acolors[47],	DFT_COLOR("rgb:00/ff/5f")),
    COLOR_RES("48",	screen.Acolors[48],	DFT_COLOR("rgb:00/ff/87")),
    COLOR_RES("49",	screen.Acolors[49],	DFT_COLOR("rgb:00/ff/af")),
    COLOR_RES("50",	screen.Acolors[50],	DFT_COLOR("rgb:00/ff/d7")),
    COLOR_RES("51",	screen.Acolors[51],	DFT_COLOR("rgb:00/ff/ff")),
    COLOR_RES("52",	screen.Acolors[52],	DFT_COLOR("rgb:5f/00/00")),
    COLOR_RES("53",	screen.Acolors[53],	DFT_COLOR("rgb:5f/00/5f")),
    COLOR_RES("54",	screen.Acolors[54],	DFT_COLOR("rgb:5f/00/87")),
    COLOR_RES("55",	screen.Acolors[55],	DFT_COLOR("rgb:5f/00/af")),
    COLOR_RES("56",	screen.Acolors[56],	DFT_COLOR("rgb:5f/00/d7")),
    COLOR_RES("57",	screen.Acolors[57],	DFT_COLOR("rgb:5f/00/ff")),
    COLOR_RES("58",	screen.Acolors[58],	DFT_COLOR("rgb:5f/5f/00")),
    COLOR_RES("59",	screen.Acolors[59],	DFT_COLOR("rgb:5f/5f/5f")),
    COLOR_RES("60",	screen.Acolors[60],	DFT_COLOR("rgb:5f/5f/87")),
    COLOR_RES("61",	screen.Acolors[61],	DFT_COLOR("rgb:5f/5f/af")),
    COLOR_RES("62",	screen.Acolors[62],	DFT_COLOR("rgb:5f/5f/d7")),
    COLOR_RES("63",	screen.Acolors[63],	DFT_COLOR("rgb:5f/5f/ff")),
    COLOR_RES("64",	screen.Acolors[64],	DFT_COLOR("rgb:5f/87/00")),
    COLOR_RES("65",	screen.Acolors[65],	DFT_COLOR("rgb:5f/87/5f")),
    COLOR_RES("66",	screen.Acolors[66],	DFT_COLOR("rgb:5f/87/87")),
    COLOR_RES("67",	screen.Acolors[67],	DFT_COLOR("rgb:5f/87/af")),
    COLOR_RES("68",	screen.Acolors[68],	DFT_COLOR("rgb:5f/87/d7")),
    COLOR_RES("69",	screen.Acolors[69],	DFT_COLOR("rgb:5f/87/ff")),
    COLOR_RES("70",	screen.Acolors[70],	DFT_COLOR("rgb:5f/af/00")),
    COLOR_RES("71",	screen.Acolors[71],	DFT_COLOR("rgb:5f/af/5f")),
    COLOR_RES("72",	screen.Acolors[72],	DFT_COLOR("rgb:5f/af/87")),
    COLOR_RES("73",	screen.Acolors[73],	DFT_COLOR("rgb:5f/af/af")),
    COLOR_RES("74",	screen.Acolors[74],	DFT_COLOR("rgb:5f/af/d7")),
    COLOR_RES("75",	screen.Acolors[75],	DFT_COLOR("rgb:5f/af/ff")),
    COLOR_RES("76",	screen.Acolors[76],	DFT_COLOR("rgb:5f/d7/00")),
    COLOR_RES("77",	screen.Acolors[77],	DFT_COLOR("rgb:5f/d7/5f")),
    COLOR_RES("78",	screen.Acolors[78],	DFT_COLOR("rgb:5f/d7/87")),
    COLOR_RES("79",	screen.Acolors[79],	DFT_COLOR("rgb:5f/d7/af")),
    COLOR_RES("80",	screen.Acolors[80],	DFT_COLOR("rgb:5f/d7/d7")),
    COLOR_RES("81",	screen.Acolors[81],	DFT_COLOR("rgb:5f/d7/ff")),
    COLOR_RES("82",	screen.Acolors[82],	DFT_COLOR("rgb:5f/ff/00")),
    COLOR_RES("83",	screen.Acolors[83],	DFT_COLOR("rgb:5f/ff/5f")),
    COLOR_RES("84",	screen.Acolors[84],	DFT_COLOR("rgb:5f/ff/87")),
    COLOR_RES("85",	screen.Acolors[85],	DFT_COLOR("rgb:5f/ff/af")),
    COLOR_RES("86",	screen.Acolors[86],	DFT_COLOR("rgb:5f/ff/d7")),
    COLOR_RES("87",	screen.Acolors[87],	DFT_COLOR("rgb:5f/ff/ff")),
    COLOR_RES("88",	screen.Acolors[88],	DFT_COLOR("rgb:87/00/00")),
    COLOR_RES("89",	screen.Acolors[89],	DFT_COLOR("rgb:87/00/5f")),
    COLOR_RES("90",	screen.Acolors[90],	DFT_COLOR("rgb:87/00/87")),
    COLOR_RES("91",	screen.Acolors[91],	DFT_COLOR("rgb:87/00/af")),
    COLOR_RES("92",	screen.Acolors[92],	DFT_COLOR("rgb:87/00/d7")),
    COLOR_RES("93",	screen.Acolors[93],	DFT_COLOR("rgb:87/00/ff")),
    COLOR_RES("94",	screen.Acolors[94],	DFT_COLOR("rgb:87/5f/00")),
    COLOR_RES("95",	screen.Acolors[95],	DFT_COLOR("rgb:87/5f/5f")),
    COLOR_RES("96",	screen.Acolors[96],	DFT_COLOR("rgb:87/5f/87")),
    COLOR_RES("97",	screen.Acolors[97],	DFT_COLOR("rgb:87/5f/af")),
    COLOR_RES("98",	screen.Acolors[98],	DFT_COLOR("rgb:87/5f/d7")),
    COLOR_RES("99",	screen.Acolors[99],	DFT_COLOR("rgb:87/5f/ff")),
    COLOR_RES("100",	screen.Acolors[100],	DFT_COLOR("rgb:87/87/00")),
    COLOR_RES("101",	screen.Acolors[101],	DFT_COLOR("rgb:87/87/5f")),
    COLOR_RES("102",	screen.Acolors[102],	DFT_COLOR("rgb:87/87/87")),
    COLOR_RES("103",	screen.Acolors[103],	DFT_COLOR("rgb:87/87/af")),
    COLOR_RES("104",	screen.Acolors[104],	DFT_COLOR("rgb:87/87/d7")),
    COLOR_RES("105",	screen.Acolors[105],	DFT_COLOR("rgb:87/87/ff")),
    COLOR_RES("106",	screen.Acolors[106],	DFT_COLOR("rgb:87/af/00")),
    COLOR_RES("107",	screen.Acolors[107],	DFT_COLOR("rgb:87/af/5f")),
    COLOR_RES("108",	screen.Acolors[108],	DFT_COLOR("rgb:87/af/87")),
    COLOR_RES("109",	screen.Acolors[109],	DFT_COLOR("rgb:87/af/af")),
    COLOR_RES("110",	screen.Acolors[110],	DFT_COLOR("rgb:87/af/d7")),
    COLOR_RES("111",	screen.Acolors[111],	DFT_COLOR("rgb:87/af/ff")),
    COLOR_RES("112",	screen.Acolors[112],	DFT_COLOR("rgb:87/d7/00")),
    COLOR_RES("113",	screen.Acolors[113],	DFT_COLOR("rgb:87/d7/5f")),
    COLOR_RES("114",	screen.Acolors[114],	DFT_COLOR("rgb:87/d7/87")),
    COLOR_RES("115",	screen.Acolors[115],	DFT_COLOR("rgb:87/d7/af")),
    COLOR_RES("116",	screen.Acolors[116],	DFT_COLOR("rgb:87/d7/d7")),
    COLOR_RES("117",	screen.Acolors[117],	DFT_COLOR("rgb:87/d7/ff")),
    COLOR_RES("118",	screen.Acolors[118],	DFT_COLOR("rgb:87/ff/00")),
    COLOR_RES("119",	screen.Acolors[119],	DFT_COLOR("rgb:87/ff/5f")),
    COLOR_RES("120",	screen.Acolors[120],	DFT_COLOR("rgb:87/ff/87")),
    COLOR_RES("121",	screen.Acolors[121],	DFT_COLOR("rgb:87/ff/af")),
    COLOR_RES("122",	screen.Acolors[122],	DFT_COLOR("rgb:87/ff/d7")),
    COLOR_RES("123",	screen.Acolors[123],	DFT_COLOR("rgb:87/ff/ff")),
    COLOR_RES("124",	screen.Acolors[124],	DFT_COLOR("rgb:af/00/00")),
    COLOR_RES("125",	screen.Acolors[125],	DFT_COLOR("rgb:af/00/5f")),
    COLOR_RES("126",	screen.Acolors[126],	DFT_COLOR("rgb:af/00/87")),
    COLOR_RES("127",	screen.Acolors[127],	DFT_COLOR("rgb:af/00/af")),
    COLOR_RES("128",	screen.Acolors[128],	DFT_COLOR("rgb:af/00/d7")),
    COLOR_RES("129",	screen.Acolors[129],	DFT_COLOR("rgb:af/00/ff")),
    COLOR_RES("130",	screen.Acolors[130],	DFT_COLOR("rgb:af/5f/00")),
    COLOR_RES("131",	screen.Acolors[131],	DFT_COLOR("rgb:af/5f/5f")),
    COLOR_RES("132",	screen.Acolors[132],	DFT_COLOR("rgb:af/5f/87")),
    COLOR_RES("133",	screen.Acolors[133],	DFT_COLOR("rgb:af/5f/af")),
    COLOR_RES("134",	screen.Acolors[134],	DFT_COLOR("rgb:af/5f/d7")),
    COLOR_RES("135",	screen.Acolors[135],	DFT_COLOR("rgb:af/5f/ff")),
    COLOR_RES("136",	screen.Acolors[136],	DFT_COLOR("rgb:af/87/00")),
    COLOR_RES("137",	screen.Acolors[137],	DFT_COLOR("rgb:af/87/5f")),
    COLOR_RES("138",	screen.Acolors[138],	DFT_COLOR("rgb:af/87/87")),
    COLOR_RES("139",	screen.Acolors[139],	DFT_COLOR("rgb:af/87/af")),
    COLOR_RES("140",	screen.Acolors[140],	DFT_COLOR("rgb:af/87/d7")),
    COLOR_RES("141",	screen.Acolors[141],	DFT_COLOR("rgb:af/87/ff")),
    COLOR_RES("142",	screen.Acolors[142],	DFT_COLOR("rgb:af/af/00")),
    COLOR_RES("143",	screen.Acolors[143],	DFT_COLOR("rgb:af/af/5f")),
    COLOR_RES("144",	screen.Acolors[144],	DFT_COLOR("rgb:af/af/87")),
    COLOR_RES("145",	screen.Acolors[145],	DFT_COLOR("rgb:af/af/af")),
    COLOR_RES("146",	screen.Acolors[146],	DFT_COLOR("rgb:af/af/d7")),
    COLOR_RES("147",	screen.Acolors[147],	DFT_COLOR("rgb:af/af/ff")),
    COLOR_RES("148",	screen.Acolors[148],	DFT_COLOR("rgb:af/d7/00")),
    COLOR_RES("149",	screen.Acolors[149],	DFT_COLOR("rgb:af/d7/5f")),
    COLOR_RES("150",	screen.Acolors[150],	DFT_COLOR("rgb:af/d7/87")),
    COLOR_RES("151",	screen.Acolors[151],	DFT_COLOR("rgb:af/d7/af")),
    COLOR_RES("152",	screen.Acolors[152],	DFT_COLOR("rgb:af/d7/d7")),
    COLOR_RES("153",	screen.Acolors[153],	DFT_COLOR("rgb:af/d7/ff")),
    COLOR_RES("154",	screen.Acolors[154],	DFT_COLOR("rgb:af/ff/00")),
    COLOR_RES("155",	screen.Acolors[155],	DFT_COLOR("rgb:af/ff/5f")),
    COLOR_RES("156",	screen.Acolors[156],	DFT_COLOR("rgb:af/ff/87")),
    COLOR_RES("157",	screen.Acolors[157],	DFT_COLOR("rgb:af/ff/af")),
    COLOR_RES("158",	screen.Acolors[158],	DFT_COLOR("rgb:af/ff/d7")),
    COLOR_RES("159",	screen.Acolors[159],	DFT_COLOR("rgb:af/ff/ff")),
    COLOR_RES("160",	screen.Acolors[160],	DFT_COLOR("rgb:d7/00/00")),
    COLOR_RES("161",	screen.Acolors[161],	DFT_COLOR("rgb:d7/00/5f")),
    COLOR_RES("162",	screen.Acolors[162],	DFT_COLOR("rgb:d7/00/87")),
    COLOR_RES("163",	screen.Acolors[163],	DFT_COLOR("rgb:d7/00/af")),
    COLOR_RES("164",	screen.Acolors[164],	DFT_COLOR("rgb:d7/00/d7")),
    COLOR_RES("165",	screen.Acolors[165],	DFT_COLOR("rgb:d7/00/ff")),
    COLOR_RES("166",	screen.Acolors[166],	DFT_COLOR("rgb:d7/5f/00")),
    COLOR_RES("167",	screen.Acolors[167],	DFT_COLOR("rgb:d7/5f/5f")),
    COLOR_RES("168",	screen.Acolors[168],	DFT_COLOR("rgb:d7/5f/87")),
    COLOR_RES("169",	screen.Acolors[169],	DFT_COLOR("rgb:d7/5f/af")),
    COLOR_RES("170",	screen.Acolors[170],	DFT_COLOR("rgb:d7/5f/d7")),
    COLOR_RES("171",	screen.Acolors[171],	DFT_COLOR("rgb:d7/5f/ff")),
    COLOR_RES("172",	screen.Acolors[172],	DFT_COLOR("rgb:d7/87/00")),
    COLOR_RES("173",	screen.Acolors[173],	DFT_COLOR("rgb:d7/87/5f")),
    COLOR_RES("174",	screen.Acolors[174],	DFT_COLOR("rgb:d7/87/87")),
    COLOR_RES("175",	screen.Acolors[175],	DFT_COLOR("rgb:d7/87/af")),
    COLOR_RES("176",	screen.Acolors[176],	DFT_COLOR("rgb:d7/87/d7")),
    COLOR_RES("177",	screen.Acolors[177],	DFT_COLOR("rgb:d7/87/ff")),
    COLOR_RES("178",	screen.Acolors[178],	DFT_COLOR("rgb:d7/af/00")),
    COLOR_RES("179",	screen.Acolors[179],	DFT_COLOR("rgb:d7/af/5f")),
    COLOR_RES("180",	screen.Acolors[180],	DFT_COLOR("rgb:d7/af/87")),
    COLOR_RES("181",	screen.Acolors[181],	DFT_COLOR("rgb:d7/af/af")),
    COLOR_RES("182",	screen.Acolors[182],	DFT_COLOR("rgb:d7/af/d7")),
    COLOR_RES("183",	screen.Acolors[183],	DFT_COLOR("rgb:d7/af/ff")),
    COLOR_RES("184",	screen.Acolors[184],	DFT_COLOR("rgb:d7/d7/00")),
    COLOR_RES("185",	screen.Acolors[185],	DFT_COLOR("rgb:d7/d7/5f")),
    COLOR_RES("186",	screen.Acolors[186],	DFT_COLOR("rgb:d7/d7/87")),
    COLOR_RES("187",	screen.Acolors[187],	DFT_COLOR("rgb:d7/d7/af")),
    COLOR_RES("188",	screen.Acolors[188],	DFT_COLOR("rgb:d7/d7/d7")),
    COLOR_RES("189",	screen.Acolors[189],	DFT_COLOR("rgb:d7/d7/ff")),
    COLOR_RES("190",	screen.Acolors[190],	DFT_COLOR("rgb:d7/ff/00")),
    COLOR_RES("191",	screen.Acolors[191],	DFT_COLOR("rgb:d7/ff/5f")),
    COLOR_RES("192",	screen.Acolors[192],	DFT_COLOR("rgb:d7/ff/87")),
    COLOR_RES("193",	screen.Acolors[193],	DFT_COLOR("rgb:d7/ff/af")),
    COLOR_RES("194",	screen.Acolors[194],	DFT_COLOR("rgb:d7/ff/d7")),
    COLOR_RES("195",	screen.Acolors[195],	DFT_COLOR("rgb:d7/ff/ff")),
    COLOR_RES("196",	screen.Acolors[196],	DFT_COLOR("rgb:ff/00/00")),
    COLOR_RES("197",	screen.Acolors[197],	DFT_COLOR("rgb:ff/00/5f")),
    COLOR_RES("198",	screen.Acolors[198],	DFT_COLOR("rgb:ff/00/87")),
    COLOR_RES("199",	screen.Acolors[199],	DFT_COLOR("rgb:ff/00/af")),
    COLOR_RES("200",	screen.Acolors[200],	DFT_COLOR("rgb:ff/00/d7")),
    COLOR_RES("201",	screen.Acolors[201],	DFT_COLOR("rgb:ff/00/ff")),
    COLOR_RES("202",	screen.Acolors[202],	DFT_COLOR("rgb:ff/5f/00")),
    COLOR_RES("203",	screen.Acolors[203],	DFT_COLOR("rgb:ff/5f/5f")),
    COLOR_RES("204",	screen.Acolors[204],	DFT_COLOR("rgb:ff/5f/87")),
    COLOR_RES("205",	screen.Acolors[205],	DFT_COLOR("rgb:ff/5f/af")),
    COLOR_RES("206",	screen.Acolors[206],	DFT_COLOR("rgb:ff/5f/d7")),
    COLOR_RES("207",	screen.Acolors[207],	DFT_COLOR("rgb:ff/5f/ff")),
    COLOR_RES("208",	screen.Acolors[208],	DFT_COLOR("rgb:ff/87/00")),
    COLOR_RES("209",	screen.Acolors[209],	DFT_COLOR("rgb:ff/87/5f")),
    COLOR_RES("210",	screen.Acolors[210],	DFT_COLOR("rgb:ff/87/87")),
    COLOR_RES("211",	screen.Acolors[211],	DFT_COLOR("rgb:ff/87/af")),
    COLOR_RES("212",	screen.Acolors[212],	DFT_COLOR("rgb:ff/87/d7")),
    COLOR_RES("213",	screen.Acolors[213],	DFT_COLOR("rgb:ff/87/ff")),
    COLOR_RES("214",	screen.Acolors[214],	DFT_COLOR("rgb:ff/af/00")),
    COLOR_RES("215",	screen.Acolors[215],	DFT_COLOR("rgb:ff/af/5f")),
    COLOR_RES("216",	screen.Acolors[216],	DFT_COLOR("rgb:ff/af/87")),
    COLOR_RES("217",	screen.Acolors[217],	DFT_COLOR("rgb:ff/af/af")),
    COLOR_RES("218",	screen.Acolors[218],	DFT_COLOR("rgb:ff/af/d7")),
    COLOR_RES("219",	screen.Acolors[219],	DFT_COLOR("rgb:ff/af/ff")),
    COLOR_RES("220",	screen.Acolors[220],	DFT_COLOR("rgb:ff/d7/00")),
    COLOR_RES("221",	screen.Acolors[221],	DFT_COLOR("rgb:ff/d7/5f")),
    COLOR_RES("222",	screen.Acolors[222],	DFT_COLOR("rgb:ff/d7/87")),
    COLOR_RES("223",	screen.Acolors[223],	DFT_COLOR("rgb:ff/d7/af")),
    COLOR_RES("224",	screen.Acolors[224],	DFT_COLOR("rgb:ff/d7/d7")),
    COLOR_RES("225",	screen.Acolors[225],	DFT_COLOR("rgb:ff/d7/ff")),
    COLOR_RES("226",	screen.Acolors[226],	DFT_COLOR("rgb:ff/ff/00")),
    COLOR_RES("227",	screen.Acolors[227],	DFT_COLOR("rgb:ff/ff/5f")),
    COLOR_RES("228",	screen.Acolors[228],	DFT_COLOR("rgb:ff/ff/87")),
    COLOR_RES("229",	screen.Acolors[229],	DFT_COLOR("rgb:ff/ff/af")),
    COLOR_RES("230",	screen.Acolors[230],	DFT_COLOR("rgb:ff/ff/d7")),
    COLOR_RES("231",	screen.Acolors[231],	DFT_COLOR("rgb:ff/ff/ff")),
    COLOR_RES("232",	screen.Acolors[232],	DFT_COLOR("rgb:08/08/08")),
    COLOR_RES("233",	screen.Acolors[233],	DFT_COLOR("rgb:12/12/12")),
    COLOR_RES("234",	screen.Acolors[234],	DFT_COLOR("rgb:1c/1c/1c")),
    COLOR_RES("235",	screen.Acolors[235],	DFT_COLOR("rgb:26/26/26")),
    COLOR_RES("236",	screen.Acolors[236],	DFT_COLOR("rgb:30/30/30")),
    COLOR_RES("237",	screen.Acolors[237],	DFT_COLOR("rgb:3a/3a/3a")),
    COLOR_RES("238",	screen.Acolors[238],	DFT_COLOR("rgb:44/44/44")),
    COLOR_RES("239",	screen.Acolors[239],	DFT_COLOR("rgb:4e/4e/4e")),
    COLOR_RES("240",	screen.Acolors[240],	DFT_COLOR("rgb:58/58/58")),
    COLOR_RES("241",	screen.Acolors[241],	DFT_COLOR("rgb:62/62/62")),
    COLOR_RES("242",	screen.Acolors[242],	DFT_COLOR("rgb:6c/6c/6c")),
    COLOR_RES("243",	screen.Acolors[243],	DFT_COLOR("rgb:76/76/76")),
    COLOR_RES("244",	screen.Acolors[244],	DFT_COLOR("rgb:80/80/80")),
    COLOR_RES("245",	screen.Acolors[245],	DFT_COLOR("rgb:8a/8a/8a")),
    COLOR_RES("246",	screen.Acolors[246],	DFT_COLOR("rgb:94/94/94")),
    COLOR_RES("247",	screen.Acolors[247],	DFT_COLOR("rgb:9e/9e/9e")),
    COLOR_RES("248",	screen.Acolors[248],	DFT_COLOR("rgb:a8/a8/a8")),
    COLOR_RES("249",	screen.Acolors[249],	DFT_COLOR("rgb:b2/b2/b2")),
    COLOR_RES("250",	screen.Acolors[250],	DFT_COLOR("rgb:bc/bc/bc")),
    COLOR_RES("251",	screen.Acolors[251],	DFT_COLOR("rgb:c6/c6/c6")),
    COLOR_RES("252",	screen.Acolors[252],	DFT_COLOR("rgb:d0/d0/d0")),
    COLOR_RES("253",	screen.Acolors[253],	DFT_COLOR("rgb:da/da/da")),
    COLOR_RES("254",	screen.Acolors[254],	DFT_COLOR("rgb:e4/e4/e4")),
    COLOR_RES("255",	screen.Acolors[255],	DFT_COLOR("rgb:ee/ee/ee")),
    
    #endif /* included_256colres_h */
    xterm-353/main.h0000644000175100001440000001420413514211217012337 0ustar  tomusers/* $XTermId: main.h,v 1.72 2019/07/19 00:45:03 tom Exp $ */
    
    /*
     * Copyright 2000-2018,2019 by Thomas E. Dickey
     *
     *                         All Rights Reserved
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     *
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * Except as contained in this notice, the name(s) of the above copyright
     * holders shall not be used in advertising or otherwise to promote the
     * sale, use or other dealings in this Software without prior written
     * authorization.
     *
     * Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
     *
     *                         All Rights Reserved
     *
     * Permission to use, copy, modify, and distribute this software and its
     * documentation for any purpose and without fee is hereby granted,
     * provided that the above copyright notice appear in all copies and that
     * both that copyright notice and this permission notice appear in
     * supporting documentation, and that the name of Digital Equipment
     * Corporation not be used in advertising or publicity pertaining to
     * distribution of the software without specific, written prior permission.
     *
     *
     * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     * SOFTWARE.
     */
    #ifndef included_main_h
    #define included_main_h
    
    #include 
    
    #ifndef DEFCLASS
    #define DEFCLASS		"XTerm"
    #endif
    
    #ifndef DEFFONT
    #define DEFFONT			"fixed"
    #endif
    
    #ifndef DEFWIDEFONT
    #define DEFWIDEFONT		NULL	/* grab one which is 2x as wide */
    #endif
    
    #ifndef DEFWIDEBOLDFONT
    #define DEFWIDEBOLDFONT		NULL
    #endif
    
    #ifndef DEFXIMFONT
    #define DEFXIMFONT		"fixed"
    #endif
    
    #ifndef DEFBOLDFONT
    #define DEFBOLDFONT		NULL	/* no bold font uses overstriking */
    #endif
    
    #ifndef DEFBORDER
    #define DEFBORDER		2
    #endif
    
    #ifndef DEFFACENAME
    #define DEFFACENAME		NULL
    #endif
    
    #ifndef DEFFACENAME_AUTO
    #define DEFFACENAME_AUTO	"mono"
    #endif
    
    #ifndef DEFFACESIZE
    #define DEFFACESIZE		"8.0"
    #endif
    
    #ifndef DEF_ALLOW_COLOR
    #define DEF_ALLOW_COLOR		True
    #endif
    
    #ifndef DEF_ALLOW_FONT
    #define DEF_ALLOW_FONT		True
    #endif
    
    #ifndef DEF_ALLOW_MOUSE
    #define DEF_ALLOW_MOUSE		True
    #endif
    
    #ifndef DEF_ALLOW_TCAP
    #define DEF_ALLOW_TCAP		True
    #endif
    
    #ifndef DEF_ALLOW_TITLE
    #define DEF_ALLOW_TITLE		True
    #endif
    
    #ifndef DEF_ALLOW_WINDOW
    #define DEF_ALLOW_WINDOW	False
    #endif
    
    #ifndef DEF_DISALLOWED_COLOR
    #define DEF_DISALLOWED_COLOR	"SetColor,GetColor,GetAnsiColor"
    #endif
    
    #ifndef DEF_DISALLOWED_FONT
    #define DEF_DISALLOWED_FONT	"SetFont,GetFont"
    #endif
    
    #ifndef DEF_DISALLOWED_MOUSE
    #define DEF_DISALLOWED_MOUSE	"*"
    #endif
    
    #ifndef DEF_DISALLOWED_PASTE_CONTROLS
    #define DEF_DISALLOWED_PASTE_CONTROLS	"BS,HT,DEL,ESC"
    #endif
    
    #ifndef DEF_DISALLOWED_TCAP
    #define DEF_DISALLOWED_TCAP	"SetTcap,GetTcap"
    #endif
    
    #ifndef DEF_DISALLOWED_WINDOW
    #define DEF_DISALLOWED_WINDOW	"20,21,SetXprop,SetSelection"
    #endif
    
    #if OPT_BLINK_TEXT
    #define DEFBLINKASBOLD		False
    #else
    #define DEFBLINKASBOLD		True
    #endif
    
    #if OPT_DOUBLE_BUFFER
    #define DEF_DOUBLE_BUFFER	True
    #else
    #define DEF_DOUBLE_BUFFER	False
    #endif
    
    #ifndef DEFDELETE_DEL
    #define DEFDELETE_DEL		Maybe
    #endif
    
    #ifndef DEF_BACKARO_ERASE
    #define DEF_BACKARO_ERASE	False
    #endif
    
    #ifndef DEF_BACKARO_BS
    #define DEF_BACKARO_BS		True
    #endif
    
    #ifndef DEF_ALT_SENDS_ESC
    #define DEF_ALT_SENDS_ESC	False
    #endif
    
    #ifndef DEF_META_SENDS_ESC
    #define DEF_META_SENDS_ESC	False
    #endif
    
    #ifndef DEF_8BIT_META
    #define DEF_8BIT_META		"true"	/* eightBitMeta */
    #endif
    
    #ifndef DEF_COLOR4
    #define DEF_COLOR4		"blue2"		/* see XTerm-col.ad */
    #endif
    
    #ifndef DEF_COLOR12
    #define DEF_COLOR12		"rgb:5c/5c/ff"	/* see XTerm-col.ad */
    #endif
    
    #ifndef DEF_INITIAL_ERASE
    #define DEF_INITIAL_ERASE	False
    #endif
    
    #ifndef DEF_MENU_LOCALE
    #define DEF_MENU_LOCALE		"C"
    #endif
    
    #ifndef DEF_POINTER_MODE
    #define DEF_POINTER_MODE	pNoMouse
    #endif
    
    #ifndef DEF_PTY_STTY_SIZE
    #if defined(linux) || defined(__APPLE__)
    #define DEF_PTY_STTY_SIZE	False
    #else
    #define DEF_PTY_STTY_SIZE	True
    #endif
    #endif
    
    #ifndef DEF_BUFFER_RATE
    #define DEF_BUFFER_RATE		40	/* frames/second, limited to 100 */
    #endif
    
    #ifndef DEF_LIMIT_RESPONSE
    #define DEF_LIMIT_RESPONSE	1024
    #endif
    
    #ifndef DEF_SAVE_LINES
    #define DEF_SAVE_LINES		1024
    #endif
    
    #ifndef DEF_SCROLL_LINES
    #define DEF_SCROLL_LINES	1
    #endif
    
    #ifndef DEF_TITLE_MODES
    #define DEF_TITLE_MODES		0
    #endif
    
    #ifndef DEF_XFT_CACHE
    #define DEF_XFT_CACHE		50
    #endif
    
    #ifndef PROJECTROOT
    #define PROJECTROOT		"/usr/X11R6"
    #endif
    
    /*
     * The configure script quotes PROJECTROOT's value.
     * imake does not quote PROJECTROOT's value.
     */
    #ifdef HAVE_CONFIG_H
    #define DEFLOCALEFILTER2(x)	x
    #else
    #define DEFLOCALEFILTER2(x)	#x
    #endif
    
    /*
     * If the configure script finds luit, we have the path directly.
     */
    #ifdef LUIT_PATH
    #define DEFLOCALEFILTER		LUIT_PATH
    #else
    #define DEFLOCALEFILTER1(x)	DEFLOCALEFILTER2(x)
    #define DEFLOCALEFILTER		DEFLOCALEFILTER1(PROJECTROOT) "/bin/luit"
    #endif
    
    /*
     * See lib/Xt/Resources.c
     */
    #define MAXRESOURCES            400
    
    #endif /* included_main_h */
    xterm-353/88colres.pl0000755000175100001440000000610110632366343013257 0ustar  tomusers#!/usr/bin/perl
    # $XTermId: 88colres.pl,v 1.17 2007/06/08 23:57:23 tom Exp $
    # -----------------------------------------------------------------------------
    # this file is part of xterm
    #
    # Copyright 1999-2005,2007 by Thomas E. Dickey
    # Copyright 1999-2000 by Steve Wall
    # 
    #                         All Rights Reserved
    # 
    # Permission is hereby granted, free of charge, to any person obtaining a
    # copy of this software and associated documentation files (the
    # "Software"), to deal in the Software without restriction, including
    # without limitation the rights to use, copy, modify, merge, publish,
    # distribute, sublicense, and/or sell copies of the Software, and to
    # permit persons to whom the Software is furnished to do so, subject to
    # the following conditions:
    # 
    # The above copyright notice and this permission notice shall be included
    # in all copies or substantial portions of the Software.
    # 
    # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
    # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    # IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
    # CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
    # 
    # Except as contained in this notice, the name(s) of the above copyright
    # holders shall not be used in advertising or otherwise to promote the
    # sale, use or other dealings in this Software without prior written
    # authorization.
    # -----------------------------------------------------------------------------
    # Made from 256colres.pl
    
    # Construct a header file defining default resources for the
    # 88-color model of xterm.
    
    # use the resources for colors 0-15 - usually more-or-less a
    # reproduction of the standard ANSI colors, but possibly more
    # pleasing shades
    
    use strict;
    
    our ( $line1, $line2, $line3 );
    our ( $red, $green, $blue, $gray );
    our ( $level, $code, @steps );
    
    print < 0 ) { $level += 23.18181818; }
        $code = 80 + $gray;
        printf($line1, $code);
        printf($line2, $code);
        printf($line3,
    	   int($level), int($level), int($level));
    }
    
    print <;
        close(FP);
        my $name = $file;
        $name =~ s,^.*/,,;
        $name =~ s/\..*$//;
        $name =~ s/^(8859)/ISO-$1/;
        $name =~ s/-/_/g;
        printf "#define map_%s(code) \\\n", $name;
        printf "\tswitch (code) { \\\n";
        my @target;
        my @noteof;
    
        for my $n ( 0 .. $#data ) {
            chomp $data[$n];
            $data[$n] =~ s/^\s*//;
            $data[$n] =~ s/\s*$//;
            next if ( $data[$n] =~ /^#/ );
            next if ( $data[$n] eq "" );
            if ( $data[$n] !~ /^0x[[:xdigit:]]+\s+0x[[:xdigit:]]+\s*#/i ) {
                printf STDERR "?? %d:%s\n", $n + 1, $data[$n];
                next;
            }
    
            my $source = $data[$n];
            $source =~ s/\s.*//;
            $source = hex($source);
            next if ( $source < 160 or $source > 255 );
            $source -= 128;
    
            my $target = $data[$n];
            $target =~ s/^[^\s]+\s+(0x[[:xdigit:]]+).*$/$1/i;
            $target = hex($target);
    
            my $noteof = $data[$n];
            $noteof =~ s/^[^#]+#\s*//;
    
            $target[$source] = $target;
            $noteof[$source] = $noteof;
        }
        my $lo = $target[32]  ? 32  : 33;
        my $hi = $target[127] ? 127 : 126;
        for my $n ( $lo .. $hi ) {
            if ( defined $target[$n] ) {
                printf "\t    UNI(0x%02x, 0x%04x);\t/* %s */ \\\n", $n,
                  $target[$n], $noteof[$n];
            }
            else {
                printf "\t    XXX(0x%02x, UNDEF);\t/* undefined */ \\\n", $n;
            }
        }
        printf "\t}\n";
    }
    
    while ( $#ARGV >= 0 ) {
        &do_file( shift @ARGV );
    }
    
    1;
    xterm-353/graphics_regis.c0000644000175100001440000065155113610650260014415 0ustar  tomusers/* $XTermId: graphics_regis.c,v 1.114 2020/01/18 18:38:40 tom Exp $ */
    
    /*
     * Copyright 2014-2019,2020 by Ross Combs
     *
     *                         All Rights Reserved
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the
     * "Software"), to deal in the Software without restriction, including
     * without limitation the rights to use, copy, modify, merge, publish,
     * distribute, sublicense, and/or sell copies of the Software, and to
     * permit persons to whom the Software is furnished to do so, subject to
     * the following conditions:
     *
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     * IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
     * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
     * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
     * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     *
     * Except as contained in this notice, the name(s) of the above copyright
     * holders shall not be used in advertising or otherwise to promote the
     * sale, use or other dealings in this Software without prior written
     * authorization.
     */
    
    #include 
    
    #include 
    #include 
    #include 
    #include 
    
    #include 
    #include 
    
    #include 
    #include 
    #include 
    
    /* get rid of shadowing warnings (we will not draw Bessel functions) */
    #define y1 my_y1
    #define y0 my_y0
    
    #define IS_HEX_DIGIT(CH) ( \
      (CH) == '0' || \
      (CH) == '1' || \
      (CH) == '2' || \
      (CH) == '3' || \
      (CH) == '4' || \
      (CH) == '5' || \
      (CH) == '6' || \
      (CH) == '7' || \
      (CH) == '8' || \
      (CH) == '9' || \
      (CH) == 'a' || \
      (CH) == 'b' || \
      (CH) == 'c' || \
      (CH) == 'd' || \
      (CH) == 'e' || \
      (CH) == 'f' || \
      (CH) == 'A' || \
      (CH) == 'B' || \
      (CH) == 'C' || \
      (CH) == 'D' || \
      (CH) == 'E' || \
      (CH) == 'F' )
    
    #define SCALE_FIXED_POINT 16U
    
    #undef DEBUG_PARSING
    #undef DEBUG_ALPHABET_LOOKUP
    #undef DEBUG_ALPHABETS
    #undef DEBUG_BEZIER
    #undef DEBUG_SPLINE_SEGMENTS
    #undef DEBUG_SPLINE_POINTS
    #undef DEBUG_SPLINE_WITH_ROTATION
    #undef DEBUG_SPLINE_WITH_OVERDRAW
    #undef DEBUG_ARC_POINTS
    #undef DEBUG_ARC_CENTER
    #undef DEBUG_ARC_START
    #undef DEBUG_ARC_END
    #undef DEBUG_SPECIFIC_CHAR_METRICS
    #define IS_DEBUG_CHAR(CH) ((CH) == 'W')		/* glyphs to dump to terminal */
    #undef DEBUG_COMPUTED_FONT_METRICS
    #undef DEBUG_FONT_NAME
    #undef DEBUG_FONT_SIZE_SEARCH
    #undef DEBUG_XFT_GLYPH
    #undef DEBUG_USER_GLYPH
    #undef DEBUG_LOAD
    
    /* controls for extensions over VT3x0 limitations */
    #define ENABLE_RGB_COLORSPECS
    #undef ENABLE_FREE_ROTATION
    #undef ENABLE_DISTORTIONLESS_ROTATION
    #define ENABLE_UPLOAD_ALPHABET_FROM_FONT
    #define ENABLE_UPLOAD_ALPHABET_ZERO
    #define ENABLE_USER_FONT_SIZE
    #define ENABLE_VARIABLE_ITALICS
    
    #define MIN_ITERATIONS_BEFORE_REFRESH 10U
    #define MIN_MS_BEFORE_REFRESH 33
    /* *INDENT-OFF* */
    typedef struct RegisPoint {
        int  x, y;
    } RegisPoint;
    
    typedef struct RegisWriteControls {
        unsigned     pv_multiplier;
        unsigned     pattern;
        unsigned     pattern_multiplier;
        unsigned     invert_pattern;
        unsigned     plane_mask;
        unsigned     write_style;
        RegisterNum  foreground;
        unsigned     shading_enabled;
        char         shading_character;
        int          shading_reference;
        unsigned     shading_reference_dim;
        unsigned     line_width;
    } RegisWriteControls;
    
    typedef struct RegisTextControls {
        unsigned  alphabet_num;
        unsigned  character_set_l; /* default: "(B" (ASCII) */
        unsigned  character_set_r; /* default: "-@" (Latin-1) */
        unsigned  character_display_w;
        unsigned  character_display_h;
        unsigned  character_unit_cell_w;
        unsigned  character_unit_cell_h;
        int       character_inc_x;
        int       character_inc_y;
        int       string_rotation;
        int       character_rotation;
        int       slant; /* for italic/oblique */
    } RegisTextControls;
    
    #define FixedCopy(dst, src, len) strncpy(dst, src, len - 1)[len - 1] = '\0'
    #define CopyFontname(dst, src) FixedCopy(dst, src, (size_t) REGIS_FONTNAME_LEN)
    
    #define MAX_REGIS_PAGES 8U
    
    #define MAX_REGIS_ALPHABETS 8U
    #define REGIS_ALPHABET_NAME_LEN 11U
    #define REGIS_FONTNAME_LEN 256U
    /* enough for a 16x24 font (about 100KB) */
    #define MAX_REGIS_ALPHABET_BYTES (256U * 16U * 24U)
    #define MAX_GLYPH_PIXELS 8192U
    #define MAX_GLYPHS 256U
    #define INVALID_ALPHABET_NUM ~0U
    
    typedef struct RegisAlphabet {
        unsigned       alphabet_num;
        unsigned       pixw, pixh;
        char           name[REGIS_ALPHABET_NAME_LEN];
        char           fontname[REGIS_FONTNAME_LEN];
        int            use_font;
        int            loaded[MAX_GLYPHS];
        unsigned char *bytes;
    } RegisAlphabet;
    
    typedef struct RegisDataFragment {
        char const  *start;
        unsigned     pos;
        unsigned     len;
    } RegisDataFragment;
    /* *INDENT-ON* */
    
    #define POSITION_STACK_SIZE 16U
    #define DUMMY_STACK_X -32768
    #define DUMMY_STACK_Y -32768
    
    #define CURVE_POSITION_ARC_EDGE     0U
    #define CURVE_POSITION_ARC_CENTER   1U
    #define CURVE_POSITION_OPEN_CURVE   2U
    #define CURVE_POSITION_CLOSED_CURVE 3U
    
    #define MAX_INPUT_CURVE_POINTS 16U
    #define MAX_CURVE_POINTS (MAX_INPUT_CURVE_POINTS + 4U)
    
    #define MAX_FILL_POINTS 2048U
    
    typedef struct RegisParseState {
        RegisDataFragment input;
        char *temp;
        unsigned templen;
        char command;
        char option;
        /* position stack */
        int stack_x[POSITION_STACK_SIZE];
        int stack_y[POSITION_STACK_SIZE];
        unsigned stack_next;	/* next empty position */
        /* curve options */
        int curve_mode;
        int arclen;
        int x_points[MAX_CURVE_POINTS];
        int y_points[MAX_CURVE_POINTS];
        unsigned num_points;
        /* load options */
        char load_name[REGIS_ALPHABET_NAME_LEN];
        unsigned load_alphabet;
        unsigned load_w, load_h;
        unsigned load_index;
        unsigned load_glyph;
        unsigned load_row;
        /* text options */
        unsigned text_tilt_state;
    } RegisParseState;
    
    #define TEXT_TILT_STATE_READY    0U
    #define TEXT_TILT_STATE_GOT_D    1U
    #define TEXT_TILT_STATE_GOT_DS   2U
    #define TEXT_TILT_STATE_GOT_DSD  3U
    
    typedef struct RegisGraphicsContext {
        XtermWidget current_widget;
        Graphic *destination_graphic;
        Graphic *display_graphic;
        int terminal_id;
        int x_off, y_off;
        int x_div, y_div;
        int width, height;
        unsigned all_planes;
        RegisterNum background;
        char const *builtin_font;
        RegisAlphabet alphabets[MAX_REGIS_ALPHABETS];
        RegisWriteControls persistent_write_controls;
        RegisWriteControls temporary_write_controls;
        RegisTextControls persistent_text_controls;
        RegisTextControls temporary_text_controls;
        RegisTextControls *current_text_controls;
        int multi_input_mode;
        int graphics_output_cursor_x;
        int graphics_output_cursor_y;
        unsigned pattern_count;
        unsigned pattern_bit;
        int fill_mode;
        RegisPoint fill_points[MAX_FILL_POINTS];
        unsigned fill_point_count;
        unsigned destination_page;
        unsigned display_page;
        int force_refresh;
    } RegisGraphicsContext;
    
    static RegisGraphicsContext persistent_context;
    static RegisParseState persistent_state;
    
    #define MAX_PATTERN_BITS 8U
    
    #define WRITE_STYLE_OVERLAY 1U
    #define WRITE_STYLE_REPLACE 2U
    #define WRITE_STYLE_COMPLEMENT 3U
    #define WRITE_STYLE_ERASE 4U
    
    #define WRITE_SHADING_REF_Y 0U
    #define WRITE_SHADING_REF_X 1U
    #define WRITE_SHADING_REF_NONE 2U
    
    /* keypress event example: http://iraf.net/forum/viewtopic.php?showtopic=61692 */
    
    #define MIN2(X, Y) ( (X) < (Y) ? (X) : (Y) )
    #define MIN3(X, Y, Z) ( MIN2(MIN2((X), (Y)), MIN2((Y), (Z))) )
    #define MAX2(X, Y) ( (X) > (Y) ? (X) : (Y) )
    #define MAX3(X, Y, Z) ( MAX2(MAX2((X), (Y)), MAX2((Y), (Z))) )
    
    #define ROT_LEFT_N(V, N) ( (((V) << ((N) & 3U )) & 255U) | \
    			   ((V) >> (8U - ((N) & 3U))) )
    #define ROT_LEFT(V) ( (((V) << 1U) & 255U) | ((V) >> 7U) )
    
    /* convert user coordinates to absolute pixel coordinates */
    #define SCALE_XCOORD(C, X, S) ( ( (X) * ((C)->width  - 1) ) / ( (C)->x_div * (S) ) )
    #define SCALE_YCOORD(C, Y, S) ( ( (Y) * ((C)->height - 1) ) / ( (C)->y_div * (S) ) )
    #define TRANSLATE_XCOORD(C, X, S) SCALE_XCOORD((C), (X) - (C)->x_off * (S), (S) )
    #define TRANSLATE_YCOORD(C, Y, S) SCALE_YCOORD((C), (Y) - (C)->y_off * (S), (S) )
    
    #if 0
    /* convert absolute pixel coordinate to user coordinates */
    #define SCALE_XPIX(C, X, S) ( ( (X) * ((C)->x_div * (S) ) ) / ((C)->width  - 1) )
    #define SCALE_YPIX(C, Y, S) ( ( (Y) * ((C)->y_div * (S) ) ) / ((C)->height - 1) )
    #define TRANSLATE_XPIX(C, X, S) ( SCALE_XPIX((C), (X), (S) ) + (C)->x_off * (S) )
    #define TRANSLATE_YPIX(C, Y, S) ( SCALE_YPIX((C), (Y), (S) ) + (C)->y_off * (S) )
    #endif
    
    #define READ_PIXEL(C, X, Y) read_pixel((C)->destination_graphic, (X), (Y))
    #define DRAW_PIXEL(C, X, Y, COL) draw_solid_pixel((C)->destination_graphic, (X), (Y), (COL))
    #define DRAW_ALL(C, COL) \
        draw_solid_rectangle((C)->destination_graphic, 0, 0, (C)->width, (C)->height, (COL))
    
    static unsigned get_shade_character_pixel(unsigned char const *pixels,
    					  unsigned w, unsigned h,
    					  unsigned smaxf, unsigned scale,
    					  int slant_dx, int px, int py);
    static void get_bitmap_of_character(RegisGraphicsContext const *context,
    				    int ch, unsigned maxw, unsigned maxh,
    				    unsigned char *pixels,
    				    unsigned *w, unsigned *h,
    				    unsigned max_pixels);
    
    static void
    init_regis_load_state(RegisParseState *state)
    {
        state->load_index = MAX_REGIS_ALPHABETS;
        state->load_w = 8U;
        state->load_h = 10U;
        state->load_alphabet = 1U;	/* FIXME: is this the correct default */
        state->load_name[0] = '\0';
        state->load_glyph = (unsigned) (unsigned char) '\0';
        state->load_row = 0U;
    }
    
    static void
    init_regis_parse_state(RegisParseState *state)
    {
        state->command = '_';
        state->option = '_';
        state->stack_next = 0U;
        state->load_index = MAX_REGIS_ALPHABETS;
        init_regis_load_state(state);
    }
    
    static int
    ifloor(double d)
    {
        double dl = floor(d);
        return (int) dl;
    }
    
    static int
    isqrt(double d)
    {
        double dl = sqrt(d);
        return (int) dl;
    }
    
    static void
    draw_regis_pixel(RegisGraphicsContext *context, int x, int y,
    		 unsigned value)
    {
        unsigned color = 0;
    
        switch (context->temporary_write_controls.write_style) {
        case WRITE_STYLE_OVERLAY:
    	/*
    	 * Update pixels with foreground when pattern is 1,
    	 * don't change when pattern is 0.
    	 */
    	if (!value) {
    	    return;
    	}
    
    	if (context->temporary_write_controls.invert_pattern) {
    	    color = context->background;
    	} else {
    	    color = context->temporary_write_controls.foreground;
    	}
    	break;
    
        case WRITE_STYLE_REPLACE:
    	/*
    	 * Update pixels with foreground when pattern is 1,
    	 * set to background when pattern is 0.
    	 */
    	{
    	    unsigned fg, bg;
    
    	    if (context->temporary_write_controls.invert_pattern) {
    		fg = context->background;
    		bg = context->temporary_write_controls.foreground;
    	    } else {
    		fg = context->temporary_write_controls.foreground;
    		bg = context->background;
    	    }
    	    color = value ? fg : bg;
    	}
    	break;
    
        case WRITE_STYLE_COMPLEMENT:
    	/*
    	 * Update pixels with background when pattern is 1,
    	 * don't change when pattern is 0.
    	 */
    	if (!value) {
    	    return;
    	}
    
    	color = READ_PIXEL(context, x, y);
    	if (color == COLOR_HOLE)
    	    color = context->background;
    	color = color ^ context->all_planes;
    	break;
    
        case WRITE_STYLE_ERASE:
    	/* Update pixels to foreground. */
    	if (context->temporary_write_controls.invert_pattern) {
    	    color = context->temporary_write_controls.foreground;
    	} else {
    	    color = context->background;
    	}
    	break;
        }
    
        if (context->temporary_write_controls.plane_mask != context->all_planes) {
    	unsigned old_color = READ_PIXEL(context, x, y);
    	if (old_color == COLOR_HOLE)
    	    old_color = context->background;
    	color = (color & context->temporary_write_controls.plane_mask) |
    	    (old_color & ~context->temporary_write_controls.plane_mask);
        }
    
        DRAW_PIXEL(context, x, y, color);
    }
    
    static void
    shade_pattern_to_pixel(RegisGraphicsContext *context, unsigned dim, int ref,
    		       int x, int y)
    {
        unsigned value;
    
        if (dim == WRITE_SHADING_REF_X) {
    	int delta = x > ref ? 1 : -1;
    	int curr_x;
    
    	context->pattern_bit = 1U << (((unsigned) y) & 7U);
    	for (curr_x = ref; curr_x != x + delta; curr_x += delta) {
    	    value = context->temporary_write_controls.pattern &
    		context->pattern_bit;
    	    draw_regis_pixel(context, curr_x, y, value);
    	}
        } else if (dim == WRITE_SHADING_REF_Y) {
    	int delta = y > ref ? 1 : -1;
    	int curr_y;
    
    	for (curr_y = ref; curr_y != y + delta; curr_y += delta) {
    	    context->pattern_bit = 1U << (((unsigned) curr_y) & 7U);
    	    value = context->temporary_write_controls.pattern &
    		context->pattern_bit;
    	    draw_regis_pixel(context, x, curr_y, value);
    	}
        } else {
    	TRACE(("ERROR: shading requested, but there is no reference axis\n"));
        }
    }
    
    static void
    shade_char_to_pixel(RegisGraphicsContext *context, unsigned char const *pixels,
    		    unsigned w, unsigned h, unsigned dim, int ref, int x, int y)
    {
        unsigned xmaxf = context->current_text_controls->character_unit_cell_w;
        unsigned ymaxf = context->current_text_controls->character_unit_cell_h;
        unsigned smaxf;
        unsigned s;
        unsigned scale;
        unsigned value;
    
        if (xmaxf > ymaxf) {
    	smaxf = ymaxf;
    	s = h;
        } else {
    	smaxf = xmaxf;
    	s = w;
        }
        scale = (s << SCALE_FIXED_POINT) / smaxf;
    
        if (dim == WRITE_SHADING_REF_X) {
    	int delta = x > ref ? 1 : -1;
    	int curr_x;
    
    	for (curr_x = ref; curr_x != x + delta; curr_x += delta) {
    	    value = get_shade_character_pixel(pixels, w, h, smaxf, scale, 0,
    					      curr_x, y);
    	    draw_regis_pixel(context, curr_x, y, value);
    	}
        } else if (dim == WRITE_SHADING_REF_Y) {
    	int delta = y > ref ? 1 : -1;
    	int curr_y;
    
    	for (curr_y = ref; curr_y != y + delta; curr_y += delta) {
    	    value = get_shade_character_pixel(pixels, w, h, smaxf, scale, 0, x,
    					      curr_y);
    	    draw_regis_pixel(context, x, curr_y, value);
    	}
        } else {
    	TRACE(("ERROR: shading requested, but there is no reference axis\n"));
        }
    }
    
    static void
    draw_patterned_pixel(RegisGraphicsContext *context, int x, int y)
    {
        if (context->pattern_count >=
    	context->temporary_write_controls.pattern_multiplier) {
    	context->pattern_count = 0U;
    	context->pattern_bit = ROT_LEFT(context->pattern_bit);
        }
        context->pattern_count++;
    
        draw_regis_pixel(context, x, y,
    		     context->temporary_write_controls.pattern &
    		     context->pattern_bit);
    }
    
    static void
    shade_to_pixel(RegisGraphicsContext *context, unsigned dim, int ref,
    	       int x, int y)
    {
        if (context->temporary_write_controls.shading_character != '\0') {
    	unsigned xmaxf = context->current_text_controls->character_unit_cell_w;
    	unsigned ymaxf = context->current_text_controls->character_unit_cell_h;
    	char ch = context->temporary_write_controls.shading_character;
    	unsigned char pixels[MAX_GLYPH_PIXELS];
    	unsigned w, h;
    
    	get_bitmap_of_character(context, ch, xmaxf, ymaxf, pixels, &w, &h,
    				MAX_GLYPH_PIXELS);
    	if (w > 0 && h > 0) {
    	    shade_char_to_pixel(context, pixels, w, h, dim, ref, x, y);
    	}
        } else {
    	shade_pattern_to_pixel(context, dim, ref, x, y);
        }
    }
    
    static void
    draw_or_save_patterned_pixel(RegisGraphicsContext *context, int x, int y)
    {
        if (context->fill_mode == 1) {
    	if (context->fill_point_count >= MAX_FILL_POINTS) {
    	    TRACE(("point %d,%d can not be added to filled polygon\n",
    		   x, y));
    	    return;
    	}
    	if (context->fill_point_count > 0U &&
    	    context->fill_points[context->fill_point_count - 1U].x == x &&
    	    context->fill_points[context->fill_point_count - 1U].y == y) {
    	    return;
    	}
    	context->fill_points[context->fill_point_count].x = x;
    	context->fill_points[context->fill_point_count].y = y;
    	context->fill_point_count++;
    	return;
        }
    
        if (context->temporary_write_controls.shading_enabled) {
    	unsigned dim = context->temporary_write_controls.shading_reference_dim;
    	int ref = context->temporary_write_controls.shading_reference;
    
    	shade_to_pixel(context, dim, ref, x, y);
    	return;
        }
    
        draw_patterned_pixel(context, x, y);
    }
    
    static int
    sort_points(void const *l, void const *r)
    {
        RegisPoint const *const lp = l;
        RegisPoint const *const rp = r;
    
        if (lp->y < rp->y)
    	return -1;
        if (lp->y > rp->y)
    	return +1;
        if (lp->x < rp->x)
    	return -1;
        if (lp->x > rp->x)
    	return +1;
        return 0;
    }
    
    static void
    draw_filled_polygon(RegisGraphicsContext *context)
    {
        unsigned p;
        int old_x, old_y;
        int inside;
        unsigned char pixels[MAX_GLYPH_PIXELS];
        unsigned w = 1, h = 1;
    
        if (context->temporary_write_controls.shading_character != '\0') {
    	char ch = context->temporary_write_controls.shading_character;
    	unsigned xmaxf = context->current_text_controls->character_unit_cell_w;
    	unsigned ymaxf = context->current_text_controls->character_unit_cell_h;
    
    	get_bitmap_of_character(context, ch, xmaxf, ymaxf, pixels, &w, &h,
    				MAX_GLYPH_PIXELS);
    	if (w < 1U || h < 1U) {
    	    return;
    	}
        }
    
        qsort(context->fill_points, (size_t) context->fill_point_count,
    	  sizeof(context->fill_points[0]), sort_points);
    
        old_x = DUMMY_STACK_X;
        old_y = DUMMY_STACK_Y;
        inside = 0;
        for (p = 0U; p < context->fill_point_count; p++) {
    	int new_x = context->fill_points[p].x;
    	int new_y = context->fill_points[p].y;
    #if 0
    	printf("got %d,%d (%d,%d) inside=%d\n", new_x, new_y, old_x, old_y, inside);
    #endif
    
    	/*
    	 * FIXME: This is using pixels to represent lines which loses
    	 * information about exact slope and how many lines are present which
    	 * causes misbehavior with some inputs (especially complex polygons).
    	 * It also takes more room than remembering vertices, but I'd rather
    	 * not have to implement line segments for arcs.  Maybe store a count
    	 * at each vertex instead (doesn't fix the slope problem).
    	 */
    	/*
    	 * FIXME: Change this to only draw inside of polygons, and round
    	 * points in a uniform direction to avoid overlapping drawing.  As an
    	 * option we could continue to support drawing the outline.
    	 */
    	if (new_y != old_y) {
    	    if (inside) {
    		/*
    		 * Just draw the vertical line when there is not a matching
    		 * edge on the right side.
    		 */
    		if (context->temporary_write_controls.shading_character != '\0') {
    		    shade_char_to_pixel(context, pixels, w, h,
    					WRITE_SHADING_REF_X,
    					old_x, old_x, old_y);
    		} else {
    		    shade_pattern_to_pixel(context, WRITE_SHADING_REF_X,
    					   old_x, old_x, old_y);
    		}
    	    }
    	    inside = 1;
    	} else {
    	    if (inside) {
    		if (context->temporary_write_controls.shading_character != '\0') {
    		    shade_char_to_pixel(context, pixels, w, h,
    					WRITE_SHADING_REF_X,
    					old_x, new_x, new_y);
    		} else {
    		    shade_pattern_to_pixel(context, WRITE_SHADING_REF_X,
    					   old_x, new_x, new_y);
    		}
    	    }
    	    if (new_x > old_x + 1) {
    		inside = !inside;
    	    }
    	}
    
    	old_x = new_x;
    	old_y = new_y;
        }
    
        context->destination_graphic->dirty = 1;
    }
    
    static void
    draw_patterned_line(RegisGraphicsContext *context, int x1, int y1,
    		    int x2, int y2)
    {
        int x, y;
        int dx, dy;
        int dir, diff;
    
        dx = abs(x1 - x2);
        dy = abs(y1 - y2);
    
        if (dx > dy) {
    	if (x1 > x2) {
    	    int tmp;
    	    EXCHANGE(x1, x2, tmp);
    	    EXCHANGE(y1, y2, tmp);
    	}
    	if (y1 < y2)
    	    dir = 1;
    	else if (y1 > y2)
    	    dir = -1;
    	else
    	    dir = 0;
    
    	diff = 0;
    	y = y1;
    	for (x = x1; x <= x2; x++) {
    	    if (diff >= dx) {
    		diff -= dx;
    		y += dir;
    	    }
    	    diff += dy;
    	    draw_or_save_patterned_pixel(context, x, y);
    	}
        } else {
    	if (y1 > y2) {
    	    int tmp;
    	    EXCHANGE(y1, y2, tmp);
    	    EXCHANGE(x1, x2, tmp);
    	}
    	if (x1 < x2)
    	    dir = 1;
    	else if (x1 > x2)
    	    dir = -1;
    	else
    	    dir = 0;
    
    	diff = 0;
    	x = x1;
    	for (y = y1; y <= y2; y++) {
    	    if (diff >= dy) {
    		diff -= dy;
    		x += dir;
    	    }
    	    diff += dx;
    	    draw_or_save_patterned_pixel(context, x, y);
    	}
        }
    
        context->destination_graphic->dirty = 1;
    }
    
    typedef struct {
        int dxx;
        int dxy;
        int dyx;
        int dyy;
    } quadmap_coords;
    
    static void
    draw_patterned_arc(RegisGraphicsContext *context,
    		   int cx, int cy,
    		   int ex, int ey,
    		   int a_start, int a_length,
    		   int *ex_final, int *ey_final)
    {
        const double third = hypot((double) (cx - ex), (double) (cy - ey));
        const int radius = (int) third;
        const int ra = radius;
        const int rb = radius;
        const quadmap_coords neg_quadmap[4] =
        {
    	{-1, 0, 0, +1},
    	{0, -1, -1, 0},
    	{+1, 0, 0, -1},
    	{0, +1, +1, 0},
        };
        const quadmap_coords pos_quadmap[4] =
        {
    	{-1, 0, 0, -1},
    	{0, -1, +1, 0},
    	{+1, 0, 0, +1},
    	{0, +1, -1, 0},
        };
        const quadmap_coords *quadmap;
        int total_points;
        int half_degree;
        int points_start, points_stop;
        int points;
        unsigned iterations;
        long rx, ry;
        long dx, dy;
        int x, y;
        long e2;
        long error;
    
        TRACE(("orig a_length=%d a_start=%d\n", a_length, a_start));
        if (a_length == 0)
    	return;
        if (a_length > 0) {
    	quadmap = pos_quadmap;
        } else {
    	quadmap = neg_quadmap;
    	if (a_start != 0)
    	    a_start = 3600 - a_start;
    	a_length = abs(a_length);
        }
        TRACE(("positive a_length=%d a_start=%d\n", a_length, a_start));
    
        rx = -ra;
        ry = 0;
        e2 = rb;
        dx = (2 * rx + 1) * e2 * e2;
        dy = rx * rx;
        error = dx + dy;
        total_points = 0;
        do {
    	total_points += 4;
    	e2 = 2 * error;
    	if (e2 >= dx) {
    	    rx++;
    	    dx += 2 * rb * rb;
    	    error += dx;
    	}
    	if (e2 <= dy) {
    	    ry++;
    	    dy += 2 * ra * ra;
    	    error += dy;
    	}
        }
        while (rx <= 0);
    
        /* FIXME: This is apparently not accurate enough because some arcs start or
         * end a few pixels off.  Maybe compare line slopes in the loop below
         * instead?
         */
        half_degree = total_points * 5;
        points_start = (total_points * a_start - half_degree) / 3600;
        points_stop = (total_points * a_start +
    		   total_points * a_length + half_degree) / 3600;
        TRACE(("drawing arc with %d points clockwise from %g degrees for %g degrees (from point %d to %d out of %d)\n",
    	   total_points, a_start / 10.0, a_length / 10.0, points_start, points_stop,
    	   total_points));
    
        /* FIXME: The four pixels at the cardinal directions are double-drawn. */
        points = 0;
        for (iterations = 0U; iterations < 8U; iterations++) {
    	int q2 = iterations & 0x3;
    
    	rx = -ra;
    	ry = 0;
    	e2 = rb;
    	dx = (2 * rx + 1) * e2 * e2;
    	dy = rx * rx;
    	error = dx + dy;
    	do {
    #ifdef DEBUG_ARC_POINTS
    	    double rad = atan2(
    				  (double) (quadmap[q2].dyx * rx +
    					    quadmap[q2].dyy * ry),
    				  (double) (quadmap[q2].dxx * rx +
    					    quadmap[q2].dxy * ry));
    	    double deg = (360.0 * rad / (2.0 * M_PI));
    	    if (deg < 0.0)
    		deg += 360.0;
    #endif
    
    	    if (points >= points_start && points <= points_stop) {
    		x = (int) (cx +
    			   quadmap[q2].dxx * rx +
    			   quadmap[q2].dxy * ry);
    		y = (int) (cy +
    			   quadmap[q2].dyx * rx +
    			   quadmap[q2].dyy * ry);
    #ifdef DEBUG_ARC_POINTS
    		TRACE(("drawing point %u at %d,%d (%.5g deg)\n",
    		       points, x, y, deg));
    #endif
    		draw_or_save_patterned_pixel(context, x, y);
    		if (ex_final)
    		    *ex_final = x;
    		if (ey_final)
    		    *ey_final = y;
    	    } else {
    #ifdef DEBUG_ARC_POINTS
    		x = (int) (cx + quadmap[q2].dxx * rx + quadmap[q2].dxy * ry);
    		y = (int) (cy + quadmap[q2].dyx * rx + quadmap[q2].dyy * ry);
    		TRACE(("skipping point %u at %d,%d which is outside of range (%.5g deg)\n",
    		       points, x, y, deg));
    #endif
    	    }
    	    points++;
    
    	    e2 = 2 * error;
    	    if (e2 >= dx) {
    		rx++;
    		dx += 2 * rb * rb;
    		error += dx;
    	    }
    	    if (e2 <= dy) {
    		ry++;
    		dy += 2 * ra * ra;
    		error += dy;
    	    }
    	}
    	while (rx <= 0);
        }
    
        context->destination_graphic->dirty = 1;
    }
    
    /*
     * The plot* functions are based on optimized rasterization primitives written
     * by Zingl Alois.
     * See http://members.chello.at/easyfilter/bresenham.html
     */
    
    /*
     * FIXME:
     * This is a terrible temporary hack.  The plot functions below can be adapted
     * to work like the other rasterization functions but there's no point in doing
     * that until we know we don't have to write something completely different.
     */
    static RegisGraphicsContext *global_context;
    static void
    setPixel(int x, int y)
    {
        draw_or_save_patterned_pixel(global_context, x, y);
    }
    
    static void
    plotLine(int x0, int y0, int x1, int y1)
    {
        int dx = abs(x1 - x0), sx = x0 < x1 ? 1 : -1;
        int dy = -abs(y1 - y0), sy = y0 < y1 ? 1 : -1;
        int err = dx + dy;		/* error value e_xy */
    
        for (;;) {			/* loop */
    	int e2;
    	setPixel(x0, y0);
    	e2 = 2 * err;
    	if (e2 >= dy) {		/* e_xy+e_x > 0 */
    	    if (x0 == x1)
    		break;
    	    err += dy;
    	    x0 += sx;
    	}
    	if (e2 <= dx) {		/* e_xy+e_y < 0 */
    	    if (y0 == y1)
    		break;
    	    err += dx;
    	    y0 += sy;
    	}
        }
    }
    
    static void
    plotQuadBezierSeg(int x0, int y0, int x1, int y1, int x2, int y2)
    {				/* plot a limited quadratic Bezier segment */
        int sx = x2 - x1;
        int sy = y2 - y1;
        long xx = (x0 - x1);	/* relative values for checks */
        long yy = (y0 - y1);
        double cur = (double) (xx * sy - yy * sx);	/* curvature */
    
        assert(xx * sx <= 0 && yy * sy <= 0);	/* sign of gradient must not change */
    
        if (sx * (long) sx + sy * (long) sy > xx * xx + yy * yy) {	/* begin with longer part */
    	x2 = x0;
    	x0 = sx + x1;
    	y2 = y0;
    	y0 = sy + y1;
    	cur = -cur;		/* swap P0 P2 */
        }
        if (cur != 0) {		/* no straight line */
    	long xy;
    	double dx, dy, err;
    
    	xx += sx;
    	xx *= (sx = (x0 < x2) ? 1 : -1);	/* x step direction */
    	yy += sy;
    	yy *= (sy = (y0 < y2) ? 1 : -1);	/* y step direction */
    	xy = 2 * xx * yy;
    	xx *= xx;
    	yy *= yy;		/* differences 2nd degree */
    	if (cur * sx * sy < 0) {	/* negated curvature? */
    	    xx = -xx;
    	    yy = -yy;
    	    xy = -xy;
    	    cur = -cur;
    	}
    	/* differences 1st degree */
    	dx = ((4.0 * sy * cur * (x1 - x0)) + (double) xx) - (double) xy;
    	dy = ((4.0 * sx * cur * (y0 - y1)) + (double) yy) - (double) xy;
    	xx += xx;
    	yy += yy;
    	err = dx + dy + (double) xy;	/* error 1st step */
    	do {
    	    setPixel(x0, y0);	/* plot curve */
    	    if (x0 == x2 && y0 == y2)
    		return;		/* last pixel -> curve finished */
    	    y1 = (2 * err) < dx;	/* save value for test of y step */
    	    if ((2 * err) > dy) {
    		x0 += sx;
    		dx -= (double) xy;
    		dy += (double) yy;
    		err += dy;
    	    }			/* x step */
    	    if (y1) {
    		y0 += sy;
    		dy -= (double) xy;
    		dx += (double) xx;
    		err += dx;
    	    }			/* y step */
    	} while (dy < 0 && dx > 0);	/* gradient negates -> algorithm fails */
        }
        plotLine(x0, y0, x2, y2);	/* plot remaining part to end */
    }
    
    #if 0
    static void
    plotQuadBezier(int x0, int y0, int x1, int y1, int x2, int y2)
    {				/* plot any quadratic Bezier curve */
        int x = x0 - x1;
        int y = y0 - y1;
        double t = x0 - 2 * x1 + x2;
        double r;
    
        if ((long) x * (x2 - x1) > 0) {	/* horizontal cut at P4? */
    	if ((long) y * (y2 - y1) > 0)	/* vertical cut at P6 too? */
    	    if (fabs((y0 - 2 * y1 + y2) / t * x) > abs(y)) {	/* which first? */
    		x0 = x2;
    		x2 = x + x1;
    		y0 = y2;
    		y2 = y + y1;	/* swap points */
    	    }			/* now horizontal cut at P4 comes first */
    	t = (x0 - x1) / t;
    	r = (1 - t) * ((1 - t) * y0 + 2.0 * t * y1) + t * t * y2;	/* By(t=P4) */
    	t = (x0 * x2 - x1 * x1) * t / (x0 - x1);	/* gradient dP4/dx=0 */
    	x = ifloor(t + 0.5);
    	y = ifloor(r + 0.5);
    	r = (y1 - y0) * (t - x0) / (x1 - x0) + y0;	/* intersect P3 | P0 P1 */
    	plotQuadBezierSeg(x0, y0, x, ifloor(r + 0.5), x, y);
    	r = (y1 - y2) * (t - x2) / (x1 - x2) + y2;	/* intersect P4 | P1 P2 */
    	x0 = x1 = x;
    	y0 = y;
    	y1 = ifloor(r + 0.5);	/* P0 = P4, P1 = P8 */
        }
        if ((long) (y0 - y1) * (y2 - y1) > 0) {	/* vertical cut at P6? */
    	t = y0 - 2 * y1 + y2;
    	t = (y0 - y1) / t;
    	r = (1 - t) * ((1 - t) * x0 + 2.0 * t * x1) + t * t * x2;	/* Bx(t=P6) */
    	t = (y0 * y2 - y1 * y1) * t / (y0 - y1);	/* gradient dP6/dy=0 */
    	x = ifloor(r + 0.5);
    	y = ifloor(t + 0.5);
    	r = (x1 - x0) * (t - y0) / (y1 - y0) + x0;	/* intersect P6 | P0 P1 */
    	plotQuadBezierSeg(x0, y0, ifloor(r + 0.5), y, x, y);
    	r = (x1 - x2) * (t - y2) / (y1 - y2) + x2;	/* intersect P7 | P1 P2 */
    	x0 = x;
    	x1 = ifloor(r + 0.5);
    	y0 = y1 = y;		/* P0 = P6, P1 = P7 */
        }
        plotQuadBezierSeg(x0, y0, x1, y1, x2, y2);	/* remaining part */
    }
    #endif
    
    static void
    plotCubicBezierSeg(int x0, int y0,
    		   double x1, double y1,
    		   double x2, double y2,
    		   int x3, int y3)
    {				/* plot limited cubic Bezier segment */
        int f, fx, fy, tt;
        int leg = 1;
        int sx = x0 < x3 ? 1 : -1;
        int sy = y0 < y3 ? 1 : -1;	/* step direction */
        double xc = -fabs(x0 + x1 - x2 - x3);
        double xa = xc - 4 * sx * (x1 - x2);
        double xb = sx * (x0 - x1 - x2 + x3);
        double yc = -fabs(y0 + y1 - y2 - y3);
        double ya = yc - 4 * sy * (y1 - y2);
        double yb = sy * (y0 - y1 - y2 + y3);
        double ab, ac, bc, cb, xx, xy, yy, dx, dy, ex, *pxy;
        double EP = 0.01;
        /* check for curve restrains */
        /* slope P0-P1 == P2-P3    and  (P0-P3 == P1-P2      or   no slope change) */
        assert((x1 - x0) * (x2 - x3) < EP &&
    	   ((x3 - x0) * (x1 - x2) < EP || xb * xb < xa * xc + EP));
        assert((y1 - y0) * (y2 - y3) < EP &&
    	   ((y3 - y0) * (y1 - y2) < EP || yb * yb < ya * yc + EP));
    
        if (xa == 0 && ya == 0) {	/* quadratic Bezier */
    	sx = ifloor((3 * x1 - x0 + 1) / 2);
    	sy = ifloor((3 * y1 - y0 + 1) / 2);	/* new midpoint */
    	plotQuadBezierSeg(x0, y0, sx, sy, x3, y3);
    	return;
        }
        x1 = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) + 1;	/* line lengths */
        x2 = (x2 - x3) * (x2 - x3) + (y2 - y3) * (y2 - y3) + 1;
        do {			/* loop over both ends */
    	ab = xa * yb - xb * ya;
    	ac = xa * yc - xc * ya;
    	bc = xb * yc - xc * yb;
    	ex = ab * (ab + ac - 3 * bc) + ac * ac;		/* P0 part of self-intersection loop? */
    	f = ((ex > 0.0)
    	     ? 1
    	     : isqrt(1 + 1024 / x1));	/* calculate resolution */
    	ab *= f;
    	ac *= f;
    	bc *= f;
    	ex *= f * f;		/* increase resolution */
    	xy = 9 * (ab + ac + bc) / 8;
    	cb = 8 * (xa - ya);	/* init differences of 1st degree */
    	dx = 27 * (8 * ab * (yb * yb - ya * yc) +
    		   ex * (ya + 2 * yb + yc)) / 64 - ya * ya * (xy - ya);
    	dy = 27 * (8 * ab * (xb * xb - xa * xc) -
    		   ex * (xa + 2 * xb + xc)) / 64 - xa * xa * (xy + xa);
    	/* init differences of 2nd degree */
    	xx = 3 * (3 * ab * (3 * yb * yb - ya * ya - 2 * ya * yc) -
    		  ya * (3 * ac * (ya + yb) + ya * cb)) / 4;
    	yy = 3 * (3 * ab * (3 * xb * xb - xa * xa - 2 * xa * xc) -
    		  xa * (3 * ac * (xa + xb) + xa * cb)) / 4;
    	xy = xa * ya * (6 * ab + 6 * ac - 3 * bc + cb);
    	ac = ya * ya;
    	cb = xa * xa;
    	xy = 3 * (xy + 9 * f * (cb * yb * yc - xb * xc * ac) -
    		  18 * xb * yb * ab) / 8;
    
    	if (ex < 0) {		/* negate values if inside self-intersection loop */
    	    dx = -dx;
    	    dy = -dy;
    	    xx = -xx;
    	    yy = -yy;
    	    xy = -xy;
    	    ac = -ac;
    	    cb = -cb;
    	}			/* init differences of 3rd degree */
    	ab = 6 * ya * ac;
    	ac = -6 * xa * ac;
    	bc = 6 * ya * cb;
    	cb = -6 * xa * cb;
    	dx += xy;
    	ex = dx + dy;
    	dy += xy;		/* error of 1st step */
    
    	for (pxy = &xy, fx = fy = f; x0 != x3 && y0 != y3;) {
    	    setPixel(x0, y0);	/* plot curve */
    	    do {		/* move sub-steps of one pixel */
    		if (dx > *pxy || dy < *pxy)
    		    goto exit;	/* confusing values */
    		y1 = 2 * ex - dy;	/* save value for test of y step */
    		if (2 * ex >= dx) {	/* x sub-step */
    		    fx--;
    		    ex += dx += xx;
    		    dy += xy += ac;
    		    yy += bc;
    		    xx += ab;
    		}
    		if (y1 <= 0) {	/* y sub-step */
    		    fy--;
    		    ex += dy += yy;
    		    dx += xy += bc;
    		    xx += ac;
    		    yy += cb;
    		}
    	    } while (fx > 0 && fy > 0);		/* pixel complete? */
    	    if (2 * fx <= f) {
    		x0 += sx;
    		fx += f;
    	    }			/* x step */
    	    if (2 * fy <= f) {
    		y0 += sy;
    		fy += f;
    	    }			/* y step */
    	    if (pxy == &xy && dx < 0 && dy > 0)
    		pxy = &EP;	/* pixel ahead valid */
    	}
          exit:
    	EXCHANGE(x0, x3, tt);
    	sx = -sx;
    	xb = -xb;		/* swap legs */
    	EXCHANGE(y0, y3, tt);
    	sy = -sy;
    	yb = -yb;
    	x1 = x2;
        } while (leg--);		/* try other end */
        plotLine(x0, y0, x3, y3);	/* remaining part in case of cusp or crunode */
    }
    
    static void
    plotCubicBezier(int x0, int y0, int x1, int y1,
    		int x2, int y2, int x3, int y3)
    {				/* plot any cubic Bezier curve */
        int n = 0, i = 0;
        long xc = x0 + x1 - x2 - x3;
        long xa = xc - 4 * (x1 - x2);
        long xb = x0 - x1 - x2 + x3;
        long xd = xb + 4 * (x1 + x2);
        long yc = y0 + y1 - y2 - y3;
        long ya = yc - 4 * (y1 - y2);
        long yb = y0 - y1 - y2 + y3;
        long yd = yb + 4 * (y1 + y2);
        double fx0 = x0;
        double fy0 = y0;
        double t1 = (double) (xb * xb - xa * xc), t2, t[5];
    
    #ifdef DEBUG_BEZIER
        printf("plotCubicBezier(%d,%d, %d,%d, %d,%d, %d,%d\n",
    	   x0, y0, x1, y1, x2, y2, x3, y3);
    #endif
        /* sub-divide curve at gradient sign changes */
        if (xa == 0) {		/* horizontal */
    	if (labs(xc) < 2 * labs(xb))
    	    t[n++] = (double) xc / (2.0 * (double) xb);		/* one change */
        } else if (t1 > 0.0) {	/* two changes */
    	t2 = sqrt(t1);
    	t1 = ((double) xb - t2) / (double) xa;
    	if (fabs(t1) < 1.0)
    	    t[n++] = t1;
    	t1 = ((double) xb + t2) / (double) xa;
    	if (fabs(t1) < 1.0)
    	    t[n++] = t1;
        }
        t1 = (double) (yb * yb - ya * yc);
        if (ya == 0) {		/* vertical */
    	if (labs(yc) < 2 * labs(yb))
    	    t[n++] = (double) yc / (2.0 * (double) yb);		/* one change */
        } else if (t1 > 0.0) {	/* two changes */
    	t2 = sqrt(t1);
    	t1 = ((double) yb - t2) / (double) ya;
    	if (fabs(t1) < 1.0)
    	    t[n++] = t1;
    	t1 = ((double) yb + t2) / (double) ya;
    	if (fabs(t1) < 1.0)
    	    t[n++] = t1;
        }
        for (i = 1; i < n; i++)	/* bubble sort of 4 points */
    	if ((t1 = t[i - 1]) > t[i]) {
    	    t[i - 1] = t[i];
    	    t[i] = t1;
    	    i = 0;
    	}
    
        t1 = -1.0;
        t[n] = 1.0;			/* begin / end point */
        for (i = 0; i <= n; i++) {	/* plot each segment separately */
    	double fx1, fx2, fx3;
    	double fy1, fy2, fy3;
    
    	t2 = t[i];		/* sub-divide at t[i-1], t[i] */
    	fx1 = (t1 * (t1 * (double) xb - (double) (2 * xc)) -
    	       t2 * (t1 * (t1 * (double) xa - (double) (2 * xb)) + (double)
    		     xc) + (double) xd) / 8 - fx0;
    	fy1 = (t1 * (t1 * (double) yb - (double) (2 * yc)) -
    	       t2 * (t1 * (t1 * (double) ya - (double) (2 * yb)) + (double)
    		     yc) + (double) yd) / 8 - fy0;
    	fx2 = (t2 * (t2 * (double) xb - (double) (2 * xc)) -
    	       t1 * (t2 * (t2 * (double) xa - (double) (2 * xb)) + (double)
    		     xc) + (double) xd) / 8 - fx0;
    	fy2 = (t2 * (t2 * (double) yb - (double) (2 * yc)) -
    	       t1 * (t2 * (t2 * (double) ya - (double) (2 * yb)) + (double)
    		     yc) + (double) yd) / 8 - fy0;
    	fx0 -= fx3 = (t2 * (t2 * ((double) (3 * xb) - t2 * (double) xa) -
    			    (double) (3 * xc)) + (double) xd) / 8;
    	fy0 -= fy3 = (t2 * (t2 * ((double) (3 * yb) - t2 * (double) ya) -
    			    (double) (3 * yc)) + (double) yd) / 8;
    	x3 = ifloor(fx3 + 0.5);
    	y3 = ifloor(fy3 + 0.5);	/* scale bounds to int */
    	if (fx0 != 0.0) {
    	    fx1 *= fx0 = (x0 - x3) / fx0;
    	    fx2 *= fx0;
    	}
    	if (fy0 != 0.0) {
    	    fy1 *= fy0 = (y0 - y3) / fy0;
    	    fy2 *= fy0;
    	}
    	if (x0 != x3 || y0 != y3)	/* segment t1 - t2 */
    	    plotCubicBezierSeg(x0, y0,
    			       x0 + fx1, y0 + fy1,
    			       x0 + fx2, y0 + fy2,
    			       x3, y3);
    	x0 = x3;
    	y0 = y3;
    	fx0 = fx3;
    	fy0 = fy3;
    	t1 = t2;
        }
    }
    
    #if 0
    static void
    plotQuadSpline(int n, int x[], int y[], int skip_segments)
    {				/* plot quadratic spline, destroys input arrays x,y */
    #define M_MAX 12
        double mi = 1, m[M_MAX];	/* diagonal constants of matrix */
        int i, x0, y0, x1, y1, x2, y2;
    #ifdef DEBUG_SPLINE_SEGMENTS
        int color = 0;
    #endif
    
        assert(n > 1);		/* need at least 3 points P[0]..P[n] */
    
    #ifdef DEBUG_SPLINE_POINTS
        {
    	int save_pattern;
    
    	i = 0;
    	global_context->temporary_write_controls.foreground = 11;
    	save_pattern = global_context->temporary_write_controls.pattern;
    	global_context->temporary_write_controls.pattern = 0xff;
    	draw_patterned_arc(global_context, x[i], y[i], x[i] + 2, y[i], 0,
    			   3600, NULL, NULL);
    	i++;
    	global_context->temporary_write_controls.foreground = 15;
    	for (; i < n; i++) {
    	    draw_patterned_arc(global_context,
    			       x[i], y[i],
    			       x[i] + 2, y[i],
    			       0, 3600, NULL, NULL);
    	}
    	global_context->temporary_write_controls.foreground = 10;
    	draw_patterned_arc(global_context, x[i], y[n], x[i] + 2, y[i], 0,
    			   3600, NULL, NULL);
    	global_context->temporary_write_controls.pattern = save_pattern;
        }
    #endif
    
        x2 = x[n];
        y2 = y[n];
    
        x[1] = x0 = 8 * x[1] - 2 * x[0];	/* first row of matrix */
        y[1] = y0 = 8 * y[1] - 2 * y[0];
    
        for (i = 2; i < n; i++) {	/* forward sweep */
    	if (i - 2 < M_MAX)
    	    m[i - 2] = mi = 1.0 / (6.0 - mi);
    	x[i] = x0 = ifloor(8 * x[i] - x0 * mi + 0.5);	/* store yi */
    	y[i] = y0 = ifloor(8 * y[i] - y0 * mi + 0.5);
        }
        x1 = ifloor((x0 - 2 * x2) / (5.0 - mi) + 0.5);	/* correction last row */
        y1 = ifloor((y0 - 2 * y2) / (5.0 - mi) + 0.5);
    
        for (i = n - 2; i > 0; i--) {	/* back substitution */
    	if (i <= M_MAX)
    	    mi = m[i - 1];
    	x0 = ifloor((x[i] - x1) * mi + 0.5);	/* next corner */
    	y0 = ifloor((y[i] - y1) * mi + 0.5);
    #ifdef DEBUG_SPLINE_SEGMENTS
    	color++;
    	global_context->temporary_write_controls.foreground = color;
    #endif
    	if ((n - 2) - i < skip_segments)
    	    plotQuadBezier((x0 + x1) / 2, (y0 + y1) / 2, x1, y1, x2, y2);
    	x2 = (x0 + x1) / 2;
    	x1 = x0;
    	y2 = (y0 + y1) / 2;
    	y1 = y0;
        }
    #ifdef DEBUG_SPLINE_SEGMENTS
        color++;
        global_context->temporary_write_controls.foreground = color;
    #endif
        if (skip_segments > 0)
    	plotQuadBezier(x[0], y[0], x1, y1, x2, y2);
    }
    #endif
    
    static void
    plotCubicSpline(int n, int x[], int y[], int skip_first_last)
    {
    #define M_MAX 12
        double mi = 0.25, m[M_MAX];	/* diagonal constants of matrix */
        int x3, y3, x4, y4;
        int i, x0, y0, x1, y1, x2, y2;
    #ifdef DEBUG_SPLINE_SEGMENTS
        RegisterNum color = 0;
    #endif
    
        assert(n > 2);		/* need at least 4 points P[0]..P[n] */
    
    #ifdef DEBUG_SPLINE_POINTS
        {
    	unsigned save_pattern;
    
    	i = 0;
    	global_context->temporary_write_controls.foreground = 11;
    	save_pattern = global_context->temporary_write_controls.pattern;
    	global_context->temporary_write_controls.pattern = 0xff;
    	draw_patterned_arc(global_context, x[i], y[i], x[i] + 2, y[i], 0,
    			   3600, NULL, NULL);
    	i++;
    	global_context->temporary_write_controls.foreground = 15;
    	for (; i < n; i++) {
    	    draw_patterned_arc(global_context,
    			       x[i], y[i],
    			       x[i] + 2, y[i],
    			       0, 3600, NULL, NULL);
    	}
    	global_context->temporary_write_controls.foreground = 10;
    	draw_patterned_arc(global_context, x[i], y[i], x[i] + 2, y[i], 0,
    			   3600, NULL, NULL);
    	global_context->temporary_write_controls.pattern = save_pattern;
        }
    #endif
    
        x3 = x[n - 1];
        y3 = y[n - 1];
        x4 = x[n];
        y4 = y[n];
    
        x[1] = x0 = 12 * x[1] - 3 * x[0];	/* first row of matrix */
        y[1] = y0 = 12 * y[1] - 3 * y[0];
    
        for (i = 2; i < n; i++) {	/* forward sweep */
    	if (i - 2 < M_MAX)
    	    m[i - 2] = mi = 0.25 / (2.0 - mi);
    	x[i] = x0 = ifloor(12 * x[i] - 2 * x0 * mi + 0.5);
    	y[i] = y0 = ifloor(12 * y[i] - 2 * y0 * mi + 0.5);
        }
        x2 = ifloor((x0 - 3 * x4) / (7 - 4 * mi) + 0.5);	/* correct last row */
        /* printf("y0=%d, y4=%d mi=%g\n", y0, y4, mi); */
        y2 = ifloor((y0 - 3 * y4) / (7 - 4 * mi) + 0.5);
        /* printf("y2=%d, y3=%d, y4=%d\n", y2, y3, y4); */
    #ifdef DEBUG_SPLINE_SEGMENTS
        color++;
        global_context->temporary_write_controls.foreground = color;
    #endif
        if (!skip_first_last)
    	plotCubicBezier(x3, y3, (x2 + x4) / 2, (y2 + y4) / 2, x4, y4, x4, y4);
    
        if (n - 3 < M_MAX)
    	mi = m[n - 3];
        x1 = ifloor((x[n - 2] - 2 * x2) * mi + 0.5);
        y1 = ifloor((y[n - 2] - 2 * y2) * mi + 0.5);
        for (i = n - 3; i > 0; i--) {	/* back substitution */
    	if (i <= M_MAX)
    	    mi = m[i - 1];
    	x0 = ifloor((x[i] - 2 * x1) * mi + 0.5);
    	y0 = ifloor((y[i] - 2 * y1) * mi + 0.5);
    	x4 = ifloor((x0 + 4 * x1 + x2 + 3) / 6.0);	/* reconstruct P[i] */
    	y4 = ifloor((y0 + 4 * y1 + y2 + 3) / 6.0);
    #ifdef DEBUG_SPLINE_SEGMENTS
    	color++;
    	global_context->temporary_write_controls.foreground = color;
    #endif
    #define CB_PARM(num) ifloor((num) / 3.0 + 0.5)
    	plotCubicBezier(x4, y4,
    			CB_PARM(2 * x1 + x2),
    			CB_PARM(2 * y1 + y2),
    			CB_PARM(x1 + 2 * x2),
    			CB_PARM(y1 + 2 * y2),
    			x3, y3);
    	x3 = x4;
    	y3 = y4;
    	x2 = x1;
    	y2 = y1;
    	x1 = x0;
    	y1 = y0;
        }
        x0 = x[0];
        x4 = ifloor((3 * x0 + 7 * x1 + 2 * x2 + 6) / 12.0);		/* reconstruct P[1] */
        y0 = y[0];
        y4 = ifloor((3 * y0 + 7 * y1 + 2 * y2 + 6) / 12.0);
    #ifdef DEBUG_SPLINE_SEGMENTS
        global_context->temporary_write_controls.foreground = 4;
    #endif
        plotCubicBezier(x4, y4,
    		    CB_PARM(2 * x1 + x2),
    		    CB_PARM(2 * y1 + y2),
    		    CB_PARM(x1 + 2 * x2),
    		    CB_PARM(y1 + 2 * y2),
    		    x3, y3);
    #ifdef DEBUG_SPLINE_SEGMENTS
        color++;
        global_context->temporary_write_controls.foreground = color;
    #endif
        if (!skip_first_last)
    	plotCubicBezier(x0, y0, x0, y0, (x0 + x1) / 2, (y0 + y1) / 2, x4, y4);
    }
    
    static unsigned
    find_free_alphabet_index(RegisGraphicsContext *context, unsigned alphabet,
    			 unsigned pixw, unsigned pixh)
    {
        unsigned ii, jj;
    
        /* try an exact match */
        for (ii = 0U; ii < MAX_REGIS_ALPHABETS; ii++) {
    	if (context->alphabets[ii].alphabet_num == alphabet &&
    	    context->alphabets[ii].pixw == pixw &&
    	    context->alphabets[ii].pixh == pixh) {
    	    return ii;
    	}
        }
    
        /* otherwise use any empty slot */
        for (ii = 0U; ii < MAX_REGIS_ALPHABETS; ii++) {
    	if (context->alphabets[ii].alphabet_num == INVALID_ALPHABET_NUM) {
    	    context->alphabets[ii].alphabet_num = alphabet;
    	    context->alphabets[ii].pixw = pixw;
    	    context->alphabets[ii].pixh = pixh;
    	    return ii;
    	}
        }
    
        /* otherwise recycle a slot with a different font size */
        for (ii = 0U; ii < MAX_REGIS_ALPHABETS; ii++) {
    	if (context->alphabets[ii].alphabet_num == alphabet) {
    	    context->alphabets[ii].pixw = pixw;
    	    context->alphabets[ii].pixh = pixh;
    	    context->alphabets[ii].name[0] = '\0';
    	    context->alphabets[ii].fontname[0] = '\0';
    	    context->alphabets[ii].use_font = 0;
    	    if (context->alphabets[ii].bytes != NULL) {
    		free(context->alphabets[ii].bytes);
    		context->alphabets[ii].bytes = NULL;
    	    }
    	    for (jj = 0U; jj < MAX_GLYPHS; jj++) {
    		context->alphabets[ii].loaded[jj] = 0;
    	    }
    	    return ii;
    	}
        }
    
        /* finally just recycle this arbitrary slot */
        context->alphabets[0U].alphabet_num = alphabet;
        context->alphabets[0U].pixw = pixw;
        context->alphabets[0U].pixh = pixh;
        context->alphabets[0U].name[0] = '\0';
        context->alphabets[0U].fontname[0] = '\0';
        context->alphabets[0U].use_font = 0;
        if (context->alphabets[0U].bytes != NULL) {
    	free(context->alphabets[0U].bytes);
    	context->alphabets[0U].bytes = NULL;
        }
        for (jj = 0U; jj < MAX_GLYPHS; jj++) {
    	context->alphabets[0U].loaded[jj] = 0;
        }
    
        return 0U;
    }
    
    #ifdef DEBUG_SPECIFIC_CHAR_METRICS
    static void
    dump_bitmap_pixels(unsigned char const *pixels, unsigned w, unsigned h)
    {
        unsigned yy, xx;
    
        for (yy = 0U; yy < h; yy++) {
    	printf(" ");
    	for (xx = 0U; xx < w; xx++) {
    	    if (pixels[yy * w + xx]) {
    		printf("#");
    	    } else {
    		printf("_");
    	    }
    	}
    	printf("\n");
        }
    }
    #endif
    
    #if OPT_RENDERFONT && defined(HAVE_TYPE_FCCHAR32)
    static int
    copy_bitmap_from_xft_font(Display *display, XftFont *font, FcChar32 ch,
    			  unsigned char *pixels, unsigned w, unsigned h,
    			  unsigned xmin, unsigned ymin)
    {
        /*
         * FIXME: cache:
         * - the bitmap for the last M characters and target dimensions
         * - reuse the pixmap object where possible
         */
        XftColor bg, fg;
        Pixmap bitmap;
        XftDraw *draw;
        XImage *image;
        unsigned bmw, bmh;
        unsigned xx, yy;
    
        bg.pixel = 0UL;
        bg.color.red = 0;
        bg.color.green = 0;
        bg.color.blue = 0;
        bg.color.alpha = 0x0;
    
        fg.pixel = 1UL;
        fg.color.red = 0xffff;
        fg.color.green = 0xffff;
        fg.color.blue = 0xffff;
        fg.color.alpha = 0xffff;
    
        bmw = w + xmin;
        bmh = h;
        bitmap = XCreatePixmap(display,
    			   DefaultRootWindow(display),
    			   bmw, bmh,
    			   1);
        if (bitmap == None) {
    	TRACE(("Unable to create Pixmap\n"));
    	return 0;
        }
        draw = XftDrawCreateBitmap(display, bitmap);
        if (!draw) {
    	TRACE(("Unable to create XftDraw\n"));
    	XFreePixmap(display, bitmap);
    	return 0;
        }
    
        XftDrawRect(draw, &bg, 0, 0, bmw, bmh);
        XftDrawString32(draw, &fg, font, 0, font->ascent - (int) ymin,
    		    &ch, 1);
    
        image = XGetImage(display, bitmap, (int) xmin, 0, w, h, 1UL, XYPixmap);
        if (!image) {
    	TRACE(("Unable to create XImage\n"));
    	XftDrawDestroy(draw);
    	XFreePixmap(display, bitmap);
    	return 0;
        }
    
        for (yy = 0U; yy < h; yy++) {
    	for (xx = 0U; xx < w; xx++) {
    	    pixels[yy * w + xx] = (unsigned char) XGetPixel(image,
    							    (int) xx,
    							    (int) yy);
    	}
        }
    
        XDestroyImage(image);
        XftDrawDestroy(draw);
        XFreePixmap(display, bitmap);
        return 1;
    }
    
    static void
    get_xft_glyph_dimensions(Display *display, XftFont *font, unsigned *w,
    			 unsigned *h, unsigned *xmin, unsigned *ymin)
    {
        unsigned workw, workh;
        FcChar32 ch;
        unsigned char *pixels;
        unsigned yy, xx;
        unsigned char_count, pixel_count;
        unsigned real_minx, real_maxx, real_miny, real_maxy;
        unsigned char_minx, char_maxx, char_miny, char_maxy;
    
        /*
         * For each ASCII or ISO-8859-1 printable code, find out what its
         * dimensions are.
         *
         * We actually render the glyphs and determine the extents ourselves
         * because the font library can lie by several pixels, and since we are
         * doing manual character placement in fixed areas the glyph boundary needs
         * to be accurate.
         *
         * Ignore control characters and spaces - their extent information is
         * misleading.
         */
    
        /* Our "work area" is just a buffer which should be big enough to hold the
         * largest glyph even if its size is under-reported by a couple of pixels
         * in each dimension.
         */
        workw = (unsigned) font->max_advance_width + 2U;
        if (font->ascent + font->descent > font->height) {
    	workh = (unsigned) (font->ascent + font->descent) + 2U;
        } else {
    	workh = (unsigned) font->height + 2U;
        }
    
        if (!(pixels = malloc((size_t) (workw * workh)))) {
    	*w = 0U;
    	*h = 0U;
    	return;
        }
    
        /* FIXME: ch is in UCS32 -- try to support non-ASCII characters */
        char_count = 0U;
        real_minx = workw - 1U;
        real_maxx = 0U;
        real_miny = workh - 1U;
        real_maxy = 0U;
        for (ch = 33; ch < 256; ++ch) {
    	if (ch >= 127 && ch <= 160)
    	    continue;
    	if (!FcCharSetHasChar(font->charset, ch))
    	    continue;
    
    	copy_bitmap_from_xft_font(display, font, ch, pixels,
    				  workw, workh, 0U, 0U);
    
    	pixel_count = 0U;
    	char_minx = workh - 1U;
    	char_maxx = 0U;
    	char_miny = workh - 1U;
    	char_maxy = 0U;
    	for (yy = 0U; yy < workh; yy++) {
    	    for (xx = 0U; xx < workw; xx++) {
    		if (pixels[yy * workw + xx]) {
    		    if (xx < char_minx)
    			char_minx = xx;
    		    if (xx > char_maxx)
    			char_maxx = xx;
    		    if (yy < char_miny)
    			char_miny = yy;
    		    if (yy > char_maxy)
    			char_maxy = yy;
    		    pixel_count++;
    		}
    	    }
    	}
    	if (pixel_count < 1U)
    	    continue;
    
    #ifdef DEBUG_SPECIFIC_CHAR_METRICS
    	if (IS_DEBUG_CHAR(ch)) {
    	    printf("char: '%c' (%d)\n", (char) ch, ch);
    	    printf(" minx: %u\n", char_minx);
    	    printf(" maxx: %u\n", char_maxx);
    	    printf(" miny: %u\n", char_miny);
    	    printf(" maxy: %u\n", char_maxy);
    	    dump_bitmap_pixels(pixels, workw, workh);
    	    printf("\n");
    	}
    #endif
    
    	if (char_minx < real_minx)
    	    real_minx = char_minx;
    	if (char_maxx > real_maxx)
    	    real_maxx = char_maxx;
    	if (char_miny < real_miny)
    	    real_miny = char_miny;
    	if (char_maxy > real_maxy)
    	    real_maxy = char_maxy;
    	char_count++;
        }
    
        free(pixels);
    
        if (char_count < 1U) {
    	*w = 0U;
    	*h = 0U;
    	return;
        }
    
        *w = (unsigned) (1 + real_maxx - real_minx);
        *h = (unsigned) (1 + real_maxy - real_miny);
        *xmin = real_minx;
        *ymin = real_miny;
    
    #ifdef DEBUG_COMPUTED_FONT_METRICS
        printf("reported metrics:\n");
        printf(" %ux%u ascent=%u descent=%u\n", font->max_advance_width,
    	   font->height, font->ascent, font->descent);
        printf("computed metrics:\n");
        printf(" real_minx=%u real_maxx=%u real_miny=%u real_maxy=%u\n",
    	   real_minx, real_maxx, real_miny, real_maxy);
        printf(" final: %ux%u xmin=%u ymin=%u\n", *w, *h, *xmin, *ymin);
    #endif
    }
    
    #define FONT_SIZE_CACHE_SIZE 32U
    
    /* Find the font pixel size which returns the font which is closest to the given
     * maxw and maxh without overstepping either dimension.
     */
    static XftFont *
    find_best_xft_font_size(XtermWidget xw,
    			char const *fontname,
    			unsigned maxw, unsigned maxh, unsigned max_pixels,
    			unsigned *w, unsigned *h,
    			unsigned *xmin, unsigned *ymin)
    {
        Display *display = XtDisplay(xw);
        Screen *screen = XtScreen(xw);
        XftFont *font;
        unsigned targeth;
        unsigned ii, cacheindex;
        static struct {
    	char fontname[REGIS_FONTNAME_LEN];
    	unsigned maxw, maxh, max_pixels;
    	unsigned targeth;
    	unsigned w, h;
    	unsigned xmin;
    	unsigned ymin;
        } cache[FONT_SIZE_CACHE_SIZE];
    
        assert(display);
        assert(screen);
        assert(fontname);
        assert(w);
        assert(h);
        assert(xmin);
        assert(ymin);
    
        cacheindex = FONT_SIZE_CACHE_SIZE;
        for (ii = 0U; ii < FONT_SIZE_CACHE_SIZE; ii++) {
    	if (cache[ii].maxw == maxw && cache[ii].maxh == maxh &&
    	    cache[ii].max_pixels == max_pixels &&
    	    strcmp(cache[ii].fontname, fontname) == 0) {
    	    cacheindex = ii;
    	    break;
    	}
        }
    
        if (cacheindex < FONT_SIZE_CACHE_SIZE) {
    	targeth = cache[cacheindex].targeth;
        } else {
    	targeth = maxh * 10U + 5U;
        }
        for (;;) {
    	if (targeth <= 5U) {
    	    TRACE(("Giving up finding suitable Xft font size for %ux%u.\n",
    		   maxw, maxh));
    	    return NULL;
    	}
    
    	/*
    	 * Xft does a bad job at:
    	 *  - two-color low-resolution anti-aliased fonts
    	 *  - non-anti-aliased fonts at low resolution unless a font size is
    	 *    given (pixel size does not help, and the value of the font size
    	 *    doesn't appear to matter).
    	 *
    	 * In those two cases it literally drops pixels, sometimes whole
    	 * columns, making the glyphs unreadable and ugly even when readable.
    	 */
    	/*
    	 * FIXME:
    	 * Also, we need to scale the width and height separately.  The
    	 * CHAR_WIDTH and CHAR_HEIGHT attributes would seem to be ideal, but
    	 * don't appear to have any effect if set.  Instead we will manually
    	 * scale the bitmap later, which may be very ugly because we won't try
    	 * to identify different parts of glyphs or preserve density.
    	 */
    	{
    	    XftPattern *pat;
    	    XftPattern *match;
    	    XftResult status;
    
    	    font = NULL;
    	    if ((pat = XftNameParse(fontname))) {
    		XftPatternBuild(pat,
    		/* arbitrary value */
    				XFT_SIZE, XftTypeDouble, 12.0,
    				XFT_PIXEL_SIZE, XftTypeDouble, (double)
    				targeth / 10.0,
    #if 0
    				XFT_CHAR_WIDTH, XftTypeInteger, (int) maxw,
    				XFT_CHAR_HEIGHT, XftTypeInteger, (int)
    				(targeth / 10U),
    #endif
    				XFT_SPACING, XftTypeInteger, XFT_MONO,
    				XFT_SLANT, XftTypeInteger, 0,
    				XFT_ANTIALIAS, XftTypeBool, False,
    				NULL);
    		if ((match = XftFontMatch(display,
    					  XScreenNumberOfScreen(screen),
    					  pat, &status))) {
    		    font = XftFontOpenPattern(display, match);
    		    maybeXftCache(xw, font);
    		}
    		XftPatternDestroy(pat);
    	    }
    	}
    	if (!font) {
    	    TRACE(("Unable to open a monospaced Xft font.\n"));
    	    return NULL;
    	}
    #ifdef DEBUG_FONT_SIZE_SEARCH
    	{
    	    char buffer[1024];
    
    	    if (XftNameUnparse(font->pattern, buffer, (int) sizeof(buffer))) {
    		printf("Testing font named \"%s\"\n", buffer);
    	    } else {
    		printf("Testing unknown font\n");
    	    }
    	}
    #endif
    
    	if (cacheindex < FONT_SIZE_CACHE_SIZE &&
    	    targeth == cache[cacheindex].targeth) {
    	    *w = cache[cacheindex].w;
    	    *h = cache[cacheindex].h;
    	    *xmin = cache[cacheindex].xmin;
    	    *ymin = cache[cacheindex].ymin;
    	} else {
    	    get_xft_glyph_dimensions(display, font, w, h, xmin, ymin);
    	}
    #ifdef DEBUG_FONT_SIZE_SEARCH
    	printf("checking max=%ux%u targeth=%u.%u\n", maxw, maxh, targeth /
    	       10U, targeth % 10U);
    #endif
    
    	if (*h > maxh) {
    	    XftFontClose(display, font);
    #ifdef DEBUG_FONT_SIZE_SEARCH
    	    printf("got %ux%u glyph; too tall; reducing target size\n", *w, *h);
    #endif
    	    if (*h > 2U * maxh) {
    		targeth /= (*h / maxh);
    	    } else if (targeth > 10U && *h > maxh + 1U) {
    		targeth -= 10U;
    	    } else {
    		targeth--;
    	    }
    	    continue;
    	}
    	if (*w > maxw) {
    	    XftFontClose(display, font);
    #ifdef DEBUG_FONT_SIZE_SEARCH
    	    printf("got %ux%u glyph; too wide; reducing target size\n", *w, *h);
    #endif
    	    if (*w > 2U * maxw) {
    		targeth /= (*w / maxw);
    	    } else if (targeth > 10U && *w > maxw + 1U) {
    		targeth -= 10U;
    	    } else {
    		targeth--;
    	    }
    	    continue;
    	}
    	if (*w * *h > max_pixels) {
    	    XftFontClose(display, font);
    #ifdef DEBUG_FONT_SIZE_SEARCH
    	    printf("got %ux%u glyph; too many pixels; reducing target size\n",
    		   *w, *h);
    #endif
    	    if (*w * *h > 2U * max_pixels) {
    		unsigned min = *w < *h ? *w : *h;
    		unsigned divisor = (*w * *h) / (max_pixels * min);
    		if (divisor > 1U) {
    		    targeth /= divisor;
    		} else if (targeth > 10U) {
    		    targeth -= 10U;
    		} else {
    		    targeth--;
    		}
    	    } else {
    		targeth--;
    	    }
    	    continue;
    	}
    #ifdef DEBUG_FONT_NAME
    	{
    	    char buffer[1024];
    
    	    if (XftNameUnparse(font->pattern, buffer, (int) sizeof(buffer))) {
    		printf("Final font for \"%s\" max %dx%d is \"%s\"\n",
    		       fontname, maxw, maxh, buffer);
    	    } else {
    		printf("Final font for \"%s\" max %dx%d is unknown\n",
    		       fontname, maxw, maxh);
    	    }
    	}
    #endif
    
    	if (cacheindex == FONT_SIZE_CACHE_SIZE) {
    	    for (ii = 0U; ii < FONT_SIZE_CACHE_SIZE; ii++) {
    		if (cache[ii].maxw == 0U || cache[ii].maxh == 0U ||
    		    cache[ii].max_pixels == 0U) {
    		    CopyFontname(cache[ii].fontname, fontname);
    		    cache[ii].maxw = maxw;
    		    cache[ii].maxh = maxh;
    		    cache[ii].max_pixels = max_pixels;
    		    cache[ii].targeth = targeth;
    		    cache[ii].w = *w;
    		    cache[ii].h = *h;
    		    cache[ii].xmin = *xmin;
    		    cache[ii].ymin = *ymin;
    		    break;
    		}
    	    }
    	    if (ii == FONT_SIZE_CACHE_SIZE) {
    		ii = targeth % FONT_SIZE_CACHE_SIZE;
    		CopyFontname(cache[ii].fontname, fontname);
    		cache[ii].maxw = maxw;
    		cache[ii].maxh = maxh;
    		cache[ii].max_pixels = max_pixels;
    		cache[ii].targeth = targeth;
    		cache[ii].w = *w;
    		cache[ii].h = *h;
    		cache[ii].xmin = *xmin;
    		cache[ii].ymin = *ymin;
    	    }
    	}
    	return font;
        }
    }
    #endif
    
    static int
    get_xft_bitmap_of_character(RegisGraphicsContext const *context,
    			    char const *fontname, int ch,
    			    unsigned maxw, unsigned maxh, unsigned char *pixels,
    			    unsigned max_pixels, unsigned *w, unsigned *h)
    {
        /*
         * See Xft / RENDERFONT stuff in fontutils.c and used in utils.c
         * Add a separate configuration for ReGIS.
         */
        /*
         * FIXME: cache:
         * - reuse the font where possible
         */
    #ifdef XRENDERFONT
        XtermWidget xw = context->destination_graphic->xw;
        Display *display = XtDisplay(xw);
        XftFont *font;
        unsigned xmin = 0U, ymin = 0U;
    
        if (!(font = find_best_xft_font_size(xw, fontname, maxw, maxh,
    					 max_pixels, w, h, &xmin, &ymin))) {
    	TRACE(("Unable to find suitable Xft font\n"));
    	return 0;
        }
    
        if (!copy_bitmap_from_xft_font(display, font, CharOf(ch), pixels, *w, *h,
    				   xmin, ymin)) {
    	TRACE(("Unable to create bitmap for '%c'\n", ch));
    	XftFontClose(display, font);
    	return 0;
        }
        XftFontClose(display, font);
        return 1;
    #else
        (void) context;
        (void) fontname;
        (void) ch;
        (void) maxw;
        (void) maxh;
        (void) pixels;
        (void) max_pixels;
        (void) w;
        (void) h;
    
        return 0;
    #endif
    }
    
    static unsigned
    find_best_alphabet_index(RegisGraphicsContext const *context,
    			 unsigned minw, unsigned minh,
    			 unsigned maxw, unsigned maxh,
    			 unsigned max_pixels)
    {
        unsigned ii;
        unsigned bestmatch;
        unsigned bestw, besth;
    
        assert(context);
        assert(maxw);
        assert(maxh);
    
        bestmatch = MAX_REGIS_ALPHABETS;
        bestw = 0U;
        besth = 0U;
        for (ii = 0U; ii < MAX_REGIS_ALPHABETS; ii++) {
    	if (context->alphabets[ii].alphabet_num ==
    	    context->current_text_controls->alphabet_num &&
    	    context->alphabets[ii].pixw >= minw &&
    	    context->alphabets[ii].pixh >= minh &&
    	    context->alphabets[ii].pixw <= maxw &&
    	    context->alphabets[ii].pixh <= maxh &&
    	    context->alphabets[ii].pixw > bestw &&
    	    context->alphabets[ii].pixh > besth &&
    	    context->alphabets[ii].pixw *
    	    context->alphabets[ii].pixh <= max_pixels) {
    	    bestmatch = ii;
    	    bestw = context->alphabets[ii].pixw;
    	    besth = context->alphabets[ii].pixh;
    	}
        }
    
    #ifdef DEBUG_ALPHABET_LOOKUP
        if (bestmatch < MAX_REGIS_ALPHABETS) {
    	TRACE(("found alphabet %u at index %u size %ux%u font=%s\n",
    	       context->current_text_controls->alphabet_num, bestmatch,
    	       bestw, besth,
    	       context->alphabets[bestmatch].use_font ?
    	       context->alphabets[bestmatch].fontname : "(none)"));
        }
    #endif
    
        return bestmatch;
    }
    
    #define GLYPH_WIDTH_BYTES(PIXW) ( ((PIXW) + 7U) >> 3U )
    
    static int
    get_user_bitmap_of_character(RegisGraphicsContext const *context,
    			     int ch,
    			     unsigned alphabet_index,
    			     unsigned char *pixels)
    {
        const unsigned char *glyph;
        unsigned w, h;
        unsigned xx, yy;
        unsigned byte, bit;
    
        assert(context);
        assert(pixels);
    
        if (!context->alphabets[alphabet_index].loaded[(unsigned char) ch]) {
    	TRACE(("in alphabet %u with alphabet index %u user glyph for '%c' not loaded\n",
    	       context->current_text_controls->alphabet_num, alphabet_index,
    	       ch));
    	return 0;
        }
    
        assert(context->alphabets[alphabet_index].bytes);
    
        w = context->alphabets[alphabet_index].pixw;
        h = context->alphabets[alphabet_index].pixh;
        glyph = &context->alphabets[alphabet_index]
    	.bytes[(unsigned char) ch * GLYPH_WIDTH_BYTES(w) * h];
    
        for (yy = 0U; yy < h; yy++) {
    	for (xx = 0U; xx < w; xx++) {
    	    byte = yy * GLYPH_WIDTH_BYTES(w) + (xx >> 3U);
    	    bit = xx & 7U;
    	    pixels[yy * w + xx] = ((unsigned) glyph[byte] >> (7U - bit)) & 1U;
    	}
        }
    
        return 1;
    }
    
    /*
     * alphabets
     *  0    built-in
     *  1-N  custom (max is 3 on VT3X0 -- up to MAX_REGIS_ALPHABETS with xterm)
     *
     * built-in 7-bit charsets
     *  (B    ASCII
     *  (0    DEC special graphics
     *  (>    DEC technical
     *  (A    NCR British
     *  (4    NCR Dutch
     *  (5    NCR Finnish
     *  (R    NCR French
     *  (9    NCR French Canadian
     *  (K    NCR German
     *  (Y    NCR Italian
     *  ('    NCR Norwegian/Danish
     *  (!6   NCR Portuguese
     *  (Z    NCR Spanish
     *  (7    NCR Swedish
     *  (-    NCR Swiss
     *
     * -@   ???
     *
     * built-in 8-bit charsets
     *  )%5   DEC supplemental graphics
     *  -A    ISO Latin-1 supplemental
     *  )<    user-preferred supplemental (94 chars)
     *
     * defaults
     *  terminal  char cell size   charsets      angle
     *  VT3x0     S1               0:ASCII(94)   0 (positive)
     *
     */
    static void
    get_bitmap_of_character(RegisGraphicsContext const *context, int ch,
    			unsigned maxw, unsigned maxh, unsigned char *pixels,
    			unsigned *w, unsigned *h, unsigned max_pixels)
    {
        unsigned bestmatch;
        char const *fontname = NULL;
    
        assert(context);
        assert(w);
        assert(h);
    
        if (context->current_text_controls->alphabet_num == 0)
    	fontname = context->builtin_font;
    
        *w = 0U;
        *h = 0U;
    
        bestmatch = find_best_alphabet_index(context, 1U, 1U, maxw, maxh,
    					 max_pixels);
        if (bestmatch < MAX_REGIS_ALPHABETS) {
    	RegisAlphabet const *alpha = &context->alphabets[bestmatch];
    
    	if (!alpha->use_font &&
    	    get_user_bitmap_of_character(context, ch, bestmatch, pixels)) {
    #ifdef DEBUG_USER_GLYPH
    	    TRACE(("found user glyph for alphabet number %d (index %u)\n\n",
    		   context->current_text_controls->alphabet_num, bestmatch));
    #endif
    	    *w = alpha->pixw;
    	    *h = alpha->pixh;
    	    return;
    	}
    
    	if (alpha->use_font)
    	    fontname = alpha->fontname;
        }
    
        if (fontname) {
    	if (get_xft_bitmap_of_character(context, fontname, ch,
    					maxw, maxh, pixels,
    					max_pixels, w, h)) {
    	    if (*w > maxw) {
    		TRACE(("BUG: Xft glyph is too wide: %ux%u but max is %ux%u\n",
    		       *w, *h, maxw, maxh));
    	    } else if (*h > maxh) {
    		TRACE(("BUG: Xft glyph is too tall: %ux%u but max is %ux%u\n",
    		       *w, *h, maxw, maxh));
    	    } else if (*w * *h > max_pixels) {
    		TRACE(("BUG: Xft glyph has too many pixels: %u but max is %u\n",
    		       *w * *h, max_pixels));
    	    } else {
    		TRACE(("got glyph from \"%s\" for alphabet number %d\n",
    		       fontname, context->current_text_controls->alphabet_num));
    #ifdef DEBUG_SPECIFIC_CHAR_METRICS
    		if (IS_DEBUG_CHAR(ch)) {
    		    printf("got %ux%u Xft bitmap for '%c' target size %ux%u:\n",
    			   *w, *h,
    			   ch, maxw, maxh);
    		    dump_bitmap_pixels(pixels, *w, *h);
    		    printf("\n");
    		}
    #endif
    		return;
    	    }
    	}
        }
    
        TRACE(("unable to load any bitmap for character '%c' in alphabet number %u at %ux%u\n",
    	   ch, context->current_text_controls->alphabet_num, maxw, maxh));
    
        /*
         * The VT3x0 series (and probably earlier ReGIS implementations) use a solid
         * block glyph for unknown glyphs.
         */
        {
    	unsigned xx, yy;
    
    	*w = MIN2(8U, maxh);
    	*h = MIN2(10U, maxw);
    	for (yy = 0U; yy < *h; yy++)
    	    for (xx = 0U; xx < *w; xx++)
    		pixels[yy * *w + xx] = '\1';
        }
    }
    
    #define ROT_SHEAR_SCALE 8192
    #define SIGNED_UNSIGNED_MOD(VAL, BASE) ( (((VAL) % (int) (BASE)) + (int) (BASE)) % (int) (BASE) )
    
    static unsigned
    get_shade_character_pixel(unsigned char const *pixels, unsigned w, unsigned h,
    			  unsigned smaxf, unsigned scale, int slant_dx,
    			  int px, int py)
    {
        unsigned wx, wy;
        unsigned fx, fy;
    
        wx = (unsigned) SIGNED_UNSIGNED_MOD(px -
    					(slant_dx * SIGNED_UNSIGNED_MOD(py, smaxf))
    					/ ROT_SHEAR_SCALE, smaxf);
        wy = (unsigned) SIGNED_UNSIGNED_MOD(py, smaxf);
    
        fx = (wx * scale) >> SCALE_FIXED_POINT;
        fy = (wy * scale) >> SCALE_FIXED_POINT;
        if (fx < w && fy < h) {
    	return (unsigned) pixels[fy * w + fx];
        }
        return 0U;
    }
    
    static void
    draw_character(RegisGraphicsContext *context, int ch,
    	       int slant_dx, int rot_shear_x,
    	       int rot_shear_y, int x_sign_x, int x_sign_y,
    	       int y_sign_x, int y_sign_y)
    {
        const unsigned xmaxd = context->current_text_controls->character_display_w;
        const unsigned ymaxd = context->current_text_controls->character_display_h;
        const unsigned xmaxf = context->current_text_controls->character_unit_cell_w;
        const unsigned ymaxf = context->current_text_controls->character_unit_cell_h;
        unsigned w, h;
        unsigned xscale, yscale;
        unsigned fx, fy;
        unsigned px, py;
        int sx;
        int rx, ry;
        int ox, oy;
        unsigned pad_left, pad_right;
        unsigned pad_top, pad_bottom;
        unsigned char pixels[MAX_GLYPH_PIXELS];
        unsigned value;
    
        get_bitmap_of_character(context, ch, xmaxf, ymaxf, pixels, &w, &h,
    			    MAX_GLYPH_PIXELS);
        if (w < 1 || h < 1) {
    	return;
        }
    
        if (xmaxd > xmaxf) {
    	pad_left = (xmaxd - xmaxf) / 2U;
    	pad_right = (xmaxd - xmaxf) - pad_left;
        } else {
    	pad_left = 0U;
    	pad_right = 0U;
        }
        if (ymaxd > ymaxf) {
    	pad_top = (ymaxd - ymaxf) / 2U;
    	pad_bottom = (ymaxd - ymaxf) - pad_top;
        } else {
    	pad_top = 0U;
    	pad_bottom = 0U;
        }
    
        xscale = (w << SCALE_FIXED_POINT) / xmaxf;
        yscale = (h << SCALE_FIXED_POINT) / ymaxf;
    
        for (py = 0U; py < ymaxd; py++) {
    	for (px = 0U; px < xmaxd; px++) {
    	    if (py < pad_top || px < pad_left ||
    		py >= ymaxd - pad_bottom || px >= xmaxd - pad_right) {
    		value = 0U;
    	    } else {
    		fx = ((px - pad_left) * xscale) >> SCALE_FIXED_POINT;
    		fy = ((py - pad_top) * yscale) >> SCALE_FIXED_POINT;
    		if (fx < w && fy < h) {
    		    value = (unsigned) pixels[fy * w + fx];
    		} else {
    		    value = 0U;
    		}
    	    }
    
    	    sx = (int) px + (slant_dx * (int) py) / ROT_SHEAR_SCALE;
    	    rx = x_sign_x * sx + x_sign_y * (int) py;
    	    ry = y_sign_x * sx + y_sign_y * (int) py;
    	    ox = rx + (rot_shear_x * ry) / ROT_SHEAR_SCALE;
    	    oy = ry + (rot_shear_y * ox) / ROT_SHEAR_SCALE;
    	    ox += (rot_shear_x * oy) / ROT_SHEAR_SCALE;
    
    	    draw_regis_pixel(context,
    			     (int) context->graphics_output_cursor_x + ox,
    			     (int) context->graphics_output_cursor_y + oy,
    			     value);
    	}
        }
    }
    
    static void
    move_text(RegisGraphicsContext *context, int dx, int dy)
    {
        double total_rotation;
        int str_invert;
        int str_shear_x, str_shear_y;
        int ox, oy;
    
        total_rotation = 2.0 * M_PI *
    	context->current_text_controls->string_rotation / 360.0;
        while (total_rotation > 1.5 * M_PI) {
    	total_rotation -= 2.0 * M_PI;
        }
        if (total_rotation > 0.5 * M_PI) {
    	total_rotation -= M_PI;
    	str_invert = -1;
        } else {
    	str_invert = 1;
        }
        str_shear_x = (int) (ROT_SHEAR_SCALE * -tan(0.5 * -total_rotation));
        str_shear_y = (int) (ROT_SHEAR_SCALE * sin(-total_rotation));
    
        total_rotation = 2.0 * M_PI *
    	context->current_text_controls->character_rotation / 360.0;
        while (total_rotation > 1.5 * M_PI) {
    	total_rotation -= 2.0 * M_PI;
        }
    
        TRACE(("str_shear: %.5f, %.5f (sign=%d)\n",
    	   str_shear_x / (double) ROT_SHEAR_SCALE,
    	   str_shear_y / (double) ROT_SHEAR_SCALE,
    	   str_invert));
    
        ox = str_invert * dx + (str_shear_x * dy) / ROT_SHEAR_SCALE;
        oy = str_invert * dy + (str_shear_y * ox) / ROT_SHEAR_SCALE;
        ox += (str_shear_x * oy) / ROT_SHEAR_SCALE;
    
        TRACE(("after pv output updating position %+d,%+d\n", ox, oy));
        context->graphics_output_cursor_x += ox;
        context->graphics_output_cursor_y += oy;
    
        return;
    }
    
    #define UPSCALE_TEXT_DIMENSION(D) do { \
    	    *(D) = (unsigned)((double)(*(D)) * M_SQRT2); \
    	} while (0)
    
    static void
    draw_text(RegisGraphicsContext *context, char const *str)
    {
    #ifndef ENABLE_DISTORTIONLESS_ROTATION
        RegisTextControls *old_text_controls = NULL;
        static RegisTextControls scratch_text_controls;
    #endif
        double total_rotation;
        size_t ii;
        int str_invert;
        int str_shear_x, str_shear_y;
        int slant_dx;
        int chr_x_sign_x, chr_x_sign_y;
        int chr_y_sign_x, chr_y_sign_y;
        int chr_shear_x, chr_shear_y;
        int begin_x, begin_y;
        int rx, ry;
        int ox, oy;
    
    #ifdef DEBUG_ALPHABETS
        {
    	unsigned n;
    
    	for (n = 0U; n < MAX_REGIS_ALPHABETS; n++) {
    	    printf("alphabet index %u\n", n);
    	    if (context->alphabets[n].alphabet_num != INVALID_ALPHABET_NUM) {
    		printf(" alphabet_num=%u\n", context->alphabets[n].alphabet_num);
    		printf(" pixw=%d\n", context->alphabets[n].pixw);
    		printf(" pixh=%d\n", context->alphabets[n].pixh);
    		printf(" name=\"%s\"\n", context->alphabets[n].name);
    		printf(" use_font=%d\n", context->alphabets[n].use_font);
    		printf(" fontname=\"%s\"\n", context->alphabets[n].fontname);
    		printf(" bytes=%p\n", context->alphabets[n].bytes);
    	    }
    	}
        }
    #endif
    
        if (context->current_text_controls->slant <= -75 ||
    	context->current_text_controls->slant >= +75) {
    	TRACE(("ERROR: unsupported character slant angle %d\n",
    	       context->current_text_controls->slant));
    	return;
        }
    
        /* FIXME: grab when first entering command */
        begin_x = context->graphics_output_cursor_x;
        begin_y = context->graphics_output_cursor_y;
    
    #ifndef ENABLE_DISTORTIONLESS_ROTATION
        if (context->current_text_controls->character_rotation != 0 &&
    	context->current_text_controls->character_rotation != 90 &&
    	context->current_text_controls->character_rotation != 180 &&
    	context->current_text_controls->character_rotation != 270) {
    	old_text_controls = context->current_text_controls;
    	scratch_text_controls = *context->current_text_controls;
    	UPSCALE_TEXT_DIMENSION(&scratch_text_controls.character_display_w);
    	UPSCALE_TEXT_DIMENSION(&scratch_text_controls.character_display_h);
    	/* FIXME: Not sure if this is really scaled.  The increment seems to
    	 * _not_ be scaled.
    	 */
    	UPSCALE_TEXT_DIMENSION(&scratch_text_controls.character_unit_cell_w);
    	UPSCALE_TEXT_DIMENSION(&scratch_text_controls.character_unit_cell_h);
    	context->current_text_controls = &scratch_text_controls;
    	TRACE(("scaled up text to %dx%d\n",
    	       scratch_text_controls.character_display_w,
    	       scratch_text_controls.character_display_h));
        }
    #endif
    
        total_rotation = 2.0 * M_PI *
    	context->current_text_controls->string_rotation / 360.0;
        while (total_rotation > 1.5 * M_PI) {
    	total_rotation -= 2.0 * M_PI;
        }
        if (total_rotation > 0.5 * M_PI) {
    	total_rotation -= M_PI;
    	str_invert = -1;
        } else {
    	str_invert = 1;
        }
        str_shear_x = (int) (ROT_SHEAR_SCALE * -tan(0.5 * -total_rotation));
        str_shear_y = (int) (ROT_SHEAR_SCALE * sin(-total_rotation));
    
        total_rotation = 2.0 * M_PI *
    	context->current_text_controls->character_rotation / 360.0;
        while (total_rotation > 1.5 * M_PI) {
    	total_rotation -= 2.0 * M_PI;
        }
        if (total_rotation > 0.5 * M_PI) {
    	total_rotation -= M_PI;
    	chr_x_sign_x = -1;
    	chr_x_sign_y = 0;
    	chr_y_sign_x = 0;
    	chr_y_sign_y = -1;
        } else {
    	chr_x_sign_x = 1;
    	chr_x_sign_y = 0;
    	chr_y_sign_x = 0;
    	chr_y_sign_y = 1;
        }
        chr_shear_x = (int) (ROT_SHEAR_SCALE * -tan(0.5 * -total_rotation));
        chr_shear_y = (int) (ROT_SHEAR_SCALE * sin(-total_rotation));
    
        {
    	const int slant = context->current_text_controls->slant;
    
    	TRACE(("float version: %.5f\n", tan(2.0 * M_PI * abs(slant) / 360.0)));
    	/* The slant is negative for forward-leaning characters. */
    	if (slant > 0) {
    	    slant_dx = (int) +(tan(2.0 * M_PI * abs(slant) / 360.0) * ROT_SHEAR_SCALE);
    	} else if (slant < 0) {
    	    slant_dx = (int) -(tan(2.0 * M_PI * abs(slant) / 360.0) * ROT_SHEAR_SCALE);
    	} else {
    	    slant_dx = 0;
    	}
    	TRACE(("string rotation: %d\n",
    	       context->current_text_controls->string_rotation));
    	TRACE(("character rotation: %d\n",
    	       context->current_text_controls->character_rotation));
    	TRACE(("character slant: %d (%.5f pixels per line)\n",
    	       slant, slant_dx / (double) ROT_SHEAR_SCALE));
        }
    
        TRACE(("str_shear: %.5f, %.5f (sign=%d)\n",
    	   str_shear_x / (double) ROT_SHEAR_SCALE,
    	   str_shear_y / (double) ROT_SHEAR_SCALE,
    	   str_invert));
        TRACE(("chr_shear: %.5f, %.5f (xsign=%d,%d, ysign=%d,%d)\n",
    	   chr_shear_x / (double) ROT_SHEAR_SCALE,
    	   chr_shear_y / (double) ROT_SHEAR_SCALE,
    	   chr_x_sign_x, chr_x_sign_y,
    	   chr_y_sign_x, chr_y_sign_y));
        TRACE(("character_inc: %d,%d\n",
    	   context->current_text_controls->character_inc_x, context->current_text_controls->character_inc_y));
    
        rx = 0;
        ry = 0;
        for (ii = 0U; ii < strlen(str); ii++) {
    	switch (str[ii]) {
    	case '\r':
    	    rx = 0;
    	    break;
    	case '\n':
    	    ry += (int) context->current_text_controls->character_display_h;
    	    break;
    	case '\b':
    	    rx -= context->current_text_controls->character_inc_x;
    	    ry -= context->current_text_controls->character_inc_y;
    	    break;
    	case '\t':
    	    rx += context->current_text_controls->character_inc_x;
    	    ry += context->current_text_controls->character_inc_y;
    	    break;
    	default:
    	    ox = str_invert * rx + (str_shear_x * ry) / ROT_SHEAR_SCALE;
    	    oy = str_invert * ry + (str_shear_y * ox) / ROT_SHEAR_SCALE;
    	    ox += (str_shear_x * oy) / ROT_SHEAR_SCALE;
    	    TRACE(("during text output updating position to %d,%d + %+d,%+d for '%c'\n",
    		   begin_x, begin_y, ox, oy, str[ii]));
    	    context->graphics_output_cursor_x = begin_x + ox;
    	    context->graphics_output_cursor_y = begin_y + oy;
    	    draw_character(context, str[ii], slant_dx,
    			   chr_shear_x, chr_shear_y,
    			   chr_x_sign_x, chr_x_sign_y,
    			   chr_y_sign_x, chr_y_sign_y);
    	    rx += context->current_text_controls->character_inc_x;
    	    ry += context->current_text_controls->character_inc_y;
    	}
        }
    
        ox = str_invert * rx + (str_shear_x * ry) / ROT_SHEAR_SCALE;
        oy = str_invert * ry + (str_shear_y * ox) / ROT_SHEAR_SCALE;
        ox += (str_shear_x * oy) / ROT_SHEAR_SCALE;
        TRACE(("after text output updating position to %d,%d + %+d,%+d\n",
    	   begin_x, begin_y, ox, oy));
        context->graphics_output_cursor_x = begin_x + ox;
        context->graphics_output_cursor_y = begin_y + oy;
    
    #ifndef ENABLE_DISTORTIONLESS_ROTATION
        if (context->current_text_controls->character_rotation != 0 &&
    	context->current_text_controls->character_rotation != 90 &&
    	context->current_text_controls->character_rotation != 180 &&
    	context->current_text_controls->character_rotation != 270) {
    	context->current_text_controls = old_text_controls;
        }
    #endif
    
        context->destination_graphic->dirty = 1;
        return;
    }
    
    /*
     * standard character cell sizes
     *   number  disp cell   unit cell       offset
     *   S0      [  9, 10]   [  8, disp_h]   [disp_w, 0]
     *   S1      [  9, 20]   [  8, disp_h]   [disp_w, 0]
     *   S2      [ 18, 30]   [ 16, disp_h]   [disp_w, 0]
     *   S3      [ 27, 45]   [ 24, disp_h]   [disp_w, 0]
     *   S4      [ 36, 60]   [ 32, disp_h]   [disp_w, 0]
     *   S5      [ 45, 75]   [ 40, disp_h]   [disp_w, 0]
     *   S6      [ 54, 90]   [ 48, disp_h]   [disp_w, 0]
     *   S7      [ 63,105]   [ 56, disp_h]   [disp_w, 0]
     *   S8      [ 72,120]   [ 64, disp_h]   [disp_w, 0]
     *   S9      [ 81,135]   [ 72, disp_h]   [disp_w, 0]
     *   S10     [ 90,150]   [ 80, disp_h]   [disp_w, 0]
     *   S11     [ 99,165]   [ 88, disp_h]   [disp_w, 0]
     *   S12     [108,180]   [ 96, disp_h]   [disp_w, 0]
     *   S13     [117,195]   [104, disp_h]   [disp_w, 0]
     *   S14     [126,210]   [112, disp_h]   [disp_w, 0]
     *   S15     [135,225]   [120, disp_h]   [disp_w, 0]
     *   S16     [144,240]   [128, disp_h]   [disp_w, 0]
     */
    static int
    get_standard_character_size(int standard, unsigned *disp_w, unsigned
    			    *disp_h, unsigned *unit_w, unsigned *unit_h,
    			    int *off_x, int *off_y)
    {
        switch (standard) {
        case 0:
    	*disp_w = 9U;
    	*disp_h = 10U;
    	*unit_w = 8U;
    	break;
        case 1:
    	*disp_w = 9U;
    	*disp_h = 20U;
    	*unit_w = 8U;
    	break;
        case 2:
    	*disp_w = 18U;
    	*disp_h = 30U;
    	*unit_w = 16U;
    	break;
        case 3:
    	*disp_w = 27U;
    	*disp_h = 45U;
    	*unit_w = 24U;
    	break;
        case 4:
    	*disp_w = 36U;
    	*disp_h = 60U;
    	*unit_w = 32U;
    	break;
        case 5:
    	*disp_w = 45U;
    	*disp_h = 75U;
    	*unit_w = 40U;
    	break;
        case 6:
    	*disp_w = 54U;
    	*disp_h = 90U;
    	*unit_w = 48U;
    	break;
        case 7:
    	*disp_w = 63U;
    	*disp_h = 105U;
    	*unit_w = 56U;
    	break;
        case 8:
    	*disp_w = 72U;
    	*disp_h = 120U;
    	*unit_w = 64U;
    	break;
        case 9:
    	*disp_w = 81U;
    	*disp_h = 135U;
    	*unit_w = 72U;
    	break;
        case 10:
    	*disp_w = 90U;
    	*disp_h = 150U;
    	*unit_w = 80U;
    	break;
        case 11:
    	*disp_w = 99U;
    	*disp_h = 165U;
    	*unit_w = 88U;
    	break;
        case 12:
    	*disp_w = 108U;
    	*disp_h = 180U;
    	*unit_w = 96U;
    	break;
        case 13:
    	*disp_w = 117U;
    	*disp_h = 195U;
    	*unit_w = 104U;
    	break;
        case 14:
    	*disp_w = 126U;
    	*disp_h = 210U;
    	*unit_w = 112U;
    	break;
        case 15:
    	*disp_w = 135U;
    	*disp_h = 225U;
    	*unit_w = 120U;
    	break;
        case 16:
    	*disp_w = 144U;
    	*disp_h = 240U;
    	*unit_w = 128U;
    	break;
        default:
    	return 1;
        }
        *unit_h = *disp_h;
        *off_x = (int) *disp_w;
        *off_y = 0;
    
        return 0;
    }
    
    static void
    init_fragment(RegisDataFragment *fragment, char const *str)
    {
        assert(fragment);
        assert(str);
    
        fragment->start = str;
        fragment->len = (unsigned) strlen(str);
        fragment->pos = 0U;
    }
    
    static void
    copy_fragment(RegisDataFragment *dst, RegisDataFragment const *src)
    {
        assert(dst);
        assert(src);
    
        dst->start = src->start;
        dst->len = src->len;
        dst->pos = src->pos;
    }
    
    static char
    peek_fragment(RegisDataFragment const *fragment)
    {
        assert(fragment);
    
        if (fragment->pos < fragment->len) {
    	return fragment->start[fragment->pos];
        }
        return '\0';
    }
    
    static char
    pop_fragment(RegisDataFragment *fragment)
    {
        assert(fragment);
    
        if (fragment->pos < fragment->len) {
    	return fragment->start[fragment->pos++];
        }
        return '\0';
    }
    
    static char
    get_fragment(RegisDataFragment const *fragment, unsigned pos)
    {
        assert(fragment);
    
        if (fragment->pos + pos < fragment->len) {
    	return fragment->start[fragment->pos + pos];
        }
        return '\0';
    }
    
    #define fragment_length(f) (f)->len
    
    static unsigned
    fragment_remaining(RegisDataFragment const *fragment)
    {
        assert(fragment);
    
        if (fragment->pos > fragment->len)
    	return 0U;
        return fragment->len - fragment->pos;
    }
    
    static int
    fragment_consumed(RegisDataFragment const *fragment)
    {
        assert(fragment);
    
        return fragment->pos >= fragment->len;
    }
    
    static void
    fragment_to_string(RegisDataFragment const *fragment, char *out,
    		   unsigned outlen)
    {
        unsigned remaininglen;
        unsigned endpos;
    
        assert(fragment);
        assert(out);
    
        if (!outlen)
    	return;
        remaininglen = fragment->len - fragment->pos;
        if (remaininglen < outlen - 1U) {
    	endpos = remaininglen;
        } else {
    	endpos = outlen - 1U;
        }
        strncpy(out, &fragment->start[fragment->pos], (size_t) endpos);
        out[endpos] = '\0';
    }
    
    #define MAX_FRAG 1024
    static char const *
    fragment_to_tempstr(RegisDataFragment const *fragment)
    {
        static char tempstr[MAX_FRAG];
    
        assert(fragment);
    
        fragment_to_string(fragment, tempstr, MAX_FRAG);
        return tempstr;
    }
    
    static int
    skip_regis_whitespace(RegisDataFragment *input)
    {
        int skipped = 0;
    
        assert(input);
    
        while (!fragment_consumed(input)) {
    	char ch = peek_fragment(input);
    	if (ch != ',' && !IsSpace(ch)) {
    	    break;
    	}
    	if (ch == '\n') {
    	    TRACE(("end of input line\n\n"));
    	}
    	skipped = 1;
    	pop_fragment(input);
        }
    
        if (skipped)
    	return 1;
        return 0;
    }
    
    static int
    extract_regis_extent(RegisDataFragment *input, RegisDataFragment *output)
    {
        char ch;
    
        assert(input);
        assert(output);
    
        output->start = &input->start[input->pos];
        output->len = 0U;
        output->pos = 0U;
    
        if (input->pos >= input->len)
    	return 0;
    
        ch = input->start[input->pos];
        if (ch != '[')
    	return 0;
        input->pos++;
        output->start++;
    
        /* FIXME: truncate to 16 bit signed integers */
        for (; input->pos < input->len; input->pos++, output->len++) {
    	ch = input->start[input->pos];
    	if (ch == ';') {
    	    TRACE(("DATA_ERROR: end of input before closing bracket\n"));
    	    break;
    	}
    	if (ch == ']')
    	    break;
        }
        if (ch == ']')
    	input->pos++;
    
        return 1;
    }
    
    static int
    extract_regis_num(RegisDataFragment *input, RegisDataFragment *output)
    {
        char ch = 0;
        int has_digits = 0;
    
        assert(input);
        assert(output);
    
        output->start = &input->start[input->pos];
        output->len = 0U;
        output->pos = 0U;
    
        if (input->start[input->pos] == '-' ||
    	input->start[input->pos] == '+') {
    	input->pos++;
    	output->len++;
        }
    
        for (; input->pos < input->len; input->pos++, output->len++) {
    	ch = input->start[input->pos];
    	if (ch != '0' && ch != '1' && ch != '2' && ch != '3' &&
    	    ch != '4' && ch != '5' && ch != '6' && ch != '7' &&
    	    ch != '8' && ch != '9') {
    	    break;
    	}
    	has_digits = 1;
        }
    
        /* FIXME: what degenerate forms should be accepted ("E10" "1E" "1e" "1." "1ee10")? */
        /* FIXME: the terminal is said to support "floating point values", truncating to int... what do these look like? */
        if (has_digits && ch == 'E') {
    	input->pos++;
    	output->len++;
    	for (; input->pos < input->len; input->pos++, output->len++) {
    	    ch = input->start[input->pos];
    	    if (ch != '0' && ch != '1' && ch != '2' && ch != '3' &&
    		ch != '4' && ch != '5' && ch != '6' && ch != '7' &&
    		ch != '8' && ch != '9') {
    		break;
    	    }
    	}
        }
    
        return has_digits;
    }
    
    static int
    extract_regis_pixelvector(RegisDataFragment *input, RegisDataFragment *output)
    {
        char ch;
        int has_digits;
    
        assert(input);
        assert(output);
    
        output->start = &input->start[input->pos];
        output->len = 0U;
        output->pos = 0U;
    
        if (input->pos < input->len) {
    	ch = input->start[input->pos];
    	if (ch == '+' || ch == '-') {
    	    input->pos++;
    	    output->len++;
    	}
        }
    
        has_digits = 0;
        for (; input->pos < input->len; input->pos++, output->len++) {
    	ch = input->start[input->pos];
    	if (ch != '0' && ch != '1' && ch != '2' && ch != '3' &&
    	    ch != '4' && ch != '5' && ch != '6' && ch != '7') {
    	    break;
    	}
    	has_digits = 1;
        }
    
        return has_digits;
    }
    
    static int
    extract_regis_command(RegisDataFragment *input, char *command)
    {
        char ch;
    
        assert(input);
        assert(command);
    
        if (input->pos >= input->len)
    	return 0;
    
        ch = input->start[input->pos];
        if (ch == '\0' || ch == ';') {
    	return 0;
        }
        if (!islower(CharOf(ch)) && !isupper(CharOf(ch)) && ch != '@') {
    	return 0;
        }
        *command = ch;
        input->pos++;
    
        return 1;
    }
    
    static int
    extract_regis_string(RegisDataFragment *input, char *out, unsigned maxlen)
    {
        char open_quote_ch;
        char ch;
        unsigned outlen;
    
        assert(input);
        assert(out);
        assert(maxlen > 0U);
    
        if (input->pos >= input->len)
    	return 0;
    
        ch = peek_fragment(input);
        if (ch != '\'' && ch != '"')
    	return 0;
        open_quote_ch = ch;
        outlen = 0U;
        pop_fragment(input);
    
        ch = '\0';
        while (!fragment_consumed(input)) {
    	char prev_ch = ch;
    	ch = peek_fragment(input);
    	/* ';' (resync) and '@' (macrograph) are not recognized in strings */
    	if (prev_ch == open_quote_ch) {
    	    if (ch == open_quote_ch) {
    		if (outlen < maxlen) {
    		    out[outlen] = ch;
    		}
    		outlen++;
    		pop_fragment(input);
    		ch = '\0';
    		continue;
    	    }
    	    if (outlen < maxlen)
    		out[outlen] = '\0';
    	    else
    		out[maxlen] = '\0';
    	    return 1;
    	}
    	if (ch == '\0')
    	    break;
    	if (ch != open_quote_ch) {
    	    if (outlen < maxlen)
    		out[outlen] = ch;
    	    outlen++;
    	}
    	pop_fragment(input);
        }
        if (ch == open_quote_ch) {
    	pop_fragment(input);
    	if (outlen < maxlen)
    	    out[outlen] = '\0';
    	else
    	    out[maxlen] = '\0';
    	return 1;
        }
        /* FIXME: handle multiple strings concatenated with commas */
    
        TRACE(("DATA_ERROR: end of input before closing quote\n"));
        return 0;
    }
    
    static int
    extract_regis_parenthesized_data(RegisDataFragment *input,
    				 RegisDataFragment *output)
    {
        char ch;
        char open_quote_ch;
        int nesting;
    
        assert(input);
        assert(output);
    
        output->start = &input->start[input->pos];
        output->len = 0U;
        output->pos = 0U;
    
        if (input->pos >= input->len)
    	return 0;
    
        ch = input->start[input->pos];
        if (ch != '(')
    	return 0;
        input->pos++;
        output->start++;
        nesting = 1;
        open_quote_ch = '\0';
    
        ch = '\0';
        for (; input->pos < input->len; input->pos++, output->len++) {
    	char prev_ch = ch;
    	ch = input->start[input->pos];
    	if (ch == '\'' || ch == '"') {
    	    if (open_quote_ch == '\0') {
    		open_quote_ch = ch;
    	    } else {
    		if (ch == prev_ch && prev_ch == open_quote_ch) {
    		    ch = '\0';
    		} else if (ch == open_quote_ch) {
    		    open_quote_ch = '\0';
    		}
    	    }
    	    continue;
    	}
    	if (open_quote_ch != '\0')
    	    continue;
    
    	if (ch == ';') {
    	    TRACE(("leaving parenthesized data nested %d levels deep due to command termination character\n",
    		   nesting));
    	    break;
    	}
    	if (ch == '(')
    	    nesting++;
    	if (ch == ')') {
    	    nesting--;
    	    if (nesting == 0) {
    		input->pos++;
    		return 1;
    	    }
    	}
        }
    
        TRACE(("DATA_ERROR: end of input before closing paren (%d levels deep)\n",
    	   nesting));
        return 0;
    }
    
    static int
    extract_regis_option(RegisDataFragment *input,
    		     char *option,
    		     RegisDataFragment *output)
    {
        char ch;
        int paren_level, bracket_level;
        char open_quote_ch;
    
        assert(input);
        assert(option);
        assert(output);
    
        /* LETTER suboptions* value? */
        /*
         * FIXME: what are the rules for using separate parens vs. sharing between
         * options?
         */
    
        output->start = &input->start[input->pos];
        output->len = 0U;
        output->pos = 0U;
    
        if (input->pos >= input->len) {
    	return 0;
        }
    
        ch = input->start[input->pos];
        /* FIXME: are options always letters or are some special characters ok? */
        if (ch == ';' || ch == ',' ||
    	ch == '(' || ch == ')' ||
    	ch == '[' || ch == ']' ||
    	ch == '"' || ch == '\'' ||
    	isdigit(CharOf(ch))) {
    	return 0;
        }
        *option = ch;
        input->pos++;
        output->start++;
        paren_level = 0;
        bracket_level = 0;
    
        open_quote_ch = '\0';
        for (; input->pos < input->len; input->pos++, output->len++) {
    	ch = input->start[input->pos];
    	TRACE(("looking at char '%c' in option '%c'\n", ch, *option));
    	/* FIXME: any special rules for commas? */
    	/* FIXME: handle escaped quotes */
    	if (ch == '\'' || ch == '"') {
    	    if (open_quote_ch == ch) {
    		open_quote_ch = '\0';
    	    } else {
    		open_quote_ch = ch;
    	    }
    	    continue;
    	}
    	if (open_quote_ch != '\0')
    	    continue;
    	if (ch == '(') {
    	    paren_level++;
    	}
    	if (ch == ')') {
    	    paren_level--;
    	    if (paren_level < 0) {
    		TRACE(("DATA_ERROR: found ReGIS option has value with too many close parens \"%c\"\n",
    		       *option));
    		return 0;
    	    }
    	}
    	if (ch == '[') {
    	    bracket_level++;
    	}
    	if (ch == ']') {
    	    bracket_level--;
    	    if (bracket_level < 0) {
    		TRACE(("DATA_ERROR: found ReGIS option has value with too many close brackets \"%c\"\n",
    		       *option));
    		return 0;
    	    }
    	}
    	if (paren_level == 0 && bracket_level == 0) {
    	    /*
    	     * Top-level commas indicate the end of this option and the start of
    	     * another.
    	     */
    	    if (ch == ',')
    		break;
    	    /*
    	     * Top-level command/option/suboption names also indicate the end of
    	     * this option.  "E" is valid as the exponent indicator in a numeric
    	     * parameter.
    	     */
    	    if (ch != 'E' && ch != 'e' &&
    		((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z')))
    		break;
    	}
    	if (ch == ';')
    	    break;
        }
        if (paren_level != 0) {
    	TRACE(("DATA_ERROR: mismatched parens in argument to ReGIS option \"%c\"\n",
    	       *option));
    	return 0;
        }
        if (bracket_level != 0) {
    	TRACE(("DATA_ERROR: mismatched brackets in argument to ReGIS option \"%c\"\n",
    	       *option));
    	return 0;
        }
    
        TRACE(("found ReGIS option and value \"%c\" \"%s\"\n",
    	   *option,
    	   fragment_to_tempstr(output)));
        return 1;
    }
    
    static int
    regis_num_to_int(RegisDataFragment const *input, int *out)
    {
        char ch;
    
        assert(input);
        assert(out);
    
        /* FIXME: handle exponential notation and rounding */
        /* FIXME: check for junk after the number */
        ch = peek_fragment(input);
        if (ch != '0' &&
    	ch != '1' &&
    	ch != '2' &&
    	ch != '3' &&
    	ch != '4' &&
    	ch != '5' &&
    	ch != '6' &&
    	ch != '7' &&
    	ch != '8' &&
    	ch != '9' &&
    	ch != '+' &&
    	ch != '-') {
    	return 0;
        }
    
        TRACE(("converting \"%s\" to an int\n", fragment_to_tempstr(input)));
        *out = atoi(fragment_to_tempstr(input));
        return 1;
    }
    
    static int
    load_regis_colorspec(RegisGraphicsContext const *context,
    		     RegisDataFragment const *input,
    		     short *r_out, short *g_out, short *b_out)
    {
        RegisDataFragment colorspec;
        short r = -1, g = -1, b = -1;
        short l = -1;
        int simple;
    
        assert(context);
        assert(input);
        assert(r_out);
        assert(g_out);
        assert(b_out);
    
        copy_fragment(&colorspec, input);
        TRACE(("colorspec option: \"%s\"\n", fragment_to_tempstr(&colorspec)));
    
        skip_regis_whitespace(&colorspec);
        simple = 0;
        if (fragment_remaining(&colorspec) == 1U) {
    	simple = 1;
        } else if (fragment_remaining(&colorspec) > 1U) {
    	char after = get_fragment(&colorspec, 1U);
    	if (IsSpace(after))
    	    simple = 1;
        }
        if (simple) {
    	char ch = pop_fragment(&colorspec);
    
    	TRACE(("got ReGIS RGB colorspec pattern '%c' with arguments: \"%s\"\n",
    	       ch, fragment_to_tempstr(&colorspec)));
    	switch (ch) {
    	case 'D':
    	case 'd':
    	    r = 0;
    	    g = 0;
    	    b = 0;
    	    l = 0;
    	    break;
    	case 'R':
    	case 'r':
    	    r = 100;
    	    g = 0;
    	    b = 0;
    	    l = 46;
    	    break;
    	case 'G':
    	case 'g':
    	    r = 0;
    	    g = 100;
    	    b = 0;
    	    l = 50;
    	    break;
    	case 'B':
    	case 'b':
    	    r = 0;
    	    g = 0;
    	    b = 100;
    	    l = 50;
    	    break;
    	case 'C':
    	case 'c':
    	    r = 0;
    	    g = 100;
    	    b = 100;
    	    l = 50;
    	    break;
    	case 'Y':
    	case 'y':
    	    r = 100;
    	    g = 100;
    	    b = 0;
    	    l = 50;
    	    break;
    	case 'M':
    	case 'm':
    	    r = 100;
    	    g = 0;
    	    b = 100;
    	    l = 50;
    	    break;
    	case 'W':
    	case 'w':
    	    r = 100;
    	    g = 100;
    	    b = 100;
    	    l = 100;
    	    break;
    	default:
    	    TRACE(("DATA_ERROR: unknown RGB color name: \"%c\"\n", ch));
    	    return 0;
    	}
        } else {
    	RegisDataFragment num;
    	int max, val;
    	char comp;
    	short h = -1;
    	short s = -1;
    
    	while (!fragment_consumed(&colorspec)) {
    	    if (skip_regis_whitespace(&colorspec))
    		continue;
    
    	    comp = pop_fragment(&colorspec);
    	    switch (comp) {
    	    case ',':
    		/* not sure if this is valid, but it is easy to handle */
    		continue;
    	    case 'H':
    	    case 'h':
    		max = 360;
    		comp = 'H';
    		break;
    	    case 'L':
    	    case 'l':
    		max = 100;
    		comp = 'L';
    		break;
    	    case 'S':
    	    case 's':
    		max = 100;
    		comp = 'S';
    		break;
    #ifdef ENABLE_RGB_COLORSPECS
    	    case 'R':		/* RLogin extension */
    	    case 'r':
    		max = 100;
    		comp = 'R';
    		break;
    	    case 'G':		/* RLogin extension */
    	    case 'g':
    		max = 100;
    		comp = 'G';
    		break;
    	    case 'B':		/* RLogin extension */
    	    case 'b':
    		max = 100;
    		comp = 'B';
    		break;
    #endif
    	    default:
    		TRACE(("DATA_ERROR: unrecognized component in colorspec: '%c'\n",
    		       comp));
    		return 0;
    	    }
    
    	    skip_regis_whitespace(&colorspec);
    	    if (!extract_regis_num(&colorspec, &num)) {
    		TRACE(("DATA_ERROR: expected int after '%c' component in colorspec: \"%s\"\n",
    		       comp, fragment_to_tempstr(&colorspec)));
    		return 0;
    	    }
    	    if (!regis_num_to_int(&num, &val)) {
    		TRACE(("DATA_ERROR: component value %s is not a number\n",
    		       fragment_to_tempstr(&num)));
    		return 0;
    	    }
    	    /* FIXME: error, truncate, wrap, ...? */
    	    if (val < 0 || val > max) {
    		TRACE(("DATA_ERROR: component value %d out of range\n", val));
    		return 0;
    	    }
    
    	    switch (comp) {
    	    case 'H':
    		h = (short) val;
    		break;
    	    case 'L':
    		l = (short) val;
    		break;
    	    case 'S':
    		s = (short) val;
    		break;
    	    case 'R':
    		r = (short) val;
    		break;
    	    case 'G':
    		g = (short) val;
    		break;
    	    case 'B':
    		b = (short) val;
    		break;
    	    }
    	}
    
    	if (h >= 0 && l >= 0 && s >= 0 && r < 0 && g < 0 && b < 0) {
    	    TRACE(("found HLS colorspec to be converted: %hd,%hd,%hd\n",
    		   h, l, s));
    	    hls2rgb(h, l, s, &r, &g, &b);
    	    TRACE(("converted to RGB: %hd,%hd,%hd\n", r, g, b));
    	} else if (h < 0 && l < 0 && s < 0 && r >= 0 && g >= 0 && b >= 0) {
    	    TRACE(("found RGB colorspec: %hd,%hd,%hd\n", r, g, b));
    	    l = (short) ((MIN3(r, g, b) + MAX3(r, g, b)) / 2);
    	    TRACE(("calculated L: %d\n", l));
    	} else if (h < 0 && l >= 0 && s < 0 && r < 0 && g < 0 && b < 0) {
    	    TRACE(("found L colorspec to be converted: %hd,%hd,%hd\n",
    		   h, l, s));
    	    hls2rgb(0, l, 0, &r, &g, &b);
    	    TRACE(("converted to RGB: %hd,%hd,%hd\n", r, g, b));
    	} else {
    	    TRACE(("DATA_ERROR: unrecognized colorspec format\n"));
    	    return 0;
    	}
        }
    
        /*
         * The VT240 and VT330 models convert to the closest grayscale value.
         */
        if (context->terminal_id == 240 || context->terminal_id == 330) {
    	hls2rgb(0, l, 0, &r, &g, &b);
    	TRACE(("converted to grayscale: %hd,%hd,%hd\n", r, g, b));
        }
    
        *r_out = r;
        *g_out = g;
        *b_out = b;
    
        skip_regis_whitespace(&colorspec);
        if (!fragment_consumed(&colorspec)) {
    	char skip;
    
    	skip = pop_fragment(&colorspec);
    	(void) skip;		/* variable needed only if tracing */
    	TRACE(("DATA_ERROR: ignoring unexpected character in ReGIS colorspec \"%c\"\n",
    	       skip));
        }
    
        return 1;
    }
    
    static int
    load_regis_regnum_or_colorspec(RegisGraphicsContext const *context,
    			       RegisDataFragment const *input,
    			       RegisterNum *out)
    {
        int val;
        RegisDataFragment colorspec;
        RegisDataFragment num;
        RegisDataFragment coloroption;
    
        copy_fragment(&colorspec, input);
        TRACE(("looking at colorspec pattern: \"%s\"\n",
    	   fragment_to_tempstr(&colorspec)));
    
        skip_regis_whitespace(&colorspec);
    
        if (extract_regis_num(&colorspec, &num)) {
    	if (!regis_num_to_int(&num, &val)) {
    	    TRACE(("DATA_ERROR: colorspec value %s is not a valid register\n",
    		   fragment_to_tempstr(&num)));
    	    return 0;
    	}
    	if (val < 0) {
    	    /* FIXME: error, truncate, wrap, ...? */
    	    TRACE(("DATA_ERROR: ignoring negative colorspec value: %d\n", val));
    	    return 0;
    	}
    	if (val >= (int) context->destination_graphic->valid_registers) {
    	    /* FIXME: error, truncate, wrap, ...? */
    	    TRACE(("DATA_ERROR: colorspec value %d is too big; wrapping\n",
    		   val));
    	    val %= (int) context->destination_graphic->valid_registers;
    	}
    
    	TRACE(("colorspec contains index for register %u\n", val));
    	*out = (RegisterNum) val;
    
    	skip_regis_whitespace(&colorspec);
    	if (!fragment_consumed(&colorspec)) {
    	    char skip;
    
    	    skip = pop_fragment(&colorspec);
    	    (void) skip;	/* variable needed only if tracing */
    	    TRACE(("DATA_ERROR: unexpected character after register \"%c\"\n",
    		   skip));
    	    return 0;
    	}
    
    	return 1;
        }
    
        if (extract_regis_parenthesized_data(&colorspec, &coloroption)) {
    	short r, g, b;
    
    	if (!load_regis_colorspec(context, &coloroption, &r, &g, &b)) {
    	    TRACE(("unable to parse colorspec\n"));
    	    return 0;
    	}
    
    	*out = find_color_register(context->destination_graphic->color_registers,
    				   r, g, b);
    	TRACE(("colorspec maps to closest register %u\n", *out));
    
    	return 1;
        }
    
        TRACE(("expected register number or colorspec, but found: \"%s\"\n",
    	   fragment_to_tempstr(&colorspec)));
        return 0;
    }
    
    static int
    to_scaled_int(char const *num, int scale, int *value)
    {
        unsigned long whole, frac;
        char *end;
    
        /* FIXME: handle whitespace? how about trailing junk? */
        whole = strtoul(num, &end, 10);
        if (end[0] == '.') {
    	char temp[5] = "0000";
    
    	if (end[1] != '\0') {
    	    temp[0] = end[1];
    	    if (end[2] != '\0') {
    		temp[1] = end[2];
    		if (end[3] != '\0') {
    		    temp[2] = end[3];
    		    if (end[4] != '\0') {
    			temp[3] = end[4];
    		    }
    		}
    	    }
    	}
    	frac = strtoul(temp, NULL, 10);
        } else if (end[0] == '\0' || end[0] == ',' || IsSpace(end[0])) {
    	frac = 0;
        } else {
    	TRACE(("unexpected character %c in number %s\n", end[0], num));
    	return 0;
        }
    
        *value = (int) (whole * (unsigned) scale +
    		    (frac * (unsigned) scale) / 10000);
    
        return 1;
    }
    
    static int
    load_regis_raw_extent(char const *extent, int *relx, int *rely,
    		      int *xloc, int *yloc, int scale)
    {
        int xsign, ysign;
        char const *xpart;
        char const *ypart;
    
        xpart = extent;
        if ((ypart = strchr(extent, ','))) {
    	ypart++;
        } else {
    	ypart = "";
        }
    
        while (IsSpace(xpart[0]))
    	xpart++;
        while (IsSpace(ypart[0]))
    	ypart++;
    
        if (xpart[0] == '-') {
    	xsign = -1;
    	xpart++;
        } else if (xpart[0] == '+') {
    	xsign = +1;
    	xpart++;
        } else {
    	xsign = 0;
        }
        if (ypart[0] == '-') {
    	ysign = -1;
    	ypart++;
        } else if (ypart[0] == '+') {
    	ysign = +1;
    	ypart++;
        } else {
    	ysign = 0;
        }
    
        if (xpart[0] == '\0' || xpart[0] == ',') {
    	*relx = 1;
    	*xloc = 0;
        } else if (xsign == 0) {
    	int val;
    
    	if (!to_scaled_int(xpart, scale, &val))
    	    return 0;
    	*relx = 0;
    	*xloc = val;
        } else {
    	int val;
    
    	if (!to_scaled_int(xpart, scale, &val))
    	    return 0;
    	*relx = 1;
    	*xloc = xsign * val;
        }
        if (ypart[0] == '\0') {
    	*rely = 1;
    	*yloc = 0;
        } else if (ysign == 0) {
    	int val;
    
    	if (!to_scaled_int(ypart, scale, &val))
    	    return 0;
    	*rely = 0;
    	*yloc = val;
        } else {
    	int val;
    
    	if (!to_scaled_int(ypart, scale, &val))
    	    return 0;
    	*rely = 1;
    	*yloc = ysign * val;
        }
    
        return 1;
    }
    
    static int
    load_regis_mult_extent(char const *extent, int *w, int *h)
    {
        int relx, rely;
        int px, py;
    
        if (!load_regis_raw_extent(extent, &relx, &rely, &px, &py, 1)) {
    	TRACE(("invalid coordinates in extent %s\n", extent));
    	return 0;
        }
        if (relx | rely) {
    	TRACE(("invalid relative value in multiplier extent %s\n", extent));
    	return 0;
        }
    
        *w = px;
        *h = py;
    
        return 1;
    }
    
    static int
    load_regis_pixel_extent(char const *extent, int origx, int origy,
    			int *xloc, int *yloc)
    {
        int relx, rely;
        int px, py;
    
        if (!load_regis_raw_extent(extent, &relx, &rely, &px, &py, 1)) {
    	TRACE(("invalid coordinates in extent %s\n", extent));
    	return 0;
        }
    
        *xloc = px;
        *yloc = py;
    
        if (relx)
    	*xloc += origx;
        if (rely)
    	*yloc += origy;
    
        return 1;
    }
    
    #define COORD_SCALE 1000
    
    static int
    load_regis_coord_extent(RegisGraphicsContext const *context, char const *extent,
    			int origx, int origy, int *xloc, int *yloc)
    {
        int relx, rely;
        int ux, uy;
    
        if (!load_regis_raw_extent(extent, &relx, &rely, &ux, &uy, COORD_SCALE)) {
    	TRACE(("invalid coordinates in extent %s\n", extent));
    	return 0;
        }
    
        if (relx) {
    	const int px = SCALE_XCOORD(context, ux, COORD_SCALE);
    	TRACE(("converted relative user X coord %.03f to relative pixel X coord %d (width=%d xoff=%d xdiv=%d)\n",
    	       ux / (double) COORD_SCALE, px, context->width,
    	       context->x_off, context->x_div));
    	*xloc = origx + px;
        } else {
    	const int px = TRANSLATE_XCOORD(context, ux, COORD_SCALE);
    	TRACE(("converted absolute user X coord %.03f to absolute pixel X coord %d\n",
    	       ux / (double) COORD_SCALE, px));
    	*xloc = px;
        }
        if (rely) {
    	const int py = SCALE_YCOORD(context, uy, COORD_SCALE);
    	TRACE(("converted relative user Y coord %.03f to relative pixel Y coord %d (height=%d yoff=%d ydiv=%d)\n",
    	       uy / (double) COORD_SCALE, py, context->height,
    	       context->y_off, context->y_div));
    	*yloc = origy + py;
        } else {
    	const int py = TRANSLATE_YCOORD(context, uy, COORD_SCALE);
    	TRACE(("converted absolute user Y coord %.03f to absolute pixel Y coord %d\n",
    	       uy / (double) COORD_SCALE, py));
    	*yloc = py;
        }
    
        return 1;
    }
    
    static int
    load_regis_raw_pixelvector_digit(char const *pixelvector,
    				 unsigned *offset,
    				 int *dx, int *dy, int mul)
    {
        switch (pixelvector[*offset]) {
        case '0':
    	*dx += mul;
    	break;
        case '1':
    	*dx += mul;
    	*dy -= mul;
    	break;
        case '2':
    	*dy -= mul;
    	break;
        case '3':
    	*dx -= mul;
    	*dy -= mul;
    	break;
        case '4':
    	*dx -= mul;
    	break;
        case '5':
    	*dx -= mul;
    	*dy += mul;
    	break;
        case '6':
    	*dy += mul;
    	break;
        case '7':
    	*dx += mul;
    	*dy += mul;
    	break;
        default:
    	return 0;
        }
    
        (*offset)++;
        return 1;
    }
    
    static int
    load_regis_pixel_pixelvector(char const *pixelvector,
    			     int mul,
    			     int origx, int origy,
    			     int *xloc, int *yloc)
    {
        int found = 0;
        int px = 0, py = 0;
        unsigned offset = 0U;
        while (load_regis_raw_pixelvector_digit(pixelvector, &offset,
    					    &px, &py,
    					    mul))
    	found = 1;
        if (pixelvector[offset] != '\0') {
    	TRACE(("DATA_ERROR: ignoring unknown pixel vector digits: \"%s\"\n",
    	       &pixelvector[offset]));
        }
    
        *xloc = origx + px;
        *yloc = origy + py;
    
        return found;
    }
    
    static int
    load_regis_coord_pixelvector(RegisGraphicsContext const *context,
    			     char const *pixelvector,
    			     int origx, int origy,
    			     int *xloc, int *yloc)
    {
        const int mul = (int) (context->temporary_write_controls.pv_multiplier
    			   * COORD_SCALE);
        int found = 0;
        int ux = 0, uy = 0;
        unsigned offset = 0U;
    
        while (load_regis_raw_pixelvector_digit(pixelvector, &offset,
    					    &ux, &uy,
    					    mul))
    	found = 1;
        if (pixelvector[offset] != '\0') {
    	TRACE(("DATA_ERROR: ignoring unknown pixel vector digits: \"%s\"\n",
    	       &pixelvector[offset]));
        } {
    	const int px = SCALE_XCOORD(context, ux, COORD_SCALE);
    	const int py = SCALE_YCOORD(context, uy, COORD_SCALE);
    
    	TRACE(("converted relative X coord %.03f to relative pixel X coord %d (width=%d xoff=%d xdiv=%d)\n",
    	       ux / (double) COORD_SCALE, px, context->width,
    	       context->x_off, context->x_div));
    	*xloc = origx + px;
    
    	TRACE(("converted relative Y coord %.03f to relative pixel Y coord %d (height=%d yoff=%d ydiv=%d)\n",
    	       uy / (double) COORD_SCALE, py, context->height,
    	       context->y_off, context->y_div));
    	*yloc = origy + py;
        }
    
        return found;
    }
    
    static int
    load_regis_coord_pixelvector_step(RegisGraphicsContext const *context,
    				  char const *pixelvector,
    				  unsigned *offset,
    				  int origx, int origy,
    				  int *xloc, int *yloc)
    {
        const int mul = (int) (context->temporary_write_controls.pv_multiplier
    			   * COORD_SCALE);
        int found = 0;
        int ux = 0, uy = 0;
        if (load_regis_raw_pixelvector_digit(pixelvector, offset, &ux, &uy, mul))
    	found = 1;
        if (!found && pixelvector[*offset] != '\0') {
    	TRACE(("DATA_ERROR: ignoring unknown pixel vector digits: \"%s\"\n",
    	       &pixelvector[*offset]));
        } {
    	const int px = SCALE_XCOORD(context, ux, COORD_SCALE);
    	const int py = SCALE_YCOORD(context, uy, COORD_SCALE);
    
    	TRACE(("converted relative X coord %.03f to relative pixel X coord %d (width=%d xoff=%d xdiv=%d)\n",
    	       ux / (double) COORD_SCALE, px, context->width,
    	       context->x_off, context->x_div));
    	*xloc = origx + px;
    
    	TRACE(("converted relative Y coord %.03f to relative pixel Y coord %d (height=%d yoff=%d ydiv=%d)\n",
    	       uy / (double) COORD_SCALE, py, context->height,
    	       context->y_off, context->y_div));
    	*yloc = origy + py;
        }
    
        return found;
    }
    
    static int
    load_regis_write_control(RegisParseState *state,
    			 RegisGraphicsContext const *context,
    			 int cur_x, int cur_y,
    			 int option,
    			 RegisDataFragment *arg,
    			 RegisWriteControls *out)
    {
        TRACE(("checking write control option \"%c\" with arg \"%s\"\n",
    	   option, fragment_to_tempstr(arg)));
        switch (option) {
        case 'A':
        case 'a':
    	TRACE(("write control alternate display method \"%s\"\n",
    	       fragment_to_tempstr(arg)));
    	{
    	    int val;
    	    if (!regis_num_to_int(arg, &val) || val < 0 || val >= 1) {
    		TRACE(("DATA_ERROR: interpreting out of range value as 0 FIXME\n"));
    		break;
    	    }
    	    if (val == 1) {
    		TRACE(("ERROR: blink display method not supported FIXME\n"));
    	    }
    	}
    	break;
        case 'C':
        case 'c':
    	TRACE(("write control compliment writing mode \"%s\"\n",
    	       fragment_to_tempstr(arg)));
    	out->write_style = WRITE_STYLE_COMPLEMENT;
    	break;
        case 'E':
        case 'e':
    	TRACE(("write control erase writing mode \"%s\"\n",
    	       fragment_to_tempstr(arg)));
    	out->write_style = WRITE_STYLE_ERASE;
    	break;
        case 'F':
        case 'f':
    	TRACE(("write control plane write mask \"%s\"\n",
    	       fragment_to_tempstr(arg)));
    	{
    	    int val;
    	    if (!regis_num_to_int(arg, &val) ||
    		val < 0 || val >= (int) context->destination_graphic->valid_registers) {
    		TRACE(("DATA_ERROR: interpreting out of range value as 0 FIXME\n"));
    		out->plane_mask = 0U;
    	    } else {
    		out->plane_mask = (unsigned) val;
    	    }
    	}
    	break;
        case 'I':
        case 'i':
    	TRACE(("write control foreground color \"%s\"\n",
    	       fragment_to_tempstr(arg)));
    	if (!load_regis_regnum_or_colorspec(context, arg, &out->foreground)) {
    	    TRACE(("DATA_ERROR: write control foreground color specifier not recognized: \"%s\"\n",
    		   fragment_to_tempstr(arg)));
    	    return 0;
    	}
    	break;
        case 'L':
        case 'l':
    	TRACE(("write control line width \"%s\" (FIXME: currently ignored)\n",
    	       fragment_to_tempstr(arg)));
    	{
    	    int val;
    	    if (!regis_num_to_int(arg, &val) ||
    		val < 0 || val >= (int) 9) {
    		TRACE(("interpreting out of range value as 1 FIXME\n"));
    		out->line_width = 1U;
    	    } else {
    		out->line_width = (unsigned) val;
    	    }
    	}
    	break;
        case 'M':
        case 'm':
    	TRACE(("write control found pixel multiplication factor \"%s\"\n",
    	       fragment_to_tempstr(arg)));
    	{
    	    int val;
    	    if (!regis_num_to_int(arg, &val) || val <= 0) {
    		TRACE(("interpreting out of range value %d as 1 FIXME\n", val));
    		out->pv_multiplier = 1U;
    	    } else {
    		out->pv_multiplier = (unsigned) val;
    	    }
    	}
    	break;
        case 'N':
        case 'n':
    	TRACE(("write control negative pattern control \"%s\"\n",
    	       fragment_to_tempstr(arg)));
    	{
    	    int val;
    	    if (!regis_num_to_int(arg, &val)) {
    		val = -1;
    	    }
    	    switch (val) {
    	    default:
    		TRACE(("interpreting out of range value %d as 0 FIXME\n", val));
    		out->invert_pattern = 0U;
    		break;
    	    case 0:
    		out->invert_pattern = 0U;
    		break;
    	    case 1:
    		out->invert_pattern = 1U;
    		break;
    	    }
    	}
    	break;
        case 'P':
        case 'p':
    	TRACE(("write control found pattern control \"%s\"\n",
    	       fragment_to_tempstr(arg)));
    	{
    	    RegisDataFragment suboptionset;
    	    RegisDataFragment suboptionarg;
    	    RegisDataFragment item;
    	    char suboption;
    
    	    while (!fragment_consumed(arg)) {
    		if (skip_regis_whitespace(arg))
    		    continue;
    
    		TRACE(("looking for option in \"%s\"\n",
    		       fragment_to_tempstr(arg)));
    		if (extract_regis_parenthesized_data(arg, &suboptionset)) {
    		    TRACE(("got write pattern suboptionset: \"%s\"\n",
    			   fragment_to_tempstr(&suboptionset)));
    		    while (!fragment_consumed(&suboptionset)) {
    			skip_regis_whitespace(&suboptionset);
    			if (extract_regis_option(&suboptionset, &suboption,
    						 &suboptionarg)) {
    			    skip_regis_whitespace(&suboptionarg);
    			    TRACE(("inspecting write pattern suboption \"%c\" with value \"%s\"\n",
    				   suboption,
    				   fragment_to_tempstr(&suboptionarg)));
    			    switch (suboption) {
    			    case 'M':
    			    case 'm':
    				TRACE(("found pattern multiplier \"%s\"\n",
    				       fragment_to_tempstr(&suboptionarg)));
    				{
    				    RegisDataFragment num;
    				    int val;
    
    				    if (extract_regis_num(&suboptionarg,
    							  &num)) {
    					if (!regis_num_to_int(&num, &val)
    					    || val < 1) {
    					    TRACE(("interpreting out of range pattern multiplier \"%s\" as 2 FIXME\n",
    						   fragment_to_tempstr(&num)));
    					    out->pattern_multiplier = 2U;
    					} else {
    					    out->pattern_multiplier =
    						(unsigned) val;
    					}
    					skip_regis_whitespace(&suboptionarg);
    				    }
    
    				    if (!fragment_consumed(&suboptionarg)) {
    					TRACE(("DATA_ERROR: unknown content after pattern multiplier \"%s\"\n",
    					       fragment_to_tempstr(&suboptionarg)));
    					return 0;
    				    }
    				}
    				break;
    			    default:
    				TRACE(("DATA_ERROR: unknown ReGIS write pattern suboption '%c' arg \"%s\"\n",
    				       suboption,
    				       fragment_to_tempstr(&suboptionarg)));
    				return 0;
    			    }
    			    continue;
    			}
    
    			TRACE(("DATA_ERROR: skipping unknown token in pattern control suboptionset (expecting option): \"%s\"\n",
    			       fragment_to_tempstr(&suboptionset)));
    			pop_fragment(&suboptionset);
    		    }
    		    continue;
    		}
    
    		TRACE(("looking for int in \"%s\"\n",
    		       fragment_to_tempstr(arg)));
    		if (extract_regis_num(arg, &item)) {
    		    if (peek_fragment(&item) == '0' ||
    			peek_fragment(&item) == '1') {
    			unsigned pattern = 0U;
    			unsigned bitcount;
    
    			TRACE(("converting pattern bits \"%s\"\n",
    			       fragment_to_tempstr(&item)));
    			for (bitcount = 0;; bitcount++) {
    			    char ch = pop_fragment(&item);
    			    if (ch == '\0')
    				break;
    			    switch (ch) {
    			    case '0':
    				if (bitcount < MAX_PATTERN_BITS) {
    				    pattern <<= 1U;
    				}
    				break;
    			    case '1':
    				if (bitcount < MAX_PATTERN_BITS) {
    				    pattern <<= 1U;
    				    pattern |= 1U;
    				}
    				break;
    			    default:
    				TRACE(("DATA_ERROR: unknown ReGIS write pattern bit value \"%c\"\n",
    				       ch));
    				return 0;
    			    }
    			}
    
    			if (bitcount > 0U) {
    			    unsigned extrabits;
    
    			    for (extrabits = 0;
    				 bitcount + extrabits < MAX_PATTERN_BITS;
    				 extrabits++) {
    				if (pattern & (1U << (bitcount - 1U))) {
    				    pattern <<= 1U;
    				    pattern |= 1U;
    				} else {
    				    pattern <<= 1U;
    				}
    			    }
    			}
    
    			out->pattern = pattern;
    		    } else {
    			int val;
    
    			TRACE(("converting pattern id \"%s\"\n",
    			       fragment_to_tempstr(&item)));
    			if (!regis_num_to_int(&item, &val))
    			    val = -1;
    			switch (val) {	/* FIXME: exponential allowed? */
    			case 0:
    			    out->pattern = 0x00;	/* solid bg */
    			    break;
    			case 1:
    			    out->pattern = 0xff;	/* solid fg */
    			    break;
    			case 2:
    			    out->pattern = 0xf0;	/* dash */
    			    break;
    			case 3:
    			    out->pattern = 0xe4;	/* dash dot */
    			    break;
    			case 4:
    			    out->pattern = 0xaa;	/* dot */
    			    break;
    			case 5:
    			    out->pattern = 0xea;	/* dash dot dot */
    			    break;
    			case 6:
    			    out->pattern = 0x88;	/* sparse dot */
    			    break;
    			case 7:
    			    out->pattern = 0x84;	/* asymmetric sparse dot */
    			    break;
    			case 8:
    			    out->pattern = 0xc8;	/* sparse dash dot */
    			    break;
    			case 9:
    			    out->pattern = 0x86;	/* sparse dot dash */
    			    break;
    			default:
    			    TRACE(("DATA_ERROR: unknown ReGIS standard write pattern \"%d\"\n",
    				   val));
    			    return 0;
    			}
    		    }
    
    		    TRACE(("final pattern is %02x\n", out->pattern));
    		    continue;
    		}
    		skip_regis_whitespace(arg);
    
    		TRACE(("DATA_ERROR: skipping unknown token in pattern suboption: \"%s\"\n",
    		       fragment_to_tempstr(arg)));
    		pop_fragment(arg);
    	    }
    	}
    	break;
        case 'R':
        case 'r':
    	TRACE(("write control switch to replacement writing mode \"%s\"\n",
    	       fragment_to_tempstr(arg)));
    	out->write_style = WRITE_STYLE_REPLACE;
    	break;
        case 'S':
        case 's':
    	TRACE(("write control shading control \"%s\"\n",
    	       fragment_to_tempstr(arg)));
    	{
    	    RegisDataFragment suboptionset;
    	    RegisDataFragment suboptionarg;
    	    RegisDataFragment item;
    	    char suboption;
    	    char shading_character = '\0';
    	    unsigned reference_dim = WRITE_SHADING_REF_Y;
    	    /* FIXME: are relative offsets additive? */
    	    int ref_x = cur_x, ref_y = cur_y;
    	    int shading_enabled = 0;
    
    	    while (!fragment_consumed(arg)) {
    		if (skip_regis_whitespace(arg))
    		    continue;
    
    		if (extract_regis_string(arg, state->temp, state->templen)) {
    		    TRACE(("found fill char \"%s\"\n", state->temp));
    		    /* FIXME: allow longer strings, ignore extra chars, or treat as error? */
    		    if (strlen(state->temp) != 1) {
    			TRACE(("DATA_ERROR: expected exactly one char in fill string FIXME\n"));
    			return 0;
    		    }
    		    shading_character = state->temp[0];
    		    shading_enabled = 1;
    		    TRACE(("shading character is: '%c' (%d)\n",
    			   shading_character, (int) shading_character));
    		    continue;
    		}
    
    		if (extract_regis_parenthesized_data(arg, &suboptionset)) {
    		    skip_regis_whitespace(&suboptionset);
    		    TRACE(("got shading control suboptionset: \"%s\"\n",
    			   fragment_to_tempstr(&suboptionset)));
    		    while (!fragment_consumed(&suboptionset)) {
    			if (skip_regis_whitespace(&suboptionset))
    			    continue;
    			if (extract_regis_option(&suboptionset, &suboption,
    						 &suboptionarg)) {
    			    TRACE(("inspecting write shading suboption \"%c\" with value \"%s\"\n",
    				   suboption,
    				   fragment_to_tempstr(&suboptionarg)));
    			    switch (suboption) {
    			    case 'X':
    			    case 'x':
    				TRACE(("found horizontal shading suboption \"%s\"\n",
    				       fragment_to_tempstr(&suboptionarg)));
    				if (!fragment_consumed(&suboptionarg)) {
    				    TRACE(("DATA_ERROR: unexpected value to horizontal shading suboption FIXME\n"));
    				    return 0;
    				}
    				reference_dim = WRITE_SHADING_REF_X;
    				shading_enabled = 1;
    				break;
    			    default:
    				TRACE(("DATA_ERROR: unknown ReGIS write pattern suboption '%c' arg \"%s\"\n",
    				       suboption,
    				       fragment_to_tempstr(&suboptionarg)));
    				return 0;
    			    }
    			    continue;
    			}
    
    			TRACE(("DATA_ERROR: skipping unknown token in shading control suboptionset (expecting option): \"%s\"\n",
    			       fragment_to_tempstr(&suboptionset)));
    			pop_fragment(&suboptionset);
    		    }
    		    continue;
    		}
    
    		if (extract_regis_extent(arg, &item)) {
    		    TRACE(("found extent in shading option curr=%d,%d ref=%d,%d\n",
    			   cur_x, cur_y, ref_x, ref_y));
    		    if (!load_regis_coord_extent(context,
    						 fragment_to_tempstr(&item),
    						 ref_x, ref_y,
    						 &ref_x, &ref_y)) {
    			TRACE(("DATA_ERROR: unable to parse extent in write shading option '%c': \"%s\"\n",
    			       option, fragment_to_tempstr(&item)));
    			return 0;
    		    }
    		    TRACE(("shading reference = %d,%d (%s)\n", ref_x, ref_y,
    			   ((reference_dim == WRITE_SHADING_REF_X)
    			    ? "X"
    			    : "Y")));
    		    continue;
    		}
    
    		if (extract_regis_num(arg, &item)) {
    		    if (!regis_num_to_int(&item, &shading_enabled)) {
    			TRACE(("DATA_ERROR: unable to parse int in write shading option '%c': \"%s\"\n",
    			       option, fragment_to_tempstr(&item)));
    			return 0;
    		    }
    		    if (shading_enabled < 0 || shading_enabled > 1) {
    			TRACE(("interpreting out of range value %d as 0 FIXME\n",
    			       shading_enabled));
    			shading_enabled = 0;
    		    }
    		    TRACE(("shading enabled = %d\n", shading_enabled));
    		    continue;
    		}
    
    		if (skip_regis_whitespace(arg)) {
    		    continue;
    		}
    
    		TRACE(("DATA_ERROR: skipping unknown token in shade suboption: \"%s\"\n",
    		       fragment_to_tempstr(arg)));
    		pop_fragment(arg);
    	    }
    
    	    if (shading_enabled) {
    		out->shading_enabled = 1U;
    		out->shading_reference_dim = reference_dim;
    		out->shading_reference = ((reference_dim == WRITE_SHADING_REF_X)
    					  ? ref_x
    					  : ref_y);
    		out->shading_character = shading_character;
    		TRACE(("final shading state: enabled, dim=%d ref=%d, char=%c\n",
    		       out->shading_reference_dim, out->shading_reference,
    		       out->shading_character));
    	    } else {
    		/* FIXME: confirm there is no effect if shading isn't enabled
    		 * in the same command
    		 */
    		out->shading_enabled = 0U;
    		TRACE(("final shading state: shading disabled\n"));
    	    }
    	}
    	break;
        case 'V':
        case 'v':
    	TRACE(("write control switch to overlay writing mode \"%s\"\n",
    	       fragment_to_tempstr(arg)));
    	out->write_style = WRITE_STYLE_OVERLAY;
    	break;
        default:
    	TRACE(("DATA_ERROR: ignoring unknown ReGIS write option \"%c\" arg \"%s\"\n",
    	       option, fragment_to_tempstr(arg)));
    	return 0;
        }
    
        return 1;
    }
    
    static int
    load_regis_write_control_set(RegisParseState *state,
    			     RegisGraphicsContext const *context,
    			     int cur_x, int cur_y,
    			     RegisDataFragment *controls,
    			     RegisWriteControls *out)
    {
        RegisDataFragment optionset;
        RegisDataFragment arg;
        char option;
    
        while (!fragment_consumed(controls)) {
    	if (skip_regis_whitespace(controls))
    	    continue;
    
    	if (extract_regis_parenthesized_data(controls, &optionset)) {
    	    TRACE(("got write control optionset: \"%s\"\n",
    		   fragment_to_tempstr(&optionset)));
    	    while (!fragment_consumed(&optionset)) {
    		skip_regis_whitespace(&optionset);
    		if (extract_regis_option(&optionset, &option, &arg)) {
    		    skip_regis_whitespace(&arg);
    		    TRACE(("got write control option and value: \"%c\" \"%s\"\n",
    			   option, fragment_to_tempstr(&arg)));
    		    if (!load_regis_write_control(state, context,
    						  cur_x, cur_y,
    						  option, &arg, out)) {
    			return 0;
    		    }
    		    continue;
    		}
    
    		TRACE(("DATA_ERROR: skipping unknown token in write control optionset (expecting option): \"%s\"\n",
    		       fragment_to_tempstr(&optionset)));
    		pop_fragment(&optionset);
    	    }
    	    continue;
    	}
    
    	TRACE(("DATA_ERROR: skipping unknown token in write controls (expecting optionset): \"%s\"\n",
    	       fragment_to_tempstr(controls)));
    	pop_fragment(controls);
        }
    
        return 1;
    }
    
    static void
    init_regis_write_controls(int terminal_id, unsigned all_planes,
    			  RegisWriteControls *controls)
    {
        controls->pv_multiplier = 1U;
        controls->pattern = 0xff;	/* solid */
        controls->pattern_multiplier = 2U;
        controls->invert_pattern = 0U;
        controls->plane_mask = all_planes;
        controls->write_style = WRITE_STYLE_OVERLAY;
        switch (terminal_id) {
        case 125:			/* FIXME: verify */
        case 240:			/* FIXME: verify */
        case 241:			/* FIXME: verify */
        case 330:
    	controls->foreground = 3U;
    	break;
        case 340:
        default:
    	controls->foreground = 7U;
    	break;
        case 382:
    	controls->foreground = 1U;	/* FIXME: verify */
    	break;
        }
        controls->shading_enabled = 0U;
        controls->shading_character = '\0';
        controls->shading_reference = 0;	/* no meaning if shading is disabled */
        controls->shading_reference_dim = WRITE_SHADING_REF_NONE;
        controls->line_width = 1U;
        /* FIXME: add the rest */
    }
    
    static void
    map_regis_graphics_pages(XtermWidget xw, RegisGraphicsContext *context)
    {
        const int charrow = 0;
        const int charcol = 0;
        unsigned old_display_id = ~0U;
    
        if (context->destination_graphic)
    	context->destination_graphic->hidden = 1;
        if (context->display_graphic) {
    	context->display_graphic->hidden = 1;
    	old_display_id = context->display_graphic->id;
        }
    
        context->destination_graphic =
    	get_new_or_matching_graphic(xw,
    				    charrow, charcol,
    				    context->width,
    				    context->height,
    				    context->destination_page);
        if (context->destination_graphic) {
    	context->destination_graphic->hidden = 1;
    	context->destination_graphic->valid = 1;
        }
    
        context->display_graphic =
    	get_new_or_matching_graphic(xw,
    				    charrow, charcol,
    				    context->width,
    				    context->height,
    				    context->display_page);
        if (context->display_graphic) {
    	context->display_graphic->hidden = 0;
    	if (old_display_id != context->display_graphic->id) {
    	    if (!context->display_graphic->valid) {
    		draw_solid_rectangle(context->display_graphic, 0, 0,
    				     context->width, context->height,
    				     context->background);
    	    }
    	    context->display_graphic->dirty = 1;
    	    context->force_refresh = 1;
    	    /* FIXME: This isn't really enough.  If there are holes in the new
    	     * graphic they should be cleared and set to the text from the same
    	     * page.  But we don't have pages for text in xterm (the alt buffer
    	     * is similar though).
    	     */
    	}
    	context->display_graphic->valid = 1;
        }
    
        TRACE(("using graphics destination=[%d -> %u] display=[%d -> %u]\n",
    	   context->destination_page,
    	   (context->destination_graphic
    	    ? context->destination_graphic->id
    	    : 0U),
    	   context->display_page,
    	   (context->display_graphic
    	    ? context->display_graphic->id
    	    : 0U)));
    }
    
    static void
    copy_regis_write_controls(RegisWriteControls const *src,
    			  RegisWriteControls *dst)
    {
        dst->pv_multiplier = src->pv_multiplier;
        dst->pattern = src->pattern;
        dst->pattern_multiplier = src->pattern_multiplier;
        dst->invert_pattern = src->invert_pattern;
        dst->foreground = src->foreground;
        dst->plane_mask = src->plane_mask;
        dst->write_style = src->write_style;
        dst->shading_enabled = src->shading_enabled;
        dst->shading_character = src->shading_character;
        dst->shading_reference = src->shading_reference;
        dst->shading_reference_dim = src->shading_reference_dim;
        dst->line_width = src->line_width;
    }
    
    static void
    init_regis_text_controls(RegisTextControls *controls)
    {
        controls->alphabet_num = 0U;	/* built-in */
        controls->character_set_l = 0U;	/* ASCII */
        controls->character_set_r = 0U;	/* Latin-1 */
        get_standard_character_size(1, &controls->character_display_w,
    				&controls->character_display_h,
    				&controls->character_unit_cell_w,
    				&controls->character_unit_cell_h,
    				&controls->character_inc_x,
    				&controls->character_inc_y);
        controls->string_rotation = 0;
        controls->character_rotation = 0;
        controls->slant = 0;
    }
    
    static void
    copy_regis_text_controls(RegisTextControls const *src, RegisTextControls *dst)
    {
        dst->alphabet_num = src->alphabet_num;
        dst->character_set_l = src->character_set_l;
        dst->character_set_r = src->character_set_r;
        dst->character_display_w = src->character_display_w;
        dst->character_display_h = src->character_display_h;
        dst->character_unit_cell_w = src->character_unit_cell_w;
        dst->character_unit_cell_h = src->character_unit_cell_h;
        dst->character_inc_x = src->character_inc_x;
        dst->character_inc_y = src->character_inc_y;
        dst->string_rotation = src->string_rotation;
        dst->character_rotation = src->character_rotation;
        dst->slant = src->slant;
    }
    
    static void
    init_regis_alphabets(RegisGraphicsContext *context)
    {
        unsigned alphabet_index;
    
        for (alphabet_index = 0U; alphabet_index < MAX_REGIS_ALPHABETS;
    	 alphabet_index++) {
    	context->alphabets[alphabet_index].alphabet_num = INVALID_ALPHABET_NUM;
    	context->alphabets[alphabet_index].pixw = 0U;
    	context->alphabets[alphabet_index].pixh = 0U;
    	context->alphabets[alphabet_index].name[0] = '\0';
    	context->alphabets[alphabet_index].fontname[0] = '\0';
    	context->alphabets[alphabet_index].use_font = 0;
    	context->alphabets[alphabet_index].bytes = NULL;
        }
    }
    
    static void
    init_regis_graphics_context(int terminal_id, int width, int height,
    			    unsigned max_colors, const char *builtin_font,
    			    RegisGraphicsContext *context)
    {
        context->destination_graphic = NULL;
        context->display_graphic = NULL;
        context->display_page = 0U;
        context->destination_page = 0U;
        context->terminal_id = terminal_id;
    
        /* reset addressing / clear user coordinates */
        context->width = width;
        context->height = height;
        context->x_off = 0;
        context->y_off = 0;
        context->x_div = width - 1;
        context->y_div = height - 1;
    
        /*
         * Generate a mask covering all valid color register address bits
         * (but don't bother past 2**16).
         */
        context->all_planes = max_colors;
        context->all_planes--;
        context->all_planes |= 1U;
        context->all_planes |= context->all_planes >> 1U;
        context->all_planes |= context->all_planes >> 2U;
        context->all_planes |= context->all_planes >> 4U;
        context->all_planes |= context->all_planes >> 8U;
    
        context->builtin_font = builtin_font;
    
        init_regis_write_controls(terminal_id, context->all_planes,
    			      &context->persistent_write_controls);
        copy_regis_write_controls(&context->persistent_write_controls,
    			      &context->temporary_write_controls);
    
        init_regis_text_controls(&context->persistent_text_controls);
        context->current_text_controls = &context->persistent_text_controls;
        init_regis_alphabets(context);
    
        context->multi_input_mode = 0;
        /* FIXME: coordinates */
        /* FIXME: scrolling */
        context->background = 0U;
        /* FIXME: input cursor location */
        /* FIXME: input cursor style */
        context->graphics_output_cursor_x = 0;
        context->graphics_output_cursor_y = 0;
        /* FIXME: output cursor style */
    
        context->force_refresh = 0;
    }
    
    static int
    parse_regis_command(RegisParseState *state)
    {
        char ch;
    
        if (!extract_regis_command(&state->input, &ch))
    	return 0;
    
        switch (ch) {
        case 'C':
        case 'c':
    	/* Curve
    
    	 * C
    	 * (A)  # set the arc length in degrees (+ or nothing for
    	 *      # counter-clockwise, - for clockwise, rounded to the
    	 *      # closest integer degree)
    	 * (B)  # begin closed curve sequence (must have at least two
    	 *      # values; this option can not be nested)
    	 * (C)  # position is the center, current location is the
    	 *      # circumference (stays in effect until next command)
    	 * (E)  # end curve sequence (drawing is performed here)
    	 * (S)  # begin open curve sequence
    	 * (W)  # temporary write options (see write command)
    	 * []  # center if (C), otherwise point on circumference
    	 * []...  # if between (B) and (E)
    	 * ...  # if between (B) and (E)
    	 */
    	TRACE(("found ReGIS command \"%c\" (curve)\n", ch));
    	state->command = 'c';
    	state->curve_mode = CURVE_POSITION_ARC_EDGE;
    	state->arclen = 360;
    	state->num_points = 0U;
    	break;
        case 'F':
        case 'f':
    	/* Fill
    
    	 * F
    	 * (V)  # polygon (see vector command)
    	 * (C)  # curve (see curve command)
    	 * (W)  # temporary write options (see write command)
    	 */
    	TRACE(("found ReGIS command \"%c\" (filled polygon)\n", ch));
    	state->command = 'f';
    	break;
        case 'L':
        case 'l':
    	/* Load
    
    	 * L
    	 * (A)  # set alphabet number or name
    	 * (F)"fontname"  # load from font (xterm extension)
    	 * (S)[w,h]  # set glyph size (xterm extension)
    	 * "ascii"xx,xx,xx,xx,xx,xx,xx,xx  # pixel values
    	 */
    	TRACE(("found ReGIS command \"%c\" (load charset)\n", ch));
    	state->command = 'l';
    	break;
        case 'P':
        case 'p':
    	/* Position
    
    	 * P
    	 * (B)  # begin bounded position stack (last point returns to first)
    	 * (E)  # end position stack
    	 * (P)  # select graphics page for the input and output cursors
    	 * (S)  # begin unbounded position stack
    	 * (W)  # temporary write options (see write command)
    	 *   # move: 0 == right, 1 == upper right, ..., 7 == lower right
    	 * []  # move to position (X, Y, or both)
    	 *
    	 * Note the stack does not need to be ended before the next command
    	 * Note: maximum depth is 16 levels
    	 */
    	TRACE(("found ReGIS command \"%c\" (position)\n", ch));
    	state->command = 'p';
    	break;
        case 'R':
        case 'r':
    	/* Report
    
    	 * R
    	 * (E)  # parse error
    	 * (I)  # set input mode (0 == one-shot, 1 == multiple) (always returns CR)
    	 * (L)  # current alphabet number and name
    	 * (M()  # macrograph contents
    	 * (M(=)  # macrograph storage (free bytes of total bytes)
    	 * (P)  # absolute output cursor position
    	 * (P(I))  # interactive locator mode (in one-shot or multiple mode)
    	 * (P(I[xmul,ymul]))  # interactive locator mode with arrow key movement multipliers
    	 */
    	TRACE(("found ReGIS command \"%c\" (report status)\n", ch));
    	state->command = 'r';
    	break;
        case 'S':
        case 's':
    	/* Screen
    
    	 * S
    	 * (A[][])  # adjust screen coordinates
    	 * (C  # 0 (cursor output off), 1 (cursor output on)
    	 * (E)  # erase to background color, resets shades, curves, and stacks
    	 * (F)  # print the graphic and erase the screen (DECprint extension)
    	 * (H(P)[][)
    	 * (I)  # set the background to a specific register
    	 * (I())  # set the background to the register closest to an "RGB" color
    	 * (I(RGB))  # set the background to the register closest to an RGB triplet (RLogin extension)
    	 * (I(HLS))  # set the background to the register closest to an HLS triplet
    	 * (I(L))  # set the background to the register closest to a grayscale value
    	 * (M()...)  # codes are D (black), R (red), G (green), B (blue), C (cyan), Y (yellow), M (magenta), W (white) (sets color and grayscale registers)
    	 * (M(A)...)  # codes are D (black), R (red), G (green), B (blue), C (cyan), Y (yellow), M (magenta), W (white) (sets color registers only)
    	 * (M(RGB)...)  # 0..100, 0..100, 0..100 (sets color and grayscale registers) (RLogin extension)
    	 * (M(ARGB)...)  # 0..100, 0..100, 0..100 (sets color registers only) (RLogin extension)
    	 * (M(HLS)...)  # 0..360, 0..100, 0..100 (sets color and grayscale registers)
    	 * (M(AHLS)...)  # 0..360, 0..100, 0..100 (sets color registers only)
    	 * (M(L)...)  # level is 0 ... 100 (sets grayscale registers only)
    	 * (P)  # 0 (default) or 1
    	 * (S()  # scale screen output by scale (default 1, VT125:max=2, VT3x0:unsupported) FIXME
    	 * (S(X)  # scale screen output horizontally by scale (default 1, VT125:max=2, VT3x0:unsupported) FIXME
    	 * (S(Y)  # scale screen output vertically by scale (default 1, VT125:max=2, VT3x0:unsupported) FIXME
    	 * (T(