123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- #!/usr/bin/env python
- #
- # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
- # Copyright (C)2013-2014 Philemon <mmgen-py@yandex.com>
- #
- # 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 <http://www.gnu.org/licenses/>.
- """
- term.py: Terminal-handling routines for the MMGen suite
- """
- import sys, os, struct
- from mmgen.util import msg, msg_r
- def _kb_hold_protect_unix():
- fd = sys.stdin.fileno()
- old = termios.tcgetattr(fd)
- tty.setcbreak(fd)
- timeout = float(0.3)
- while True:
- key = select([sys.stdin], [], [], timeout)[0]
- if key: sys.stdin.read(1)
- else:
- termios.tcsetattr(fd, termios.TCSADRAIN, old)
- break
- def _get_keypress_unix(prompt="",immed_chars="",prehold_protect=True):
- msg_r(prompt)
- timeout = float(0.3)
- fd = sys.stdin.fileno()
- old = termios.tcgetattr(fd)
- tty.setcbreak(fd)
- while True:
- # Protect against held-down key before read()
- key = select([sys.stdin], [], [], timeout)[0]
- ch = sys.stdin.read(1)
- if prehold_protect:
- if key: continue
- if immed_chars == "ALL" or ch in immed_chars: break
- if immed_chars == "ALL_EXCEPT_ENTER" and not ch in "\n\r": break
- # Protect against long keypress
- key = select([sys.stdin], [], [], timeout)[0]
- if not key: break
- termios.tcsetattr(fd, termios.TCSADRAIN, old)
- return ch
- def _kb_hold_protect_mswin():
- timeout = float(0.5)
- while True:
- hit_time = time.time()
- while True:
- if msvcrt.kbhit():
- msvcrt.getch()
- break
- if float(time.time() - hit_time) > timeout:
- return
- def _get_keypress_mswin(prompt="",immed_chars="",prehold_protect=True):
- msg_r(prompt)
- timeout = float(0.5)
- while True:
- if msvcrt.kbhit():
- ch = msvcrt.getch()
- if ord(ch) == 3: raise KeyboardInterrupt
- if immed_chars == "ALL" or ch in immed_chars:
- return ch
- if immed_chars == "ALL_EXCEPT_ENTER" and not ch in "\n\r":
- return ch
- hit_time = time.time()
- while True:
- if msvcrt.kbhit(): break
- if float(time.time() - hit_time) > timeout:
- return ch
- def _get_terminal_size_linux():
- def ioctl_GWINSZ(fd):
- try:
- import fcntl
- cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
- return cr
- except:
- pass
- cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
- if not cr:
- try:
- fd = os.open(os.ctermid(), os.O_RDONLY)
- cr = ioctl_GWINSZ(fd)
- os.close(fd)
- except:
- pass
- if not cr:
- try:
- cr = (os.environ['LINES'], os.environ['COLUMNS'])
- except:
- return 80,25
- return int(cr[1]), int(cr[0])
- def _get_terminal_size_mswin():
- try:
- from ctypes import windll, create_string_buffer
- # stdin handle is -10
- # stdout handle is -11
- # stderr handle is -12
- h = windll.kernel32.GetStdHandle(-12)
- csbi = create_string_buffer(22)
- res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
- if res:
- (bufx, bufy, curx, cury, wattr, left, top, right, bottom,
- maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
- sizex = right - left + 1
- sizey = bottom - top + 1
- return sizex, sizey
- except:
- return 80,25
- def mswin_dummy_flush(fd,termconst): pass
- try:
- import tty, termios
- from select import select
- get_char = _get_keypress_unix
- kb_hold_protect = _kb_hold_protect_unix
- get_terminal_size = _get_terminal_size_linux
- myflush = termios.tcflush
- # call: myflush(sys.stdin, termios.TCIOFLUSH)
- except:
- try:
- import msvcrt, time
- get_char = _get_keypress_mswin
- kb_hold_protect = _kb_hold_protect_mswin
- get_terminal_size = _get_terminal_size_mswin
- myflush = mswin_dummy_flush
- except:
- if not sys.platform.startswith("linux") \
- and not sys.platform.startswith("win"):
- msg("Unsupported platform: %s" % sys.platform)
- msg("This program currently runs only on Linux and Windows")
- else:
- msg("Unable to set terminal mode")
- sys.exit(2)
- def do_pager(text):
- pagers = ["less","more"]
- shell = False
- from os import environ
- # Hack for MS Windows command line (i.e. non CygWin) environment
- # When 'shell' is true, Windows aborts the calling program if executable
- # not found.
- # When 'shell' is false, an exception is raised, invoking the fallback
- # 'print' instead of the pager.
- # We risk assuming that "more" will always be available on a stock
- # Windows installation.
- if sys.platform.startswith("win") and 'HOME' not in environ:
- shell = True
- pagers = ["more"]
- if 'PAGER' in environ and environ['PAGER'] != pagers[0]:
- pagers = [environ['PAGER']] + pagers
- for pager in pagers:
- end = "" if pager == "less" else "\n(end of text)\n"
- try:
- from subprocess import Popen, PIPE, STDOUT
- p = Popen([pager], stdin=PIPE, shell=shell)
- except: pass
- else:
- p.communicate(text+end+"\n")
- msg_r("\r")
- break
- else: print text+end
|