Question

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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top