Did I miss a reason for the alternative?   Because if you add a caching
layer this approach has been working for me for decades.  I rewrote
dired in perl just because perl was everywhere and I could.  I've been
dragging the perl one around since at least 1990 and it worked for me
on pretty much any version of Unix.  I think MacOS isn't supported but
I'm sure it could be.

To avoid calling tput over and over again, I cached the output for each
terminal and then just evaled the cache which sets a bunch of variables
to the escapes I needed.

It performed just fine on 20mhz SPARCstations so I'm sort of wondering
why the solution for the problem isn't good enough.

# Dig out all the terminal info so we know the escape chars for this terminal.
sub terminal_init
{
        local($term) = "$ENV{'HOME'}/.term/$ENV{'TERM'}";
        local($i) = 0;

        $| = 1;
        @pids = ();
        $SIG{TERM} = sub { exit(0); };
        $SIG{PIPE} = 'IGNORE';
        # RedHat 5.0 seems to get this wrong somehow.
        #chop($tc_rows = `tput lines`);
        #chop($tc_cols = `tput cols`);
        open(STTY, "stty -a|");
        while (defined($_ = <STTY>)) {
                last if /rows = \d/ || /\d rows/ || /rows \d/;
        }
        close(STTY);
        #speed 9600 baud; rows 58; columns 80; line = 0;
        #speed 9600 baud; 47 rows; 80 columns;
        #rows = 66; columns = 80
        $tc_cols = 0;
        if (/rows (\d+); columns (\d+);/) {
                $tc_rows = $1;
                $tc_cols = $2;
        } elsif (/(\d+) rows; (\d+) columns;/) {
                $tc_rows = $1;
                $tc_cols = $2;
        } elsif (/rows = (\d+); columns = (\d+)/) {
                $tc_rows = $1;
                $tc_cols = $2;
        }
        if ($tc_cols == 0) {
                die "Can't get terminal settings.\n";
        }
        $half_of_screen = int($tc_rows / 2);

        # it's cached, go grab it.
        if (-f $term) {
                open(T, $term);
                @t = <T>;
                close(T);
                eval "@t";
                &ttyraw;
                return unless $i < $tc_rows;
        }

        print "Getting terminal info just this once and saving it...";
        mkdir("$ENV{'HOME'}/.term", 0755);
        open(T, ">$term");
        $tc_smcup = `tput smcup`;
        $tc_rmcup = `tput rmcup`;
        $tc_bold = `tput bold`;
        $tc_normal = `tput sgr0`;
        $tc_clear = `tput clear`;
        $tc_clreos = `tput ed`;
        $tc_clreol = `tput el`;

        if ($tc_cols < 60) {
                die "$0: needs 60 columns";
        }
        if (length($tc_clreos) == 0) {
                die "$0: needs clear to end of screen";
        }
        if (length($tc_clreol) == 0) {
                die "$0: needs clear to end of line";
        }

        print T "\$tc_smcup = \"$tc_smcup\";\n";
        print T "\$tc_rmcup = \"$tc_rmcup\";\n";
        print T "\$tc_bold = \"$tc_bold\";\n";
        print T "\$tc_normal = \"$tc_normal\";\n";
        print T "\$tc_clear = \"$tc_clear\";\n";
        print T "\$tc_clreol = \"$tc_clreol\";\n";
        print T "\$tc_clreos = \"$tc_clreos\";\n";

        for ($i = 0; $i < $tc_rows; ++$i) {
                $left[$i] = `tput cup $i 0`;
                print T '$left[' . "$i] = \"" . $left[$i] . "\";\n";
                if ($i < $half_of_screen) {
                        $middle[$i] = `tput cup $i 44`;
                        print T
                            '$middle[' . "$i] = \"" . $middle[$i] . "\";\n";
                }
        }
        print T '$i = ' . "$i;\n";
        close(T);
        print "done\n";
        &ttyraw;
}

Reply via email to