the curse does not work when addch is called in the lower right corner

I'm starting to learn curses in Python. I use Python 3.5 on Mac OS X. When I try to write in the lower right corner, the program crashes with the following error:

$ python ex_curses.py [...] File "ex_curses.py", line 19, in do_curses screen.addch(mlines, mcols, 'c') _curses.error: add_wch() returned ERR 

Program Example:

 import curses def do_curses(screen): curses.noecho() curses.curs_set(0) screen.keypad(1) (line, col) = 12, 0 screen.addstr(line, col, "Hello world!") line += 1 screen.addstr(line, col, "Hello world!", curses.A_REVERSE) screen.addch(0, 0, "c") (mlines, mcols) = screen.getmaxyx() mlines -= 1 mcols -= 1 screen.addch(mlines, mcols, 'c') while True: event = screen.getch() if event == ord("q"): break curses.endwin() if __name__ == "__main__": curses.wrapper(do_curses) 

I have a feeling that I am missing something obvious, but I don’t know what.

+9
source share
4 answers

This is the expected behavior (quirk) because addch tries to wrap the next line after adding a character. There is a comment in lib_addch.c regarding this:

 /* * The _WRAPPED flag is useful only for telling an application that we've just * wrapped the cursor. We don't do anything with this flag except set it when * wrapping, and clear it whenever we move the cursor. If we try to wrap at * the lower-right corner of a window, we cannot move the cursor (since that * wouldn't be legal). So we return an error (which is what SVr4 does). * Unlike SVr4, we can successfully add a character to the lower-right corner * (Solaris 2.6 does this also, however). */ 
+4
source

For future readers. After @Thomas Dickey's answer, I added the following code snippet.

 try: screen.addch(mlines, mcols, 'c') except _curses.error as e: pass 

Now my code looks like this:

 import curses import _curses def do_curses(screen): curses.noecho() curses.curs_set(0) screen.keypad(1) (line, col) = 12, 0 screen.addstr(line, col, "Hello world!") line += 1 screen.addstr(line, col, "Hello world!", curses.A_REVERSE) screen.addch(0, 0, "c") (mlines, mcols) = screen.getmaxyx() mlines -= 1 mcols -= 1 try: screen.addch(mlines, mcols, 'c') except _curses.error as e: pass while True: event = screen.getch() if event == ord("q"): break curses.endwin() if __name__ == "__main__": curses.wrapper(do_curses) 
+3
source

This is a kind of exotic solution using the fact that curses can draw the lower right character when drawing the border (without exception). See the full example:

 # -*- coding: utf-8 -*- import curses def addch_bottom_right(window, ch): """ Somehow, the underlying ncurses library has an issue with writing a char into bottom-right corner (see the https://stackoverflow.com/a/36389161 for example). But we can use the workaround: - create a subwindow 1x1 of the current window in the bottom-right corner - draw a border of that window, consisting only of the desired character: for a 1x1 window, that border will consist exclusively of this single character. - refresh the screen to show your new 'window' with the 'border'. """ print("Putting char '%s' in the bottom-right corner" % ch) beg_y, beg_x = window.getbegyx() max_y, max_x = window.getmaxyx() br_y = beg_y + max_y - 1 br_x = beg_x + max_x - 1 print('Coordinates of current window: %sx%s' % (br_y, br_x)) w = window.subwin(1, 1, br_y, br_x) # only 'br' (bottom-right corner) gets printed for 1x1 box w.border(*([ch] * 8)) w.noutrefresh() window.noutrefresh() curses.doupdate() def demo(screen, show_border=True): """ Try the workaround with three different windows nesting levels. Borders drawn here only to show where the windows are. """ curses.curs_set(0) w = screen.subwin(8, 8, 10, 10) if show_border: w.border() addch_bottom_right(w, 'Window'[0]) w2 = w.subwin(3, 3, 12, 12) if show_border: w2.box() addch_bottom_right(w2, 'Subwindow'[0]) addch_bottom_right(screen, 'Main screen'[0]) screen.getch() if __name__ == '__main__': curses.wrapper(demo) 
0
source

window.insch(...) can place a symbol in the lower right corner of the window without moving the cursor. Any character in this position will be struck to the right without causing an error.

0
source

Source: https://habr.com/ru/post/1246342/


All Articles