1e0a2b6dfSmrg#!/usr/bin/env perl
204b94745Smrg# $XTermId: paste64.pl,v 1.14 2018/11/20 01:05:55 tom Exp $
320d2c4d2Smrg# -----------------------------------------------------------------------------
420d2c4d2Smrg# this file is part of xterm
5d522f475Smrg#
6f2e35a3aSmrg# Copyright 2006-2014,2018 by Thomas E. Dickey
701037d57Smrg#
820d2c4d2Smrg#                         All Rights Reserved
901037d57Smrg#
1020d2c4d2Smrg# Permission is hereby granted, free of charge, to any person obtaining a
1120d2c4d2Smrg# copy of this software and associated documentation files (the
1220d2c4d2Smrg# "Software"), to deal in the Software without restriction, including
1320d2c4d2Smrg# without limitation the rights to use, copy, modify, merge, publish,
1420d2c4d2Smrg# distribute, sublicense, and/or sell copies of the Software, and to
1520d2c4d2Smrg# permit persons to whom the Software is furnished to do so, subject to
1620d2c4d2Smrg# the following conditions:
1701037d57Smrg#
1820d2c4d2Smrg# The above copyright notice and this permission notice shall be included
1920d2c4d2Smrg# in all copies or substantial portions of the Software.
2001037d57Smrg#
2120d2c4d2Smrg# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
2220d2c4d2Smrg# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
2320d2c4d2Smrg# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
2420d2c4d2Smrg# IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE LIABLE FOR ANY
2520d2c4d2Smrg# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2620d2c4d2Smrg# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2720d2c4d2Smrg# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2801037d57Smrg#
2920d2c4d2Smrg# Except as contained in this notice, the name(s) of the above copyright
3020d2c4d2Smrg# holders shall not be used in advertising or otherwise to promote the
3120d2c4d2Smrg# sale, use or other dealings in this Software without prior written
3220d2c4d2Smrg# authorization.
3320d2c4d2Smrg# -----------------------------------------------------------------------------
34d522f475Smrg# Test the paste64 option of xterm.
35d522f475Smrg
36d522f475Smrguse strict;
37e0a2b6dfSmrguse warnings;
38e0a2b6dfSmrg
39d522f475Smrguse Term::ReadKey;
40d522f475Smrguse IO::Handle;
41d522f475Smrguse MIME::Base64;
42d522f475Smrg
43d522f475Smrgour $target = "";
44d522f475Smrg
45d522f475Smrgsub to_hex($) {
4601037d57Smrg    my $value  = $_[0];
4701037d57Smrg    my $result = "";
4801037d57Smrg    my $n;
4901037d57Smrg
5001037d57Smrg    for ( $n = 0 ; $n < length($value) ; ++$n ) {
5101037d57Smrg        $result .= sprintf( "%02X", ord substr( $value, $n, 1 ) );
5201037d57Smrg    }
5301037d57Smrg    return $result;
54d522f475Smrg}
55d522f475Smrg
56d522f475Smrgsub show_string($) {
5701037d57Smrg    my $value = $_[0];
5801037d57Smrg    my $n;
5901037d57Smrg
6001037d57Smrg    my $result = "";
6101037d57Smrg    for ( $n = 0 ; $n < length($value) ; $n += 1 ) {
6201037d57Smrg        my $c = ord substr( $value, $n, 1 );
6301037d57Smrg        if ( $c == ord '\\' ) {
6401037d57Smrg            $result .= "\\\\";
6501037d57Smrg        }
6601037d57Smrg        elsif ( $c == 0x1b ) {
6701037d57Smrg            $result .= "\\E";
6801037d57Smrg        }
6901037d57Smrg        elsif ( $c == 0x7f ) {
7001037d57Smrg            $result .= "^?";
7101037d57Smrg        }
7201037d57Smrg        elsif ( $c == 32 ) {
7301037d57Smrg            $result .= "\\s";
7401037d57Smrg        }
7501037d57Smrg        elsif ( $c < 32 ) {
7601037d57Smrg            $result .= sprintf( "^%c", $c + 64 );
7701037d57Smrg        }
7801037d57Smrg        elsif ( $c > 128 ) {
7901037d57Smrg            $result .= sprintf( "\\%03o", $c );
8001037d57Smrg        }
8101037d57Smrg        else {
8201037d57Smrg            $result .= chr($c);
8301037d57Smrg        }
8401037d57Smrg    }
8501037d57Smrg
8601037d57Smrg    printf "%s\r\n", $result;
87d522f475Smrg}
88d522f475Smrg
89d522f475Smrgsub get_reply($) {
9001037d57Smrg    my $command = $_[0];
9101037d57Smrg    my $reply   = "";
9201037d57Smrg
9301037d57Smrg    printf "send: ";
9401037d57Smrg    show_string($command);
9501037d57Smrg
9601037d57Smrg    print STDOUT $command;
9701037d57Smrg    autoflush STDOUT 1;
9801037d57Smrg    while (1) {
9901037d57Smrg        my $test = ReadKey 1;
10001037d57Smrg        last if not defined $test;
10101037d57Smrg
10201037d57Smrg        #printf "%d:%s\r\n", length($reply), to_hex($test);
10301037d57Smrg        $reply .= $test;
10401037d57Smrg    }
10501037d57Smrg    return $reply;
106d522f475Smrg}
107d522f475Smrg
108d522f475Smrgsub get_paste() {
10901037d57Smrg    my $reply = get_reply( "\x1b]52;" . $target . ";?\x1b\\" );
110d522f475Smrg
11101037d57Smrg    printf "read: ";
11201037d57Smrg    show_string($reply);
113d522f475Smrg
11401037d57Smrg    my $data = $reply;
11501037d57Smrg    $data =~ s/^\x1b]52;[[:alnum:]]*;//;
11601037d57Smrg    $data =~ s/\x1b\\$//;
11701037d57Smrg    printf "chop: ";
11801037d57Smrg    show_string($data);
119d522f475Smrg
12001037d57Smrg    $data = decode_base64($data);
12101037d57Smrg    printf "data: ";
12201037d57Smrg    show_string($data);
123d522f475Smrg}
124d522f475Smrg
125d522f475Smrgsub put_paste() {
12601037d57Smrg    ReadMode 1;
127d522f475Smrg
12801037d57Smrg    printf "data: ";
12901037d57Smrg    my $data = ReadLine 0;
13001037d57Smrg    chomp $data;
13101037d57Smrg    ReadMode 5;
132d522f475Smrg
13301037d57Smrg    $data = encode_base64($data);
13401037d57Smrg    chomp $data;
13501037d57Smrg    printf "data: ";
13601037d57Smrg    show_string($data);
137d522f475Smrg
13801037d57Smrg    my $send = "\x1b]52;" . $target . ";" . $data . "\x1b\\";
139d522f475Smrg
14001037d57Smrg    printf "send: ";
14101037d57Smrg    show_string($send);
14201037d57Smrg    print STDOUT $send;
14301037d57Smrg    autoflush STDOUT 1;
144d522f475Smrg}
145d522f475Smrg
146d522f475Smrgsub set_target() {
14701037d57Smrg    ReadMode 1;
148d522f475Smrg
14901037d57Smrg    printf "target: ";
15001037d57Smrg    $target = ReadLine 0;
151f2e35a3aSmrg    $target =~ s/[^cps01234567]//g;
15201037d57Smrg    ReadMode 5;
15301037d57Smrg    printf "result: %s\r\n", $target;
154d522f475Smrg}
155d522f475Smrg
15601037d57SmrgReadMode 5, 'STDIN';    # allow single-character inputs
157d522f475Smrgwhile (1) {
15801037d57Smrg    my $cmd;
15901037d57Smrg
16001037d57Smrg    printf "\r\nCommand (? for help):";
16101037d57Smrg    $cmd = ReadKey 0;
16201037d57Smrg    if ( $cmd eq "?" ) {
16301037d57Smrg        printf "\r\np=put selection,"
16401037d57Smrg          . " g=get selection,"
16501037d57Smrg          . " q=quit,"
16601037d57Smrg          . " r=reset target,"
16701037d57Smrg          . " s=set target\r\n";
16801037d57Smrg    }
16901037d57Smrg    elsif ( $cmd eq "p" ) {
17001037d57Smrg        printf " ...put selection\r\n";
17101037d57Smrg        put_paste();
17201037d57Smrg    }
17301037d57Smrg    elsif ( $cmd eq "g" ) {
17401037d57Smrg        printf " ...get selection\r\n";
17501037d57Smrg        get_paste();
17601037d57Smrg    }
17701037d57Smrg    elsif ( $cmd eq "q" ) {
17801037d57Smrg        printf " ...quit\r\n";
17901037d57Smrg        last;
18001037d57Smrg    }
18101037d57Smrg    elsif ( $cmd eq "r" ) {
18201037d57Smrg        printf " ...reset\r\n";
18301037d57Smrg        $target = "";
18401037d57Smrg    }
18501037d57Smrg    elsif ( $cmd eq "s" ) {
18601037d57Smrg        printf " ...set target\r\n";
18701037d57Smrg        set_target();
18801037d57Smrg    }
189d522f475Smrg}
19001037d57SmrgReadMode 0, 'STDIN';    # Reset tty mode before exiting
191