1 /*  Copyright (C) 2008 e_k (e_k@users.sourceforge.net)
2 
3     This library is free software; you can redistribute it and/or
4     modify it under the terms of the GNU Library General Public
5     License as published by the Free Software Foundation; either
6     version 2 of the License, or (at your option) any later version.
7 
8     This library is distributed in the hope that it will be useful,
9     but WITHOUT ANY WARRANTY; without even the implied warranty of
10     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11     Library General Public License for more details.
12 
13     You should have received a copy of the GNU Library General Public License
14     along with this library; see the file COPYING.LIB.  If not, write to
15     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16     Boston, MA 02110-1301, USA.
17 */
18 
19 #include <QLayout>
20 #include <QBoxLayout>
21 #include <QtDebug>
22 #include <QDir>
23 #include <QMessageBox>
24 
25 #include "ColorTables.h"
26 #include "Session.h"
27 #include "Screen.h"
28 #include "ScreenWindow.h"
29 #include "Emulation.h"
30 #include "TerminalDisplay.h"
31 #include "KeyboardTranslator.h"
32 #include "ColorScheme.h"
33 #include "SearchBar.h"
34 #include "qtermwidget.h"
35 
36 
37 #define STEP_ZOOM 1
38 
39 using namespace Konsole;
40 
createTermWidget(int startnow,void * parent)41 void *createTermWidget(int startnow, void *parent)
42 {
43     return (void*) new QTermWidget(startnow, (QWidget*)parent);
44 }
45 
46 struct TermWidgetImpl {
47     TermWidgetImpl(QWidget* parent = 0);
48 
49     TerminalDisplay *m_terminalDisplay;
50     Session *m_session;
51 
52     Session* createSession(QWidget* parent);
53     TerminalDisplay* createTerminalDisplay(Session *session, QWidget* parent);
54 };
55 
TermWidgetImpl(QWidget * parent)56 TermWidgetImpl::TermWidgetImpl(QWidget* parent)
57 {
58     this->m_session = createSession(parent);
59     this->m_terminalDisplay = createTerminalDisplay(this->m_session, parent);
60 }
61 
62 
createSession(QWidget * parent)63 Session *TermWidgetImpl::createSession(QWidget* parent)
64 {
65     Session *session = new Session(parent);
66 
67     session->setTitle(Session::NameRole, QLatin1String("QTermWidget"));
68 
69     /* Thats a freaking bad idea!!!!
70      * /bin/bash is not there on every system
71      * better set it to the current $SHELL
72      * Maybe you can also make a list available and then let the widget-owner decide what to use.
73      * By setting it to $SHELL right away we actually make the first filecheck obsolete.
74      * But as iam not sure if you want to do anything else ill just let both checks in and set this to $SHELL anyway.
75      */
76     //session->setProgram("/bin/bash");
77 
78     session->setProgram(QString::fromLocal8Bit(qgetenv("SHELL")));
79 
80 
81 
82     QStringList args = QStringList(QString());
83     session->setArguments(args);
84     session->setAutoClose(true);
85 
86     session->setCodec(QTextCodec::codecForName("UTF-8"));
87 
88     session->setFlowControlEnabled(true);
89     session->setHistoryType(HistoryTypeBuffer(1000));
90 
91     session->setDarkBackground(true);
92 
93     session->setKeyBindings(QString());
94     return session;
95 }
96 
createTerminalDisplay(Session * session,QWidget * parent)97 TerminalDisplay *TermWidgetImpl::createTerminalDisplay(Session *session, QWidget* parent)
98 {
99 //    TerminalDisplay* display = new TerminalDisplay(this);
100     TerminalDisplay* display = new TerminalDisplay(parent);
101 
102     display->setBellMode(TerminalDisplay::NotifyBell);
103     display->setTerminalSizeHint(true);
104     display->setTripleClickMode(TerminalDisplay::SelectWholeLine);
105     display->setTerminalSizeStartup(true);
106 
107     display->setRandomSeed(session->sessionId() * 31);
108 
109     return display;
110 }
111 
112 
QTermWidget(int startnow,QWidget * parent)113 QTermWidget::QTermWidget(int startnow, QWidget *parent)
114     : QWidget(parent)
115 {
116     init(startnow);
117 }
118 
QTermWidget(QWidget * parent)119 QTermWidget::QTermWidget(QWidget *parent)
120     : QWidget(parent)
121 {
122     init(1);
123 }
124 
selectionChanged(bool textSelected)125 void QTermWidget::selectionChanged(bool textSelected)
126 {
127     emit copyAvailable(textSelected);
128 }
129 
find()130 void QTermWidget::find()
131 {
132     search(true, false);
133 }
134 
findNext()135 void QTermWidget::findNext()
136 {
137     search(true, true);
138 }
139 
findPrevious()140 void QTermWidget::findPrevious()
141 {
142     search(false, false);
143 }
144 
search(bool forwards,bool next)145 void QTermWidget::search(bool forwards, bool next)
146 {
147     int startColumn, startLine;
148 
149     if (next) // search from just after current selection
150     {
151         m_impl->m_terminalDisplay->screenWindow()->screen()->getSelectionEnd(startColumn, startLine);
152         startColumn++;
153     }
154     else // search from start of current selection
155     {
156         m_impl->m_terminalDisplay->screenWindow()->screen()->getSelectionStart(startColumn, startLine);
157     }
158 
159     qDebug() << "current selection starts at: " << startColumn << startLine;
160     qDebug() << "current cursor position: " << m_impl->m_terminalDisplay->screenWindow()->cursorPosition();
161 
162     QRegExp regExp(m_searchBar->searchText());
163     regExp.setPatternSyntax(m_searchBar->useRegularExpression() ? QRegExp::RegExp : QRegExp::FixedString);
164     regExp.setCaseSensitivity(m_searchBar->matchCase() ? Qt::CaseSensitive : Qt::CaseInsensitive);
165 
166     HistorySearch *historySearch =
167             new HistorySearch(m_impl->m_session->emulation(), regExp, forwards, startColumn, startLine, this);
168     connect(historySearch, SIGNAL(matchFound(int, int, int, int)), this, SLOT(matchFound(int, int, int, int)));
169     connect(historySearch, SIGNAL(noMatchFound()), this, SLOT(noMatchFound()));
170     connect(historySearch, SIGNAL(noMatchFound()), m_searchBar, SLOT(noMatchFound()));
171     historySearch->search();
172 }
173 
174 
matchFound(int startColumn,int startLine,int endColumn,int endLine)175 void QTermWidget::matchFound(int startColumn, int startLine, int endColumn, int endLine)
176 {
177     ScreenWindow* sw = m_impl->m_terminalDisplay->screenWindow();
178     qDebug() << "Scroll to" << startLine;
179     sw->scrollTo(startLine);
180     sw->setTrackOutput(false);
181     sw->notifyOutputChanged();
182     sw->setSelectionStart(startColumn, startLine - sw->currentLine(), false);
183     sw->setSelectionEnd(endColumn, endLine - sw->currentLine());
184 }
185 
noMatchFound()186 void QTermWidget::noMatchFound()
187 {
188         m_impl->m_terminalDisplay->screenWindow()->clearSelection();
189 }
190 
getShellPID()191 int QTermWidget::getShellPID()
192 {
193     return m_impl->m_session->processId();
194 }
195 
changeDir(const QString & dir)196 void QTermWidget::changeDir(const QString & dir)
197 {
198     /*
199        this is a very hackish way of trying to determine if the shell is in
200        the foreground before attempting to change the directory.  It may not
201        be portable to anything other than Linux.
202     */
203     QString strCmd;
204     strCmd.setNum(getShellPID());
205     strCmd.prepend(QLatin1String("ps -j "));
206     strCmd.append(QLatin1String(" | tail -1 | awk '{ print $5 }' | grep -q \\+"));
207     int retval = system(strCmd.toStdString().c_str());
208 
209     if (!retval) {
210         QString cmd = QLatin1String("cd ") + dir + QLatin1Char('\n');
211         sendText(cmd);
212     }
213 }
214 
sizeHint() const215 QSize QTermWidget::sizeHint() const
216 {
217     QSize size = m_impl->m_terminalDisplay->sizeHint();
218     size.rheight() = 150;
219     return size;
220 }
221 
setTerminalSizeHint(bool on)222 void QTermWidget::setTerminalSizeHint(bool on)
223 {
224     if (!m_impl->m_terminalDisplay)
225         return;
226     m_impl->m_terminalDisplay->setTerminalSizeHint(on);
227 }
228 
terminalSizeHint()229 bool QTermWidget::terminalSizeHint()
230 {
231     if (!m_impl->m_terminalDisplay)
232         return true;
233     return m_impl->m_terminalDisplay->terminalSizeHint();
234 }
235 
startShellProgram()236 void QTermWidget::startShellProgram()
237 {
238     if ( m_impl->m_session->isRunning() ) {
239         return;
240     }
241 
242     m_impl->m_session->run();
243 }
244 
startTerminalTeletype()245 void QTermWidget::startTerminalTeletype()
246 {
247     if ( m_impl->m_session->isRunning() ) {
248         return;
249     }
250 
251     m_impl->m_session->runEmptyPTY();
252     // redirect data from TTY to external recipient
253     connect( m_impl->m_session->emulation(), SIGNAL(sendData(const char *,int)),
254              this, SIGNAL(sendData(const char *,int)) );
255 }
256 
init(int startnow)257 void QTermWidget::init(int startnow)
258 {
259     m_layout = new QVBoxLayout();
260     m_layout->setMargin(0);
261     setLayout(m_layout);
262 
263     // translations
264     // First check $XDG_DATA_DIRS. This follows the implementation in libqtxdg
265     QString d = QFile::decodeName(qgetenv("XDG_DATA_DIRS"));
266     QStringList dirs = d.split(QLatin1Char(':'), QString::SkipEmptyParts);
267     if (dirs.isEmpty()) {
268         dirs.append(QString::fromLatin1("/usr/local/share"));
269         dirs.append(QString::fromLatin1("/usr/share"));
270     }
271     dirs.append(QFile::decodeName(TRANSLATIONS_DIR));
272 
273     m_translator = new QTranslator(this);
274 
275     for (const QString& dir : dirs) {
276         qDebug() << "Trying to load translation file from dir" << dir;
277         if (m_translator->load(QLocale::system(), QLatin1String("qtermwidget"), QLatin1String(QLatin1String("_")), dir)) {
278             qApp->installTranslator(m_translator);
279             qDebug() << "Translations found in" << dir;
280             break;
281         }
282     }
283 
284     m_impl = new TermWidgetImpl(this);
285     m_layout->addWidget(m_impl->m_terminalDisplay);
286 
287     connect(m_impl->m_session, SIGNAL(bellRequest(QString)), m_impl->m_terminalDisplay, SLOT(bell(QString)));
288     connect(m_impl->m_terminalDisplay, SIGNAL(notifyBell(QString)), this, SIGNAL(bell(QString)));
289 
290     connect(m_impl->m_session, SIGNAL(activity()), this, SIGNAL(activity()));
291     connect(m_impl->m_session, SIGNAL(silence()), this, SIGNAL(silence()));
292     connect(m_impl->m_session, &Session::profileChangeCommandReceived, this, &QTermWidget::profileChanged);
293     connect(m_impl->m_session, &Session::receivedData, this, &QTermWidget::receivedData);
294 
295     // That's OK, FilterChain's dtor takes care of UrlFilter.
296     UrlFilter *urlFilter = new UrlFilter();
297     connect(urlFilter, &UrlFilter::activated, this, &QTermWidget::urlActivated);
298     m_impl->m_terminalDisplay->filterChain()->addFilter(urlFilter);
299 
300     m_searchBar = new SearchBar(this);
301     m_searchBar->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Maximum);
302     connect(m_searchBar, SIGNAL(searchCriteriaChanged()), this, SLOT(find()));
303     connect(m_searchBar, SIGNAL(findNext()), this, SLOT(findNext()));
304     connect(m_searchBar, SIGNAL(findPrevious()), this, SLOT(findPrevious()));
305     m_layout->addWidget(m_searchBar);
306     m_searchBar->hide();
307 
308     if (startnow && m_impl->m_session) {
309         m_impl->m_session->run();
310     }
311 
312     this->setFocus( Qt::OtherFocusReason );
313     this->setFocusPolicy( Qt::WheelFocus );
314     m_impl->m_terminalDisplay->resize(this->size());
315 
316     this->setFocusProxy(m_impl->m_terminalDisplay);
317     connect(m_impl->m_terminalDisplay, SIGNAL(copyAvailable(bool)),
318             this, SLOT(selectionChanged(bool)));
319     connect(m_impl->m_terminalDisplay, SIGNAL(termGetFocus()),
320             this, SIGNAL(termGetFocus()));
321     connect(m_impl->m_terminalDisplay, SIGNAL(termLostFocus()),
322             this, SIGNAL(termLostFocus()));
323     connect(m_impl->m_terminalDisplay, SIGNAL(keyPressedSignal(QKeyEvent *)),
324             this, SIGNAL(termKeyPressed(QKeyEvent *)));
325 //    m_impl->m_terminalDisplay->setSize(80, 40);
326 
327     QFont font = QApplication::font();
328     font.setFamily(QLatin1String("Monospace"));
329     font.setPointSize(10);
330     font.setStyleHint(QFont::TypeWriter);
331     setTerminalFont(font);
332     m_searchBar->setFont(font);
333 
334     setScrollBarPosition(NoScrollBar);
335     setKeyboardCursorShape(Emulation::KeyboardCursorShape::BlockCursor);
336 
337     m_impl->m_session->addView(m_impl->m_terminalDisplay);
338 
339     connect(m_impl->m_session, SIGNAL(resizeRequest(QSize)), this, SLOT(setSize(QSize)));
340     connect(m_impl->m_session, SIGNAL(finished()), this, SLOT(sessionFinished()));
341     connect(m_impl->m_session, &Session::titleChanged, this, &QTermWidget::titleChanged);
342     connect(m_impl->m_session, &Session::cursorChanged, this, &QTermWidget::cursorChanged);
343 }
344 
345 
~QTermWidget()346 QTermWidget::~QTermWidget()
347 {
348     delete m_impl;
349     emit destroyed();
350 }
351 
352 
setTerminalFont(const QFont & font)353 void QTermWidget::setTerminalFont(const QFont &font)
354 {
355     if (!m_impl->m_terminalDisplay)
356         return;
357     m_impl->m_terminalDisplay->setVTFont(font);
358 }
359 
getTerminalFont()360 QFont QTermWidget::getTerminalFont()
361 {
362     if (!m_impl->m_terminalDisplay)
363         return QFont();
364     return m_impl->m_terminalDisplay->getVTFont();
365 }
366 
setTerminalOpacity(qreal level)367 void QTermWidget::setTerminalOpacity(qreal level)
368 {
369     if (!m_impl->m_terminalDisplay)
370         return;
371 
372     m_impl->m_terminalDisplay->setOpacity(level);
373 }
374 
setTerminalBackgroundImage(QString backgroundImage)375 void QTermWidget::setTerminalBackgroundImage(QString backgroundImage)
376 {
377     if (!m_impl->m_terminalDisplay)
378         return;
379 
380     m_impl->m_terminalDisplay->setBackgroundImage(backgroundImage);
381 }
382 
setShellProgram(const QString & progname)383 void QTermWidget::setShellProgram(const QString &progname)
384 {
385     if (!m_impl->m_session)
386         return;
387     m_impl->m_session->setProgram(progname);
388 }
389 
setWorkingDirectory(const QString & dir)390 void QTermWidget::setWorkingDirectory(const QString& dir)
391 {
392     if (!m_impl->m_session)
393         return;
394     m_impl->m_session->setInitialWorkingDirectory(dir);
395 }
396 
workingDirectory()397 QString QTermWidget::workingDirectory()
398 {
399     if (!m_impl->m_session)
400         return QString();
401 
402 #ifdef Q_OS_LINUX
403     // Christian Surlykke: On linux we could look at /proc/<pid>/cwd which should be a link to current
404     // working directory (<pid>: process id of the shell). I don't know about BSD.
405     // Maybe we could just offer it when running linux, for a start.
406     QDir d(QString::fromLatin1("/proc/%1/cwd").arg(getShellPID()));
407     if (!d.exists())
408     {
409         qDebug() << "Cannot find" << d.dirName();
410         goto fallback;
411     }
412     return d.canonicalPath();
413 #endif
414 
415 fallback:
416     // fallback, initial WD
417     return m_impl->m_session->initialWorkingDirectory();
418 }
419 
setArgs(const QStringList & args)420 void QTermWidget::setArgs(const QStringList &args)
421 {
422     if (!m_impl->m_session)
423         return;
424     m_impl->m_session->setArguments(args);
425 }
426 
setTextCodec(QTextCodec * codec)427 void QTermWidget::setTextCodec(QTextCodec *codec)
428 {
429     if (!m_impl->m_session)
430         return;
431     m_impl->m_session->setCodec(codec);
432 }
433 
setColorScheme(const QString & origName)434 void QTermWidget::setColorScheme(const QString& origName)
435 {
436     const ColorScheme *cs = 0;
437 
438     const bool isFile = QFile::exists(origName);
439     const QString& name = isFile ?
440             QFileInfo(origName).baseName() :
441             origName;
442 
443     // avoid legacy (int) solution
444     if (!availableColorSchemes().contains(name))
445     {
446         if (isFile)
447         {
448             if (ColorSchemeManager::instance()->loadCustomColorScheme(origName))
449                 cs = ColorSchemeManager::instance()->findColorScheme(name);
450             else
451                 qWarning () << Q_FUNC_INFO
452                         << "cannot load color scheme from"
453                         << origName;
454         }
455 
456         if (!cs)
457             cs = ColorSchemeManager::instance()->defaultColorScheme();
458     }
459     else
460         cs = ColorSchemeManager::instance()->findColorScheme(name);
461 
462     if (! cs)
463     {
464         QMessageBox::information(this,
465                                  tr("Color Scheme Error"),
466                                  tr("Cannot load color scheme: %1").arg(name));
467         return;
468     }
469     ColorEntry table[TABLE_COLORS];
470     cs->getColorTable(table);
471     m_impl->m_terminalDisplay->setColorTable(table);
472 }
473 
availableColorSchemes()474 QStringList QTermWidget::availableColorSchemes()
475 {
476     QStringList ret;
477     const auto allColorSchemes = ColorSchemeManager::instance()->allColorSchemes();
478     for (const ColorScheme* cs : allColorSchemes)
479         ret.append(cs->name());
480     return ret;
481 }
482 
addCustomColorSchemeDir(const QString & custom_dir)483 void QTermWidget::addCustomColorSchemeDir(const QString& custom_dir)
484 {
485     ColorSchemeManager::instance()->addCustomColorSchemeDir(custom_dir);
486 }
487 
setSize(const QSize & size)488 void QTermWidget::setSize(const QSize &size)
489 {
490     if (!m_impl->m_terminalDisplay)
491         return;
492     m_impl->m_terminalDisplay->setSize(size.width(), size.height());
493 }
494 
setHistorySize(int lines)495 void QTermWidget::setHistorySize(int lines)
496 {
497     if (lines < 0)
498         m_impl->m_session->setHistoryType(HistoryTypeFile());
499     else
500         m_impl->m_session->setHistoryType(HistoryTypeBuffer(lines));
501 }
502 
setScrollBarPosition(ScrollBarPosition pos)503 void QTermWidget::setScrollBarPosition(ScrollBarPosition pos)
504 {
505     if (!m_impl->m_terminalDisplay)
506         return;
507     m_impl->m_terminalDisplay->setScrollBarPosition(pos);
508 }
509 
scrollToEnd()510 void QTermWidget::scrollToEnd()
511 {
512     if (!m_impl->m_terminalDisplay)
513         return;
514     m_impl->m_terminalDisplay->scrollToEnd();
515 }
516 
sendText(const QString & text)517 void QTermWidget::sendText(const QString &text)
518 {
519     m_impl->m_session->sendText(text);
520 }
521 
resizeEvent(QResizeEvent *)522 void QTermWidget::resizeEvent(QResizeEvent*)
523 {
524 //qDebug("global window resizing...with %d %d", this->size().width(), this->size().height());
525     m_impl->m_terminalDisplay->resize(this->size());
526 }
527 
528 
sessionFinished()529 void QTermWidget::sessionFinished()
530 {
531     emit finished();
532 }
533 
bracketText(QString & text)534 void QTermWidget::bracketText(QString& text)
535 {
536     m_impl->m_terminalDisplay->bracketText(text);
537 }
538 
copyClipboard()539 void QTermWidget::copyClipboard()
540 {
541     m_impl->m_terminalDisplay->copyClipboard();
542 }
543 
pasteClipboard()544 void QTermWidget::pasteClipboard()
545 {
546     m_impl->m_terminalDisplay->pasteClipboard();
547 }
548 
pasteSelection()549 void QTermWidget::pasteSelection()
550 {
551     m_impl->m_terminalDisplay->pasteSelection();
552 }
553 
setZoom(int step)554 void QTermWidget::setZoom(int step)
555 {
556     if (!m_impl->m_terminalDisplay)
557         return;
558 
559     QFont font = m_impl->m_terminalDisplay->getVTFont();
560 
561     font.setPointSize(font.pointSize() + step);
562     setTerminalFont(font);
563 }
564 
zoomIn()565 void QTermWidget::zoomIn()
566 {
567     setZoom(STEP_ZOOM);
568 }
569 
zoomOut()570 void QTermWidget::zoomOut()
571 {
572     setZoom(-STEP_ZOOM);
573 }
574 
setKeyBindings(const QString & kb)575 void QTermWidget::setKeyBindings(const QString & kb)
576 {
577     m_impl->m_session->setKeyBindings(kb);
578 }
579 
clear()580 void QTermWidget::clear()
581 {
582     m_impl->m_session->emulation()->reset();
583     m_impl->m_session->refresh();
584     m_impl->m_session->clearHistory();
585 }
586 
setFlowControlEnabled(bool enabled)587 void QTermWidget::setFlowControlEnabled(bool enabled)
588 {
589     m_impl->m_session->setFlowControlEnabled(enabled);
590 }
591 
availableKeyBindings()592 QStringList QTermWidget::availableKeyBindings()
593 {
594     return KeyboardTranslatorManager::instance()->allTranslators();
595 }
596 
keyBindings()597 QString QTermWidget::keyBindings()
598 {
599     return m_impl->m_session->keyBindings();
600 }
601 
toggleShowSearchBar()602 void QTermWidget::toggleShowSearchBar()
603 {
604     m_searchBar->isHidden() ? m_searchBar->show() : m_searchBar->hide();
605 }
606 
flowControlEnabled(void)607 bool QTermWidget::flowControlEnabled(void)
608 {
609     return m_impl->m_session->flowControlEnabled();
610 }
611 
setFlowControlWarningEnabled(bool enabled)612 void QTermWidget::setFlowControlWarningEnabled(bool enabled)
613 {
614     if (flowControlEnabled()) {
615         // Do not show warning label if flow control is disabled
616         m_impl->m_terminalDisplay->setFlowControlWarningEnabled(enabled);
617     }
618 }
619 
setEnvironment(const QStringList & environment)620 void QTermWidget::setEnvironment(const QStringList& environment)
621 {
622     m_impl->m_session->setEnvironment(environment);
623 }
624 
setMotionAfterPasting(int action)625 void QTermWidget::setMotionAfterPasting(int action)
626 {
627     m_impl->m_terminalDisplay->setMotionAfterPasting((Konsole::MotionAfterPasting) action);
628 }
629 
historyLinesCount()630 int QTermWidget::historyLinesCount()
631 {
632     return m_impl->m_terminalDisplay->screenWindow()->screen()->getHistLines();
633 }
634 
screenColumnsCount()635 int QTermWidget::screenColumnsCount()
636 {
637     return m_impl->m_terminalDisplay->screenWindow()->screen()->getColumns();
638 }
639 
screenLinesCount()640 int QTermWidget::screenLinesCount()
641 {
642     return m_impl->m_terminalDisplay->screenWindow()->screen()->getLines();
643 }
644 
setSelectionStart(int row,int column)645 void QTermWidget::setSelectionStart(int row, int column)
646 {
647     m_impl->m_terminalDisplay->screenWindow()->screen()->setSelectionStart(column, row, true);
648 }
649 
setSelectionEnd(int row,int column)650 void QTermWidget::setSelectionEnd(int row, int column)
651 {
652     m_impl->m_terminalDisplay->screenWindow()->screen()->setSelectionEnd(column, row);
653 }
654 
getSelectionStart(int & row,int & column)655 void QTermWidget::getSelectionStart(int& row, int& column)
656 {
657     m_impl->m_terminalDisplay->screenWindow()->screen()->getSelectionStart(column, row);
658 }
659 
getSelectionEnd(int & row,int & column)660 void QTermWidget::getSelectionEnd(int& row, int& column)
661 {
662     m_impl->m_terminalDisplay->screenWindow()->screen()->getSelectionEnd(column, row);
663 }
664 
selectedText(bool preserveLineBreaks)665 QString QTermWidget::selectedText(bool preserveLineBreaks)
666 {
667     return m_impl->m_terminalDisplay->screenWindow()->screen()->selectedText(preserveLineBreaks);
668 }
669 
setMonitorActivity(bool monitor)670 void QTermWidget::setMonitorActivity(bool monitor)
671 {
672     m_impl->m_session->setMonitorActivity(monitor);
673 }
674 
setMonitorSilence(bool monitor)675 void QTermWidget::setMonitorSilence(bool monitor)
676 {
677     m_impl->m_session->setMonitorSilence(monitor);
678 }
679 
setSilenceTimeout(int seconds)680 void QTermWidget::setSilenceTimeout(int seconds)
681 {
682     m_impl->m_session->setMonitorSilenceSeconds(seconds);
683 }
684 
getHotSpotAt(const QPoint & pos) const685 Filter::HotSpot* QTermWidget::getHotSpotAt(const QPoint &pos) const
686 {
687     int row = 0, column = 0;
688     m_impl->m_terminalDisplay->getCharacterPosition(pos, row, column);
689     return getHotSpotAt(row, column);
690 }
691 
getHotSpotAt(int row,int column) const692 Filter::HotSpot* QTermWidget::getHotSpotAt(int row, int column) const
693 {
694     return m_impl->m_terminalDisplay->filterChain()->hotSpotAt(row, column);
695 }
696 
filterActions(const QPoint & position,QWidget * parent)697 QList<QAction*> QTermWidget::filterActions(const QPoint& position, QWidget* parent)
698 {
699     return m_impl->m_terminalDisplay->filterActions(position, parent);
700 }
701 
getPtySlaveFd() const702 int QTermWidget::getPtySlaveFd() const
703 {
704     return m_impl->m_session->getPtySlaveFd();
705 }
706 
setKeyboardCursorShape(KeyboardCursorShape shape)707 void QTermWidget::setKeyboardCursorShape(KeyboardCursorShape shape)
708 {
709     if (!m_impl->m_terminalDisplay)
710         return;
711     m_impl->m_terminalDisplay->setKeyboardCursorShape(shape);
712 }
713 
setBlinkingCursor(bool blink)714 void QTermWidget::setBlinkingCursor(bool blink)
715 {
716     if (!m_impl->m_terminalDisplay)
717         return;
718     m_impl->m_terminalDisplay->setBlinkingCursor(blink);
719 }
720 
setBidiEnabled(bool enabled)721 void QTermWidget::setBidiEnabled(bool enabled)
722 {
723     if (!m_impl->m_terminalDisplay)
724         return;
725     m_impl->m_terminalDisplay->setBidiEnabled(enabled);
726 }
727 
isBidiEnabled()728 bool QTermWidget::isBidiEnabled()
729 {
730     if (!m_impl->m_terminalDisplay)
731         return false; // Default value
732     return m_impl->m_terminalDisplay->isBidiEnabled();
733 }
734 
title() const735 QString QTermWidget::title() const
736 {
737     QString title = m_impl->m_session->userTitle();
738     if (title.isEmpty())
739         title = m_impl->m_session->title(Konsole::Session::NameRole);
740     return title;
741 }
742 
icon() const743 QString QTermWidget::icon() const
744 {
745     QString icon = m_impl->m_session->iconText();
746     if (icon.isEmpty())
747         icon = m_impl->m_session->iconName();
748     return icon;
749 }
750 
isTitleChanged() const751 bool QTermWidget::isTitleChanged() const
752 {
753     return m_impl->m_session->isTitleChanged();
754 }
755 
setAutoClose(bool autoClose)756 void QTermWidget::setAutoClose(bool autoClose)
757 {
758     m_impl->m_session->setAutoClose(autoClose);
759 }
760 
cursorChanged(Konsole::Emulation::KeyboardCursorShape cursorShape,bool blinkingCursorEnabled)761 void QTermWidget::cursorChanged(Konsole::Emulation::KeyboardCursorShape cursorShape, bool blinkingCursorEnabled)
762 {
763     // TODO: A switch to enable/disable DECSCUSR?
764     setKeyboardCursorShape(cursorShape);
765     setBlinkingCursor(blinkingCursorEnabled);
766 }
767 
setMargin(int margin)768 void QTermWidget::setMargin(int margin)
769 {
770     m_impl->m_terminalDisplay->setMargin(margin);
771 }
772 
getMargin() const773 int QTermWidget::getMargin() const
774 {
775     return m_impl->m_terminalDisplay->margin();
776 }
777