term.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #!/usr/bin/env python
  2. #
  3. # mmgen = Multi-Mode GENerator, command-line Bitcoin cold storage solution
  4. # Copyright (C) 2013-2014 by philemon <mmgen-py@yandex.com>
  5. #
  6. # This program is free software: you can redistribute it and/or modify
  7. # it under the terms of the GNU General Public License as published by
  8. # the Free Software Foundation, either version 3 of the License, or
  9. # (at your option) any later version.
  10. #
  11. # This program is distributed in the hope that it will be useful,
  12. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. # GNU General Public License for more details.
  15. #
  16. # You should have received a copy of the GNU General Public License
  17. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. """
  19. term.py: Terminal-handling routines for the mmgen suite
  20. """
  21. import sys, os, struct
  22. def msg(s): sys.stderr.write(s + "\n")
  23. def msg_r(s): sys.stderr.write(s)
  24. def _kb_hold_protect_unix():
  25. fd = sys.stdin.fileno()
  26. old = termios.tcgetattr(fd)
  27. tty.setcbreak(fd)
  28. timeout = float(0.3)
  29. try:
  30. while True:
  31. key = select([sys.stdin], [], [], timeout)[0]
  32. if key: sys.stdin.read(1)
  33. else: break
  34. except KeyboardInterrupt:
  35. msg("\nUser interrupt")
  36. sys.exit(1)
  37. finally:
  38. termios.tcsetattr(fd, termios.TCSADRAIN, old)
  39. def _get_keypress_unix(prompt="",immed_chars=""):
  40. msg_r(prompt)
  41. timeout = float(0.3)
  42. fd = sys.stdin.fileno()
  43. old = termios.tcgetattr(fd)
  44. tty.setcbreak(fd)
  45. try:
  46. while True:
  47. select([sys.stdin], [], [], False)
  48. ch = sys.stdin.read(1)
  49. if immed_chars == "ALL" or ch in immed_chars:
  50. return ch
  51. if immed_chars == "ALL_EXCEPT_ENTER" and not ch in "\n\r":
  52. return ch
  53. second_key = select([sys.stdin], [], [], timeout)[0]
  54. if second_key: continue
  55. else: return ch
  56. except KeyboardInterrupt:
  57. msg("\nUser interrupt")
  58. sys.exit(1)
  59. finally:
  60. termios.tcsetattr(fd, termios.TCSADRAIN, old)
  61. def _kb_hold_protect_mswin():
  62. timeout = float(0.5)
  63. try:
  64. while True:
  65. hit_time = time.time()
  66. while True:
  67. if msvcrt.kbhit():
  68. msvcrt.getch()
  69. break
  70. if float(time.time() - hit_time) > timeout:
  71. return
  72. except KeyboardInterrupt:
  73. msg("\nUser interrupt")
  74. sys.exit(1)
  75. def _get_keypress_mswin(prompt="",immed_chars=""):
  76. msg_r(prompt)
  77. timeout = float(0.5)
  78. try:
  79. while True:
  80. if msvcrt.kbhit():
  81. ch = msvcrt.getch()
  82. if ord(ch) == 3: raise KeyboardInterrupt
  83. if immed_chars == "ALL" or ch in immed_chars:
  84. return ch
  85. if immed_chars == "ALL_EXCEPT_ENTER" and not ch in "\n\r":
  86. return ch
  87. hit_time = time.time()
  88. while True:
  89. if msvcrt.kbhit(): break
  90. if float(time.time() - hit_time) > timeout:
  91. return ch
  92. except KeyboardInterrupt:
  93. msg("\nUser interrupt")
  94. sys.exit(1)
  95. def _get_terminal_size_linux():
  96. def ioctl_GWINSZ(fd):
  97. try:
  98. import fcntl
  99. import termios
  100. cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
  101. return cr
  102. except:
  103. pass
  104. cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
  105. if not cr:
  106. try:
  107. fd = os.open(os.ctermid(), os.O_RDONLY)
  108. cr = ioctl_GWINSZ(fd)
  109. os.close(fd)
  110. except:
  111. pass
  112. if not cr:
  113. try:
  114. cr = (os.environ['LINES'], os.environ['COLUMNS'])
  115. except:
  116. return 80,25
  117. return int(cr[1]), int(cr[0])
  118. def _get_terminal_size_mswin():
  119. try:
  120. from ctypes import windll, create_string_buffer
  121. # stdin handle is -10
  122. # stdout handle is -11
  123. # stderr handle is -12
  124. h = windll.kernel32.GetStdHandle(-12)
  125. csbi = create_string_buffer(22)
  126. res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
  127. if res:
  128. (bufx, bufy, curx, cury, wattr, left, top, right, bottom,
  129. maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
  130. sizex = right - left + 1
  131. sizey = bottom - top + 1
  132. return sizex, sizey
  133. except:
  134. return 80,25
  135. try:
  136. import tty, termios
  137. from select import select
  138. get_char = _get_keypress_unix
  139. kb_hold_protect = _kb_hold_protect_unix
  140. get_terminal_size = _get_terminal_size_linux
  141. except:
  142. try:
  143. import msvcrt, time
  144. get_char = _get_keypress_mswin
  145. kb_hold_protect = _kb_hold_protect_mswin
  146. get_terminal_size = _get_terminal_size_mswin
  147. except:
  148. if not sys.platform.startswith("linux") \
  149. and not sys.platform.startswith("win"):
  150. msg("Unsupported platform: %s" % sys.platform)
  151. msg("This program currently runs only on Linux and Windows")
  152. else:
  153. msg("Unable to set terminal mode")
  154. sys.exit(2)
  155. if __name__ == "__main__":
  156. print "columns: {}, rows: {}".format(*get_terminal_size())