When printing wide characters using Python 3's ncurses bindings, spaces are compressed when using window.insnstr. Here's the code to reproduce the issue:
import curses
def main(window):
window.insnstr(0, 0, "insnstr", 80)
window.insnstr(1, 0, "赵启明 XXX", 80)
window.insnstr(2, 0, "001122 XXX", 80)
window.insnstr(3, 0, "赵启明 XXX", 80)
window.insnstr(4, 0, "001122 XXX", 80)
window.addnstr(6, 0, "addnstr", 80)
window.addnstr(7, 0, "赵启明 XXX", 80)
window.addnstr(8, 0, "001122 XXX", 80)
window.addnstr(9, 0, "赵启明 XXX", 80)
window.addnstr(10, 0, "001122 XXX", 80)
window.addnstr(11, 0, "Press any key to exit.", 80)
window.refresh()
window.get_wch()
if __name__ == "__main__":
curses.wrapper(main)
With tmux, Xterm and st, I get the following output:
insnstr
赵启明 XXX
001122 XXX
赵启明 XXX
001122 XXX
addnstr
赵启明 XXX
001122 XXX
赵启明 XXX
001122 XXX
Press any key to exit.
I expect the alignment to be the same in both blocks. Interestingly, if I replace the spaces with any other character, the alignment is consistent:
insnstr
赵启明----------XXX
001122----------XXX
赵启明----------XXX
001122----------XXX
addnstr
赵启明----------XXX
001122----------XXX
赵启明----------XXX
001122----------XXX
Press any key to exit.
Depending on your browser font, the numbers may or may not be aligned; refer to this screenshot to see how the output looks in a terminal emulator:
Is this a bug in the ncurses library, in Python's implementation of the library, or am I misunderstanding how this curses function should work?
It looks like a bug in the ncurses library: addstr flavors are used far more often than the insert/delete operations, and ncurses has to do some special bookkeeping to keep track of double-width characters.
This is fixed in patch 6.0.20160220, which eventually will be in whatever package you use.