ncurses in urxvt does not print repeating characte

2019-01-29 12:01发布

问题:

Running an ncurses program in urxvt squeezes repeating characters in strings. For example I expect "--------" but I get "-".

I have written a short program that reproduces the problem. The code is below.

I have verified that the output is as correct when using xterm rather than urxvt.

This is the first time I am working with ncurses, however, the sample program is as simple as they come. Therefore, I don't think it is likely that the problem is with how I'm using ncurses. This is also supported by the fact that xterm gives the expected results.

I am using urxvt on Arch Linux. I am providing related configuration below too. I have vanilla xterm installed without any additional configuration. Both had zsh running.

Sample Program (C)

#include <curses.h>

int main(){
  initscr();
  printw("------\n");        // (1) 6 '-' chars          urxvt: "------"   xterm: "------"
  printw("-------\n");       // (2) 7 '-' chars          urxvt: "-"        xterm: "-------"
  printw("--------\n");      // (3) 8 '-' chars          urxvt: "-"        xterm: "--------"
  printw("0--------0\n");    // (4) 8 '-' between '0'    urxvt: "0-0"      xterm: "0--------0"
  printw("xxxxxxxx\n");      // (5) Replacing '-' with 'x' does not make a difference.
  printw("---- ----\n");     // (6) Two '-' sequences separated by ' ' display correctly.
  printw("12345678\n");      // (7) Strings with different characters display correctly.
  for(int i=0; i<8; i++) addch('-');    // (8) 8 '-' chars      urxvt: "-"   xterm: "--------" 
  addch('\n');
  for(char c='0'; c<'8'; c++) addch(c); // (9) Both display correctly
  addch('\n');
  refresh();
  getch();
  endwin();
  return 0;
}

xterm Output (Correct)

------
-------
--------
0--------0
xxxxxxxx
---- ----
12345678
--------
01234567

urxvt Output (Incorrect)

------
-
-
0-0
x
---- ----
12345678
-
01234567

Observations

  • Up to 6 repeating characters are displayed correctly.
  • 7 and more repeating characters are displayed as a single character.
  • This problem does not occur if the characters are non-repeating, so the length of the string itself is not the problem.
  • The location of the repeating substring is not important. In (7), the substring that got squeezed was sandwiched by '0' characters on each end.
    • The problem is not due to a specific character. It happens with '-' as well as 'x'.
  • The problem was observed using both the printw and addch functions. The associated manpages state that these functions move the cursor, so there should be no need to explicitly move the cursor. This is obviously the case, as otherwise the problem would not be limited to repeating characters, and would also happen with xterm.

urxvt Configuration

  • rxvt-unicode v9.22
  • $TERM is xterm-256color

回答1:

urxvt is not xterm, so $TERM should be rxvt-unicode and not xterm-256color.

I didn't figure this out right until the very end of typing my question, when I was adding the urxvt configuration. I suppose thinking about what information might be relevant to put into a SO question is can lead to solving your own problem. Rather than deleting everything, I thought I might as well post nonetheless and perhaps it will be useful to someone else out there.

The thing is, I added that env setting a long, long time ago when I was experimenting with Arch Linux and urxvt for the first time. I must admit, I did not really spend too much time thinking about it. I recall all I cared about at the time was having unicode characters, fonts and colors displayed properly (in addition to a pretty looking color scheme). Setting $TERM to xterm-256color seemed to work at the time, and in all this time using the system, it continued seeming to work, until today. There were glitches here and there, of course, and perhaps they were the result of this. Then again, perhaps they were due to something else. I have to say I am rather amused at how silly and simple the problem turned out to be.

It is also interesting to see the strange behavior this error led to. I'm still curious to know why exactly my mistake leads to the behavior I document in the question. I might return to this just for kicks when I have some time.

EDIT

This exact issue is mentioned in ncurses' FAQ, as pointed out by Thomas Dickey.

..., in mid-2017, an update to the xterm terminal description added the ECMA-48 REP (repeat character) control. It was part of xterm since January 1997, but a terminal description using the feature was part of xterm only (not ncurses).

Terminal emulators that use TERM=xterm but do not support this xterm feature exhibited bugs once this feature was introduced to ncurses. rxvt was unaffected since it does not use TERM=xterm, or rather, as it should not use TERM=xterm, as I had been doing.

REP is used to indicate that the preceding character in the data stream, if it is a graphic character (represented by one or more bit combinations) including SPACE, is to be repeated n times, where n equals the value of Pn. If the character preceding REP is a control function or part of a control function, the effect of REP is not defined by this Standard. REP - ECMA-048

I should also mention that the ncurses FAQ includes an excellent discussion concerning why people tend to use TERM=xterm, and why they should not, straight from the horse's mouth!



标签: c ncurses urxvt