Commit c61e4cac authored by Luis Javier Merino's avatar Luis Javier Merino Committed by Kurt Hindenburg
Browse files

Allow writing only half of a double-height line

While DECHDL sequences should be used in pairs on adjacent lines, the
first line drawing the top half, and the second line drawing the bottom
half, apparently real VTxxx (or at least the VT220) terminals did draw
only the top or bottom of characters when confronted with an isolated
DECDHL line (https://retrocomputing.stackexchange.com/questions/18023/).
xterm has that same behavior. So behave likewise.
parent 2232ed67
......@@ -1118,7 +1118,7 @@ void Screen::clearImage(int loca, int loce, char c, bool resetLineRendition)
}
if (resetLineRendition && startCol == 0 && endCol == _columns - 1) {
_lineProperties[y] &= ~(LINE_DOUBLEWIDTH | LINE_DOUBLEHEIGHT);
_lineProperties[y] &= ~(LINE_DOUBLEWIDTH | LINE_DOUBLEHEIGHT_TOP | LINE_DOUBLEHEIGHT_BOTTOM);
}
}
}
......
......@@ -509,10 +509,12 @@ public:
* LINE_WRAPPED: Specifies that the line is wrapped.
* LINE_DOUBLEWIDTH: Specifies that the characters in the current line
* should be double the normal width.
* LINE_DOUBLEHEIGHT:Specifies that the characters in the current line
* LINE_DOUBLEHEIGHT_TOP:
* LINE_DOUBLEHEIGHT_BOTTOM: Specifies that the characters in the current line
* should be double the normal height.
* Double-height lines are formed of two lines containing the same characters,
* with both having the LINE_DOUBLEHEIGHT attribute.
* with the top one having the LINE_DOUBLEHEIGHT_TOP attribute
* and the bottom one having the LINE_DOUBLEHEIGHT_BOTTOM attribute.
* This allows other parts of the code to work on the
* assumption that all lines are the same height.
*
......
......@@ -635,19 +635,23 @@ void Vt102Emulation::processToken(int token, int p, int q)
case token_esc_de('3' ) : /* Double height line, top half */
_currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );
_currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );
_currentScreen->setLineProperty( LINE_DOUBLEHEIGHT_TOP , true );
_currentScreen->setLineProperty( LINE_DOUBLEHEIGHT_BOTTOM , false );
break;
case token_esc_de('4' ) : /* Double height line, bottom half */
_currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true );
_currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , true );
_currentScreen->setLineProperty( LINE_DOUBLEHEIGHT_TOP , false );
_currentScreen->setLineProperty( LINE_DOUBLEHEIGHT_BOTTOM , true );
break;
case token_esc_de('5' ) : /* Single width, single height line*/
_currentScreen->setLineProperty( LINE_DOUBLEWIDTH , false);
_currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false);
_currentScreen->setLineProperty( LINE_DOUBLEHEIGHT_TOP , false);
_currentScreen->setLineProperty( LINE_DOUBLEHEIGHT_BOTTOM , false);
break;
case token_esc_de('6' ) : /* Double width, single height line*/
_currentScreen->setLineProperty( LINE_DOUBLEWIDTH , true);
_currentScreen->setLineProperty( LINE_DOUBLEHEIGHT , false);
_currentScreen->setLineProperty( LINE_DOUBLEHEIGHT_TOP , false);
_currentScreen->setLineProperty( LINE_DOUBLEHEIGHT_BOTTOM , false);
break;
case token_esc_de('8' ) : _currentScreen->helpAlign ( ); break;
......
......@@ -20,10 +20,11 @@ typedef unsigned char LineProperty;
typedef quint16 RenditionFlags;
const int LINE_DEFAULT = 0;
const int LINE_WRAPPED = (1 << 0);
const int LINE_DOUBLEWIDTH = (1 << 1);
const int LINE_DOUBLEHEIGHT = (1 << 2);
const int LINE_DEFAULT = 0;
const int LINE_WRAPPED = (1 << 0);
const int LINE_DOUBLEWIDTH = (1 << 1);
const int LINE_DOUBLEHEIGHT_TOP = (1 << 2);
const int LINE_DOUBLEHEIGHT_BOTTOM = (1 << 3);
const RenditionFlags DEFAULT_RENDITION = 0;
const RenditionFlags RE_BOLD = (1 << 0);
......
......@@ -614,7 +614,7 @@ void TerminalDisplay::updateImage()
//the top one is actually
//drawn.
if (_lineProperties.count() > y) {
updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT);
updateLine |= (_lineProperties[y] & LINE_DOUBLEHEIGHT_TOP);
}
// if the characters on the line are different in the old and the new _image
......
......@@ -508,7 +508,7 @@ Q_SIGNALS:
void drawBackground(QPainter &painter, const QRect &rect, const QColor &backgroundColor, bool useOpacitySetting);
void drawCharacters(QPainter &painter, const QRect &rect, const QString &text,
const Character *style, const QColor &characterColor);
const Character *style, const QColor &characterColor, const LineProperty lineProperty);
void drawInputMethodPreeditString(QPainter &painter, const QRect &rect, TerminalDisplay::InputMethodData &inputMethodData, Character *image);
protected:
......
......@@ -72,6 +72,7 @@ namespace Konsole
for (int y = rect.y(); y <= rect.bottom(); y++) {
int x = rect.x();
bool doubleHeightLinePair = false;
// Search for start of multi-column character
if ((image[display->loc(rect.x(), y)].character == 0u) && (x != 0)) {
......@@ -182,6 +183,7 @@ namespace Konsole
}
QMatrix textScale;
bool doubleHeight = false;
bool doubleWidthLine = false;
if (y < lineProperties.size()) {
......@@ -190,11 +192,18 @@ namespace Konsole
doubleWidthLine = true;
}
if ((lineProperties[y] & LINE_DOUBLEHEIGHT) != 0) {
doubleHeight = lineProperties[y] & (LINE_DOUBLEHEIGHT_TOP | LINE_DOUBLEHEIGHT_BOTTOM);
if (doubleHeight) {
textScale.scale(1, 2);
}
}
if (y < lineProperties.size() - 1) {
if (((lineProperties[y] & LINE_DOUBLEHEIGHT_TOP) != 0) && ((lineProperties[y+1] & LINE_DOUBLEHEIGHT_BOTTOM) != 0)) {
doubleHeightLinePair = true;
}
}
// Apply text scaling matrix
paint.setWorldTransform(QTransform(textScale), true);
......@@ -202,7 +211,7 @@ namespace Konsole
QRect textArea = QRect(display->contentRect().left() + display->contentsRect().left() + display->terminalFont()->fontWidth() * x * (doubleWidthLine ? 2 : 1),
display->contentRect().top() + display->contentsRect().top() + display->terminalFont()->fontHeight() * y,
display->terminalFont()->fontWidth() * len,
display->terminalFont()->fontHeight());
doubleHeight && !doubleHeightLinePair ? display->terminalFont()->fontHeight() / 2 : display->terminalFont()->fontHeight());
//move the calculated area to take account of scaling applied to the painter.
//the position of the area from the origin (0,0) is scaled
......@@ -221,13 +230,15 @@ namespace Konsole
drawPrinterFriendlyTextFragment(paint,
textArea,
unistr,
&image[display->loc(x, y)]);
&image[display->loc(x, y)],
y < lineProperties.size() ? lineProperties[y] : 0);
} else {
drawTextFragment(paint,
textArea,
unistr,
&image[display->loc(x, y)],
display->terminalColor()->colorTable());
display->terminalColor()->colorTable(),
y < lineProperties.size() ? lineProperties[y] : 0);
}
paint.setWorldTransform(QTransform(textScale.inverted()), true);
......@@ -235,10 +246,8 @@ namespace Konsole
x += len - 1;
}
if (y < lineProperties.size() - 1) {
if ((lineProperties[y] & LINE_DOUBLEHEIGHT) != 0) {
y++;
}
if (doubleHeightLinePair) {
y++;
}
}
}
......@@ -387,7 +396,7 @@ namespace Konsole
}
void TerminalPainter::drawTextFragment(QPainter &painter, const QRect &rect, const QString &text,
const Character *style, const QColor *colorTable)
const Character *style, const QColor *colorTable, const LineProperty lineProperty)
{
// setup painter
const QColor foregroundColor = style->foregroundColor.color(colorTable);
......@@ -403,17 +412,17 @@ namespace Konsole
}
// draw text
drawCharacters(painter, rect, text, style, characterColor);
drawCharacters(painter, rect, text, style, characterColor, lineProperty);
}
void TerminalPainter::drawPrinterFriendlyTextFragment(QPainter &painter, const QRect &rect, const QString &text,
const Character *style)
const Character *style, const LineProperty lineProperty)
{
Character print_style = *style;
print_style.foregroundColor = CharacterColor(COLOR_SPACE_RGB, 0x00000000);
print_style.backgroundColor = CharacterColor(COLOR_SPACE_RGB, 0xFFFFFFFF);
drawCharacters(painter, rect, text, &print_style, QColor());
drawCharacters(painter, rect, text, &print_style, QColor(), lineProperty);
}
void TerminalPainter::drawBackground(QPainter &painter, const QRect &rect, const QColor &backgroundColor,
......@@ -491,7 +500,7 @@ namespace Konsole
}
void TerminalPainter::drawCharacters(QPainter &painter, const QRect &rect, const QString &text,
const Character *style, const QColor &characterColor)
const Character *style, const QColor &characterColor, const LineProperty lineProperty)
{
const auto display = qobject_cast<TerminalDisplay*>(sender());
......@@ -547,14 +556,27 @@ namespace Konsole
painter.setClipRect(rect);
// draw text
if (isLineCharString(text) && !display->terminalFont()->useFontLineCharacters()) {
drawLineCharString(display, painter, rect.x(), rect.y(), text, style);
int y = rect.y();
if (lineProperty & LINE_DOUBLEHEIGHT_BOTTOM) {
y -= display->terminalFont()->fontHeight() / 2;
}
drawLineCharString(display, painter, rect.x(), y, text, style);
} else {
painter.setLayoutDirection(Qt::LeftToRight);
int y = rect.y() + display->terminalFont()->fontAscent();
if (lineProperty & LINE_DOUBLEHEIGHT_BOTTOM) {
y -= display->terminalFont()->fontHeight() / 2;
} else {
y += display->terminalFont()->lineSpacing();
}
if (display->bidiEnabled()) {
painter.drawText(rect.x(), rect.y() + display->terminalFont()->fontAscent() + display->terminalFont()->lineSpacing(), text);
painter.drawText(rect.x(), y, text);
} else {
painter.drawText(rect.x(), rect.y() + display->terminalFont()->fontAscent() + display->terminalFont()->lineSpacing(), LTR_OVERRIDE_CHAR + text);
painter.drawText(rect.x(), y, LTR_OVERRIDE_CHAR + text);
}
}
painter.setClipRegion(origClipRegion);
......@@ -591,7 +613,7 @@ namespace Konsole
drawBackground(painter, rect, background, true);
drawCursor(painter, rect, foreground, background, characterColor);
drawCharacters(painter, rect, inputMethodData.preeditString, style, characterColor);
drawCharacters(painter, rect, inputMethodData.preeditString, style, characterColor, 0);
inputMethodData.previousPreeditRect = rect;
}
......
......@@ -70,7 +70,7 @@ namespace Konsole
// draws the characters or line graphics in a text fragment
void drawCharacters(QPainter &painter, const QRect &rect, const QString &text,
const Character *style, const QColor &characterColor);
const Character *style, const QColor &characterColor, const LineProperty lineProperty);
// draws the preedit string for input methods
void drawInputMethodPreeditString(QPainter &painter, const QRect &rect, TerminalDisplay::InputMethodData &inputMethodData, Character *image);
......@@ -82,10 +82,10 @@ namespace Konsole
// draws a section of text, all the text in this section
// has a common color and style
void drawTextFragment(QPainter &painter, const QRect &rect, const QString &text,
const Character *style, const QColor *colorTable);
const Character *style, const QColor *colorTable, const LineProperty lineProperty);
void drawPrinterFriendlyTextFragment(QPainter &painter, const QRect &rect, const QString &text,
const Character *style);
const Character *style, const LineProperty lineProperty);
// draws the cursor character
void drawCursor(QPainter &painter, const QRect &rect, const QColor &foregroundColor,
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment