# Manipulation of ECMA-48 (ANSI X3.64) terminals with DEC extensions # # Copyright (C) 2015 Patrick "P. J." McDermott # # This program 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 . term_tty= term_byte= term_num_lines= term_num_columns= term_init() { term_tty="$(tty)" read -r term_num_lines term_num_columns <<-EOF $(stty size) EOF return 0 } term_lines() { printf '%d' ${term_num_lines} return 0 } term_columns() { printf '%d' ${term_num_columns} return 0 } term_echo() { stty echo return 0 } term_noecho() { stty -echo return 0 } term_raw() { stty raw return 0 } term_cooked() { stty cooked return 0 } term_cursor_up() { local n="${1}" shift 1 # CUU printf '\033[%dA' ${n} >"${term_tty}" return 0 } term_cursor_down() { local n="${1}" shift 1 # CUD printf '\033[%dB' ${n} >"${term_tty}" return 0 } term_cursor_forward() { local n="${1}" shift 1 # CUF printf '\033[%dC' ${n} >"${term_tty}" return 0 } term_cursor_back() { local n="${1}" shift 1 # CUB printf '\033[%dD' ${n} >"${term_tty}" return 0 } term_cursor_position() { local row="${1}" local col="${2}" shift 2 # CUP printf '\033[%d;%dH' ${row} ${col} >"${term_tty}" return 0 } term_clear() { # ED with n=2 printf '\033[2J' >"${term_tty}" term_cursor_position 1 1 return 0 } term_hide_cursor() { # DECTCEM with code "l" printf '\033[?25l' >"${term_tty}" return 0 } term_show_cursor() { # DECTCEM with code "h" printf '\033[?25h' >"${term_tty}" return 0 } term_attr_on() { local attr="${1}" shift 1 local attr_code= case "${attr}" in blink) attr_code=5;; bold) attr_code=1;; dim) attr_code=2;; invis) attr_code=8;; reverse) attr_code=7;; underline) attr_code=4;; *) return 1;; esac # SGR printf '\033[%dm' ${attr_code} >"${term_tty}" return 0 } term_attr_off() { local attr="${1}" shift 1 local attr_code= case "${attr}" in blink) attr_code=25;; bold) attr_code=22;; dim) attr_code=22;; invis) attr_code=28;; reverse) attr_code=27;; underline) attr_code=24;; *) return 1;; esac # SGR printf '\033[%dm' ${attr_code} >"${term_tty}" return 0 } term_fg_color_set() { local color="${1}" shift 1 case "${color}" in black) color=0;; red) color=1;; green) color=2;; yellow) color=3;; blue) color=4;; magenta) color=5;; cyan) color=6;; white) color=7;; *) return 1;; esac # SGR printf '\033[%dm' $((30 + $color)) >"${term_tty}" return 0 } term_bg_color_set() { local color="${1}" shift 1 case "${color}" in black) color=0;; red) color=1;; green) color=2;; yellow) color=3;; blue) color=4;; magenta) color=5;; cyan) color=6;; white) color=7;; *) return 1;; esac # SGR printf '\033[%dm' $((40 + $color)) >"${term_tty}" return 0 } term_attr_reset() { # SGR printf '\033[0m' >"${term_tty}" return 0 } term_write() { local s="${1}" shift 1 printf '%s' "${s}" >"${term_tty}" return 0 } _term_get_byte() { # Damn command substitutions eat trailing whitespace. Even if # whitespace is the /only/ thing printed and exactly what we want from # the command. term_byte="$(dd bs=1 count=1 2>/dev/null; printf '.')" term_byte="${term_byte%.}" return 0 } _term_get_escseq() { local key=KEY_INVALID _term_get_byte case "${term_byte}" in '[') _term_get_byte case "${term_byte}" in 'A') key=KEY_UP;; 'B') key=KEY_DOWN;; 'C') key=KEY_RIGHT;; 'D') key=KEY_LEFT;; 'H') key=KEY_HOME;; # XTerm 'F') key=KEY_END;; # XTerm '1') _term_get_byte case "${term_byte}" in '~') key=KEY_HOME;; # Linux esac ;; '3') _term_get_byte case "${term_byte}" in '~') key=KEY_DEL;; esac ;; '4') _term_get_byte case "${term_byte}" in '~') key=KEY_END;; # Linux esac ;; esac ;; 'O') _term_get_byte case "${term_byte}" in 'H') key=KEY_HOME;; # VTE 'F') key=KEY_END;; # VTE esac ;; esac printf '%s' "${key}" return 0 } term_getch() { local key=KEY_INVALID _term_get_byte case "${term_byte}" in "$(printf '\033')") key="$(_term_get_escseq)" ;; ' ') key=KEY_SPACE;; "${HT}") key=KEY_TAB;; "$(printf '\015')") key=KEY_ENTER;; "$(printf '\177')") key=KEY_BACKSPACE;; *) key="${term_byte}";; esac printf '%s' "${key}" return 0 }