1 /* Copyright (C) 2008 e_k (e_k@users.sourceforge.net)
2 Copyright (C) 2012-2019 Jacob Dawid <jacob.dawid@cybercatalyst.com>
3
4 This library is free software: you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation; either
7 version 2 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18 */
19
20 #include <QDebug>
21
22 #include "unix/QUnixTerminalImpl.h"
23 #include "unix/kpty.h"
24
25 #include <termios.h>
26
QUnixTerminalImpl(QWidget * p)27 QUnixTerminalImpl::QUnixTerminalImpl(QWidget *p)
28 : QTerminal(p),
29 _parent (p)
30 {
31 initialize();
32 }
33
initialize()34 void QUnixTerminalImpl::initialize()
35 {
36 m_terminalView = new TerminalView(this);
37 m_terminalView->setKeyboardCursorShape(TerminalView::UnderlineCursor);
38 m_terminalView->setBlinkingCursor(true);
39 m_terminalView->setBellMode(TerminalView::NotifyBell);
40 m_terminalView->setTerminalSizeHint(true);
41 m_terminalView->setContextMenuPolicy(Qt::CustomContextMenu);
42 m_terminalView->setTripleClickMode(TerminalView::SelectWholeLine);
43 m_terminalView->setTerminalSizeStartup(true);
44 m_terminalView->setSize(80, 40);
45 m_terminalView->setScrollBarPosition(TerminalView::ScrollBarRight);
46
47 UrlFilter *url_filter = new UrlFilter();
48 m_terminalView->filterChain ()->addFilter (url_filter);
49
50 UrlFilter *file_filter = new UrlFilter (Filter::Type::ErrorLink);
51 m_terminalView->filterChain ()->addFilter (file_filter);
52
53 connect (file_filter, SIGNAL (request_edit_mfile_signal (const QString&, int)),
54 _parent, SLOT (edit_mfile (const QString&, int)));
55 connect (file_filter, SIGNAL (request_open_file_signal (const QString&, int)),
56 _parent, SLOT (open_file (const QString&, int)));
57
58 connect(m_terminalView, SIGNAL(customContextMenuRequested(QPoint)),
59 this, SLOT(handleCustomContextMenuRequested(QPoint)));
60
61 connect (m_terminalView, SIGNAL (interrupt_signal (void)),
62 this, SLOT (terminal_interrupt ()));
63
64 #ifdef Q_OS_MAC
65 QFont font = QFont("Monaco");
66 font.setStyleHint(QFont::TypeWriter);
67 font.setPointSize(11);
68 #else
69 QFont font = QFont("Monospace");
70 font.setStyleHint(QFont::TypeWriter);
71 font.setPointSize(10);
72 #endif
73 setTerminalFont(font);
74 setFocusPolicy (Qt::StrongFocus);
75 setFocusProxy(m_terminalView);
76 setFocus(Qt::OtherFocusReason);
77
78 m_kpty = new KPty();
79 m_kpty->open();
80
81 m_terminalModel = new TerminalModel(m_kpty);
82 m_terminalModel->setAutoClose(true);
83 m_terminalModel->setCodec(QTextCodec::codecForName("UTF-8"));
84 m_terminalModel->setHistoryType(HistoryTypeBuffer (1000));
85 m_terminalModel->setDarkBackground(true);
86 m_terminalModel->setKeyBindings("");
87 m_terminalModel->run();
88 m_terminalModel->addView(m_terminalView);
89 connectToPty();
90 }
setScrollBufferSize(int value)91 void QUnixTerminalImpl::setScrollBufferSize(int value)
92 {
93 if (value > 0)
94 {
95 m_terminalModel->clearHistory ();
96 m_terminalModel->setHistoryType (HistoryTypeBuffer ( value ));
97 }
98 else
99 m_terminalModel->setHistoryType (HistoryTypeNone ());
100 }
101
102 QList<QAction*>
get_hotspot_actions(const QPoint & at)103 QUnixTerminalImpl::get_hotspot_actions (const QPoint& at)
104 {
105 return m_terminalView->filterActions (at);
106 }
107
connectToPty()108 void QUnixTerminalImpl::connectToPty()
109 {
110 // Store the file descriptor associated with the STDERR stream onto
111 // another temporary file descriptor for reconnect in the destructor.
112 fdstderr = dup (STDERR_FILENO);
113
114 int fds = m_kpty->slaveFd();
115
116 dup2 (fds, STDIN_FILENO);
117 dup2 (fds, STDOUT_FILENO);
118 dup2 (fds, STDERR_FILENO);
119
120 if(!isatty(STDIN_FILENO)) {
121 qDebug("Error: stdin is not a tty.");
122 }
123
124 if(!isatty(STDOUT_FILENO)) {
125 qDebug("Error: stdout is not a tty.");
126 }
127
128 if(!isatty(STDERR_FILENO)) {
129 qDebug("Error: stderr is not a tty.");
130 }
131 }
132
~QUnixTerminalImpl()133 QUnixTerminalImpl::~QUnixTerminalImpl()
134 {
135 delete m_terminalModel;
136 delete m_kpty;
137 delete m_terminalView;
138
139 // Restore stderr so that any errors at exit might appear somewhere.
140 dup2 (fdstderr, STDERR_FILENO);
141
142 emit destroyed();
143 }
144
setTerminalFont(const QFont & font)145 void QUnixTerminalImpl::setTerminalFont(const QFont &font)
146 {
147 if(!m_terminalView)
148 return;
149 m_terminalView->setVTFont(font);
150 }
151
setSize(int h,int v)152 void QUnixTerminalImpl::setSize(int h, int v)
153 {
154 if(!m_terminalView)
155 return;
156 m_terminalView->setSize(h, v);
157 }
158
sendText(const QString & text)159 void QUnixTerminalImpl::sendText(const QString& text)
160 {
161 m_terminalModel->sendText(text);
162 }
163
setCursorType(CursorType type,bool blinking)164 void QUnixTerminalImpl::setCursorType(CursorType type, bool blinking)
165 {
166 switch(type) {
167 case UnderlineCursor: m_terminalView->setKeyboardCursorShape(TerminalView::UnderlineCursor); break;
168 case BlockCursor: m_terminalView->setKeyboardCursorShape(TerminalView::BlockCursor); break;
169 case IBeamCursor: m_terminalView->setKeyboardCursorShape(TerminalView::IBeamCursor); break;
170 }
171 m_terminalView->setBlinkingCursor(blinking);
172 }
173
174 // FIXME -- not sure how to make these work properly given the way the
175 // Unix terminal handles colors.
setBackgroundColor(const QColor & color)176 void QUnixTerminalImpl::setBackgroundColor (const QColor& color)
177 {
178 ColorEntry cols[TABLE_COLORS];
179
180 const ColorEntry * curr_cols = m_terminalView->colorTable();
181 for(int i=0;i<TABLE_COLORS;i++)
182 {
183 cols[i] = curr_cols[i];
184 }
185
186 cols[DEFAULT_BACK_COLOR].color = color;
187
188 m_terminalView->setColorTable(cols);
189
190 QString css = QString ("TerminalView {\n"
191 " background: %1;\n"
192 "}\n").arg (color.name ());
193 setStyleSheet (css);
194
195 }
setForegroundColor(const QColor & color)196 void QUnixTerminalImpl::setForegroundColor (const QColor& color)
197 {
198 ColorEntry cols[TABLE_COLORS];
199
200 const ColorEntry * curr_cols = m_terminalView->colorTable();
201 for(int i=0;i<TABLE_COLORS;i++)
202 {
203 cols[i] = curr_cols[i];
204 }
205
206 cols[DEFAULT_FORE_COLOR].color = color;
207
208 m_terminalView->setColorTable(cols);
209
210
211 }
setSelectionColor(const QColor & color)212 void QUnixTerminalImpl::setSelectionColor (const QColor& color) { }
213
setCursorColor(bool useForegroundColor,const QColor & color)214 void QUnixTerminalImpl::setCursorColor (bool useForegroundColor,
215 const QColor& color)
216 {
217 m_terminalView->setKeyboardCursorColor (useForegroundColor, color);
218 }
219
showEvent(QShowEvent *)220 void QUnixTerminalImpl::showEvent(QShowEvent *)
221 {
222 m_terminalView->updateImage();
223 m_terminalView->repaint();
224 m_terminalView->update();
225 }
226
resizeEvent(QResizeEvent *)227 void QUnixTerminalImpl::resizeEvent(QResizeEvent*)
228 {
229 m_terminalView->resize(this->size());
230 m_terminalView->updateImage();
231 m_terminalView->repaint();
232 m_terminalView->update();
233 }
234
copyClipboard()235 void QUnixTerminalImpl::copyClipboard()
236 {
237 m_terminalView->copyClipboard (_extra_interrupt);
238 }
239
pasteClipboard()240 void QUnixTerminalImpl::pasteClipboard()
241 {
242 m_terminalView->pasteClipboard();
243 }
244
selectAll()245 void QUnixTerminalImpl::selectAll()
246 {
247 m_terminalView->selectAll();
248 }
249
250
selectedText()251 QString QUnixTerminalImpl::selectedText ()
252 {
253 return m_terminalView->selectedText ();
254 }
255
256 void
has_extra_interrupt(bool extra)257 QUnixTerminalImpl::has_extra_interrupt (bool extra)
258 {
259 _extra_interrupt = extra;
260 }
261
262 void
handle_visibility_changed(bool visible)263 QUnixTerminalImpl::handle_visibility_changed (bool visible)
264 {
265 m_terminalView->visibility_changed (visible);
266 };
267