Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ncurses 10,10 pad causes error when addstr to 9, 9

After declaring a 10 by 10 pad, I apparently can't write to lower right corner, 9, 9 without an error. What is going on here?

import curses

def start(stdscr):
    curses.curs_set(0)
    movement = curses.newpad(10, 10)

    movement.addstr(8, 9, '+')
    movement.addstr(9, 8, '+') 
    movement.addstr(9, 9, '+') #This line causes an error

if __name__ == '__main__':
    curses.wrapper(start)

causes:

  File "curses_movement_testing.py", line 35, in <module>
    curses.wrapper(start)
  File "/usr/lib64/python2.6/curses/wrapper.py", line 43, in wrapper
    return func(stdscr, *args, **kwds)
  File "curses_movement_testing.py", line 10, in start
    movement.addstr(9, 9, '+')
_curses.error: addstr() returned ERR

why can't I write to the the lower right corner cell?

like image 621
Dan Avatar asked Feb 17 '23 10:02

Dan


1 Answers

The problem is that the character added results in an attempt to scroll the pad, and scrolling is disabled. The character is successfully added (at least on my system's ncurses implementation): if you catch the error and update the screen, you should see it:

import curses, time

def start(stdscr):
    curses.start_color()
    try:
        curses.curs_set(0)
    except curses.error:
        pass
    movement = curses.newpad(10, 10)

    movement.addstr(8, 9, '+')
    movement.addstr(9, 8, '+')
    try:
        movement.addstr(9, 9, '+')
    except curses.error:
        movement.addstr(0, 0, 'CAUGHT')
    movement.refresh(0, 0, 0, 0, 9, 9)
    curses.doupdate()
    time.sleep(1)

if __name__ == '__main__':
    curses.wrapper(start)

If you call movement.scrollok(True) before writing to the lower right corner, there will be no error but the window will scroll: probably not what you want.

Since a pad can be bigger than the actual screen, one easy solution is to add an extra line below the part you will refresh. You can check to see if you've written into the part that won't be displayed. Here's a final example:

import curses, sys, time

def start(stdscr):
    curses.start_color()
    try:
        curses.curs_set(0)
    except curses.error:
        pass
    movement = curses.newpad(11, 10)

    movement.addstr(8, 9, '+')
    movement.addstr(9, 8, '+')
    text = sys.argv[1] if len(sys.argv) > 1 else '+'
    try:
        movement.addstr(9, 9, text)
        y, x = movement.getyx()
    except curses.error:
        y, x = movement.getyx()
        movement.addstr(0, 0, 'CAUGHT')
    if y >= 10 and x > 0:
        movement.addstr(1, 0, 'toolong')
    movement.refresh(0, 0, 0, 0, 9, 9)
    curses.doupdate()
    time.sleep(1)

if __name__ == '__main__':
    curses.wrapper(start)

Run as python cursesx.py and the pluses appear; run as python cursesx.py foo and the f and toolong messages appear; run as python cursesx.py waytoolongtofit and the w, CAUGHT, and toolong messages all appear.

like image 131
torek Avatar answered Feb 27 '23 21:02

torek