30 #include <QApplication>
34 #include <QtCore/QEvent>
35 #include <QtCore/QTime>
36 #include <QtCore/QFile>
37 #include <QGridLayout>
55 #define loc(X,Y) ((Y)*_columns+(X))
58 #define yMouseScroll 1
60 #define REPCHAR "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
61 "abcdefgjijklmnopqrstuvwxyz" \
116 QPalette p = palette();
121 _scrollBar->setPalette( QApplication::palette() );
144 static inline bool isLineChar(quint16 c) {
return ((c & 0xFF80) == 0x2500);}
155 0x0020, 0x25C6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0,
156 0x00b1, 0x2424, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c,
157 0xF800, 0xF801, 0x2500, 0xF803, 0xF804, 0x251c, 0x2524, 0x2534,
158 0x252c, 0x2502, 0x2264, 0x2265, 0x03C0, 0x2260, 0x00A3, 0x00b7
163 QFontMetrics fm(font());
176 for(
unsigned int i=1; i< strlen(
REPCHAR); i++)
178 if (fw != fm.width(
REPCHAR[i]))
201 QFontMetrics metrics(font);
203 if ( metrics.height() < height() && metrics.maxWidth() < width() )
208 font.setStyleStrategy( QFont::NoAntialias );
248 ,_terminalSizeHint(false)
249 ,_terminalSizeStartup(true)
251 ,_wordSelectionMode(false)
252 ,_lineSelectionMode(false)
253 ,_preserveLineBreaks(false)
254 ,_columnSelectionMode(false)
255 ,_scrollbarLocation(NoScrollBar)
256 ,_wordCharacters(
":@-./_~")
257 ,_bellMode(SystemBeepBell)
259 ,_cursorBlinking(false)
260 ,_hasBlinkingCursor(false)
262 ,_tripleClickMode(SelectWholeLine)
264 ,_possibleTripleClick(false)
267 ,_outputSuspendedLabel(0)
269 ,_colorsInverted(false)
270 ,_blendColor(qRgba(0,0,0,0xff))
272 ,_cursorShape(BlockCursor)
277 setLayoutDirection(Qt::LeftToRight);
290 connect(
_scrollBar, SIGNAL(valueChanged(
int)),
this,
303 setMouseTracking(
true);
306 setAcceptDrops(
true);
309 setFocusPolicy( Qt::WheelFocus );
312 setAttribute(Qt::WA_InputMethodEnabled,
true);
316 setAttribute(Qt::WA_OpaquePaintEvent);
324 parent->parent (), SLOT (set_global_shortcuts (
bool)));
330 qApp->removeEventFilter(
this );
395 static void drawLineChar(QPainter& paint,
int x,
int y,
int w,
int h, uchar code)
407 paint.drawLine(cx-1, y, cx-1, cy-2);
409 paint.drawLine(cx, y, cx, cy-2);
411 paint.drawLine(cx+1, y, cx+1, cy-2);
415 paint.drawLine(cx-1, cy+2, cx-1, ey);
417 paint.drawLine(cx, cy+2, cx, ey);
419 paint.drawLine(cx+1, cy+2, cx+1, ey);
423 paint.drawLine(x, cy-1, cx-2, cy-1);
425 paint.drawLine(x, cy, cx-2, cy);
427 paint.drawLine(x, cy+1, cx-2, cy+1);
431 paint.drawLine(cx+2, cy-1, ex, cy-1);
433 paint.drawLine(cx+2, cy, ex, cy);
435 paint.drawLine(cx+2, cy+1, ex, cy+1);
439 paint.drawPoint(cx-1, cy-1);
441 paint.drawPoint(cx, cy-1);
443 paint.drawPoint(cx+1, cy-1);
446 paint.drawPoint(cx-1, cy);
448 paint.drawPoint(cx, cy);
450 paint.drawPoint(cx+1, cy);
453 paint.drawPoint(cx-1, cy+1);
455 paint.drawPoint(cx, cy+1);
457 paint.drawPoint(cx+1, cy+1);
464 const QPen& currentPen = painter.pen();
468 QPen boldPen(currentPen);
470 painter.setPen( boldPen );
473 for (
int i=0 ; i < str.length(); i++)
475 uchar code = str[i].cell();
480 painter.setPen( currentPen );
493 if (useForegroundColor)
517 QRect scrollBarArea =
_scrollBar->isVisible() ?
521 QRegion contentsRegion = QRegion(rect).subtracted(scrollBarArea);
522 QRect contentsRect = contentsRegion.boundingRect();
524 painter.fillRect(contentsRect, backgroundColor);
525 painter.fillRect(scrollBarArea,
_scrollBar->palette().background());
530 const QColor& foregroundColor,
532 bool& invertCharacterColor)
534 QRect cursorRect = rect;
542 painter.setPen(foregroundColor);
549 int penWidth = qMax(1,painter.pen().width());
551 painter.drawRect(cursorRect.adjusted(penWidth/2,
553 - penWidth/2 - penWidth%2,
554 - penWidth/2 - penWidth%2));
563 invertCharacterColor =
true;
568 painter.drawLine(cursorRect.left(),
571 cursorRect.bottom());
573 painter.drawLine(cursorRect.left(),
576 cursorRect.bottom());
585 bool invertCharacterColor)
595 QFont font = painter.font();
596 if ( font.bold() != useBold
597 || font.underline() != useUnderline )
599 font.setBold(useBold);
600 font.setUnderline(useUnderline);
601 painter.setFont(font);
607 QPen pen = painter.pen();
608 if ( pen.color() != color )
611 painter.setPen(color);
624 painter.drawText(rect,0,text);
640 if ( backgroundColor != palette().background().color() )
645 bool invertCharacterColor =
false;
648 drawCursor(painter,rect,foregroundColor,backgroundColor,invertCharacterColor);
662 void TerminalDisplay::setCursorPos(
const int curx,
const int cury)
664 QPoint tL = contentsRect().topLeft();
669 ypos = _topMargin + tLy + _fontHeight*(cury-1) + _fontAscent;
670 xpos = _leftMargin + tLx + _fontWidth*curx;
704 QRect region = screenWindowRegion;
705 region.setBottom( qMin(region.bottom(),this->
_lines-2) );
710 || (region.top() +
abs(lines)) >= region.bottom()
711 || this->
_lines <= region.height() )
return;
719 int linesToMove = region.height() -
abs(lines);
720 int bytesToMove = linesToMove *
724 Q_ASSERT( linesToMove > 0 );
725 Q_ASSERT( bytesToMove > 0 );
731 Q_ASSERT( (
char*)lastCharPos + bytesToMove <
734 Q_ASSERT( (lines*this->_columns) <
_imageSize );
737 memmove( firstCharPos , lastCharPos , bytesToMove );
748 Q_ASSERT( (
char*)firstCharPos + bytesToMove <
752 memmove( lastCharPos , firstCharPos , bytesToMove );
758 scrollRect = QRect( topPoint ,
760 linesToMove * _fontHeight ));
776 rect.setBottom(hotSpot->
endLine());
803 update( preUpdateHotSpots | postUpdateHotSpots );
828 Q_ASSERT( this->_usedLines <= this->
_lines );
829 Q_ASSERT( this->_usedColumns <= this->
_columns );
833 QPoint tL = contentsRect().topLeft();
843 const int linesToUpdate = qMin(this->_lines, qMax(0,lines ));
844 const int columnsToUpdate = qMin(this->_columns,qMax(0,columns));
846 QChar *disstrU =
new QChar[columnsToUpdate];
847 char *dirtyMask =
new char[columnsToUpdate+2];
853 int dirtyLineCount = 0;
855 for (y = 0; y < linesToUpdate; y++)
860 bool updateLine =
false;
865 memset(dirtyMask, 0, columnsToUpdate+2);
867 for( x = 0 ; x < columnsToUpdate ; x++)
869 if ( newLine[x] != currentLine[x] )
876 for (x = 0; x < columnsToUpdate; x++)
891 bool doubleWidth = (x+1 == columnsToUpdate) ?
false : (newLine[x+1].character == 0);
895 int lln = columnsToUpdate -
x;
896 for (len = 1; len < lln; len++)
903 bool nextIsDoubleWidth = (x+len+1 == columnsToUpdate) ?
false : (newLine[x+len+1].character == 0);
910 nextIsDoubleWidth != doubleWidth )
916 QString unistr(disstrU, p);
952 dirtyRegion |= dirtyRect;
957 memcpy((
void*)currentLine,(
const void*)newLine,columnsToUpdate*
sizeof(
Character));
1007 _resizeWidget->setStyleSheet(
"background-color:palette(window);border-style:solid;border-width:1px;border-color:palette(dark)");
1048 QPainter paint(
this);
1051 foreach (QRect rect, (pe->region() & contentsRect()).rects())
1098 if ( preeditLength == 0 )
1114 bool invertColors =
false;
1120 drawCursor(painter,rect,foreground,background,invertColors);
1137 QPoint cursorPos = mapFromGlobal(QCursor::pos());
1149 QListIterator<Filter::HotSpot*> iter(spots);
1150 while (iter.hasNext())
1156 int startColumn = 0;
1162 while ( QChar(
_image[
loc(endColumn,
line)].character).isSpace() && endColumn > 0 )
1190 QFontMetrics metrics(font());
1194 int baseline = r.bottom() - metrics.descent();
1196 int underlinePos = baseline + metrics.underlinePos();
1198 if ( r.contains( mapFromGlobal(QCursor::pos()) ) )
1199 painter.drawLine( r.left() , underlinePos ,
1200 r.right() , underlinePos );
1207 painter.fillRect(r,QBrush(QColor(255,0,0,120)));
1216 QPoint topLeft = contentsRect().topLeft();
1218 int topLeftY = topLeft.y();
1232 QChar *disstrU =
new QChar[bufferSize];
1233 for (
int y = leftUpperY; y <= rightLowerY; y++)
1239 for (; x <= rightLowerX; x++)
1248 ushort extendedCharLength = 0;
1251 for (
int index = 0 ; index < extendedCharLength ; index++ )
1253 Q_ASSERT( p < bufferSize );
1254 disstrU[p++] = chars[index];
1263 Q_ASSERT( p < bufferSize );
1274 while (x+len <= rightLowerX &&
1275 _image[
loc(x+len,y)].foregroundColor == currentForeground &&
1276 _image[
loc(x+len,y)].backgroundColor == currentBackground &&
1277 _image[
loc(x+len,y)].rendition == currentRendition &&
1295 QString unistr(disstrU,p);
1320 QMatrix inverted = paint.matrix().inverted();
1321 textArea.moveCenter( inverted.map(textArea.center()) );
1334 paint.resetMatrix();
1368 result.setWidth(
_fontWidth * imageArea.width() );
1369 result.setHeight(
_fontHeight * imageArea.height() );
1403 parentWidget()->adjustSize();
1404 parentWidget()->setFixedSize(parentWidget()->
sizeHint());
1431 (
void*)&oldimg[oldcol*line],columns*
sizeof(
Character));
1446 #if defined (SIGWINCH)
1542 if ( !contentsRect().contains(ev->pos()) )
return;
1549 QPoint pos = QPoint(charColumn,charLine);
1551 if ( ev->button() == Qt::LeftButton)
1558 bool selected =
false;
1566 if ((!
_ctrlDrag || ev->modifiers() & Qt::ControlModifier) && selected ) {
1575 _preserveLineBreaks = !( ( ev->modifiers() & Qt::ControlModifier ) && !(ev->modifiers() & Qt::AltModifier) );
1576 _columnSelectionMode = (ev->modifiers() & Qt::AltModifier) && (ev->modifiers() & Qt::ControlModifier);
1578 if (
_mouseMarks || (ev->modifiers() & Qt::ShiftModifier))
1594 else if ( ev->button() == Qt::MidButton )
1601 else if ( ev->button() == Qt::RightButton )
1603 if (
_mouseMarks || (ev->modifiers() & Qt::ShiftModifier))
1606 ev->modifiers() & (Qt::ShiftModifier|Qt::ControlModifier),
1619 int charLine, charColumn;
1642 qMax(spot->startColumn() , spot->endColumn()) *
_fontHeight,
1647 const QString& tooltip = spot->tooltip();
1648 if ( !tooltip.isEmpty() )
1663 if (ev->buttons() == Qt::NoButton )
return;
1668 if (!
_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))
1671 if (ev->buttons() & Qt::LeftButton)
1673 if (ev->buttons() & Qt::MidButton)
1675 if (ev->buttons() & Qt::RightButton)
1714 if (ev->buttons() & Qt::MidButton)
return;
1720 void TerminalDisplay::setSelectionEnd()
1722 extendSelection( _configureRequestPoint );
1727 QPoint pos = position;
1733 QPoint tL = contentsRect().topLeft();
1767 QPoint here = QPoint(charColumn, charLine);
1773 bool swapping =
false;
1780 bool left_not_right = (here.y() < _iPntSelCorr.y() ||
1781 (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x()));
1782 bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() ||
1783 (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x()));
1784 swapping = left_not_right != old_left_not_right;
1787 QPoint
left = left_not_right ? here : _iPntSelCorr;
1788 i =
loc(left.x(), left.y());
1804 QPoint right = left_not_right ? _iPntSelCorr : here;
1805 i =
loc(right.x(), right.y());
1821 if (left_not_right) {
1833 bool above_not_below = (here.y() < _iPntSelCorr.y());
1835 QPoint above = above_not_below ? here : _iPntSelCorr;
1836 QPoint below = above_not_below ? _iPntSelCorr : here;
1849 if (above_not_below) {
1857 QPoint newSelBegin = QPoint(ohere.x(), ohere.y());
1869 bool left_not_right = (here.y() < _iPntSelCorr.y() ||
1870 (here.y() == _iPntSelCorr.y() && here.x() < _iPntSelCorr.x()));
1871 bool old_left_not_right = (_pntSelCorr.y() < _iPntSelCorr.y() ||
1872 (_pntSelCorr.y() == _iPntSelCorr.y() && _pntSelCorr.x() < _iPntSelCorr.x()));
1873 swapping = left_not_right != old_left_not_right;
1876 QPoint
left = left_not_right ? here : _iPntSelCorr;
1879 QPoint right = left_not_right ? _iPntSelCorr : here;
1881 i =
loc(right.x(), right.y());
1884 if (selClass ==
' ') {
1891 right = left_not_right ? _iPntSelCorr : here;
1900 if (left_not_right) {
1911 if ((here == _pntSelCorr) && (scroll ==
_scrollBar->value())) {
1915 if (here == ohere) {
1919 if (
_actSel < 2 || swapping) {
1921 _screenWindow->setSelectionStart(ohere.x(), ohere.y(),
true);
1923 _screenWindow->setSelectionStart(ohere.x() - 1 - offset , ohere.y(),
false);
1935 _screenWindow->setSelectionEnd(here.x() + offset, here.y());
1948 if ( ev->button() == Qt::LeftButton)
1970 if (!
_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))
1980 ((ev->button() == Qt::RightButton && !(ev->modifiers() & Qt::ShiftModifier))
1981 || ev->button() == Qt::MidButton) )
2025 if ( ev->button() != Qt::LeftButton)
return;
2033 QPoint pos(charColumn,charLine);
2036 if (!
_mouseMarks && !(ev->modifiers() & Qt::ShiftModifier))
2048 QPoint bgnSel = pos;
2049 QPoint endSel = pos;
2050 int i =
loc(bgnSel.x(),bgnSel.y());
2075 _screenWindow->setSelectionStart( bgnSel.x() , bgnSel.y() , false );
2078 i =
loc( endSel.x(), endSel.y() );
2096 if ( ( QChar(
_image[i].character ) ==
'@' ) && ( ( endSel.x() - bgnSel.x() ) > 0 ) )
2097 endSel.setX( x - 1 );
2109 QTimer::singleShot(QApplication::doubleClickInterval(),
this,
2115 if (ev->orientation() != Qt::Vertical)
2145 _iPntSel = QPoint(charColumn,charLine);
2160 int i =
loc(_iPntSel.x(),_iPntSel.y());
2162 int x = _iPntSel.x();
2179 _screenWindow->setSelectionStart( x , _iPntSel.y() , false );
2183 _screenWindow->setSelectionStart( 0 , _iPntSel.y() , false );
2211 QChar qch=QChar(ch);
2212 if ( qch.isSpace() )
return ' ';
2214 if ( qch.isLetterOrNumber() ||
_wordCharacters.contains(qch, Qt::CaseInsensitive ) )
2229 setCursor(
_mouseMarks ? Qt::IBeamCursor : Qt::ArrowCursor );
2250 QString
text = QApplication::clipboard()->
text(useXselection ? QClipboard::Selection :
2251 QClipboard::Clipboard);
2254 if ( ! text.isEmpty() )
2256 text.replace(
"\n",
"\r");
2257 QKeyEvent e(QEvent::KeyPress, 0, Qt::NoModifier, text);
2266 QApplication::clipboard()->setText(t, QClipboard::Selection);
2276 if (text.isEmpty ())
2279 QApplication::clipboard()->setText(text);
2305 bool emitKeyPressSignal =
true;
2308 if ( event->modifiers() == Qt::ShiftModifier )
2312 if ( event->key() == Qt::Key_PageUp )
2317 else if ( event->key() == Qt::Key_PageDown )
2322 else if ( event->key() == Qt::Key_Up )
2327 else if ( event->key() == Qt::Key_Down )
2345 emitKeyPressSignal =
false;
2376 QKeyEvent keyEvent(QEvent::KeyPress,0,Qt::NoModifier,event->commitString());
2389 case Qt::ImMicroFocus:
2390 return imageToWidget(QRect(cursorPos.x(),cursorPos.y(),1,1));
2395 case Qt::ImCursorPosition:
2397 return cursorPos.x();
2399 case Qt::ImSurroundingText:
2403 QTextStream stream(&lineText);
2405 decoder.
begin(&stream);
2411 case Qt::ImCurrentSelection:
2423 if ( e->type() == QEvent::ShortcutOverride )
2425 QKeyEvent* keyEvent =
static_cast<QKeyEvent *
>( e );
2433 if ( (keyEvent->modifiers() == Qt::AltModifier) &&
2434 !keyEvent->text().isEmpty() )
2442 int keyCode = keyEvent->key() | keyEvent->modifiers();
2447 case Qt::Key_Delete:
2450 case Qt::Key_Backspace:
2495 _scrollBar->resize(QApplication::style()->pixelMetric(QStyle::PM_ScrollBarExtent),
2496 contentsRect().height());
2557 QSize newSize = QSize( columns *
_fontWidth ,
2560 if ( newSize !=
size() )
2600 if (event->mimeData()->hasFormat(
"text/plain"))
2601 event->acceptProposedAction();
2636 if(event->mimeData()->hasFormat(
"text/plain"))
2646 QMimeData *mimeData =
new QMimeData;
2647 mimeData->setText(QApplication::clipboard()->
text(QClipboard::Selection));
2664 "<a href=\"http://en.wikipedia.org/wiki/XON\">suspended</a>"
2665 " by pressing Ctrl+S."
2666 " Press <b>Ctrl+Q</b> to resume.</qt>"),
2671 palette.setColor(QPalette::Normal, QPalette::WindowText, QColor(Qt::white));
2672 palette.setColor(QPalette::Normal, QPalette::Window, QColor(Qt::black));
2683 Qt::LinksAccessibleByKeyboard);
2688 _gridLayout->addItem(
new QSpacerItem(0,0,QSizePolicy::Expanding,
2689 QSizePolicy::Expanding),