From 2b7cef952b84dff8511ffc8a4356c76298ba6375 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 9 Nov 2015 14:37:50 +0530 Subject: [PATCH] Do not use curses to get terminal size libncursesw.so is very difficult to bundle in the binary build and there are now two major versions of it in use so.5 and so.6 So instead use an IOCTL directly. Should be faster as well :) --- src/calibre/test_build.py | 5 ++-- src/calibre/utils/terminal.py | 45 +++++++++++++++++++++++++++-------- 2 files changed, 37 insertions(+), 13 deletions(-) diff --git a/src/calibre/test_build.py b/src/calibre/test_build.py index 16ad1b46b1..98d0f531a8 100644 --- a/src/calibre/test_build.py +++ b/src/calibre/test_build.py @@ -228,10 +228,9 @@ def test_podofo(): print ('podofo OK!') def test_terminal(): - import readline, curses - curses.setupterm() + import readline del readline - print ('readline and curses OK!') + print ('readline OK!') def test_markdown(): from calibre.ebooks.markdown import Markdown diff --git a/src/calibre/utils/terminal.py b/src/calibre/utils/terminal.py index 0b589c0a9b..8f899396d8 100644 --- a/src/calibre/utils/terminal.py +++ b/src/calibre/utils/terminal.py @@ -325,23 +325,48 @@ def windows_terminfo(): raise Exception('stdout is not a console?') return csbi +def get_term_geometry(): + import fcntl, termios, struct + + def ioctl_GWINSZ(fd): + try: + return struct.unpack(b'hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, b'1234')) + except Exception: + return None, None + + for f in (sys.stdin, sys.stdout, sys.stderr): + lines, cols = ioctl_GWINSZ(f.fileno()) + if lines is not None: + return lines, cols + try: + fd = os.open(os.ctermid(), os.O_RDONLY) + try: + lines, cols = ioctl_GWINSZ(fd) + if lines is not None: + return lines, cols + finally: + os.close(fd) + except Exception: + pass + return None, None + + def geometry(): if iswindows: try: ti = windows_terminfo() - return (ti.dwSize.X or 80, ti.dwSize.Y or 80) + return (ti.dwSize.X or 80, ti.dwSize.Y or 25) except: - return 80, 80 - try: - import curses - curses.setupterm() - except: - return 80, 80 + return 80, 25 else: - width = curses.tigetnum('cols') or 80 - height = curses.tigetnum('lines') or 80 - return width, height + try: + lines, cols = get_term_geometry() + if lines is not None: + return cols, lines + except Exception: + pass + return 80, 25 def test(): s = ANSIStream()