Commit d4e1f4ac authored by Matan Ziv-Av's avatar Matan Ziv-Av Committed by Tomaz Canabrava
Browse files

Add support for iterm2 file upload protocol

Only supporting the case inline=1 for displaying graphics.
parent d691a3d7
......@@ -436,6 +436,48 @@ void Vt102Emulation::receiveChars(const QVector<uint> &chars)
resetTokenizer();
continue;
}
// Special case: iterm file protocol is a long escape sequence
if (tokenState == -1) {
tokenStateChange = "1337;File=:";
tokenState = 0;
} else if (tokenState >= 0) {
if ((uint)tokenStateChange[tokenState] == s[p - 1]) {
tokenState++;
tokenPos = p;
if ((uint)tokenState == strlen(tokenStateChange)) {
tokenState = -2;
tokenData.clear();
}
continue;
}
} else if (tokenState == -2) {
if (p - tokenPos == 4) {
tokenData.append(QByteArray::fromBase64(QString::fromUcs4(&tokenBuffer[tokenPos], 4).toLocal8Bit()));
tokenBufferPos -= 4;
continue;
}
}
// Special case: Session::Wallpaper is a long escape sequence
if (tokenState == -1) {
tokenStateChange = "114502;,,";
tokenState = 0;
} else if (tokenState >= 0) {
if ((uint)tokenStateChange[tokenState] == s[p - 1]) {
tokenState++;
tokenPos = p;
if ((uint)tokenState == strlen(tokenStateChange)) {
tokenState = -2;
tokenData.clear();
}
continue;
}
} else if (tokenState == -2) {
if (p - tokenPos == 4) {
tokenData.append(QByteArray::fromBase64(QString::fromUcs4(&tokenBuffer[tokenPos], 4).toLocal8Bit()));
tokenBufferPos -= 4;
continue;
}
}
}
/* clang-format off */
......@@ -650,6 +692,90 @@ void Vt102Emulation::processSessionAttributeRequest(int tokenSize)
}
}
if (attribute == 1337) {
if (!value.startsWith(QLatin1String("File=")))
return;
int pos = value.indexOf(QLatin1Char(':'));
QStringList params = value.mid(5, pos - 5).split(QLatin1Char(';'));
int keepAspect = 1;
int scaledWidth = 0;
int scaledHeight = 0;
for (const auto &p : params) {
int eq = p.indexOf(QLatin1Char('='));
if (eq > 0) {
QString var = p.mid(0, eq);
QString val = p.mid(eq + 1);
if (var == QLatin1String("inline")) {
if (val != QLatin1String("1"))
return;
}
if (var == QLatin1String("preserveAspectRatio")) {
if (val == QLatin1String("0"))
keepAspect = 0;
}
if (var == QLatin1String("width")) {
int unitPos = val.toStdString().find_first_not_of("0123456789");
scaledWidth = val.mid(0, unitPos).toInt();
if (unitPos == -1) {
scaledWidth *= _currentScreen->currentTerminalDisplay()->terminalFont()->fontWidth();
} else {
if (val.mid(unitPos) == QLatin1String("%")) {
scaledWidth *= _currentScreen->currentTerminalDisplay()->terminalFont()->fontWidth() * _currentScreen->getColumns() / 100;
}
}
}
if (var == QLatin1String("height")) {
int unitPos = val.toStdString().find_first_not_of("0123456789");
scaledHeight = val.mid(0, unitPos).toInt();
if (unitPos == -1) {
scaledHeight *= _currentScreen->currentTerminalDisplay()->terminalFont()->fontHeight();
} else {
if (val.mid(unitPos) == QLatin1String("%")) {
scaledHeight *= _currentScreen->currentTerminalDisplay()->terminalFont()->fontHeight() * _currentScreen->getLines() / 100;
}
}
}
}
}
QImage image;
image.loadFromData(tokenData);
if (image.isNull())
return;
TerminalGraphicsPlacement_t *p = new TerminalGraphicsPlacement_t();
p->id = -1;
p->pid = -1;
p->z = 1;
p->X = 0;
p->Y = 0;
p->opacity = 1.0;
p->col = _currentScreen->getCursorX();
p->row = _currentScreen->getCursorY();
p->pixmap = QPixmap::fromImage(image);
if (scaledWidth && scaledHeight) {
p->pixmap = p->pixmap.scaled(scaledWidth, scaledHeight, (Qt::AspectRatioMode)keepAspect);
} else {
if (keepAspect && scaledWidth) {
p->pixmap = p->pixmap.scaledToWidth(scaledWidth);
} else if (keepAspect && scaledHeight) {
p->pixmap = p->pixmap.scaledToHeight(scaledHeight);
}
}
int rows = (p->pixmap.height() - 1) / _currentScreen->currentTerminalDisplay()->terminalFont()->fontHeight() + 1;
int cols = (p->pixmap.width() - 1) / _currentScreen->currentTerminalDisplay()->terminalFont()->fontWidth() + 1;
p->cols = cols;
p->rows = rows;
int needScroll = p->row + p->rows - _currentScreen->bottomMargin() - 1;
if (needScroll < 0)
needScroll = 0;
if (needScroll > 0)
_currentScreen->scrollUp(needScroll);
p->row -= needScroll;
_currentScreen->currentTerminalDisplay()->addPlacement(p);
_currentScreen->cursorDown(rows - needScroll);
_currentScreen->cursorRight(cols);
}
_pendingSessionAttributesUpdates[attribute] = value;
_sessionAttributesUpdateTimer->start(20);
}
......
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