diff --git a/src/Screen.h b/src/Screen.h --- a/src/Screen.h +++ b/src/Screen.h @@ -220,6 +220,11 @@ * If @p n is 0 then one character is inserted. */ void insertChars(int n); + /** + * Repeat the preceeding graphic character @n times, including SPACE. + * If @n is 0 then the character is repeated once. + */ + void repeatChars(int n); /** * Removes @p n lines beginning from the current cursor position. * The position of the cursor is not altered. @@ -717,6 +722,9 @@ // last position where we added a character int _lastPos; + + // used in REP (repeating char) + unsigned short _lastDrawnChar; }; } diff --git a/src/Screen.cpp b/src/Screen.cpp --- a/src/Screen.cpp +++ b/src/Screen.cpp @@ -73,7 +73,8 @@ _effectiveForeground(CharacterColor()), _effectiveBackground(CharacterColor()), _effectiveRendition(DEFAULT_RENDITION), - _lastPos(-1) + _lastPos(-1), + _lastDrawnChar(0) { _lineProperties.resize(_lines + 1); for (int i = 0; i < _lines + 1; i++) { @@ -248,6 +249,24 @@ } } +void Screen::repeatChars(int n) +{ + if (n == 0) { + n = 1; // Default + } + + // From ECMA-48 version 5, section 8.3.103: + // "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." + // + // So, a "normal" program should always use REP immediately after a visible + // character (those other than escape sequences). So, _lastDrawnChar can be + // safely used. + for (int i = 0; i < n; i++) { + displayCharacter(_lastDrawnChar); + } +} + void Screen::deleteLines(int n) { if (n == 0) { @@ -751,6 +770,8 @@ currentChar.rendition = _effectiveRendition; currentChar.isRealCharacter = true; + _lastDrawnChar = c; + int i = 0; const int newCursorX = _cuX + w--; while (w != 0) { diff --git a/src/Vt102Emulation.cpp b/src/Vt102Emulation.cpp --- a/src/Vt102Emulation.cpp +++ b/src/Vt102Emulation.cpp @@ -240,7 +240,7 @@ for (i = 32; i < 256; ++i) { charClass[i] |= CHR; } - for (s = (quint8 *)"@ABCDGHILMPSTXZcdfry"; *s != 0u; ++s) { + for (s = (quint8 *)"@ABCDGHILMPSTXZbcdfry"; *s != 0u; ++s) { charClass[*s] |= CPN; } // resize = \e[8;;t @@ -684,6 +684,7 @@ case TY_CSI_PN('T' ) : _currentScreen->scrollDown (p ); break; case TY_CSI_PN('X' ) : _currentScreen->eraseChars (p ); break; case TY_CSI_PN('Z' ) : _currentScreen->backtab (p ); break; + case TY_CSI_PN('b' ) : _currentScreen->repeatChars (p ); break; case TY_CSI_PN('c' ) : reportTerminalType ( ); break; //VT100 case TY_CSI_PN('d' ) : _currentScreen->setCursorY (p ); break; //LINUX case TY_CSI_PN('f' ) : _currentScreen->setCursorYX (p, q); break; //VT100