├── qml
├── qml.pro
└── Yat
│ ├── qmldir
│ ├── Yat.pro
│ ├── plugin
│ ├── yat_extension_plugin.h
│ ├── object_destruct_item.h
│ ├── object_destruct_item.cpp
│ ├── terminal_screen.h
│ ├── terminal_screen.cpp
│ ├── yat_extension_plugin.cpp
│ ├── mono_text.h
│ └── mono_text.cpp
│ ├── Cursor.qml
│ ├── Text.qml
│ ├── Selection.qml
│ └── Screen.qml
├── tests
├── tests.pro
└── auto
│ ├── auto.pro
│ └── block
│ └── block.pro
├── docs
└── Ecma-048.pdf
├── yat_app
├── yat.qrc
├── yat_app.pro
├── main.cpp
└── yat.qml
├── .gitignore
├── yat.pro
├── backend
├── text_style.cpp
├── backend.pri
├── color_palette.h
├── main.cpp
├── nrc_text_codec.h
├── text_style.h
├── yat_pty.h
├── scrollback.h
├── selection.h
├── parser.h
├── utf8_decoder.h
├── block.h
├── text.h
├── yat_pty.cpp
├── nrc_text_codec.cpp
├── screen_data.h
├── screen.h
├── cursor.h
├── selection.cpp
├── controll_chars.h
├── text.cpp
├── scrollback.cpp
├── color_palette.cpp
├── cursor.cpp
├── character_sets.h
├── screen_data.cpp
└── screen.cpp
└── README.md
/qml/qml.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE=subdirs
2 | SUBDIRS= \
3 | Yat \
4 |
--------------------------------------------------------------------------------
/tests/tests.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 | SUBDIRS = \
3 | auto
4 |
--------------------------------------------------------------------------------
/tests/auto/auto.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = subdirs
2 | SUBDIRS = \
3 | block
4 |
--------------------------------------------------------------------------------
/qml/Yat/qmldir:
--------------------------------------------------------------------------------
1 | module Yat
2 | plugin yat
3 | classname YatExtensionPlugin
4 |
--------------------------------------------------------------------------------
/docs/Ecma-048.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jorgen/yat/HEAD/docs/Ecma-048.pdf
--------------------------------------------------------------------------------
/yat_app/yat.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | yat.qml
4 |
5 |
6 |
--------------------------------------------------------------------------------
/yat_app/yat_app.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE = app
2 | TARGET = yat
3 |
4 | QT += qml quick
5 | SOURCES += main.cpp
6 |
7 | RESOURCES += yat.qrc
8 |
9 |
--------------------------------------------------------------------------------
/tests/auto/block/block.pro:
--------------------------------------------------------------------------------
1 | CONFIG += testcase
2 | QT += testlib quick
3 |
4 | include(../../../backend/backend.pri)
5 |
6 | SOURCES += \
7 | tst_block.cpp \
8 |
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Makefile
2 | .moc
3 | .obj
4 | yat
5 | yat.pro.user
6 | yat.pro.user.1.3
7 | yat.pro.user.2.6pre1
8 | yat_declarative/qrc_qml_sources.cpp
9 | *.o
10 | moc_*
11 | imports/Yat/*
12 |
--------------------------------------------------------------------------------
/yat.pro:
--------------------------------------------------------------------------------
1 | TEMPLATE=subdirs
2 | CONFIG += ordered
3 |
4 | !no_tests {
5 | SUBDIRS += tests
6 | } else {
7 | message(Tests are disabled)
8 | }
9 |
10 | SUBDIRS += qml
11 |
12 | CONFIG_VARS = $${OUT_PWD}$${QMAKE_DIR_SEP}.config.vars
13 | QMAKE_CACHE = $${OUT_PWD}$${QMAKE_DIR_SEP}.qmake.cache
14 |
15 | exists($$CONFIG_VARS) {
16 | system(echo include\\\($$CONFIG_VARS\\\) >> $$QMAKE_CACHE)
17 | }
18 |
--------------------------------------------------------------------------------
/yat_app/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | int main(int argc, char* argv[])
8 | {
9 | // do this before constructing QGuiApplication so that the custom logging rules will override the setFilterRules below
10 | qputenv("QT_LOGGING_CONF", QDir::homePath().toLocal8Bit() + "/.config/QtProject/qtlogging.ini");
11 | QGuiApplication app(argc, argv);
12 | QLoggingCategory::setFilterRules(QStringLiteral("yat.*.debug=false\nyat.*.info=false"));
13 | QQmlApplicationEngine engine(QUrl("qrc:///yat.qml"));
14 | return app.exec();
15 | }
16 |
--------------------------------------------------------------------------------
/backend/text_style.cpp:
--------------------------------------------------------------------------------
1 | #include "text_style.h"
2 |
3 | #include "screen.h"
4 | #include "text.h"
5 |
6 | #include
7 |
8 | TextStyle::TextStyle()
9 | : style(Normal)
10 | , foreground(0)
11 | , background(0)
12 | {
13 | }
14 |
15 | bool TextStyle::isCompatible(const TextStyle &other) const
16 | {
17 | return foreground == other.foreground
18 | && background == other.background
19 | && style == other.style;
20 | }
21 |
22 | QDebug operator<<(QDebug debug, TextStyleLine line)
23 | {
24 | debug << "[" << line.start_index << "(" << line.style << ":" << line.foreground << ":" << line.background << ")" << line.end_index << "]";
25 | return debug;
26 | }
27 |
28 | void TextStyleLine::releaseTextSegment(Screen *screen)
29 | {
30 | if (text_segment) {
31 | text_segment->setVisible(false);
32 | screen->releaseTextSegment(text_segment);
33 | text_segment = 0;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/backend/backend.pri:
--------------------------------------------------------------------------------
1 | DEPENDPATH += $$PWD
2 | INCLUDEPATH += $$PWD
3 |
4 | LIBS += -lutil
5 |
6 | CONFIG += c++11
7 |
8 | MOC_DIR = .moc
9 | OBJECTS_DIR = .obj
10 |
11 | HEADERS += \
12 | $$PWD/yat_pty.h \
13 | $$PWD/text.h \
14 | $$PWD/controll_chars.h \
15 | $$PWD/parser.h \
16 | $$PWD/screen.h \
17 | $$PWD/block.h \
18 | $$PWD/color_palette.h \
19 | $$PWD/text_style.h \
20 | $$PWD/screen_data.h \
21 | $$PWD/cursor.h \
22 | $$PWD/nrc_text_codec.h \
23 | $$PWD/scrollback.h \
24 | $$PWD/utf8_decoder.h \
25 | $$PWD/selection.h
26 |
27 | SOURCES += \
28 | $$PWD/yat_pty.cpp \
29 | $$PWD/text.cpp \
30 | $$PWD/controll_chars.cpp \
31 | $$PWD/parser.cpp \
32 | $$PWD/screen.cpp \
33 | $$PWD/block.cpp \
34 | $$PWD/color_palette.cpp \
35 | $$PWD/text_style.cpp \
36 | $$PWD/screen_data.cpp \
37 | $$PWD/cursor.cpp \
38 | $$PWD/nrc_text_codec.cpp \
39 | $$PWD/scrollback.cpp \
40 | $$PWD/selection.cpp
41 |
42 |
--------------------------------------------------------------------------------
/qml/Yat/Yat.pro:
--------------------------------------------------------------------------------
1 | QT += core-private gui-private qml-private quick quick-private
2 | TARGET = yat
3 | TEMPLATE = lib
4 | CONFIG += plugin
5 | TARGETPATH = Yat
6 | DESTDIR = ../../imports/$$TARGETPATH
7 |
8 | include(../../backend/backend.pri)
9 |
10 | SOURCES += \
11 | plugin/terminal_screen.cpp \
12 | plugin/object_destruct_item.cpp \
13 | plugin/mono_text.cpp \
14 | plugin/yat_extension_plugin.cpp \
15 |
16 | HEADERS += \
17 | plugin/terminal_screen.h \
18 | plugin/object_destruct_item.h \
19 | plugin/mono_text.h \
20 | plugin/yat_extension_plugin.h \
21 |
22 | OTHER_FILES = \
23 | qmldir \
24 | Cursor.qml \
25 | Text.qml \
26 | Screen.qml \
27 | Selection.qml
28 |
29 | isEmpty(YAT_INSTALL_QML):YAT_INSTALL_QML = $$[QT_INSTALL_QML]
30 |
31 | target.path = $$YAT_INSTALL_QML/$$TARGETPATH
32 | INSTALLS += target
33 |
34 | other_files.files = $$OTHER_FILES
35 | other_files.path = $$YAT_INSTALL_QML/$$TARGETPATH
36 | INSTALLS += other_files
37 |
38 | for(other_file, OTHER_FILES) {
39 | ARGUMENTS = $${PWD}$${QMAKE_DIR_SEP}$$other_file $$DESTDIR
40 | !isEmpty(QMAKE_POST_LINK):QMAKE_POST_LINK += &&
41 | QMAKE_POST_LINK += $$QMAKE_COPY $$replace(ARGUMENTS, /, $$QMAKE_DIR_SEP)
42 | }
43 |
--------------------------------------------------------------------------------
/backend/color_palette.h:
--------------------------------------------------------------------------------
1 | #ifndef COLOR_PALETTE_H
2 | #define COLOR_PALETTE_H
3 |
4 | #include
5 | #include
6 |
7 | #include
8 |
9 |
10 |
11 | class ColorPalette : public QObject
12 | {
13 | Q_OBJECT
14 | Q_PROPERTY(QColor defaultBackground READ defaultBackground NOTIFY defaultBackgroundColorChanged)
15 | public:
16 | ColorPalette(QObject *parent = 0);
17 |
18 | enum Color {
19 | Black,
20 | Red,
21 | Green,
22 | Yellow,
23 | Blue,
24 | Magenta,
25 | Cyan,
26 | White,
27 | DefaultForeground,
28 | DefaultBackground,
29 | numberOfColors
30 | };
31 | Q_ENUM(Color)
32 |
33 | QColor color(Color color, bool bold = false) const;
34 | QColor normalColor(Color color) const;
35 | QColor lightColor(Color color) const;
36 | QRgb normalRgb(int index);
37 | QRgb xtermRgb(int index);
38 |
39 | void setInverseDefaultColors(bool inverse);
40 |
41 | QColor defaultForeground() const;
42 | QColor defaultBackground() const;
43 | signals:
44 | void changed();
45 | void defaultBackgroundColorChanged();
46 |
47 | private:
48 | QVector m_normalColors;
49 | QVector m_lightColors;
50 | QVector m_xtermColors;
51 |
52 | bool m_inverse_default;
53 | };
54 |
55 | #endif // COLOR_PALETTE_H
56 |
--------------------------------------------------------------------------------
/backend/main.cpp:
--------------------------------------------------------------------------------
1 | /**************************************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5 | * associated documentation files (the "Software"), to deal in the Software without restriction,
6 | * including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in all copies or
11 | * substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14 | * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
17 | * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 | *
19 | ***************************************************************************************************/
20 |
21 | #include "terminal_state.h"
22 |
23 | #include
24 |
25 | int main(int argc, char *argv[])
26 | {
27 | QGuiApplication app(argc, argv);
28 |
29 | TerminalState state;
30 |
31 | return app.exec();
32 | }
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Yat (yet another terminal) is a VT100-emulating terminal written with Qt Quick.
2 |
3 | Currently, master branch requires Qt 5.10; previous versions targeted older versions of Qt.
4 |
5 | ## To compile and try it out
6 |
7 | ```
8 | qmake
9 | make
10 | qml -I imports yat_app/yat.qml
11 | ```
12 |
13 | ## To install on your system
14 |
15 | First install the dependencies in your system Qt path, then install yat.qml somewhere in your PATH
16 | (use sudo if it gives you permission errors, and if you agree about the installation directory):
17 |
18 | ```
19 | qmake
20 | make install
21 | cp yat_app/yat.qml /usr/bin/yat
22 | ```
23 |
24 | yat.qml is a script starting with a shebang, so you can run it just like that, the same way
25 | you could run a Python script for example. And as with Python, the dependencies need to
26 | be installed too; ```make install``` will by default install in a directory called Yat
27 | under Qt's Qml2ImportsPath, which may be something like /usr/lib/qt/qml
28 | if you are using your distro's Qt packages.
29 |
30 | If the QML is installed in this way, yat can also be used as a component inside other applications.
31 |
32 |
33 | ## To build a self-contained executable
34 |
35 | This is not necessary, but if you prefer to make a self-contained executable instead of installing the QML files separately:
36 |
37 | ```
38 | cd yat_app
39 | qmake
40 | make
41 | ```
42 |
43 | It will incorporate the QML into the executable's resources, and you now have a moveable executable.
44 | But the downside is you cannot customize the QML at runtime - you need to compile it again
45 | if you make a change.
46 |
47 |
--------------------------------------------------------------------------------
/qml/Yat/plugin/yat_extension_plugin.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in all
12 | * copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #ifndef YAT_EXTENSION_PLUGIN
25 | #define YAT_EXTENSION_PLUGIN
26 |
27 | #include
28 |
29 | class YatExtensionPlugin : public QQmlExtensionPlugin
30 | {
31 | Q_OBJECT
32 | Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0")
33 | public:
34 | void registerTypes(const char *uri);
35 | void initializeEngine(QQmlEngine *engine, const char *uri);
36 | };
37 |
38 | #endif
39 |
--------------------------------------------------------------------------------
/yat_app/yat.qml:
--------------------------------------------------------------------------------
1 | #!/bin/env qml
2 | /*******************************************************************************
3 | * Copyright (c) 2013 Jørgen Lind
4 | *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy
6 | * of this software and associated documentation files (the "Software"), to deal
7 | * in the Software without restriction, including without limitation the rights
8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | * copies of the Software, and to permit persons to whom the Software is
10 | * furnished to do so, subject to the following conditions:
11 | *
12 | * The above copyright notice and this permission notice shall be included in all
13 | * copies or substantial portions of the Software.
14 | *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | * SOFTWARE.
22 | *
23 | *******************************************************************************/
24 |
25 | import QtQuick 2.0
26 | import QtQuick.Window 2.0
27 |
28 | import Yat 1.0 as Yat
29 |
30 | Window {
31 | id: terminalWindow
32 | Yat.Screen {
33 | id: terminal
34 | anchors.fill: parent
35 | Component.onCompleted: terminalWindow.visible = true
36 | onAboutToBeDestroyed: Qt.quit()
37 | }
38 | width: 800
39 | height: 600
40 | color: terminal.screen.defaultBackgroundColor
41 | }
42 |
--------------------------------------------------------------------------------
/backend/nrc_text_codec.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #include "character_sets.h"
25 |
26 | #include
27 | #include
28 |
29 | class NrcTextCodec : public QTextCodec
30 | {
31 | public:
32 | NrcTextCodec(const QByteArray &name, int mib, const QChar character_set[]);
33 | QByteArray name() const;
34 | int mibEnum() const;
35 |
36 | static void initialize();
37 | protected:
38 | QString convertToUnicode(const char *in, int length, ConverterState *state) const;
39 | QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const;
40 |
41 | private:
42 | const QByteArray m_name;
43 | const int m_mib;
44 | const QChar *m_character_set;
45 | };
46 |
--------------------------------------------------------------------------------
/qml/Yat/plugin/object_destruct_item.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in all
12 | * copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #ifndef OBJECT_DESTRUCT_ITEM_H
25 | #define OBJECT_DESTRUCT_ITEM_H
26 |
27 | #include
28 | #include
29 |
30 | class ObjectDestructItem : public QQuickItem
31 | {
32 | Q_OBJECT
33 |
34 | Q_PROPERTY(QObject *objectHandle READ objectHandle WRITE setObjectHandle NOTIFY objectHandleChanged)
35 |
36 | public:
37 | ObjectDestructItem(QQuickItem *parent = 0);
38 |
39 | QObject *objectHandle() const;
40 | void setObjectHandle(QObject *line);
41 |
42 | signals:
43 | void objectHandleChanged();
44 |
45 | private slots:
46 | void objectDestroyed();
47 |
48 | private:
49 | QObject *m_object;
50 | };
51 |
52 | #endif //OBJECT_DESTRUCT_ITEM_H
53 |
--------------------------------------------------------------------------------
/qml/Yat/plugin/object_destruct_item.cpp:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in all
12 | * copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #include "object_destruct_item.h"
25 |
26 | ObjectDestructItem::ObjectDestructItem(QQuickItem *parent)
27 | : QQuickItem(parent)
28 | , m_object(0)
29 | {
30 | }
31 |
32 | QObject *ObjectDestructItem::objectHandle() const
33 | {
34 | return m_object;
35 | }
36 |
37 | void ObjectDestructItem::setObjectHandle(QObject *object)
38 | {
39 | bool emit_changed = m_object != object;
40 | if (m_object) {
41 | m_object->disconnect(this);
42 | }
43 |
44 | m_object = object;
45 | connect(m_object, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
46 |
47 | if (emit_changed)
48 | emit objectHandleChanged();
49 | }
50 |
51 | void ObjectDestructItem::objectDestroyed()
52 | {
53 | delete this;
54 | }
55 |
56 |
--------------------------------------------------------------------------------
/backend/text_style.h:
--------------------------------------------------------------------------------
1 | #ifndef TEXT_STYLE_H
2 | #define TEXT_STYLE_H
3 |
4 | #include
5 |
6 | #include "color_palette.h"
7 |
8 | class Screen;
9 |
10 | class TextStyle
11 | {
12 | public:
13 | enum Style {
14 | Normal = 0x0000,
15 | Italic = 0x0001,
16 | Bold = 0x0002,
17 | Underlined = 0x0004,
18 | Blinking = 0x0008,
19 | FastBlinking = 0x0010,
20 | Gothic = 0x0020,
21 | DoubleUnderlined = 0x0040,
22 | Framed = 0x0080,
23 | Overlined = 0x0100,
24 | Encircled = 0x0200,
25 | Inverse = 0x0400
26 | };
27 | Q_DECLARE_FLAGS(Styles, Style)
28 |
29 | TextStyle();
30 |
31 | Styles style;
32 | QRgb foreground;
33 | QRgb background;
34 |
35 | bool isCompatible(const TextStyle &other) const;
36 | };
37 |
38 | class Text;
39 | class TextStyleLine : public TextStyle {
40 | public:
41 | TextStyleLine(const TextStyle &style, int start_index, int end_index)
42 | : TextStyle(style)
43 | , start_index(start_index)
44 | , end_index(end_index)
45 | , old_index(-1)
46 | , text_segment(0)
47 | , style_dirty(true)
48 | , index_dirty(true)
49 | , text_dirty(true)
50 | {
51 | }
52 |
53 | TextStyleLine()
54 | : start_index(0)
55 | , end_index(0)
56 | , old_index(-1)
57 | , text_segment(0)
58 | , style_dirty(false)
59 | , index_dirty(false)
60 | , text_dirty(false)
61 | {
62 |
63 | }
64 |
65 | void releaseTextSegment(Screen *screen);
66 |
67 | int start_index;
68 | int end_index;
69 |
70 | int old_index;
71 | Text *text_segment;
72 | bool style_dirty;
73 | bool index_dirty;
74 | bool text_dirty;
75 |
76 | void setStyle(const TextStyle &style) {
77 | foreground = style.foreground;
78 | background = style.background;
79 | this->style = style.style;
80 | }
81 | };
82 | QDebug operator<<(QDebug debug, TextStyleLine line);
83 |
84 |
85 | #endif // TEXT_STYLE_H
86 |
--------------------------------------------------------------------------------
/qml/Yat/plugin/terminal_screen.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | ******************************************************************************/
23 |
24 | #ifndef TERMINALITEM_H
25 | #define TERMINALITEM_H
26 |
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | #include "screen.h"
33 |
34 | class TerminalScreen : public QQuickItem
35 | {
36 | Q_OBJECT
37 |
38 | Q_PROPERTY(Screen *screen READ screen CONSTANT)
39 | public:
40 | TerminalScreen(QQuickItem *parent = 0);
41 | ~TerminalScreen();
42 |
43 | Screen *screen() const;
44 |
45 | QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
46 |
47 | public slots:
48 | void hangupReceived();
49 | signals:
50 | void aboutToBeDestroyed(TerminalScreen *screen);
51 |
52 | protected:
53 | void inputMethodEvent(QInputMethodEvent *event);
54 |
55 | private:
56 | Screen *m_screen;
57 | };
58 |
59 | #endif // TERMINALITEM_H
60 |
--------------------------------------------------------------------------------
/backend/yat_pty.h:
--------------------------------------------------------------------------------
1 | /**************************************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5 | * associated documentation files (the "Software"), to deal in the Software without restriction,
6 | * including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in all copies or
11 | * substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14 | * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
17 | * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 | *
19 | ***************************************************************************************************/
20 |
21 | #ifndef YAT_PTY_H
22 | #define YAT_PTY_H
23 |
24 | #include
25 |
26 | #include
27 | #include
28 | #include
29 |
30 | class QSocketNotifier;
31 |
32 | class YatPty : public QObject
33 | {
34 | Q_OBJECT
35 | public:
36 | YatPty();
37 | ~YatPty();
38 |
39 | void write(const QByteArray &data);
40 |
41 | void setWidth(int width, int pixelWidth = 0);
42 | void setHeight(int height, int pixelHeight = 0);
43 | QSize size() const;
44 |
45 | int masterDevice() const;
46 |
47 | signals:
48 | void hangupReceived();
49 | void readyRead(const QByteArray &data);
50 |
51 | private:
52 | void readData();
53 |
54 | pid_t m_terminal_pid;
55 | int m_master_fd;
56 | char m_slave_file_name[PATH_MAX];
57 | struct winsize *m_winsize;
58 | char m_data_buffer[1024];
59 | QSocketNotifier *m_reader;
60 | };
61 |
62 | #endif //YAT_PTY_H
63 |
--------------------------------------------------------------------------------
/qml/Yat/Cursor.qml:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in all
12 | * copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | import QtQuick 2.0
25 |
26 | import Yat 1.0
27 |
28 | ObjectDestructItem {
29 | id: cursor
30 |
31 | property real fontHeight
32 | property real fontWidth
33 |
34 | height: fontHeight
35 | width: fontWidth
36 | x: objectHandle.x * fontWidth
37 | y: objectHandle.y * fontHeight
38 | z: 1.1
39 |
40 | visible: objectHandle.visible
41 |
42 | ShaderEffect {
43 | anchors.fill: parent
44 |
45 | property variant source: fragmentSource
46 |
47 | fragmentShader:
48 | "uniform lowp float qt_Opacity;" +
49 | "uniform sampler2D source;" +
50 | "varying highp vec2 qt_TexCoord0;" +
51 |
52 | "void main() {" +
53 | " lowp vec4 color = texture2D(source, qt_TexCoord0 ) * qt_Opacity;" +
54 | " gl_FragColor = vec4(1.0 - color.r, 1.0 - color.g, 1.0 - color.b, color.a);" +
55 | "}"
56 |
57 | ShaderEffectSource {
58 | id: fragmentSource
59 |
60 | sourceItem: textContainer
61 | live: true
62 |
63 | sourceRect: Qt.rect(cursor.x,cursor.y,cursor.width,cursor.height);
64 | }
65 | }
66 | }
67 |
68 |
--------------------------------------------------------------------------------
/qml/Yat/plugin/terminal_screen.cpp:
--------------------------------------------------------------------------------
1 | /**************************************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5 | * associated documentation files (the "Software"), to deal in the Software without restriction,
6 | * including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in all copies or
11 | * substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14 | * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
17 | * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 | *
19 | ***************************************************************************************************/
20 |
21 | #include "terminal_screen.h"
22 |
23 | TerminalScreen::TerminalScreen(QQuickItem *parent)
24 | : QQuickItem(parent)
25 | , m_screen(new Screen(this))
26 | {
27 | setFlag(QQuickItem::ItemAcceptsInputMethod);
28 | connect(m_screen, &Screen::hangup, this, &TerminalScreen::hangupReceived);
29 | }
30 |
31 | TerminalScreen::~TerminalScreen()
32 | {
33 | delete m_screen;
34 | }
35 |
36 | Screen *TerminalScreen::screen() const
37 | {
38 | return m_screen;
39 | }
40 |
41 | QVariant TerminalScreen::inputMethodQuery(Qt::InputMethodQuery query) const
42 | {
43 | switch (query) {
44 | case Qt::ImEnabled:
45 | return QVariant(true);
46 | case Qt::ImHints:
47 | return QVariant(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
48 | default:
49 | return QVariant();
50 | }
51 | }
52 |
53 | void TerminalScreen::inputMethodEvent(QInputMethodEvent *event)
54 | {
55 | QString commitString = event->commitString();
56 | if (commitString.isEmpty()) {
57 | return;
58 | }
59 |
60 | Qt::Key key = Qt::Key_unknown;
61 | if (commitString == " ") {
62 | key = Qt::Key_Space; // screen requires
63 | }
64 |
65 | m_screen->sendKey(commitString, key, 0);
66 | }
67 |
68 | void TerminalScreen::hangupReceived()
69 | {
70 | emit aboutToBeDestroyed(this);
71 | deleteLater();
72 | }
73 |
--------------------------------------------------------------------------------
/qml/Yat/plugin/yat_extension_plugin.cpp:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2014 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in all
12 | * copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #include "yat_extension_plugin.h"
25 |
26 | #include
27 |
28 | #include
29 |
30 | #include "terminal_screen.h"
31 | #include "object_destruct_item.h"
32 | #include "screen.h"
33 | #include "text.h"
34 | #include "cursor.h"
35 | #include "mono_text.h"
36 | #include "selection.h"
37 |
38 | static const struct {
39 | const char *type;
40 | int major, minor;
41 | } qmldir [] = {
42 | { "Screen", 1, 0},
43 | { "Text", 1, 0},
44 | { "Cursor", 1, 0},
45 | { "Selection", 1, 0},
46 | };
47 |
48 | void YatExtensionPlugin::registerTypes(const char *uri)
49 | {
50 | Q_ASSERT(uri == QByteArrayLiteral("Yat"));
51 | qmlRegisterType("Yat", 1, 0, "TerminalScreen");
52 | qmlRegisterType("Yat", 1, 0, "ObjectDestructItem");
53 | qmlRegisterType("Yat", 1, 0, "MonoText");
54 | qmlRegisterType();
55 | qmlRegisterType();
56 | qmlRegisterType();
57 | qmlRegisterType();
58 |
59 | const QString filesLocation = baseUrl().toString();
60 | for (int i = 0; i < int(sizeof(qmldir)/sizeof(qmldir[0])); i++)
61 | qmlRegisterType(QUrl(filesLocation + "/" + qmldir[i].type + ".qml"), uri, qmldir[i].major, qmldir[i].minor, qmldir[i].type);
62 | }
63 |
64 | void YatExtensionPlugin::initializeEngine(QQmlEngine *engine, const char *uri)
65 | {
66 | Q_UNUSED(uri);
67 | Q_UNUSED(engine);
68 | }
69 |
--------------------------------------------------------------------------------
/backend/scrollback.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | ******************************************************************************/
23 |
24 | #ifndef SCROLLBACK_H
25 | #define SCROLLBACK_H
26 |
27 | #include "selection.h"
28 |
29 | #include
30 |
31 | #include
32 | #include
33 | class ScreenData;
34 | class Block;
35 |
36 | struct Page {
37 | int page_no;
38 | int size;
39 | std::list::iterator it;
40 | };
41 |
42 | class Scrollback
43 | {
44 | public:
45 | Scrollback(size_t max_size, ScreenData *screen_data);
46 |
47 | void addBlock(Block *block);
48 | Block *reclaimBlock();
49 | void ensureVisiblePages(int top_line);
50 |
51 | size_t height() const;
52 |
53 | void setWidth(int width);
54 |
55 | size_t blockCount() { return m_block_count; }
56 |
57 | QString selection(const QPoint &start, const QPoint &end) const;
58 | const SelectionRange getDoubleClickSelectionRange(size_t character, size_t line);
59 | private:
60 | void ensurePageVisible(Page &page, int new_height);
61 | void ensurePageNotVisible(Page &page);
62 | std::list::iterator findIteratorForPage(int page_no);
63 | std::list::iterator findIteratorForLine(size_t line);
64 | void adjustVisiblePages();
65 | ScreenData *m_screen_data;
66 |
67 | std::list m_blocks;
68 | std::list m_visible_pages;
69 | size_t m_height;
70 | size_t m_width;
71 | size_t m_block_count;
72 | size_t m_max_size;
73 | size_t m_adjust_visible_pages;
74 | };
75 |
76 | #endif //SCROLLBACK_H
77 |
--------------------------------------------------------------------------------
/qml/Yat/plugin/mono_text.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | ******************************************************************************/
23 |
24 | #ifndef MONO_TEXT_H
25 | #define MONO_TEXT_H
26 |
27 | #include
28 | #include
29 |
30 | class MonoText : public QQuickItem
31 | {
32 | Q_OBJECT
33 | Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
34 | Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
35 | Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
36 | Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedWidthChanged)
37 | Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedHeightChanged)
38 | Q_PROPERTY(bool latin READ latin WRITE setLatin NOTIFY latinChanged);
39 | public:
40 | MonoText(QQuickItem *parent=0);
41 | ~MonoText();
42 |
43 | QString text() const;
44 | void setText(const QString &text);
45 |
46 | QFont font() const;
47 | void setFont(const QFont &font);
48 |
49 | QColor color() const;
50 | void setColor(const QColor &color);
51 |
52 | qreal paintedWidth() const;
53 | qreal paintedHeight() const;
54 |
55 | bool latin() const;
56 | void setLatin(bool latin);
57 |
58 | signals:
59 | void textChanged();
60 | void fontChanged();
61 | void colorChanged();
62 | void paintedWidthChanged();
63 | void paintedHeightChanged();
64 | void latinChanged();
65 | protected:
66 | QSGNode *updatePaintNode(QSGNode *old, UpdatePaintNodeData *data) Q_DECL_OVERRIDE;
67 | void updatePolish() Q_DECL_OVERRIDE;
68 | private:
69 | Q_DISABLE_COPY(MonoText);
70 | void updateSize();
71 |
72 | QString m_text;
73 | QFont m_font;
74 | QColor m_color;
75 | bool m_color_changed;
76 | bool m_latin;
77 | bool m_old_latin;
78 | QSizeF m_text_size;
79 | };
80 |
81 | #endif
82 |
--------------------------------------------------------------------------------
/qml/Yat/Text.qml:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in all
12 | * copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | import QtQuick 2.0
25 |
26 | import Yat 1.0
27 |
28 | ObjectDestructItem {
29 | id: textItem
30 | property font font
31 | property real fontWidth
32 | property real fontHeight
33 |
34 | y: objectHandle.line * fontHeight;
35 | x: objectHandle.index * fontWidth;
36 |
37 | width: textElement.paintedWidth
38 | height: textElement.paintedHeight
39 |
40 | visible: objectHandle.visible
41 |
42 | Rectangle {
43 | anchors.fill: parent
44 | color: objectHandle.backgroundColor
45 |
46 | MonoText {
47 | id: textElement
48 | anchors.fill: parent
49 | text: objectHandle.text
50 | color: objectHandle.foregroundColor
51 | font.family: textItem.font.family
52 | font.pixelSize: textItem.font.pixelSize
53 | font.bold: objectHandle.bold
54 | font.underline: objectHandle.underline
55 | latin: objectHandle.latin
56 |
57 | onTextChanged: {
58 | }
59 | SequentialAnimation {
60 | running: objectHandle.blinking
61 | loops: Animation.Infinite
62 | onRunningChanged: {
63 | if (running === false)
64 | textElement.opacity = 1
65 | }
66 | NumberAnimation {
67 | target: textElement
68 | property: "opacity"
69 | to: 0
70 | duration: 250
71 | }
72 | NumberAnimation {
73 | target: textElement
74 | property: "opacity"
75 | to: 1
76 | duration: 250
77 | }
78 | }
79 | }
80 | }
81 |
82 | }
83 |
--------------------------------------------------------------------------------
/backend/selection.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #ifndef SELECTION_H
25 | #define SELECTION_H
26 |
27 | #include
28 | #include
29 |
30 | class Screen;
31 | class Block;
32 |
33 | class SelectionRange
34 | {
35 | public:
36 | QPoint start;
37 | QPoint end;
38 | };
39 |
40 | class Selection : public QObject
41 | {
42 | Q_OBJECT
43 |
44 | Q_PROPERTY(int startX READ startX WRITE setStartX NOTIFY startXChanged)
45 | Q_PROPERTY(int startY READ startY WRITE setStartY NOTIFY startYChanged)
46 | Q_PROPERTY(int endX READ endX WRITE setEndX NOTIFY endXChanged)
47 | Q_PROPERTY(int endY READ endY WRITE setEndY NOTIFY endYChanged)
48 | Q_PROPERTY(bool enable READ enable WRITE setEnable NOTIFY enableChanged)
49 |
50 | public:
51 | explicit Selection(Screen *screen);
52 |
53 | void setStartX(int x);
54 | int startX() const;
55 |
56 | void setStartY(int y);
57 | int startY() const;
58 |
59 | void setEndX(int x);
60 | int endX() const;
61 |
62 | void setEndY(int y);
63 | int endY() const;
64 |
65 | void setEnable(bool enabled);
66 | bool enable() const;
67 |
68 | Q_INVOKABLE void sendToClipboard() const;
69 | Q_INVOKABLE void sendToSelection() const;
70 | Q_INVOKABLE void pasteFromSelection();
71 | Q_INVOKABLE void pasteFromClipboard();
72 |
73 | void dispatchChanges();
74 |
75 | static const SelectionRange getDoubleClickRange(std::list::iterator it, size_t character, size_t line, int width);
76 | signals:
77 | void startXChanged();
78 | void startYChanged();
79 | void endXChanged();
80 | void endYChanged();
81 | void enableChanged();
82 |
83 | private slots:
84 | void screenContentModified(size_t lineModified, int lineDiff, int contentDiff);
85 |
86 | private:
87 | void setValidity();
88 | QPoint start_new_point() const { return QPoint(m_new_start_x, m_new_start_y); }
89 | QPoint end_new_point() const { return QPoint(m_new_end_x, m_new_end_y); }
90 |
91 | Screen *m_screen;
92 | int m_new_start_x;
93 | int m_start_x;
94 | int m_new_start_y;
95 | int m_start_y;
96 | int m_new_end_x;
97 | int m_end_x;
98 | int m_new_end_y;
99 | int m_end_y;
100 | bool m_new_enable;
101 | bool m_enable;
102 | };
103 | #endif
104 |
--------------------------------------------------------------------------------
/backend/parser.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #ifndef PARSER_H
25 | #define PARSER_H
26 |
27 | #include
28 | #include
29 | #include
30 |
31 | #include "controll_chars.h"
32 | #include "utf8_decoder.h"
33 |
34 | class Screen;
35 |
36 | class Parser
37 | {
38 | public:
39 | Parser(Screen *screen);
40 |
41 | void addData(const QByteArray &data);
42 |
43 | private:
44 |
45 | enum DecodeState {
46 | PlainText,
47 | DecodeC0,
48 | DecodeC1_7bit,
49 | DecodeCSI,
50 | DecodeOSC,
51 | DecodeCharacterSet,
52 | DecodeFontSize
53 | };
54 |
55 | enum DecodeOSCState {
56 | None,
57 | ChangeWindowAndIconName,
58 | ChangeIconTitle,
59 | ChangeWindowTitle,
60 | FilePath,
61 | Unknown
62 | };
63 |
64 | void decodeC0(uchar character);
65 | void decodeC1_7bit(uchar character);
66 | void decodeParameters(uchar character);
67 | void decodeCSI(uchar character);
68 | void decodeOSC(uchar character);
69 | void decodeCharacterSet(uchar character);
70 | void decodeFontSize(uchar character);
71 |
72 | void setMode(int mode);
73 | void setDecMode(int mode);
74 | void resetMode(int mode);
75 | void resetDecMode(int mode);
76 |
77 | void handleSGR();
78 | int handleXtermColor(int param, int i);
79 |
80 | void tokenFinished();
81 |
82 | void appendParameter();
83 | void handleDefaultParameters(int defaultValue);
84 |
85 | DecodeState m_decode_state;
86 | DecodeOSCState m_decode_osc_state;
87 | QByteArray m_osc_data;
88 |
89 | QByteArray m_current_data;
90 |
91 | int m_current_token_start;
92 | int m_current_position;
93 |
94 | QChar m_intermediate_char;
95 |
96 | QByteArray m_parameter_string;
97 | QVector m_parameters;
98 | bool m_parameters_expecting_more;
99 | bool m_dec_mode;
100 | bool m_gt_param;
101 | bool m_lnm_mode_set;
102 | bool m_contains_only_latin;
103 |
104 | int m_decode_graphics_set;
105 | QTextCodec *m_graphic_codecs[4];
106 | Utf8Decoder m_utf8_decoder;
107 |
108 | Screen *m_screen;
109 | friend QDebug operator<<(QDebug debug, DecodeState decodeState);
110 | };
111 | QDebug operator<<(QDebug debug, Parser::DecodeState decodeState);
112 |
113 | #endif // PARSER_H
114 |
--------------------------------------------------------------------------------
/backend/utf8_decoder.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #ifndef UTF8_DECODER
25 | #define UTF8_DECODER
26 |
27 | #include "controll_chars.h"
28 |
29 | class Utf8Decoder
30 | {
31 | public:
32 | inline Utf8Decoder();
33 |
34 | inline void addChar(uchar character);
35 |
36 | inline bool isLatin() const;
37 | inline bool isC1() const;
38 |
39 | inline void clear();
40 | private:
41 | short m_expected_length;
42 | short m_length;
43 | uint32_t m_unicode;
44 | };
45 |
46 | Utf8Decoder::Utf8Decoder()
47 | {
48 | clear();
49 | }
50 |
51 | void Utf8Decoder::addChar(uchar character)
52 | {
53 | if (m_length && m_length == m_expected_length) {
54 | clear();
55 | }
56 |
57 | if (character < 0x80)
58 | return;
59 |
60 | fprintf(stderr, "Character: 0x%x\n", character);
61 | if (m_expected_length == 0) {
62 | //this is naive. There must be a faster way.
63 | if ((character & 0xfc) == 0xfc) {
64 | m_expected_length = 5;
65 | m_unicode = character & 0x01;
66 | } else if ((character & 0xf8) == 0xf8) {
67 | m_expected_length = 4;
68 | m_unicode = character & 0x03;
69 | } else if ((character & 0xf0) == 0xf0) {
70 | m_expected_length = 3;
71 | m_unicode = character & 0x07;
72 | } else if ((character & 0xe0) == 0xe0) {
73 | m_expected_length = 2;
74 | m_unicode = character & 0x0f;
75 | } else if ((character & 0xc0) == 0xc0) {
76 | m_expected_length = 1;
77 | m_unicode = character & 0x1f;
78 | } else {
79 | m_expected_length = 0;
80 | m_unicode = 0;
81 | qWarning("Utf8Decoder: invalid decoder character");
82 | }
83 | } else {
84 | fprintf(stderr, "Before 0x%x adding 0x%x pure 0x%x\n", m_unicode,(character & 0x3f), character);
85 | m_unicode = (m_unicode << 6) | (character & 0x3f);
86 | fprintf(stderr, "After 0x%x\n", m_unicode);
87 | m_length++;
88 | }
89 | }
90 |
91 | bool Utf8Decoder::isLatin() const
92 | {
93 | return m_expected_length < 2 && m_unicode < 0xff;
94 | }
95 |
96 | bool Utf8Decoder::isC1() const
97 | {
98 | return m_expected_length == 2 && m_length == m_expected_length &&
99 | (m_unicode >= C1_8bit::C1_8bit_Start && m_unicode <= C1_8bit::C1_8bit_Stop);
100 | }
101 |
102 | void Utf8Decoder::clear()
103 | {
104 | m_expected_length = 0;
105 | m_length = 0;
106 | m_unicode = 0;
107 | }
108 |
109 | #endif
110 |
--------------------------------------------------------------------------------
/qml/Yat/Selection.qml:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in all
12 | * copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | import QtQuick 2.0
25 |
26 | Item {
27 | id: highlightArea
28 |
29 | property real characterWidth: 0
30 | property real characterHeight: 0
31 | property int screenWidth: 0
32 |
33 | property int startX
34 | property int startY
35 |
36 | property int endX
37 | property int endY
38 |
39 | property color color: "grey"
40 |
41 | y: startY * characterHeight
42 | width: parent.width
43 | height: (endY - startY + 1) * characterHeight
44 |
45 | opacity: 0.8
46 |
47 | Rectangle {
48 | id: begginning_rectangle
49 | color: parent.color
50 | opacity: parent.opacity
51 | y:0
52 | height: characterHeight
53 | }
54 |
55 | Rectangle {
56 | id: middle_rectangle
57 | color: parent.color
58 | opacity: parent.opacity
59 | width: parent.width
60 | x: 0
61 | anchors.top: begginning_rectangle.bottom
62 |
63 | }
64 |
65 | Rectangle {
66 | id: end_rectangle
67 | color: parent.color
68 | opacity: parent.opacity
69 | x: 0
70 | height: characterHeight
71 | anchors.top: middle_rectangle.bottom
72 | }
73 |
74 | onCharacterWidthChanged: calculateRectangles();
75 | onCharacterHeightChanged: calculateRectangles();
76 | onScreenWidthChanged: calculateRectangles();
77 |
78 | onStartXChanged: calculateRectangles();
79 | onStartYChanged: calculateRectangles();
80 | onEndXChanged: calculateRectangles();
81 | onEndYChanged: calculateRectangles();
82 |
83 | function calculateRectangles() {
84 | highlightArea.y = startY * characterHeight;
85 | begginning_rectangle.x = startX * characterWidth;
86 | if (startY === endY) {
87 | middle_rectangle.visible = false;
88 | end_rectangle.visible = false
89 | begginning_rectangle.width = (endX - startX) * characterWidth;
90 | } else {
91 | begginning_rectangle.width = (screenWidth - startX) * characterWidth;
92 | if (startY === endY - 1) {
93 | middle_rectangle.height = 0;
94 | middle_rectangle.visible = false;
95 | }else {
96 | middle_rectangle.visible = true;
97 | middle_rectangle.height = (endY - startY - 1) * characterHeight;
98 | }
99 | end_rectangle.visible = true;
100 | end_rectangle.width = endX * characterWidth;
101 | }
102 | }
103 |
104 | }
105 |
--------------------------------------------------------------------------------
/backend/block.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #ifndef BLOCK_H
25 | #define BLOCK_H
26 |
27 | #include
28 |
29 | #include "text_style.h"
30 |
31 | class Text;
32 | class Screen;
33 |
34 | class Block
35 | {
36 | public:
37 | Block(Screen *screen);
38 | ~Block();
39 |
40 | Q_INVOKABLE Screen *screen() const;
41 |
42 | void clear();
43 | void clearToEnd(int from);
44 | void clearCharacters(int from, int to);
45 | void deleteCharacters(int from, int to);
46 | void deleteToEnd(int from);
47 | void deleteLines(int from);
48 |
49 | void replaceAtPos(int i, const QString &text, const TextStyle &style, bool only_latin = true);
50 | void insertAtPos(int i, const QString &text, const TextStyle &style, bool only_latin = true);
51 |
52 | void setScreenIndex(int index) { m_screen_index = index; }
53 | int screenIndex() const { return m_screen_index; }
54 | size_t line() { return m_new_line; }
55 | void setLine(size_t line) {
56 | if (line != m_new_line) {
57 | m_changed = true;
58 | m_new_line = line;
59 | }
60 | }
61 |
62 | const QString &textLine() const;
63 | int textSize() { return m_text_line.size(); }
64 |
65 | int width() const { return m_width; }
66 | void setWidth(int width);
67 | int lineCount() const { return (std::max((m_text_line.size() - 1),0) / m_width) + 1; }
68 | int lineCountAfterModified(int from_char, int text_size, bool replace) {
69 | int new_size = replace ? std::max(from_char + text_size, m_text_line.size())
70 | : std::max(from_char, m_text_line.size()) + text_size;
71 | return ((new_size - 1) / m_width) + 1;
72 | }
73 |
74 | void setVisible(bool visible);
75 | bool visible() const;
76 |
77 | Block *split(int line);
78 | Block *takeLine(int line);
79 | void removeLine(int line);
80 |
81 | void moveLinesFromBlock(Block *block, int start_line, int count);
82 |
83 | void dispatchEvents();
84 | void releaseTextObjects();
85 |
86 | QVector style_list();
87 |
88 | void printStyleList() const;
89 | void printStyleList(QDebug &debug) const;
90 | void printStyleListWidthText() const;
91 |
92 | private:
93 | void mergeCompatibleStyles();
94 | void ensureStyleAlignWithLines(int i);
95 | Screen *m_screen;
96 | QString m_text_line;
97 | QVector m_style_list;
98 | size_t m_line;
99 | size_t m_new_line;
100 | int m_screen_index;
101 |
102 | int m_width;
103 |
104 | bool m_visible;
105 | bool m_changed;
106 | bool m_only_latin;
107 | };
108 |
109 | #endif // BLOCK_H
110 |
--------------------------------------------------------------------------------
/backend/text.h:
--------------------------------------------------------------------------------
1 | /**************************************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5 | * associated documentation files (the "Software"), to deal in the Software without restriction,
6 | * including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in all copies or
11 | * substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14 | * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
17 | * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 | *
19 | ***************************************************************************************************/
20 |
21 | #ifndef TEXT_SEGMENT_H
22 | #define TEXT_SEGMENT_H
23 |
24 | #include
25 | #include
26 | #include
27 | #include
28 |
29 | #include "text_style.h"
30 |
31 | class Screen;
32 | class QQuickItem;
33 |
34 | class Text : public QObject
35 | {
36 | Q_OBJECT
37 | Q_PROPERTY(int index READ index NOTIFY indexChanged)
38 | Q_PROPERTY(int line READ line NOTIFY lineChanged)
39 | Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged)
40 | Q_PROPERTY(QString text READ text NOTIFY textChanged)
41 | Q_PROPERTY(QColor foregroundColor READ foregroundColor NOTIFY foregroundColorChanged)
42 | Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY backgroundColorChanged)
43 | Q_PROPERTY(bool bold READ bold NOTIFY boldChanged)
44 | Q_PROPERTY(bool blinking READ blinking NOTIFY blinkingChanged)
45 | Q_PROPERTY(bool underline READ underline NOTIFY underlineChanged)
46 | Q_PROPERTY(bool latin READ latin NOTIFY latinChanged)
47 | public:
48 | Text(Screen *screen);
49 | ~Text();
50 |
51 | int index() const;
52 |
53 | int line() const;
54 | void setLine(int line, int width, const QString *textLine);
55 |
56 | bool visible() const;
57 | void setVisible(bool visible);
58 |
59 | QString text() const;
60 | QColor foregroundColor() const;
61 | QColor backgroundColor() const;
62 |
63 | void setStringSegment(int start_index, int end_index, bool textChanged);
64 | void setTextStyle(const TextStyle &style);
65 |
66 | bool bold() const;
67 | bool blinking() const;
68 | bool underline() const;
69 |
70 | void setLatin(bool latin);
71 | bool latin() const;
72 |
73 | QObject *item() const;
74 |
75 | public slots:
76 | void dispatchEvents();
77 |
78 | signals:
79 | void indexChanged();
80 | void lineChanged();
81 | void visibleChanged();
82 | void textChanged();
83 | void foregroundColorChanged();
84 | void backgroundColorChanged();
85 | void boldChanged();
86 | void blinkingChanged();
87 | void underlineChanged();
88 | void latinChanged();
89 |
90 | private slots:
91 | void paletteChanged();
92 |
93 | private:
94 | void setBackgroundColor();
95 | void setForegroundColor();
96 |
97 | Screen *m_screen;
98 | QString m_text;
99 | const QString *m_text_line;
100 | int m_start_index;
101 | int m_old_start_index;
102 | int m_end_index;
103 | int m_line;
104 | int m_old_line;
105 | int m_width;
106 |
107 | TextStyle m_style;
108 | TextStyle m_new_style;
109 |
110 | bool m_style_dirty;
111 | bool m_text_dirty;
112 | bool m_visible;
113 | bool m_visible_old;
114 | bool m_latin;
115 | bool m_latin_old;
116 |
117 | QColor m_foregroundColor;
118 | QColor m_backgroundColor;
119 | };
120 |
121 | #endif // TEXT_SEGMENT_H
122 |
--------------------------------------------------------------------------------
/backend/yat_pty.cpp:
--------------------------------------------------------------------------------
1 | /**************************************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5 | * associated documentation files (the "Software"), to deal in the Software without restriction,
6 | * including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in all copies or
11 | * substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14 | * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
17 | * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 | *
19 | ***************************************************************************************************/
20 |
21 | #include "yat_pty.h"
22 |
23 | #include
24 | #include
25 |
26 | #ifdef LINUX
27 | #include
28 | #endif
29 |
30 | #include
31 | #ifdef Q_OS_MAC
32 | #include
33 | #else
34 | #include
35 | #endif
36 | #include
37 |
38 | #include
39 | #include
40 | #include
41 | #include
42 | #include
43 |
44 | static char env_variables[][255] = {
45 | "TERM=xterm-color",
46 | "COLORTERM=xterm",
47 | "COLORFGBG=15;0",
48 | "LINES",
49 | "COLUMNS",
50 | "TERMCAP"
51 | };
52 | static int env_variables_size = sizeof(env_variables) / sizeof(env_variables[0]);
53 |
54 | YatPty::YatPty()
55 | : m_winsize(0)
56 | {
57 | m_terminal_pid = forkpty(&m_master_fd,
58 | NULL,
59 | NULL,
60 | NULL);
61 |
62 | if (m_terminal_pid == 0) {
63 | for (int i = 0; i < env_variables_size; i++) {
64 | ::putenv(env_variables[i]);
65 | }
66 | ::execl("/bin/bash", "/bin/bash", "--login", (const char *) 0);
67 | exit(0);
68 | }
69 |
70 | m_reader = new QSocketNotifier(m_master_fd,QSocketNotifier::Read,this);
71 | connect(m_reader, &QSocketNotifier::activated, this, &YatPty::readData);
72 | }
73 |
74 | YatPty::~YatPty()
75 | {
76 | }
77 |
78 | void YatPty::write(const QByteArray &data)
79 | {
80 | if (::write(m_master_fd, data.constData(), data.size()) < 0) {
81 | qDebug() << "Something whent wrong when writing to m_master_fd";
82 | }
83 | }
84 |
85 | void YatPty::setWidth(int width, int pixelWidth)
86 | {
87 | if (!m_winsize) {
88 | m_winsize = new struct winsize;
89 | m_winsize->ws_row = 25;
90 | m_winsize->ws_ypixel = 0;
91 | }
92 |
93 | m_winsize->ws_col = width;
94 | m_winsize->ws_xpixel = pixelWidth;
95 | ioctl(m_master_fd, TIOCSWINSZ, m_winsize);
96 | }
97 |
98 | void YatPty::setHeight(int height, int pixelHeight)
99 | {
100 | if (!m_winsize) {
101 | m_winsize = new struct winsize;
102 | m_winsize->ws_col = 80;
103 | m_winsize->ws_xpixel = 0;
104 | }
105 | m_winsize->ws_row = height;
106 | m_winsize->ws_ypixel = pixelHeight;
107 | ioctl(m_master_fd, TIOCSWINSZ, m_winsize);
108 |
109 | }
110 |
111 | QSize YatPty::size() const
112 | {
113 | if (!m_winsize) {
114 | YatPty *that = const_cast(this);
115 | that->m_winsize = new struct winsize;
116 | ioctl(m_master_fd, TIOCGWINSZ, m_winsize);
117 | }
118 | return QSize(m_winsize->ws_col, m_winsize->ws_row);
119 | }
120 |
121 | int YatPty::masterDevice() const
122 | {
123 | return m_master_fd;
124 | }
125 |
126 |
127 | void YatPty::readData()
128 | {
129 | int size_of_buffer = sizeof m_data_buffer / sizeof *m_data_buffer;
130 | ssize_t read_size = ::read(m_master_fd,m_data_buffer,size_of_buffer);
131 | if (read_size > 0) {
132 | QByteArray to_return = QByteArray::fromRawData(m_data_buffer,read_size);
133 | emit readyRead(to_return);
134 | } else if (read_size <= 0) {
135 | delete m_reader;
136 | emit hangupReceived();
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/backend/nrc_text_codec.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #include "nrc_text_codec.h"
25 |
26 | static bool nrc_text_codec_init = false;
27 | void NrcTextCodec::initialize()
28 | {
29 | if (!nrc_text_codec_init) {
30 | nrc_text_codec_init = true;
31 | new NrcTextCodec("dec_special_graphics", 500001, dec_special_graphics_char_set);
32 | new NrcTextCodec("nrc_british", 500002, nrc_british_char_set);
33 | new NrcTextCodec("nrc_norwegian_danish", 5002, nrc_norwegian_danish_char_set);
34 | new NrcTextCodec("nrc_dutch", 5002, nrc_dutch_char_set);
35 | new NrcTextCodec("nrc_finnish", 5002, nrc_finnish_char_set);
36 | new NrcTextCodec("nrc_french", 5002, nrc_french_char_set);
37 | new NrcTextCodec("nrc_french_canadian", 5002, nrc_french_canadian_char_set);
38 | new NrcTextCodec("nrc_german", 5002, nrc_german_char_set);
39 | new NrcTextCodec("nrc_italian", 5002, nrc_italian_char_set);
40 | new NrcTextCodec("nrc_spanish", 5002, nrc_spanish_char_set);
41 | new NrcTextCodec("nrc_swedish", 5002, nrc_swedish_char_set);
42 | new NrcTextCodec("nrc_swiss", 5002, nrc_swiss_char_set);
43 | }
44 | }
45 |
46 | NrcTextCodec::NrcTextCodec(const QByteArray &name, int mib, const QChar character_set[])
47 | : QTextCodec()
48 | , m_name(name)
49 | , m_mib(mib)
50 | , m_character_set(character_set)
51 | {
52 | }
53 |
54 | QByteArray NrcTextCodec::name() const
55 | {
56 | return m_name;
57 | }
58 | int NrcTextCodec::mibEnum() const
59 | {
60 | return m_mib;
61 | }
62 |
63 | QString NrcTextCodec::convertToUnicode(const char *in, int length, QTextCodec::ConverterState *state) const
64 | {
65 | QString ret_str;
66 | ret_str.reserve(length);
67 | for (int i = 0; i < length; i++) {
68 | uchar in_char = *(in + i);
69 | if (in_char < 128) {
70 | QChar unicode = m_character_set[in_char];
71 | if (unicode.isNull())
72 | unicode = QChar(in_char);
73 | ret_str.append(unicode);
74 | } else {
75 | if (state) {
76 | if (state->flags & QTextCodec::ConvertInvalidToNull) {
77 | state->invalidChars++;
78 | ret_str.append(0);
79 | } else {
80 | state->invalidChars++;
81 | state->remainingChars = length - i;
82 | return ret_str;
83 | }
84 | }
85 | }
86 | }
87 | return ret_str;
88 | }
89 |
90 | QByteArray NrcTextCodec::convertFromUnicode(const QChar *in, int length, ConverterState *state) const
91 | {
92 | QByteArray ret_array;
93 | ret_array.reserve(length);
94 |
95 | for (int i = 0; i < length; i++) {
96 | QChar out_char = *(in + i);
97 | if (out_char.unicode() < 128) {
98 | uchar out = out_char.unicode();
99 | ret_array.append(out);
100 | } else {
101 | bool found = false;
102 | for (uchar n = 0; n < 128; n++) {
103 | if (m_character_set[n] == out_char) {
104 | ret_array.append(n);
105 | found = true;
106 | break;
107 | }
108 | }
109 |
110 | if (!found && state) {
111 | if (state->flags & QTextCodec::ConvertInvalidToNull) {
112 | state->invalidChars++;
113 | ret_array.append(char(0));
114 | } else {
115 | state->invalidChars++;
116 | state->remainingChars = length - i;
117 | return ret_array;
118 | }
119 | }
120 | }
121 | }
122 | return ret_array;
123 | }
124 |
125 |
--------------------------------------------------------------------------------
/backend/screen_data.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #ifndef SCREENDATA_H
25 | #define SCREENDATA_H
26 |
27 | #include "text_style.h"
28 | #include "block.h"
29 | #include "selection.h"
30 |
31 | #include
32 | #include
33 | #include
34 | #include
35 |
36 | #include
37 | class Screen;
38 | class Scrollback;
39 |
40 | class CursorDiff
41 | {
42 | public:
43 | int line;
44 | int character;
45 | };
46 |
47 | class ScreenData : public QObject
48 | {
49 | Q_OBJECT
50 | public:
51 | ScreenData(size_t max_scrollback, Screen *screen);
52 | ~ScreenData();
53 |
54 | int contentHeight() const;
55 |
56 | void clearToEndOfLine(const QPoint &pos);
57 | void clearToEndOfScreen(int y);
58 | void clearToBeginningOfLine(const QPoint &pos);
59 | void clearToBeginningOfScreen(int y);
60 | void clearLine(const QPoint &pos);
61 | void clear();
62 | void releaseTextObjects();
63 |
64 | void clearCharacters(const QPoint &pos, int to);
65 | void deleteCharacters(const QPoint &pos, int to);
66 |
67 | const CursorDiff replace(const QPoint &pos, const QString &text, const TextStyle &style, bool only_latin);
68 | const CursorDiff insert(const QPoint &pos, const QString &text, const TextStyle &style, bool only_latin);
69 |
70 | void moveLine(int from, int to);
71 | void insertLine(int insertAt, int topMargin);
72 |
73 | void fill(const QChar &character);
74 |
75 | void dispatchLineEvents();
76 |
77 | void printRuler(QDebug &debug) const;
78 | void printStyleInformation() const;
79 |
80 | Screen *screen() const;
81 |
82 | void ensureVisiblePages(int top_line);
83 |
84 | Scrollback *scrollback() const;
85 |
86 | void sendSelectionToClipboard(const QPoint &start, const QPoint &end, QClipboard::Mode mode);
87 |
88 | inline std::list::iterator it_for_row(int row);
89 | inline std::list::iterator it_for_block(Block *block);
90 | bool it_is_end(std::list::iterator it) const { return m_screen_blocks.end() == it; }
91 |
92 | const SelectionRange getDoubleClickSelectionRange(size_t character, size_t line);
93 | public slots:
94 | void setHeight(int height, int currentCursorLine);
95 | void setWidth(int width);
96 |
97 | signals:
98 | void contentHeightChanged();
99 | void contentModified(size_t lineModified, int lineDiff, int contentDiff);
100 | void dataHeightChanged(int newHeight, int removedBeginning, int reclaimed);
101 | void dataWidthChanged(int newHeight, int removedBeginning, int reclaimed);
102 |
103 | private:
104 | const CursorDiff modify(const QPoint &pos, const QString &text, const TextStyle &style, bool replace, bool only_latin);
105 | void clearBlock(std::list::iterator line);
106 | std::list::iterator it_for_row_ensure_single_line_block(int row);
107 | std::list::iterator split_out_row_from_block(std::list::iterator block_it, int row_in_block);
108 | int push_at_most_to_scrollback(int lines);
109 | int reclaim_at_least(int lines);
110 | int remove_lines_from_end(int lines);
111 | int ensure_at_least_height(int height);
112 | int content_height_diff(size_t old_content_height);
113 | Screen *m_screen;
114 | Scrollback *m_scrollback;
115 | int m_screen_height;
116 | int m_height;
117 | int m_width;
118 | int m_block_count;
119 | int m_old_total_lines;
120 |
121 | std::list m_screen_blocks;
122 | };
123 |
124 | std::list::iterator ScreenData::it_for_row(int row)
125 | {
126 | if (row >= m_screen_height) {
127 | return m_screen_blocks.end();
128 | }
129 | auto it = m_screen_blocks.end();
130 | int line_for_block = m_screen_height;
131 | size_t abs_line = contentHeight();
132 | while (it != m_screen_blocks.begin()) {
133 | --it;
134 | line_for_block -= (*it)->lineCount();
135 | abs_line -= (*it)->lineCount();
136 | if (line_for_block <= row) {
137 | (*it)->setScreenIndex(line_for_block);
138 | (*it)->setLine(abs_line);
139 | return it;
140 | }
141 | }
142 |
143 | return m_screen_blocks.end();
144 | }
145 | inline std::list::iterator ScreenData::it_for_block(Block *block)
146 | {
147 | if (!block)
148 | return m_screen_blocks.end();
149 | auto it = m_screen_blocks.end();
150 | int line_for_block = m_screen_height;
151 | size_t abs_line = contentHeight();
152 | while(it != m_screen_blocks.begin()) {
153 | --it;
154 | line_for_block -= (*it)->lineCount();
155 | abs_line -= (*it)->lineCount();
156 | if (*it == block) {
157 | (*it)->setScreenIndex(line_for_block);
158 | (*it)->setLine(abs_line);
159 | return it;
160 | }
161 | }
162 | return m_screen_blocks.end();
163 | }
164 | #endif // SCREENDATA_H
165 |
--------------------------------------------------------------------------------
/backend/screen.h:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #ifndef TERMINALSCREEN_H
25 | #define TERMINALSCREEN_H
26 |
27 | #include
28 |
29 | #include "color_palette.h"
30 | #include "parser.h"
31 | #include "yat_pty.h"
32 | #include "text_style.h"
33 |
34 | #include
35 | #include
36 | #include
37 | #include
38 |
39 | class Block;
40 | class Cursor;
41 | class Text;
42 | class ScreenData;
43 | class Selection;
44 |
45 | class Screen : public QObject
46 | {
47 | Q_OBJECT
48 |
49 | Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged)
50 | Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged)
51 | Q_PROPERTY(int contentHeight READ contentHeight NOTIFY contentHeightChanged)
52 | Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY screenTitleChanged)
53 | Q_PROPERTY(Selection *selection READ selection CONSTANT)
54 | Q_PROPERTY(QColor defaultBackgroundColor READ defaultBackgroundColor NOTIFY defaultBackgroundColorChanged)
55 | Q_PROPERTY(QString platformName READ platformName CONSTANT)
56 |
57 | public:
58 | explicit Screen(QObject *parent = 0);
59 | ~Screen();
60 |
61 | void emitRequestHeight(int newHeight);
62 | void setHeight(int height);
63 | int height() const;
64 | int contentHeight() const;
65 |
66 | void emitRequestWidth(int newWidth);
67 | void setWidth(int width);
68 | int width() const;
69 |
70 | ScreenData *currentScreenData() const { return m_current_data; }
71 | void useAlternateScreenBuffer();
72 | void useNormalScreenBuffer();
73 |
74 | Cursor *currentCursor() const { return m_cursor_stack.last(); }
75 | void saveCursor();
76 | void restoreCursor();
77 |
78 | TextStyle defaultTextStyle() const;
79 |
80 | QColor defaultForegroundColor() const;
81 | QColor defaultBackgroundColor() const;
82 |
83 | ColorPalette *colorPalette() const;
84 |
85 | void clearScreen();
86 |
87 | void fill(const QChar character);
88 | void clear();
89 |
90 | void setFastScroll(bool fast);
91 | bool fastScroll() const;
92 |
93 | Selection *selection() const;
94 | Q_INVOKABLE void doubleClicked(double character, double line);
95 |
96 | void setTitle(const QString &title);
97 | QString title() const;
98 |
99 | QString platformName() const;
100 |
101 | void scheduleFlash();
102 |
103 | Q_INVOKABLE void printScreen() const;
104 |
105 | void scheduleEventDispatch();
106 | void dispatchChanges();
107 |
108 | void sendPrimaryDA();
109 | void sendSecondaryDA();
110 |
111 | void setApplicationCursorKeysMode(bool enable);
112 | bool applicationCursorKeyMode() const;
113 |
114 | Q_INVOKABLE void sendKey(const QString &text, Qt::Key key, Qt::KeyboardModifiers modifiers);
115 |
116 | YatPty *pty();
117 |
118 | Q_INVOKABLE void ensureVisiblePages(int top_line);
119 | Text *createTextSegment(const TextStyleLine &style_line);
120 | void releaseTextSegment(Text *text);
121 |
122 | public slots:
123 | void readData(const QByteArray &data);
124 | void paletteChanged();
125 | signals:
126 | void reset();
127 |
128 | void flash();
129 |
130 | void dispatchLineChanges();
131 | void dispatchTextSegmentChanges();
132 |
133 | void screenTitleChanged();
134 |
135 | void textCreated(Text *text);
136 | void cursorCreated(Cursor *cursor);
137 |
138 | void requestHeightChange(int newHeight);
139 | void heightChanged();
140 | void contentHeightChanged();
141 |
142 | void requestWidthChange(int newWidth);
143 | void widthChanged();
144 |
145 | void defaultBackgroundColorChanged();
146 |
147 | void contentModified(size_t lineModified, int lineDiff, int contentDiff);
148 | void dataHeightChanged(int newHeight, int removedBeginning, int reclaimed);
149 | void widthAboutToChange(int width);
150 | void dataWidthChanged(int newWidth, int removedBeginning, int reclaimed);
151 |
152 | void hangup();
153 | protected:
154 | void timerEvent(QTimerEvent *);
155 |
156 | private:
157 | ColorPalette *m_palette;
158 | YatPty m_pty;
159 | Parser m_parser;
160 | QElapsedTimer m_time_since_parsed;
161 | QElapsedTimer m_time_since_initiated;
162 |
163 | int m_timer_event_id;
164 | int m_width;
165 | int m_height;
166 |
167 | ScreenData *m_primary_data;
168 | ScreenData *m_alternate_data;
169 | ScreenData *m_current_data;
170 | ScreenData *m_old_current_data;
171 |
172 | QVector m_cursor_stack;
173 | QVector m_new_cursors;
174 | QVector m_delete_cursors;
175 |
176 | QString m_title;
177 |
178 | Selection *m_selection;
179 |
180 | bool m_flash;
181 | bool m_cursor_changed;
182 | bool m_application_cursor_key_mode;
183 | bool m_fast_scroll;
184 |
185 | QVector m_to_delete;
186 |
187 | QColor m_default_background;
188 |
189 | friend class ScreenData;
190 | };
191 |
192 | #endif // TERMINALSCREEN_H
193 |
--------------------------------------------------------------------------------
/backend/cursor.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in all
12 | * copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #ifndef CURSOR_H
25 | #define CURSOR_H
26 |
27 | #include "text_style.h"
28 | #include "screen.h"
29 |
30 | #include
31 |
32 | class Cursor : public QObject
33 | {
34 | Q_OBJECT
35 |
36 | Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibilityChanged)
37 | Q_PROPERTY(bool blinking READ blinking WRITE setBlinking NOTIFY blinkingChanged)
38 | Q_PROPERTY(int x READ x NOTIFY xChanged)
39 | Q_PROPERTY(int y READ y NOTIFY yChanged)
40 | public:
41 | enum InsertMode {
42 | Insert,
43 | Replace
44 | };
45 |
46 | Cursor(Screen *screen);
47 | ~Cursor();
48 |
49 | bool visible() const;
50 | void setVisible(bool visible);
51 |
52 | bool blinking() const;
53 | void setBlinking(bool blinking);
54 |
55 | void setTextStyle(TextStyle::Style style, bool add = true);
56 | void resetStyle();
57 | TextStyle currentTextStyle() const;
58 |
59 | ColorPalette *colorPalette() const;
60 | void setTextForegroundColor(QRgb color);
61 | void setTextBackgroundColor(QRgb color);
62 | void setTextForegroundColorIndex(ColorPalette::Color color);
63 | void setTextBackgroundColorIndex(ColorPalette::Color color);
64 |
65 | QPoint position() const;
66 | int x() const;
67 | int y() const;
68 | int new_x() const { return m_new_position.x(); }
69 | int new_y() const { return m_new_position.y(); }
70 |
71 | void moveOrigin();
72 | void moveBeginningOfLine();
73 | void moveUp(int lines = 1);
74 | void moveDown(int lines = 1);
75 | void moveLeft(int positions = 1);
76 | void moveRight(int positions = 1);
77 | void move(int new_x, int new_y);
78 | void moveToLine(int line);
79 | void moveToCharacter(int character);
80 |
81 | void moveToNextTab();
82 | void setTabStop();
83 | void removeTabStop();
84 | void clearTabStops();
85 |
86 | void clearToBeginningOfLine();
87 | void clearToEndOfLine();
88 | void clearToBeginningOfScreen();
89 | void clearToEndOfScreen();
90 | void clearLine();
91 |
92 | void deleteCharacters(int characters);
93 |
94 | void setWrapAround(bool wrap);
95 | void addAtCursor(const QByteArray &text, bool only_latin = true);
96 | void insertAtCursor(const QByteArray &text, bool only_latin = true);
97 | void replaceAtCursor(const QByteArray &text, bool only_latin = true);
98 |
99 | void lineFeed();
100 | void reverseLineFeed();
101 |
102 | void setOriginAtMargin(bool atMargin);
103 | void setScrollArea(int from, int to);
104 | void resetScrollArea();
105 |
106 | void scrollUp(int lines);
107 | void scrollDown(int lines);
108 |
109 | void setTextCodec(QTextCodec *codec);
110 |
111 | void setInsertMode(InsertMode mode);
112 |
113 | inline void notifyChanged();
114 | void dispatchEvents();
115 |
116 | public slots:
117 | void setScreenWidthAboutToChange(int width);
118 | void setScreenWidth(int newWidth, int removedBeginning, int reclaimed);
119 | void setScreenHeight(int newHeight, int removedBeginning, int reclaimed);
120 |
121 | signals:
122 | void xChanged();
123 | void yChanged();
124 | void visibilityChanged();
125 | void blinkingChanged();
126 |
127 | private slots:
128 | void contentHeightChanged();
129 |
130 | private:
131 | ScreenData *screen_data() const { return m_screen->currentScreenData(); }
132 | int &new_rx() { return m_new_position.rx(); }
133 | int &new_ry() { return m_new_position.ry(); }
134 | int adjusted_new_x() const { return m_origin_at_margin ?
135 | m_new_position.x() - m_top_margin : m_new_position.x(); }
136 | int adjusted_new_y() const { return m_origin_at_margin ?
137 | m_new_position.y() - m_top_margin : m_new_position.y(); }
138 | int adjusted_top() const { return m_origin_at_margin ? m_top_margin : 0; }
139 | int adjusted_bottom() const { return m_origin_at_margin ? m_bottom_margin : m_screen_height - 1; }
140 | int top() const { return m_scroll_margins_set ? m_top_margin : 0; }
141 | int bottom() const { return m_scroll_margins_set ? m_bottom_margin : m_screen_height - 1; }
142 | Screen *m_screen;
143 | TextStyle m_current_text_style;
144 | QPoint m_position;
145 | QPoint m_new_position;
146 |
147 | int m_screen_width;
148 | int m_screen_height;
149 |
150 | int m_top_margin;
151 | int m_bottom_margin;
152 | bool m_scroll_margins_set;
153 | bool m_origin_at_margin;
154 |
155 | QVector m_tab_stops;
156 |
157 | bool m_notified;
158 | bool m_visible;
159 | bool m_new_visibillity;
160 | bool m_blinking;
161 | bool m_new_blinking;
162 | bool m_wrap_around;
163 | bool m_content_height_changed;
164 |
165 | QTextDecoder *m_gl_text_codec;
166 | QTextDecoder *m_gr_text_codec;
167 |
168 | InsertMode m_insert_mode;
169 |
170 | Block *m_resize_block;
171 | int m_current_pos_in_block;
172 | };
173 |
174 | void Cursor::notifyChanged()
175 | {
176 | if (!m_notified) {
177 | m_notified = true;
178 | m_screen->scheduleEventDispatch();
179 | }
180 | }
181 |
182 | #endif //CUROSOR_H
183 |
--------------------------------------------------------------------------------
/backend/selection.cpp:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #include "selection.h"
25 |
26 | #include "screen.h"
27 | #include "screen_data.h"
28 | #include "block.h"
29 |
30 | #include
31 |
32 | Selection::Selection(Screen *screen)
33 | : QObject(screen)
34 | , m_screen(screen)
35 | , m_new_start_x(0)
36 | , m_start_x(0)
37 | , m_new_start_y(0)
38 | , m_start_y(0)
39 | , m_new_end_x(0)
40 | , m_end_x(0)
41 | , m_new_end_y(0)
42 | , m_end_y(0)
43 | , m_new_enable(false)
44 | {
45 | connect(screen, &Screen::contentModified, this, &Selection::screenContentModified);
46 |
47 | }
48 |
49 | void Selection::setStartX(int x)
50 | {
51 | if (x != m_new_start_x) {
52 | m_new_start_x = x;
53 | setValidity();
54 | m_screen->scheduleEventDispatch();
55 | }
56 | }
57 |
58 | int Selection::startX() const
59 | {
60 | return m_start_x;
61 | }
62 |
63 | void Selection::setStartY(int y)
64 | {
65 | if (y != m_new_start_y) {
66 | m_new_start_y = y;
67 | setValidity();
68 | m_screen->scheduleEventDispatch();
69 | }
70 | }
71 |
72 | int Selection::startY() const
73 | {
74 | return m_start_y;
75 | }
76 |
77 | void Selection::setEndX(int x)
78 | {
79 | if (m_new_end_x != x) {
80 | m_new_end_x = x;
81 | setValidity();
82 | m_screen->scheduleEventDispatch();
83 | }
84 | }
85 |
86 | int Selection::endX() const
87 | {
88 | return m_end_x;
89 | }
90 |
91 | void Selection::setEndY(int y)
92 | {
93 | if (m_new_end_y != y) {
94 | m_new_end_y = y;
95 | setValidity();
96 | m_screen->scheduleEventDispatch();
97 | }
98 | }
99 |
100 | int Selection::endY() const
101 | {
102 | return m_end_y;
103 | }
104 |
105 | void Selection::setEnable(bool enable)
106 | {
107 | if (m_new_enable != enable) {
108 | m_new_enable = enable;
109 | m_screen->scheduleEventDispatch();
110 | }
111 | }
112 |
113 | void Selection::screenContentModified(size_t lineModified, int lineDiff, int contentDiff)
114 | {
115 | if (!m_new_enable)
116 | return;
117 |
118 | if (lineModified >= size_t(m_new_start_y) && lineModified <= size_t(m_new_end_y)) {
119 | setEnable(false);
120 | return;
121 | }
122 |
123 | if (size_t(m_new_end_y) < lineModified && lineDiff != contentDiff) {
124 | m_new_end_y -= lineDiff - contentDiff;
125 | m_new_start_y -= lineDiff - contentDiff;
126 | if (m_new_end_y < 0) {
127 | setEnable(false);
128 | return;
129 | }
130 | if (m_new_start_y < 0) {
131 | m_new_start_y = 0;
132 | }
133 | m_screen->scheduleEventDispatch();
134 | }
135 | }
136 |
137 | void Selection::setValidity()
138 | {
139 | if (m_new_end_y > m_new_start_y ||
140 | (m_new_end_y == m_new_start_y &&
141 | m_new_end_x > m_new_start_x)) {
142 | setEnable(true);
143 | } else {
144 | setEnable(false);
145 | }
146 | }
147 |
148 | void Selection::sendToClipboard() const
149 | {
150 | m_screen->currentScreenData()->sendSelectionToClipboard(start_new_point(), end_new_point(), QClipboard::Clipboard);
151 | }
152 |
153 | void Selection::sendToSelection() const
154 | {
155 | m_screen->currentScreenData()->sendSelectionToClipboard(start_new_point(), end_new_point(), QClipboard::Selection);
156 | }
157 |
158 | void Selection::pasteFromSelection()
159 | {
160 | m_screen->pty()->write(QGuiApplication::clipboard()->text(QClipboard::Selection).toUtf8());
161 | }
162 |
163 | void Selection::pasteFromClipboard()
164 | {
165 | m_screen->pty()->write(QGuiApplication::clipboard()->text(QClipboard::Clipboard).toUtf8());
166 | }
167 |
168 | void Selection::dispatchChanges()
169 | {
170 | if (!m_new_enable && !m_enable)
171 | return;
172 |
173 | if (m_new_start_y != m_start_y) {
174 | m_start_y = m_new_start_y;
175 | emit startYChanged();
176 | }
177 | if (m_new_start_x != m_start_x) {
178 | m_start_x = m_new_start_x;
179 | emit startXChanged();
180 | }
181 | if (m_new_end_y != m_end_y) {
182 | m_end_y = m_new_end_y;
183 | emit endYChanged();
184 | }
185 | if (m_new_end_x != m_end_x) {
186 | m_end_x = m_new_end_x;
187 | emit endXChanged();
188 | }
189 | if (m_new_enable != m_enable) {
190 | m_enable = m_new_enable;
191 | emit enableChanged();
192 | }
193 | }
194 |
195 | static const QChar delimiter_array[] = { ' ', '\n', '{', '(', '[', '}', ')', ']' };
196 | static const size_t delimiter_array_size = sizeof(delimiter_array) / sizeof(delimiter_array[0]);
197 | const SelectionRange Selection::getDoubleClickRange(std::list::iterator it, size_t character, size_t line, int width)
198 | {
199 | const QString &string = (*it)->textLine();
200 | size_t start_pos = ((line - (*it)->line()) * width) + character;
201 | if (start_pos > size_t(string.size()))
202 | return { QPoint(), QPoint() };
203 | size_t end_pos = start_pos + 1;
204 | for (bool found = false; start_pos > 0; start_pos--) {
205 | for (size_t i = 0; i < delimiter_array_size; i++) {
206 | if (string.at(start_pos - 1) == delimiter_array[i]) {
207 | found = true;
208 | break;
209 | }
210 | }
211 | if (found)
212 | break;
213 | }
214 |
215 | for (bool found = false; end_pos < size_t(string.size()); end_pos++) {
216 | for (size_t i = 0; i < delimiter_array_size; i++) {
217 | if (string.at(end_pos) == delimiter_array[i]) {
218 | found = true;
219 | break;
220 | }
221 | }
222 | if (found)
223 | break;
224 | }
225 |
226 | size_t start_line = (start_pos / width) + (*it)->line();
227 | size_t end_line = (end_pos / width) + (*it)->line();
228 |
229 | return { QPoint(static_cast(start_pos), static_cast(start_line)),
230 | QPoint(static_cast(end_pos) , static_cast(end_line)) };
231 | }
232 | bool Selection::enable() const
233 | {
234 | return m_enable;
235 | }
236 |
--------------------------------------------------------------------------------
/backend/controll_chars.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #ifndef CONTROLL_CHARS_H
25 | #define CONTROLL_CHARS_H
26 |
27 | //This is taken largely from Standard ECMA-48
28 | //http://www.ecma-international.org/publications/standards/Ecma-048.htm
29 | //Also to heres a few handy references
30 | //http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
31 | //http://www.vt100.net/docs/vt100-ug/chapter3.html
32 |
33 | #include
34 |
35 | namespace C0 {
36 | enum C0 {
37 | NUL = 0x00,
38 | SOH = 0x01,
39 | STX = 0x02,
40 | ETX = 0x03,
41 | EOT = 0x04,
42 | ENQ = 0x05,
43 | ACK = 0x06,
44 | BEL = 0x07,
45 | BS = 0x08,
46 | HT = 0x09,
47 | LF = 0x0a,
48 | VT = 0x0b,
49 | FF = 0x0c,
50 | CR = 0x0d,
51 | SOorLS1 = 0x0e,
52 | SIorLS0 = 0x0f,
53 | DLE = 0x10,
54 | DC1 = 0x11,
55 | DC2 = 0x12,
56 | DC3 = 0x13,
57 | DC4 = 0x14,
58 | NAK = 0x15,
59 | SYN = 0x16,
60 | ETB = 0x17,
61 | CAN = 0x18,
62 | EM = 0x19,
63 | SUB = 0x1a,
64 | ESC = 0x1b,
65 | IS4 = 0x1c,
66 | IS3 = 0x1d,
67 | IS2 = 0x1e,
68 | IS1 = 0x1f,
69 | C0_END = 0x20
70 | };
71 | QDebug operator<<(QDebug debug, C0 character);
72 | }
73 |
74 | namespace C1_7bit {
75 | enum C1_7bit {
76 | C1_7bit_Start = 0x1b,
77 | ESC = 0x1b,
78 | SCS_G0 = 0x28,
79 | SCS_G1 = 0x29,
80 | SCS_G2 = 0x2a,
81 | SCS_G3 = 0x2b,
82 | DECSC = 0x37,
83 | DECRC = 0x38,
84 | NOT_DEFINED = 0x40,
85 | NOT_DEFINED1 = 0x41,
86 | BPH = 0x42,
87 | NBH = 0x43,
88 | IND = 0x44,
89 | NEL = 0x45,
90 | SSA = 0x46,
91 | ESA = 0x47,
92 | HTS = 0x48,
93 | HTJ = 0x49,
94 | VTS = 0x4a,
95 | PLD = 0x4b,
96 | PLU = 0x4c,
97 | RI = 0x4d,
98 | SS2 = 0x4e,
99 | SS3 = 0x4f,
100 | DCS = 0x50,
101 | PU1 = 0x51,
102 | PU2 = 0x52,
103 | STS = 0x53,
104 | CCH = 0x54,
105 | MW = 0x55,
106 | SPA = 0x56,
107 | EPA = 0x57,
108 | SOS = 0x58,
109 | NOT_DEFINED3 = 0x59,
110 | SCI = 0x5a,
111 | CSI = 0x5b,
112 | ST = 0x5c,
113 | OSC = 0x5d,
114 | PM = 0x5e,
115 | APC = 0x5f,
116 | C1_7bit_Stop = 0x60
117 | };
118 | QDebug operator<<(QDebug debug, C1_7bit character);
119 | }
120 | namespace C1_8bit {
121 | enum C1_8bit {
122 | C1_8bit_Start = 0x80,
123 | NOT_DEFINED = C1_8bit_Start,
124 | NOT_DEFINED1 = 0x81,
125 | BPH = 0x82,
126 | NBH = 0x83,
127 | NOT_DEFINED2 = 0x84,
128 | NEL = 0x85,
129 | SSA = 0x86,
130 | ESA = 0x87,
131 | HTS = 0x88,
132 | HTJ = 0x89,
133 | VTS = 0x8a,
134 | PLD = 0x8b,
135 | PLU = 0x8c,
136 | RI = 0x8d,
137 | SS2 = 0x8e,
138 | SS3 = 0x8f,
139 | DCS = 0x90,
140 | PU1 = 0x91,
141 | PU2C1_7bit = 0x92,
142 | STS = 0x93,
143 | CCH = 0x94,
144 | MW = 0x95,
145 | SPA = 0x96,
146 | EPA = 0x97,
147 | SOS = 0x98,
148 | NOT_DEFINED3 = 0x99,
149 | SCI = 0x9a,
150 | CSI = 0x9b,
151 | ST = 0x9c,
152 | OSC = 0x9d,
153 | PM = 0x9e,
154 | APC = 0x9f,
155 | C1_8bit_Stop = 0xa0
156 | };
157 | QDebug operator<<(QDebug debug, C1_8bit character);
158 | }
159 |
160 | namespace FinalBytesNoIntermediate {
161 | enum FinalBytesNoIntermediate {
162 | ICH = 0x40,
163 | CUU = 0x41,
164 | CUD = 0x42,
165 | CUF = 0x43,
166 | CUB = 0x44,
167 | CNL = 0x45,
168 | CPL = 0x46,
169 | CHA = 0x47,
170 | CUP = 0x48,
171 | CHT = 0x49,
172 | ED = 0x4a,
173 | EL = 0x4b,
174 | IL = 0x4c,
175 | DL = 0x4d,
176 | EF = 0x4e,
177 | EA = 0x4f,
178 | DCH = 0x50,
179 | SSE = 0x51,
180 | CPR = 0x52,
181 | SU = 0x53,
182 | SD = 0x54,
183 | NP = 0x55,
184 | PP = 0x56,
185 | CTC = 0x57,
186 | ECH = 0x58,
187 | CVT = 0x59,
188 | CBT = 0x5a,
189 | SRS = 0x5b,
190 | PTX = 0x5c,
191 | SDS = 0x5d,
192 | SIMD = 0x5e,
193 | NOT_DEFINED = 0x5f,
194 | HPA = 0x60,
195 | HPR = 0x61,
196 | REP = 0x62,
197 | DA = 0x63,
198 | VPA = 0x64,
199 | VPR = 0x65,
200 | HVP = 0x66,
201 | TBC = 0x67,
202 | SM = 0x68,
203 | MC = 0x69,
204 | HPB = 0x6a,
205 | VPB = 0x6b,
206 | RM = 0x6c,
207 | SGR = 0x6d,
208 | DSR = 0x6e,
209 | DAQ = 0x6f,
210 | Reserved0 = 0x70,
211 | Reserved1 = 0x71,
212 | DECSTBM = 0x72,
213 | Reserved3 = 0x73,
214 | Reserved4 = 0x74,
215 | Reserved5 = 0x75,
216 | Reserved6 = 0x76,
217 | Reserved7 = 0x77,
218 | Reserved8 = 0x78,
219 | Reserved9 = 0x79,
220 | Reserveda = 0x7a,
221 | Reservedb = 0x7b,
222 | Reservedc = 0x7c,
223 | Reservedd = 0x7d,
224 | Reservede = 0x7e,
225 | Reservedf = 0x7f
226 | };
227 | QDebug operator<<(QDebug debug, FinalBytesNoIntermediate character);
228 | }
229 |
230 | namespace FinalBytesSingleIntermediate {
231 | enum FinalBytesSingleIntermediate {
232 | SL = 0x40,
233 | SR = 0x41,
234 | GSM = 0x42,
235 | GSS = 0x43,
236 | FNT = 0x44,
237 | TSS = 0x45,
238 | JFY = 0x46,
239 | SPI = 0x47,
240 | QUAD = 0x48,
241 | SSU = 0x49,
242 | PFS = 0x4a,
243 | SHS = 0x4b,
244 | SVS = 0x4c,
245 | IGS = 0x4d,
246 | NOT_DEFINED = 0x4e,
247 | IDCS = 0x4f,
248 | PPA = 0x50,
249 | PPR = 0x51,
250 | PPB = 0x52,
251 | SPD = 0x53,
252 | DTA = 0x54,
253 | SHL = 0x55,
254 | SLL = 0x56,
255 | FNK = 0x57,
256 | SPQR = 0x58,
257 | SEF = 0x59,
258 | PEC = 0x5a,
259 | SSW = 0x5b,
260 | SACS = 0x5c,
261 | SAPV = 0x5d,
262 | STAB = 0x5e,
263 | GCC = 0x5f,
264 | TATE = 0x60,
265 | TALE = 0x61,
266 | TAC = 0x62,
267 | TCC = 0x63,
268 | TSR = 0x64,
269 | SCO = 0x65,
270 | SRCS = 0x66,
271 | SCS = 0x67,
272 | SLS = 0x68,
273 | NOT_DEFINED2 = 0x69,
274 | NOT_DEFINED3 = 0x6a,
275 | SCP = 0x6b,
276 | NOT_DEFINED4 = 0x6c,
277 | NOT_DEFINED5 = 0x6d,
278 | NOT_DEFINED6 = 0x6e,
279 | NOT_DEFINED7 = 0x6f,
280 | Reserved0 = 0x70,
281 | Reserved1 = 0x71,
282 | Reserved2 = 0x72,
283 | Reserved3 = 0x73,
284 | Reserved4 = 0x74,
285 | Reserved5 = 0x75,
286 | Reserved6 = 0x76,
287 | Reserved7 = 0x77,
288 | Reserved8 = 0x78,
289 | Reserved9 = 0x79,
290 | Reserveda = 0x7a,
291 | Reservedb = 0x7b,
292 | Reservedc = 0x7c,
293 | Reservedd = 0x7d,
294 | Reservedf = 0x7f
295 | };
296 | QDebug operator<<(QDebug debug, FinalBytesSingleIntermediate character);
297 | }
298 |
299 | #endif // CONTROLL_CHARS_H
300 |
--------------------------------------------------------------------------------
/backend/text.cpp:
--------------------------------------------------------------------------------
1 | /**************************************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5 | * associated documentation files (the "Software"), to deal in the Software without restriction,
6 | * including without limitation the rights to use, copy, modify, merge, publish, distribute,
7 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
8 | * furnished to do so, subject to the following conditions:
9 | *
10 | * The above copyright notice and this permission notice shall be included in all copies or
11 | * substantial portions of the Software.
12 | *
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14 | * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
16 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
17 | * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
18 | *
19 | ***************************************************************************************************/
20 |
21 | #include "text.h"
22 |
23 | #include "screen.h"
24 | #include "block.h"
25 | #include
26 |
27 | #include
28 |
29 | Text::Text(Screen *screen)
30 | : QObject(screen)
31 | , m_screen(screen)
32 | , m_text_line(0)
33 | , m_start_index(0)
34 | , m_old_start_index(0)
35 | , m_end_index(0)
36 | , m_line(0)
37 | , m_old_line(0)
38 | , m_width(1)
39 | , m_style(screen->defaultTextStyle())
40 | , m_new_style(screen->defaultTextStyle())
41 | , m_style_dirty(true)
42 | , m_text_dirty(true)
43 | , m_visible(true)
44 | , m_visible_old(true)
45 | , m_latin(true)
46 | , m_latin_old(true)
47 | , m_foregroundColor(m_screen->defaultForegroundColor())
48 | , m_backgroundColor(m_screen->defaultBackgroundColor())
49 | {
50 | connect(m_screen->colorPalette(), SIGNAL(changed()), this, SLOT(paletteChanged()));
51 | connect(m_screen, SIGNAL(dispatchTextSegmentChanges()), this, SLOT(dispatchEvents()));
52 | }
53 |
54 | Text::~Text()
55 | {
56 | }
57 |
58 | int Text::index() const
59 | {
60 | return m_start_index % m_width;
61 | }
62 |
63 | int Text::line() const
64 | {
65 | return m_line + (m_start_index / m_width);
66 | }
67 |
68 | void Text::setLine(int line, int width, const QString *textLine)
69 | {
70 | m_line = line;
71 | m_width = width;
72 | m_text_dirty = true;
73 | m_text_line = textLine;
74 | }
75 |
76 | bool Text::visible() const
77 | {
78 | return m_visible;
79 | }
80 |
81 | void Text::setVisible(bool visible)
82 | {
83 | m_visible = visible;
84 | }
85 |
86 | QString Text::text() const
87 | {
88 | return m_text;
89 | }
90 |
91 | QColor Text::foregroundColor() const
92 | {
93 | return m_foregroundColor;
94 | }
95 |
96 |
97 | QColor Text::backgroundColor() const
98 | {
99 | return m_backgroundColor;
100 | }
101 |
102 | void Text::setStringSegment(int start_index, int end_index, bool text_changed)
103 | {
104 | m_start_index = start_index;
105 | m_end_index = end_index;
106 |
107 | m_text_dirty = text_changed;
108 | }
109 |
110 | void Text::setTextStyle(const TextStyle &style)
111 | {
112 | m_new_style = style;
113 | m_style_dirty = true;
114 | }
115 |
116 | bool Text::bold() const
117 | {
118 | return m_style.style & TextStyle::Bold;
119 | }
120 |
121 | bool Text::blinking() const
122 | {
123 | return m_style.style & TextStyle::Blinking;
124 | }
125 |
126 | bool Text::underline() const
127 | {
128 | return m_style.style & TextStyle::Underlined;
129 | }
130 |
131 | void Text::setLatin(bool latin)
132 | {
133 | m_latin = latin;
134 | }
135 |
136 | bool Text::latin() const
137 | {
138 | return m_latin_old;
139 | }
140 |
141 | static bool differentStyle(TextStyle::Styles a, TextStyle::Styles b, TextStyle::Style style)
142 | {
143 | return (a & style) != (b & style);
144 | }
145 |
146 | void Text::dispatchEvents()
147 | {
148 | int old_line = m_old_line + (m_old_start_index / m_width);
149 | int new_line = m_line + (m_start_index / m_width);
150 | if (old_line != new_line) {
151 | m_old_line = m_line;
152 | emit lineChanged();
153 | }
154 |
155 | if (m_latin != m_latin_old) {
156 | m_latin_old = m_latin;
157 | emit latinChanged();
158 | }
159 |
160 | if (m_old_start_index != m_start_index
161 | || m_text_dirty) {
162 | m_text_dirty = false;
163 | QString old_text = m_text;
164 | m_text = m_text_line->mid(m_start_index, m_end_index - m_start_index + 1);
165 | if (m_old_start_index != m_start_index) {
166 | m_old_start_index = m_start_index;
167 | emit indexChanged();
168 | }
169 | emit textChanged();
170 | }
171 |
172 | if (m_style_dirty) {
173 | m_style_dirty = false;
174 |
175 | bool emit_foreground = m_new_style.foreground != m_style.foreground;
176 | bool emit_background = m_new_style.background != m_style.background;
177 | TextStyle::Styles new_style = m_new_style.style;
178 | TextStyle::Styles old_style = m_style.style;
179 |
180 | bool emit_bold = false;
181 | bool emit_blink = false;
182 | bool emit_underline = false;
183 | bool emit_inverse = false;
184 | if (new_style != old_style) {
185 | emit_bold = differentStyle(new_style, old_style, TextStyle::Bold);
186 | emit_blink = differentStyle(new_style, old_style, TextStyle::Blinking);
187 | emit_underline = differentStyle(new_style, old_style, TextStyle::Underlined);
188 | emit_inverse = differentStyle(new_style, old_style, TextStyle::Inverse);
189 | }
190 |
191 | m_style = m_new_style;
192 | if (emit_inverse) {
193 | setForegroundColor();
194 | setBackgroundColor();
195 | } else {
196 | if (emit_foreground || emit_bold) {
197 | setForegroundColor();
198 | }
199 | if (emit_background) {
200 | setBackgroundColor();
201 | }
202 | }
203 |
204 | if (emit_bold) {
205 | emit boldChanged();
206 | }
207 |
208 | if (emit_blink) {
209 | emit blinkingChanged();
210 | }
211 |
212 | if (emit_underline) {
213 | emit underlineChanged();
214 | }
215 |
216 | }
217 |
218 |
219 | if (m_visible_old != m_visible) {
220 | m_visible_old = m_visible;
221 | emit visibleChanged();
222 | }
223 | }
224 |
225 | void Text::paletteChanged()
226 | {
227 | setBackgroundColor();
228 | setForegroundColor();
229 | }
230 |
231 | void Text::setBackgroundColor()
232 | {
233 | QColor new_background;
234 | if (m_style.style & TextStyle::Inverse) {
235 | new_background = m_style.foreground;
236 | } else {
237 | new_background = m_style.background;
238 | }
239 | if (new_background != m_backgroundColor) {
240 | m_backgroundColor = new_background;
241 | emit backgroundColorChanged();
242 | }
243 | }
244 |
245 | void Text::setForegroundColor()
246 | {
247 | QColor new_foreground;
248 | if (m_style.style & TextStyle::Inverse) {
249 | new_foreground = m_style.background;
250 | } else {
251 | new_foreground = m_style.foreground;
252 | }
253 | if (new_foreground != m_foregroundColor) {
254 | m_foregroundColor = new_foreground;
255 | emit foregroundColorChanged();
256 | }
257 | }
258 |
--------------------------------------------------------------------------------
/qml/Yat/plugin/mono_text.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | ******************************************************************************/
23 |
24 | #include "mono_text.h"
25 |
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | class MonoSGNode : public QSGTransformNode
33 | {
34 | public:
35 | MonoSGNode(QQuickItem *owner)
36 | : m_owner(owner)
37 | {
38 | }
39 |
40 | void deleteContent()
41 | {
42 | QSGNode *subnode = firstChild();
43 | while (subnode) {
44 | // We can't delete the node now as it might be in the preprocess list
45 | // It will be deleted in the next preprocess
46 | m_nodes_to_delete.append(subnode);
47 | subnode = subnode->nextSibling();
48 | }
49 | removeAllChildNodes();
50 | }
51 |
52 | void preprocess()
53 | {
54 | while (m_nodes_to_delete.count())
55 | delete m_nodes_to_delete.takeLast();
56 | }
57 |
58 | void setLatinText(const QString &text, const QFont &font, const QColor &color) {
59 | QRawFont raw_font = QRawFont::fromFont(font, QFontDatabase::Latin);
60 |
61 | if (raw_font != m_raw_font) {
62 | m_raw_font = raw_font;
63 | m_positions.clear();
64 | }
65 |
66 | if (m_positions.size() < text.size()) {
67 | qreal x_pos = 0;
68 | qreal max_char_width = raw_font.averageCharWidth();
69 | qreal ascent = raw_font.ascent();
70 | if (m_positions.size())
71 | x_pos = m_positions.last().x() + max_char_width;
72 | int to_add = text.size() - m_positions.size();
73 | for (int i = 0; i < to_add; i++) {
74 | m_positions << QPointF(x_pos, ascent);
75 | x_pos += max_char_width;
76 | }
77 | }
78 |
79 | deleteContent();
80 | QSGRenderContext *sgr = QQuickItemPrivate::get(m_owner)->sceneGraphRenderContext();
81 | QSGGlyphNode *node = sgr->sceneGraphContext()->createGlyphNode(sgr, false);
82 | node->setOwnerElement(m_owner);
83 | node->geometry()->setIndexDataPattern(QSGGeometry::StaticPattern);
84 | node->geometry()->setVertexDataPattern(QSGGeometry::StaticPattern);
85 | node->setStyle(QQuickText::Normal);
86 |
87 | node->setColor(color);
88 | QGlyphRun glyphrun;
89 | glyphrun.setRawFont(raw_font);
90 | glyphrun.setGlyphIndexes(raw_font.glyphIndexesForString(text));
91 |
92 | glyphrun.setPositions(m_positions);
93 | node->setGlyphs(QPointF(0, raw_font.ascent()), glyphrun);
94 | node->update();
95 | appendChildNode(node);
96 | }
97 |
98 | void setUnicodeText(const QString &text, const QFont &font, const QColor &color)
99 | {
100 | deleteContent();
101 | QRawFont raw_font = QRawFont::fromFont(font, QFontDatabase::Latin);
102 | qreal line_width = raw_font.averageCharWidth() * text.size();
103 | QSGRenderContext *sgr = QQuickItemPrivate::get(m_owner)->sceneGraphRenderContext();
104 | QTextLayout layout(text,font);
105 | layout.beginLayout();
106 | QTextLine line = layout.createLine();
107 | line.setLineWidth(line_width);
108 | //Q_ASSERT(!layout.createLine().isValid());
109 | layout.endLayout();
110 | QList glyphRuns = line.glyphRuns();
111 | qreal xpos = 0;
112 | for (int i = 0; i < glyphRuns.size(); i++) {
113 | QSGGlyphNode *node = sgr->sceneGraphContext()->createGlyphNode(sgr, false);
114 | node->setOwnerElement(m_owner);
115 | node->geometry()->setIndexDataPattern(QSGGeometry::StaticPattern);
116 | node->geometry()->setVertexDataPattern(QSGGeometry::StaticPattern);
117 | node->setGlyphs(QPointF(xpos, raw_font.ascent()), glyphRuns.at(i));
118 | node->setStyle(QQuickText::Normal);
119 | node->setColor(color);
120 | xpos += raw_font.averageCharWidth() * glyphRuns.at(i).positions().size();
121 | node->update();
122 | appendChildNode(node);
123 | }
124 | }
125 | private:
126 | QQuickItem *m_owner;
127 | QVector m_positions;
128 | QLinkedList m_nodes_to_delete;
129 | QRawFont m_raw_font;
130 | };
131 |
132 | MonoText::MonoText(QQuickItem *parent)
133 | : QQuickItem(parent)
134 | , m_color_changed(false)
135 | , m_latin(true)
136 | , m_old_latin(true)
137 | {
138 | setFlag(ItemHasContents, true);
139 | }
140 |
141 | MonoText::~MonoText()
142 | {
143 |
144 | }
145 |
146 | QString MonoText::text() const
147 | {
148 | return m_text;
149 | }
150 |
151 | void MonoText::setText(const QString &text)
152 | {
153 | if (m_text != text) {
154 | m_text = text;
155 | emit textChanged();
156 | polish();
157 | }
158 | }
159 |
160 | QFont MonoText::font() const
161 | {
162 | return m_font;
163 | }
164 |
165 | void MonoText::setFont(const QFont &font)
166 | {
167 | if (font != m_font) {
168 | m_font = font;
169 | emit fontChanged();
170 | polish();
171 | }
172 | }
173 |
174 | QColor MonoText::color() const
175 | {
176 | return m_color;
177 | }
178 |
179 | void MonoText::setColor(const QColor &color)
180 | {
181 | if (m_color != color) {
182 | m_color = color;
183 | emit colorChanged();
184 | update();
185 | }
186 | }
187 |
188 | qreal MonoText::paintedWidth() const
189 | {
190 | return implicitWidth();
191 | }
192 |
193 | qreal MonoText::paintedHeight() const
194 | {
195 | return implicitHeight();
196 | }
197 |
198 | bool MonoText::latin() const
199 | {
200 | return m_latin;
201 | }
202 |
203 | void MonoText::setLatin(bool latin)
204 | {
205 | if (latin == m_latin)
206 | return;
207 |
208 | m_latin = latin;
209 | emit latinChanged();
210 | }
211 |
212 | QSGNode *MonoText::updatePaintNode(QSGNode *old, UpdatePaintNodeData *)
213 | {
214 | if (m_text.size() == 0 || m_text.trimmed().size() == 0) {
215 | delete old;
216 | return 0;
217 | }
218 | MonoSGNode *node = static_cast(old);
219 | if (!node) {
220 | node = new MonoSGNode(this);
221 | }
222 |
223 | if (m_latin) {
224 | node->setLatinText(m_text, m_font, m_color);
225 | } else {
226 | node->setUnicodeText(m_text, m_font, m_color);
227 | }
228 |
229 | return node;
230 | }
231 |
232 | void MonoText::updatePolish()
233 | {
234 | QRawFont raw_font = QRawFont::fromFont(m_font, QFontDatabase::Latin);
235 |
236 | qreal height = raw_font.descent() + raw_font.ascent() + raw_font.lineThickness();
237 | qreal width = raw_font.averageCharWidth() * m_text.size();
238 |
239 | bool emit_text_width_changed = width != implicitWidth();
240 | bool emit_text_height_changed = height != implicitHeight();
241 | setImplicitSize(width, height);
242 |
243 | if (emit_text_width_changed)
244 | emit paintedWidthChanged();
245 | if (emit_text_height_changed)
246 | emit paintedHeightChanged();
247 |
248 | update();
249 | }
250 |
--------------------------------------------------------------------------------
/backend/scrollback.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | ******************************************************************************/
23 |
24 | #include "scrollback.h"
25 |
26 | #include "screen_data.h"
27 | #include "screen.h"
28 | #include "block.h"
29 |
30 | #include
31 |
32 | #define P_VAR(variable) \
33 | #variable ":" << variable
34 |
35 | Scrollback::Scrollback(size_t max_size, ScreenData *screen_data)
36 | : m_screen_data(screen_data)
37 | , m_height(0)
38 | , m_width(0)
39 | , m_block_count(0)
40 | , m_max_size(max_size)
41 | , m_adjust_visible_pages(0)
42 | {
43 | }
44 |
45 | void Scrollback::addBlock(Block *block)
46 | {
47 | if (!m_max_size) {
48 | delete block;
49 | return;
50 | }
51 |
52 | m_blocks.push_back(block);
53 | block->releaseTextObjects();
54 | m_block_count++;
55 | m_height += m_blocks.back()->lineCount();
56 |
57 | while (m_blocks.front() != block && m_height - m_blocks.front()->lineCount() >= m_max_size) {
58 | m_block_count--;
59 | m_height -= std::min(m_blocks.front()->lineCount(), (int)m_height);
60 | delete m_blocks.front();
61 | m_blocks.pop_front();
62 | m_adjust_visible_pages++;
63 | }
64 |
65 | m_visible_pages.clear();
66 | }
67 |
68 | Block *Scrollback::reclaimBlock()
69 | {
70 | if (m_blocks.empty())
71 | return nullptr;
72 |
73 | Block *last = m_blocks.back();
74 | last->setWidth(m_width);
75 | m_block_count--;
76 | m_height -= last->lineCount();
77 | m_blocks.pop_back();
78 |
79 | m_visible_pages.clear();
80 | return last;
81 | }
82 |
83 | void Scrollback::ensureVisiblePages(int top_line)
84 | {
85 | if (top_line < 0)
86 | return;
87 | if (size_t(top_line) >= m_height)
88 | return;
89 |
90 | uint height = std::max(m_screen_data->screen()->height(), 1);
91 |
92 | int complete_pages = m_height / height;
93 | int remainder = m_height - (complete_pages * height);
94 |
95 | int top_page = top_line / height;
96 | int bottom_page = top_page + 1;
97 |
98 | std::set pages_to_update;
99 | pages_to_update.insert(top_page);
100 | if (bottom_page * height < m_height)
101 | pages_to_update.insert(bottom_page);
102 |
103 | for (auto it = m_visible_pages.begin(); it != m_visible_pages.end(); ++it) {
104 | Page &page = *it;
105 | if (pages_to_update.count(page.page_no) != 0) {
106 | if (page.page_no < complete_pages) {
107 | ensurePageVisible(page, height);
108 | } else if (page.page_no == complete_pages) {
109 | ensurePageVisible(page, remainder);
110 | }
111 | pages_to_update.erase(page.page_no);
112 | } else {
113 | ensurePageNotVisible(page);
114 | auto to_remove = it;
115 | --it;
116 | m_visible_pages.erase(to_remove);
117 | }
118 | }
119 |
120 | for (auto it = pages_to_update.begin(); it != pages_to_update.end(); ++it) {
121 | auto page_it = findIteratorForPage(*it);
122 | m_visible_pages.push_back( { *it, 0, page_it } );
123 | if (*it < complete_pages) {
124 | ensurePageVisible(m_visible_pages.back(), height);
125 | } else if (*it == complete_pages) {
126 | ensurePageVisible(m_visible_pages.back(), remainder);
127 | }
128 | }
129 | }
130 |
131 | void Scrollback::ensurePageVisible(Page &page, int new_height)
132 | {
133 | if (page.size == new_height || !m_block_count)
134 | return;
135 |
136 | int line_no = page.page_no * m_screen_data->screen()->height();
137 | auto it = page.it;
138 | std::advance(it, page.size);
139 | for (int i = page.size; i < new_height; ++it, i++) {
140 | (*it)->setLine(line_no + i);
141 | (*it)->dispatchEvents();
142 | }
143 | page.size = new_height;
144 | }
145 |
146 | void Scrollback::ensurePageNotVisible(Page &page)
147 | {
148 | auto it = page.it;
149 | for (int i = 0; i < page.size; ++it, i++) {
150 | (*it)->releaseTextObjects();
151 | }
152 | page.size = 0;
153 | }
154 |
155 | std::list::iterator Scrollback::findIteratorForPage(int page_no)
156 | {
157 | uint line = page_no * m_screen_data->screen()->height();
158 | Q_ASSERT(line < m_height);
159 | for (auto it = m_visible_pages.begin(); it != m_visible_pages.end(); ++it) {
160 | Page &page = *it;
161 | int diff = page_no - page.page_no;
162 | if (diff < 5 && diff > 5) {
163 | auto to_return = page.it;
164 | int advance = diff * m_screen_data->screen()->height();
165 | std::advance(to_return, advance);
166 | return to_return;
167 | }
168 | }
169 |
170 | if (line > m_height / 2) {
171 | auto to_return = m_blocks.end();
172 | std::advance(to_return, line - m_height);
173 | return to_return;
174 | }
175 |
176 | auto to_return = m_blocks.begin();
177 | std::advance(to_return, line);
178 | return to_return;
179 | }
180 |
181 | std::list::iterator Scrollback::findIteratorForLine(size_t line)
182 | {
183 | size_t current_line = m_height;
184 | auto it = m_blocks.end();
185 | while (it != m_blocks.begin()) {
186 | --it;
187 | current_line -= (*it)->lineCount();
188 | if (current_line <= line)
189 | return it;
190 | }
191 | return m_blocks.end();
192 | }
193 |
194 | void Scrollback::adjustVisiblePages()
195 | {
196 | if (!m_adjust_visible_pages)
197 | return;
198 |
199 | for (auto it = m_visible_pages.begin(); it != m_visible_pages.end(); ++it) {
200 | Page &page = *it;
201 | const size_t line_for_page = page.page_no * m_screen_data->screen()->height();
202 | if (line_for_page < m_adjust_visible_pages) {
203 | auto to_remove = it;
204 | --it;
205 | m_visible_pages.erase(to_remove);
206 | } else {
207 | page.size = 0;
208 | std::advance(page.it, m_adjust_visible_pages);
209 | }
210 | }
211 |
212 | m_adjust_visible_pages = 0;
213 | }
214 |
215 | size_t Scrollback::height() const
216 | {
217 | return m_height;
218 | }
219 |
220 | void Scrollback::setWidth(int width)
221 | {
222 | m_width = width;
223 | }
224 |
225 | QString Scrollback::selection(const QPoint &start, const QPoint &end) const
226 | {
227 | Q_ASSERT(start.y() >= 0);
228 | Q_ASSERT(end.y() >= 0);
229 | Q_ASSERT(size_t(end.y()) < m_height);
230 | QString return_string;
231 |
232 | size_t current_line = m_height;
233 | auto it = m_blocks.end();
234 |
235 | bool should_continue = true;
236 | while (it != m_blocks.begin() && should_continue) {
237 | --it;
238 | const int block_height = (*it)->lineCount();
239 | current_line -= block_height;
240 | if (current_line > size_t(end.y())) {
241 | continue;
242 | }
243 |
244 | int end_pos = (*it)->textSize();
245 | if (current_line <= size_t(end.y()) && current_line + block_height >= size_t(end.y())) {
246 | size_t end_line_count = end.y() - current_line;
247 | end_pos = end_line_count * m_width + end.x();
248 | }
249 | int start_pos = 0;
250 | if (current_line <= size_t(start.y()) && current_line + block_height >= size_t(start.y())) {
251 | size_t start_line_count = start.y() - current_line;
252 | start_pos = start_line_count * m_width + start.x();
253 | should_continue = false;
254 | } else if (current_line + block_height < size_t(start.y())) {
255 | should_continue = false;
256 | }
257 | return_string.prepend((*it)->textLine().mid(start_pos, end_pos));
258 | if (should_continue)
259 | return_string.prepend(QChar('\n'));
260 | }
261 |
262 | return return_string;
263 | }
264 |
265 | const SelectionRange Scrollback::getDoubleClickSelectionRange(size_t character, size_t line)
266 | {
267 | auto it = findIteratorForLine(line);
268 | if (it != m_blocks.end())
269 | return Selection::getDoubleClickRange(it, character,line, m_width);
270 | return { QPoint(), QPoint() };
271 | }
272 |
--------------------------------------------------------------------------------
/qml/Yat/Screen.qml:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in all
12 | * copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | import QtQuick 2.10
25 | import QtQuick.Controls 2.2
26 | import Qt.labs.handlers 1.0
27 | import Yat 1.0 as Yat
28 |
29 | Yat.TerminalScreen {
30 | id: screenItem
31 |
32 | property font font
33 | property real fontWidth: fontMetricText.paintedWidth
34 | property real fontHeight: fontMetricText.paintedHeight
35 |
36 | font.family: screen.platformName != "cocoa" ? "monospace" : "menlo"
37 | anchors.fill: parent
38 | focus: true
39 |
40 | Component {
41 | id: textComponent
42 | Yat.Text { }
43 | }
44 | Component {
45 | id: cursorComponent
46 | Yat.Cursor { }
47 | }
48 | Shortcut {
49 | sequence: "Ctrl+Shift+C"
50 | onActivated: screen.selection.sendToClipboard()
51 | }
52 | Shortcut {
53 | sequence: "Ctrl+Shift+V"
54 | onActivated: screen.selection.pasteFromClipboard()
55 | }
56 | Shortcut {
57 | sequence: "Shift+Insert"
58 | onActivated: screen.selection.pasteFromSelection()
59 | }
60 |
61 | onActiveFocusChanged: {
62 | if (activeFocus)
63 | Qt.inputMethod.show();
64 | }
65 |
66 | Keys.onPressed: {
67 | if (event.text === "?")
68 | screen.printScreen()
69 | screen.sendKey(event.text, event.key, event.modifiers);
70 | }
71 |
72 | Text {
73 | id: fontMetricText
74 | text: "B"
75 | font: parent.font
76 | visible: false
77 | textFormat: Text.PlainText
78 | }
79 |
80 | Rectangle {
81 | id: background
82 | anchors.fill: parent
83 | color: screen.defaultBackgroundColor
84 | }
85 | Flickable {
86 | id: flickable
87 | anchors.top: parent.top
88 | anchors.left: parent.left
89 | contentWidth: width
90 | contentHeight: textContainer.height
91 | interactive: true
92 | flickableDirection: Flickable.VerticalFlick
93 | contentY: ((screen.contentHeight - screen.height) * screenItem.fontHeight)
94 | ScrollBar.vertical: ScrollBar { }
95 |
96 | Item {
97 | id: textContainer
98 | width: parent.width
99 | height: screen.contentHeight * screenItem.fontHeight
100 |
101 | Selection {
102 | characterHeight: fontHeight
103 | characterWidth: fontWidth
104 | screenWidth: screenItem.width
105 |
106 | startX: screen.selection.startX
107 | startY: screen.selection.startY
108 |
109 | endX: screen.selection.endX
110 | endY: screen.selection.endY
111 | visible: screen.selection.enable
112 | z: 1
113 | }
114 |
115 | DragHandler {
116 | target: null
117 | acceptedDevices: PointerDevice.Mouse
118 | property int drag_start_x
119 | property int drag_start_y
120 | onActiveChanged: {
121 | if (active) {
122 | drag_start_x = Math.floor((point.pressPosition.x / fontWidth));
123 | drag_start_y = Math.floor(point.pressPosition.y / fontHeight);
124 | screen.selection.startX = drag_start_x;
125 | screen.selection.startY = drag_start_y;
126 | screen.selection.endX = drag_start_x;
127 | screen.selection.endY = drag_start_y;
128 | } else {
129 | screen.selection.sendToSelection();
130 | }
131 | }
132 | onPointChanged: if (active) {
133 | var character = Math.floor(point.position.x / fontWidth);
134 | var line = Math.floor(point.position.y / fontHeight);
135 | var current_pos = Qt.point(character,line);
136 | if (line < drag_start_y || (line === drag_start_y && character < drag_start_x)) {
137 | screen.selection.startX = character;
138 | screen.selection.startY = line;
139 | screen.selection.endX = drag_start_x;
140 | screen.selection.endY = drag_start_y;
141 | } else {
142 | screen.selection.startX = drag_start_x;
143 | screen.selection.startY = drag_start_y;
144 | screen.selection.endX = character;
145 | screen.selection.endY = line;
146 | }
147 | }
148 | }
149 |
150 | TapHandler {
151 | acceptedButtons: Qt.MiddleButton
152 | gesturePolicy: TapHandler.DragThreshold
153 | onTapped: screen.selection.pasteFromSelection()
154 | }
155 |
156 | TapHandler {
157 | gesturePolicy: TapHandler.DragThreshold
158 | onTapped: {
159 | switch (tapCount) {
160 | case 1:
161 | screen.selection.startX = 0;
162 | screen.selection.startY = 0;
163 | screen.selection.endX = 0;
164 | screen.selection.endY = 0;
165 | break;
166 | case 2:
167 | var character = Math.floor(point.position.x / fontWidth);
168 | var line = Math.floor(point.position.y / fontHeight);
169 | screen.doubleClicked(character,line);
170 | screen.selection.sendToSelection();
171 | break;
172 | }
173 | }
174 | }
175 | }
176 |
177 | Item {
178 | id: cursorContainer
179 | width: textContainer.width
180 | height: textContainer.height
181 | }
182 |
183 | onContentYChanged: {
184 | if (!atYEnd) {
185 | var top_line = Math.floor(Math.max(contentY,0) / screenItem.fontHeight);
186 | screen.ensureVisiblePages(top_line);
187 | }
188 | }
189 | }
190 |
191 | Connections {
192 | id: connections
193 | target: screen
194 | onFlash: flashAnimation.start()
195 | onReset: resetScreenItems();
196 |
197 | onTextCreated: {
198 | var textSegment = textComponent.createObject(screenItem,
199 | {
200 | "parent" : textContainer,
201 | "objectHandle" : text,
202 | "font" : screenItem.font,
203 | "fontWidth" : screenItem.fontWidth,
204 | "fontHeight" : screenItem.fontHeight,
205 | });
206 | }
207 |
208 | onCursorCreated: {
209 | if (cursorComponent.status != Component.Ready) {
210 | console.log(cursorComponent.errorString());
211 | return;
212 | }
213 | var cursorVariable = cursorComponent.createObject(screenItem,
214 | {
215 | "parent" : cursorContainer,
216 | "objectHandle" : cursor,
217 | "fontWidth" : screenItem.fontWidth,
218 | "fontHeight" : screenItem.fontHeight,
219 | })
220 | }
221 |
222 | onRequestHeightChange: {
223 | terminalWindow.height = newHeight * screenItem.fontHeight;
224 | terminalWindow.contentItem.height = newHeight * screenItem.fontHeight;
225 | }
226 |
227 | onRequestWidthChange: {
228 | terminalWindow.width = newWidth * screenItem.fontWidth;
229 | terminalWindow.contentItem.width = newWidth * screenItem.fontWidth;
230 | }
231 | }
232 |
233 | onFontChanged: {
234 | setTerminalHeight();
235 | setTerminalWidth();
236 | }
237 |
238 | onWidthChanged: setTerminalWidth();
239 |
240 | onHeightChanged: setTerminalHeight();
241 |
242 | function setTerminalWidth() {
243 | if (fontWidth > 0) {
244 | var pty_width = Math.floor(width / fontWidth);
245 | flickable.width = pty_width * fontWidth;
246 | screen.width = pty_width;
247 | }
248 | }
249 |
250 | function setTerminalHeight() {
251 | if (fontHeight > 0) {
252 | var pty_height = Math.floor(height / fontHeight);
253 | flickable.height = pty_height * fontHeight;
254 | screen.height = pty_height;
255 | }
256 | }
257 |
258 | Rectangle {
259 | id: flash
260 | z: 1.2
261 | anchors.fill: parent
262 | color: "grey"
263 | opacity: 0
264 | SequentialAnimation {
265 | id: flashAnimation
266 | NumberAnimation {
267 | target: flash
268 | property: "opacity"
269 | to: 1
270 | duration: 75
271 | }
272 | NumberAnimation {
273 | target: flash
274 | property: "opacity"
275 | to: 0
276 | duration: 75
277 | }
278 | }
279 | }
280 | }
281 |
--------------------------------------------------------------------------------
/backend/color_palette.cpp:
--------------------------------------------------------------------------------
1 | #include "color_palette.h"
2 |
3 | #include
4 |
5 | static QVector defaultXtermColors = {
6 | QColor(0,0,0).rgb(), // index 16
7 | QColor(0,0,95).rgb(),
8 | QColor(0,0,135).rgb(),
9 | QColor(0,0,175).rgb(),
10 | QColor(0,0,215).rgb(),
11 | QColor(0,0,255).rgb(),
12 | QColor(0,95,0).rgb(),
13 | QColor(0,95,95).rgb(),
14 | QColor(0,95,135).rgb(),
15 | QColor(0,95,175).rgb(),
16 | QColor(0,95,215).rgb(),
17 | QColor(0,95,255).rgb(),
18 | QColor(0,135,0).rgb(),
19 | QColor(0,135,95).rgb(),
20 | QColor(0,135,135).rgb(),
21 | QColor(0,135,175).rgb(),
22 | QColor(0,135,215).rgb(),
23 | QColor(0,135,255).rgb(),
24 | QColor(0,175,0).rgb(),
25 | QColor(0,175,95).rgb(),
26 | QColor(0,175,135).rgb(),
27 | QColor(0,175,175).rgb(),
28 | QColor(0,175,215).rgb(),
29 | QColor(0,175,255).rgb(),
30 | QColor(0,215,0).rgb(),
31 | QColor(0,215,95).rgb(),
32 | QColor(0,215,135).rgb(),
33 | QColor(0,215,175).rgb(),
34 | QColor(0,215,215).rgb(),
35 | QColor(0,215,255).rgb(),
36 | QColor(0,255,0).rgb(),
37 | QColor(0,255,95).rgb(),
38 | QColor(0,255,135).rgb(),
39 | QColor(0,255,175).rgb(),
40 | QColor(0,255,215).rgb(),
41 | QColor(0,255,255).rgb(),
42 | QColor(95,0,0).rgb(),
43 | QColor(95,0,95).rgb(),
44 | QColor(95,0,135).rgb(),
45 | QColor(95,0,175).rgb(),
46 | QColor(95,0,215).rgb(),
47 | QColor(95,0,255).rgb(),
48 | QColor(95,95,0).rgb(),
49 | QColor(95,95,95).rgb(),
50 | QColor(95,95,135).rgb(),
51 | QColor(95,95,175).rgb(),
52 | QColor(95,95,215).rgb(),
53 | QColor(95,95,255).rgb(),
54 | QColor(95,135,0).rgb(),
55 | QColor(95,135,95).rgb(),
56 | QColor(95,135,135).rgb(),
57 | QColor(95,135,175).rgb(),
58 | QColor(95,135,215).rgb(),
59 | QColor(95,135,255).rgb(),
60 | QColor(95,175,0).rgb(),
61 | QColor(95,175,95).rgb(),
62 | QColor(95,175,135).rgb(),
63 | QColor(95,175,175).rgb(),
64 | QColor(95,175,215).rgb(),
65 | QColor(95,175,255).rgb(),
66 | QColor(95,215,0).rgb(),
67 | QColor(95,215,95).rgb(),
68 | QColor(95,215,135).rgb(),
69 | QColor(95,215,175).rgb(),
70 | QColor(95,215,215).rgb(),
71 | QColor(95,215,255).rgb(),
72 | QColor(95,255,0).rgb(),
73 | QColor(95,255,95).rgb(),
74 | QColor(95,255,135).rgb(),
75 | QColor(95,255,175).rgb(),
76 | QColor(95,255,215).rgb(),
77 | QColor(95,255,255).rgb(),
78 | QColor(135,0,0).rgb(),
79 | QColor(135,0,95).rgb(),
80 | QColor(135,0,135).rgb(),
81 | QColor(135,0,175).rgb(),
82 | QColor(135,0,215).rgb(),
83 | QColor(135,0,255).rgb(),
84 | QColor(135,95,0).rgb(),
85 | QColor(135,95,95).rgb(),
86 | QColor(135,95,135).rgb(),
87 | QColor(135,95,175).rgb(),
88 | QColor(135,95,215).rgb(),
89 | QColor(135,95,255).rgb(),
90 | QColor(135,135,0).rgb(),
91 | QColor(135,135,95).rgb(),
92 | QColor(135,135,135).rgb(),
93 | QColor(135,135,175).rgb(),
94 | QColor(135,135,215).rgb(),
95 | QColor(135,135,255).rgb(),
96 | QColor(135,175,0).rgb(),
97 | QColor(135,175,95).rgb(),
98 | QColor(135,175,135).rgb(),
99 | QColor(135,175,175).rgb(),
100 | QColor(135,175,215).rgb(),
101 | QColor(135,175,255).rgb(),
102 | QColor(135,215,0).rgb(),
103 | QColor(135,215,95).rgb(),
104 | QColor(135,215,135).rgb(),
105 | QColor(135,215,175).rgb(),
106 | QColor(135,215,215).rgb(),
107 | QColor(135,215,255).rgb(),
108 | QColor(135,255,0).rgb(),
109 | QColor(135,255,95).rgb(),
110 | QColor(135,255,135).rgb(),
111 | QColor(135,255,175).rgb(),
112 | QColor(135,255,215).rgb(),
113 | QColor(135,255,255).rgb(),
114 | QColor(175,0,0).rgb(),
115 | QColor(175,0,95).rgb(),
116 | QColor(175,0,135).rgb(),
117 | QColor(175,0,175).rgb(),
118 | QColor(175,0,215).rgb(),
119 | QColor(175,0,255).rgb(),
120 | QColor(175,95,0).rgb(),
121 | QColor(175,95,95).rgb(),
122 | QColor(175,95,135).rgb(),
123 | QColor(175,95,175).rgb(),
124 | QColor(175,95,215).rgb(),
125 | QColor(175,95,255).rgb(),
126 | QColor(175,135,0).rgb(),
127 | QColor(175,135,95).rgb(),
128 | QColor(175,135,135).rgb(),
129 | QColor(175,135,175).rgb(),
130 | QColor(175,135,215).rgb(),
131 | QColor(175,135,255).rgb(),
132 | QColor(175,175,0).rgb(),
133 | QColor(175,175,95).rgb(),
134 | QColor(175,175,135).rgb(),
135 | QColor(175,175,175).rgb(),
136 | QColor(175,175,215).rgb(),
137 | QColor(175,175,255).rgb(),
138 | QColor(175,215,0).rgb(),
139 | QColor(175,215,95).rgb(),
140 | QColor(175,215,135).rgb(),
141 | QColor(175,215,175).rgb(),
142 | QColor(175,215,215).rgb(),
143 | QColor(175,215,255).rgb(),
144 | QColor(175,255,0).rgb(),
145 | QColor(175,255,95).rgb(),
146 | QColor(175,255,135).rgb(),
147 | QColor(175,255,175).rgb(),
148 | QColor(175,255,215).rgb(),
149 | QColor(175,255,255).rgb(),
150 | QColor(215,0,0).rgb(),
151 | QColor(215,0,95).rgb(),
152 | QColor(215,0,135).rgb(),
153 | QColor(215,0,175).rgb(),
154 | QColor(215,0,215).rgb(),
155 | QColor(215,0,255).rgb(),
156 | QColor(215,95,0).rgb(),
157 | QColor(215,95,95).rgb(),
158 | QColor(215,95,135).rgb(),
159 | QColor(215,95,175).rgb(),
160 | QColor(215,95,215).rgb(),
161 | QColor(215,95,255).rgb(),
162 | QColor(215,135,0).rgb(),
163 | QColor(215,135,95).rgb(),
164 | QColor(215,135,135).rgb(),
165 | QColor(215,135,175).rgb(),
166 | QColor(215,135,215).rgb(),
167 | QColor(215,135,255).rgb(),
168 | QColor(215,175,0).rgb(),
169 | QColor(215,175,95).rgb(),
170 | QColor(215,175,135).rgb(),
171 | QColor(215,175,175).rgb(),
172 | QColor(215,175,215).rgb(),
173 | QColor(215,175,255).rgb(),
174 | QColor(215,215,0).rgb(),
175 | QColor(215,215,95).rgb(),
176 | QColor(215,215,135).rgb(),
177 | QColor(215,215,175).rgb(),
178 | QColor(215,215,215).rgb(),
179 | QColor(215,215,255).rgb(),
180 | QColor(215,255,0).rgb(),
181 | QColor(215,255,95).rgb(),
182 | QColor(215,255,135).rgb(),
183 | QColor(215,255,175).rgb(),
184 | QColor(215,255,215).rgb(),
185 | QColor(215,255,255).rgb(),
186 | QColor(255,0,0).rgb(),
187 | QColor(255,0,95).rgb(),
188 | QColor(255,0,135).rgb(),
189 | QColor(255,0,175).rgb(),
190 | QColor(255,0,215).rgb(),
191 | QColor(255,0,255).rgb(),
192 | QColor(255,95,0).rgb(),
193 | QColor(255,95,95).rgb(),
194 | QColor(255,95,135).rgb(),
195 | QColor(255,95,175).rgb(),
196 | QColor(255,95,215).rgb(),
197 | QColor(255,95,255).rgb(),
198 | QColor(255,135,0).rgb(),
199 | QColor(255,135,95).rgb(),
200 | QColor(255,135,135).rgb(),
201 | QColor(255,135,175).rgb(),
202 | QColor(255,135,215).rgb(),
203 | QColor(255,135,255).rgb(),
204 | QColor(255,175,0).rgb(),
205 | QColor(255,175,95).rgb(),
206 | QColor(255,175,135).rgb(),
207 | QColor(255,175,175).rgb(),
208 | QColor(255,175,215).rgb(),
209 | QColor(255,175,255).rgb(),
210 | QColor(255,215,0).rgb(),
211 | QColor(255,215,95).rgb(),
212 | QColor(255,215,135).rgb(),
213 | QColor(255,215,175).rgb(),
214 | QColor(255,215,215).rgb(),
215 | QColor(255,215,255).rgb(),
216 | QColor(255,255,0).rgb(),
217 | QColor(255,255,95).rgb(),
218 | QColor(255,255,135).rgb(),
219 | QColor(255,255,175).rgb(),
220 | QColor(255,255,215).rgb(),
221 | QColor(255,255,255).rgb(),
222 | QColor(8,8,8).rgb(),
223 | QColor(18,18,18).rgb(),
224 | QColor(28,28,28).rgb(),
225 | QColor(38,38,38).rgb(),
226 | QColor(48,48,48).rgb(),
227 | QColor(58,58,58).rgb(),
228 | QColor(68,68,68).rgb(),
229 | QColor(78,78,78).rgb(),
230 | QColor(88,88,88).rgb(),
231 | QColor(98,98,98).rgb(),
232 | QColor(108,108,108).rgb(),
233 | QColor(118,118,118).rgb(),
234 | QColor(128,128,128).rgb(),
235 | QColor(138,138,138).rgb(),
236 | QColor(148,148,148).rgb(),
237 | QColor(158,158,158).rgb(),
238 | QColor(168,168,168).rgb(),
239 | QColor(178,178,178).rgb(),
240 | QColor(188,188,188).rgb(),
241 | QColor(198,198,198).rgb(),
242 | QColor(208,208,208).rgb(),
243 | QColor(218,218,218).rgb(),
244 | QColor(228,228,228).rgb(),
245 | QColor(238,238,238).rgb() // index 255
246 | };
247 |
248 |
249 | ColorPalette::ColorPalette(QObject *parent)
250 | : QObject(parent)
251 | , m_normalColors(numberOfColors)
252 | , m_lightColors(numberOfColors)
253 | , m_xtermColors(defaultXtermColors)
254 | , m_inverse_default(false)
255 | {
256 | m_normalColors[0].setRgb(0,0,0);
257 | m_normalColors[1].setRgb(194,54,33);
258 | m_normalColors[2].setRgb(37,188,36);
259 | m_normalColors[3].setRgb(173,173,39);
260 | m_normalColors[4].setRgb(63,84,255);
261 | m_normalColors[5].setRgb(211,56,211);
262 | m_normalColors[6].setRgb(51,187,199);
263 | m_normalColors[7].setRgb(229,229,229);
264 | m_normalColors[8].setRgb(178,178,178);
265 | m_normalColors[9].setRgb(0,0,0);
266 |
267 | m_lightColors[0].setRgb(129,131,131);
268 | m_lightColors[1].setRgb(252,57,31);
269 | m_lightColors[2].setRgb(49,231,34);
270 | m_lightColors[3].setRgb(234,236,35);
271 | m_lightColors[4].setRgb(88,51,255);
272 | m_lightColors[5].setRgb(249,53,248);
273 | m_lightColors[6].setRgb(20,240,240);
274 | m_lightColors[7].setRgb(233,233,233);
275 | m_lightColors[8].setRgb(220,220,220);
276 | m_lightColors[9].setRgb(50,50,50);
277 |
278 | }
279 |
280 | QColor ColorPalette::color(ColorPalette::Color color, bool bold) const
281 | {
282 | if (m_inverse_default) {
283 | if (color == DefaultForeground)
284 | color = DefaultBackground;
285 | else if (color == DefaultBackground)
286 | color = DefaultForeground;
287 | }
288 | if (bold)
289 | return m_lightColors.at(color);
290 |
291 | return m_normalColors.at(color);
292 | }
293 |
294 | QColor ColorPalette::normalColor(ColorPalette::Color color) const
295 | {
296 | return this->color(color, false);
297 | }
298 |
299 | QColor ColorPalette::lightColor(ColorPalette::Color color) const
300 | {
301 | return this->color(color,true);
302 | }
303 |
304 | QRgb ColorPalette::normalRgb(int index)
305 | {
306 | return m_normalColors[index].rgb();
307 | }
308 |
309 | QRgb ColorPalette::xtermRgb(int index)
310 | {
311 | Q_ASSERT(index >= 16);
312 | return m_xtermColors[index - 16];
313 | }
314 |
315 | void ColorPalette::setInverseDefaultColors(bool inverse)
316 | {
317 | bool emit_changed = inverse != m_inverse_default;
318 | if (emit_changed) {
319 | m_inverse_default = inverse;
320 | emit changed();
321 | emit defaultBackgroundColorChanged();
322 | }
323 | }
324 |
325 | QColor ColorPalette::defaultForeground() const
326 | {
327 | return normalColor(DefaultForeground);
328 | }
329 |
330 | QColor ColorPalette::defaultBackground() const
331 | {
332 | return normalColor(DefaultBackground);
333 | }
334 |
--------------------------------------------------------------------------------
/backend/cursor.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in all
12 | * copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #include "cursor.h"
25 |
26 | #include "block.h"
27 | #include "screen_data.h"
28 |
29 | #include
30 | #include
31 |
32 | Q_LOGGING_CATEGORY(lcCursor, "yat.cursor")
33 |
34 | Cursor::Cursor(Screen* screen)
35 | : QObject(screen)
36 | , m_screen(screen)
37 | , m_current_text_style(screen->defaultTextStyle())
38 | , m_position(0,0)
39 | , m_new_position(0,0)
40 | , m_screen_width(screen->width())
41 | , m_screen_height(screen->height())
42 | , m_top_margin(0)
43 | , m_bottom_margin(0)
44 | , m_scroll_margins_set(false)
45 | , m_origin_at_margin(false)
46 | , m_notified(false)
47 | , m_visible(true)
48 | , m_new_visibillity(true)
49 | , m_blinking(false)
50 | , m_new_blinking(false)
51 | , m_wrap_around(true)
52 | , m_content_height_changed(false)
53 | , m_insert_mode(Replace)
54 | , m_resize_block(0)
55 | , m_current_pos_in_block(0)
56 | {
57 | connect(screen, &Screen::widthAboutToChange, this, &Cursor::setScreenWidthAboutToChange);
58 | connect(screen, &Screen::dataWidthChanged, this, &Cursor::setScreenWidth);
59 | connect(screen, &Screen::dataHeightChanged, this, &Cursor::setScreenHeight);
60 | connect(screen, &Screen::contentHeightChanged, this, &Cursor::contentHeightChanged);
61 |
62 | m_gl_text_codec = QTextCodec::codecForName("utf-8")->makeDecoder();
63 | m_gr_text_codec = QTextCodec::codecForName("utf-8")->makeDecoder();
64 |
65 | for (int i = 0; i < m_screen_width; i++) {
66 | if (i % 8 == 0) {
67 | m_tab_stops.append(i);
68 | }
69 | }
70 | }
71 |
72 | Cursor::~Cursor()
73 | {
74 |
75 | }
76 |
77 | void Cursor::setScreenWidthAboutToChange(int width)
78 | {
79 | Q_UNUSED(width);
80 | auto it = m_screen->currentScreenData()->it_for_row(new_y());
81 | if (m_screen->currentScreenData()->it_is_end(it))
82 | return;
83 |
84 | m_resize_block = *it;
85 | int line_diff = new_y() - m_resize_block->screenIndex();
86 | m_current_pos_in_block = (line_diff * m_screen_width) + new_x();
87 | }
88 |
89 | void Cursor::setScreenWidth(int newWidth, int removedBeginning, int reclaimed)
90 | {
91 | if (newWidth > m_screen_width) {
92 | for (int i = m_screen_width -1; i < newWidth; i++) {
93 | if (i % 8 == 0) {
94 | m_tab_stops.append(i);
95 | }
96 | }
97 | }
98 |
99 | m_screen_width = newWidth;
100 |
101 | auto it = m_screen->currentScreenData()->it_for_block(m_resize_block);
102 | if (m_screen->currentScreenData()->it_is_end(it)) {
103 | if (removedBeginning > reclaimed) {
104 | new_ry() = 0;
105 | new_rx() = 0;
106 | } else {
107 | new_ry() = m_screen_height - 1;
108 | new_rx() = 0;
109 | }
110 | } else {
111 | new_ry() = (*it)->screenIndex() + m_current_pos_in_block / newWidth;
112 | new_rx() = m_current_pos_in_block % newWidth;
113 | }
114 | m_resize_block = 0;
115 | m_current_pos_in_block = 0;
116 | notifyChanged();
117 | }
118 |
119 | void Cursor::setScreenHeight(int newHeight, int removedBeginning, int reclaimed)
120 | {
121 | resetScrollArea();
122 | m_screen_height = newHeight;
123 | new_ry() -= removedBeginning;
124 | new_ry() += reclaimed;
125 | if (new_y() <= 0) {
126 | new_ry() = 0;
127 | }
128 | }
129 |
130 | bool Cursor::visible() const
131 | {
132 | return m_visible;
133 | }
134 | void Cursor::setVisible(bool visible)
135 | {
136 | m_new_visibillity = visible;
137 | }
138 |
139 | bool Cursor::blinking() const
140 | {
141 | return m_blinking;
142 | }
143 |
144 | void Cursor::setBlinking(bool blinking)
145 | {
146 | m_new_blinking = blinking;
147 | }
148 |
149 | void Cursor::setTextStyle(TextStyle::Style style, bool add)
150 | {
151 | if (add) {
152 | m_current_text_style.style |= style;
153 | } else {
154 | m_current_text_style.style &= !style;
155 | }
156 | }
157 |
158 | void Cursor::resetStyle()
159 | {
160 | m_current_text_style.background = colorPalette()->defaultBackground().rgb();
161 | m_current_text_style.foreground = colorPalette()->defaultForeground().rgb();
162 | m_current_text_style.style = TextStyle::Normal;
163 | }
164 |
165 | void Cursor::scrollUp(int lines)
166 | {
167 | if (new_y() < top() || new_y() > bottom())
168 | return;
169 | for (int i = 0; i < lines; i++) {
170 | screen_data()->moveLine(bottom(), top());
171 | }
172 | }
173 |
174 | void Cursor::scrollDown(int lines)
175 | {
176 | if (new_y() < top() || new_y() > bottom())
177 | return;
178 | for (int i = 0; i < lines; i++) {
179 | screen_data()->moveLine(top(), bottom());
180 | }
181 | }
182 |
183 | void Cursor::setTextCodec(QTextCodec *codec)
184 | {
185 | m_gl_text_codec = codec->makeDecoder();
186 | }
187 |
188 | void Cursor::setInsertMode(InsertMode mode)
189 | {
190 | m_insert_mode = mode;
191 | }
192 |
193 | TextStyle Cursor::currentTextStyle() const
194 | {
195 | return m_current_text_style;
196 | }
197 |
198 | void Cursor::setTextForegroundColor(QRgb color)
199 | {
200 | m_current_text_style.foreground = color;
201 | }
202 |
203 | void Cursor::setTextBackgroundColor(QRgb color)
204 | {
205 | m_current_text_style.background = color;
206 | }
207 |
208 | void Cursor::setTextForegroundColorIndex(ColorPalette::Color color)
209 | {
210 | qCDebug(lcCursor) << color;
211 | setTextForegroundColor(colorPalette()->color(color).rgb());
212 | }
213 |
214 | void Cursor::setTextBackgroundColorIndex(ColorPalette::Color color)
215 | {
216 | qCDebug(lcCursor) << color;
217 | setTextBackgroundColor(colorPalette()->color(color).rgb());
218 | }
219 |
220 | ColorPalette *Cursor::colorPalette() const
221 | {
222 | return m_screen->colorPalette();
223 | }
224 |
225 | QPoint Cursor::position() const
226 | {
227 | return m_position;
228 | }
229 |
230 | int Cursor::x() const
231 | {
232 | return m_position.x();
233 | }
234 |
235 | int Cursor::y() const
236 | {
237 | return (m_screen->currentScreenData()->contentHeight() - m_screen->height()) + m_position.y();
238 | }
239 |
240 | void Cursor::moveOrigin()
241 | {
242 | m_new_position = QPoint(0,adjusted_top());
243 | notifyChanged();
244 | }
245 |
246 | void Cursor::moveBeginningOfLine()
247 | {
248 | new_rx() = 0;
249 | notifyChanged();
250 | }
251 |
252 | void Cursor::moveUp(int lines)
253 | {
254 | int adjusted_new_y = this->adjusted_new_y();
255 | if (!adjusted_new_y || !lines)
256 | return;
257 |
258 | if (lines < adjusted_new_y) {
259 | new_ry() -= lines;
260 | } else {
261 | new_ry() = adjusted_top();
262 | }
263 | notifyChanged();
264 | }
265 |
266 | void Cursor::moveDown(int lines)
267 | {
268 | int bottom = adjusted_bottom();
269 | if (new_y() == bottom || !lines)
270 | return;
271 |
272 | if (new_y() + lines <= bottom) {
273 | new_ry() += lines;
274 | } else {
275 | new_ry() = bottom;
276 | }
277 | notifyChanged();
278 | }
279 |
280 | void Cursor::moveLeft(int positions)
281 | {
282 | if (!new_x() || !positions)
283 | return;
284 | if (positions < new_x()) {
285 | new_rx() -= positions;
286 | } else {
287 | new_rx() = 0;
288 | }
289 | notifyChanged();
290 | }
291 |
292 | void Cursor::moveRight(int positions)
293 | {
294 | int width = m_screen->width();
295 | if (new_x() == width -1 || !positions)
296 | return;
297 | if (positions < width - new_x()) {
298 | new_rx() += positions;
299 | } else {
300 | new_rx() = width -1;
301 | }
302 |
303 | notifyChanged();
304 | }
305 |
306 | void Cursor::move(int new_x, int new_y)
307 | {
308 | int width = m_screen->width();
309 |
310 | if (m_origin_at_margin) {
311 | new_y += m_top_margin;
312 | }
313 |
314 | if (new_x < 0) {
315 | new_x = 0;
316 | } else if (new_x >= width) {
317 | new_x = width - 1;
318 | }
319 |
320 | if (new_y < adjusted_top()) {
321 | new_y = adjusted_top();
322 | } else if (new_y > adjusted_bottom()) {
323 | new_y = adjusted_bottom();
324 | }
325 |
326 | if (this->new_y() != new_y || this->new_x() != new_x) {
327 | m_new_position = QPoint(new_x, new_y);
328 | notifyChanged();
329 | }
330 | }
331 |
332 | void Cursor::moveToLine(int line)
333 | {
334 | const int height = m_screen->height();
335 | if (line < adjusted_top()) {
336 | line = 0;
337 | } else if (line > adjusted_bottom()) {
338 | line = height -1;
339 | }
340 |
341 | if (line != new_y()) {
342 | new_rx() = line;
343 | notifyChanged();
344 | }
345 | }
346 |
347 | void Cursor::moveToCharacter(int character)
348 | {
349 | const int width = m_screen->width();
350 | if (character < 0) {
351 | character = 1;
352 | } else if (character > width) {
353 | character = width;
354 | }
355 | if (character != new_x()) {
356 | new_rx() = character;
357 | notifyChanged();
358 | }
359 | }
360 |
361 | void Cursor::moveToNextTab()
362 | {
363 | for (int i = 0; i < m_tab_stops.size(); i++) {
364 | if (new_x() < m_tab_stops.at(i)) {
365 | moveToCharacter(std::min(m_tab_stops.at(i), m_screen_width -1));
366 | return;
367 | }
368 | }
369 | moveToCharacter(m_screen_width - 1);
370 | }
371 |
372 | void Cursor::setTabStop()
373 | {
374 | int i;
375 | for (i = 0; i < m_tab_stops.size(); i++) {
376 | if (new_x() == m_tab_stops.at(i))
377 | return;
378 | if (new_x() > m_tab_stops.at(i)) {
379 | continue;
380 | } else {
381 | break;
382 | }
383 | }
384 | m_tab_stops.insert(i,new_x());
385 | }
386 |
387 | void Cursor::removeTabStop()
388 | {
389 | for (int i = 0; i < m_tab_stops.size(); i++) {
390 | if (new_x() == m_tab_stops.at(i)) {
391 | m_tab_stops.remove(i);
392 | return;
393 | } else if (new_x() < m_tab_stops.at(i)) {
394 | return;
395 | }
396 | }
397 | }
398 |
399 | void Cursor::clearTabStops()
400 | {
401 | m_tab_stops.clear();
402 | }
403 |
404 | void Cursor::clearToBeginningOfLine()
405 | {
406 | screen_data()->clearToBeginningOfLine(m_new_position);
407 | }
408 |
409 | void Cursor::clearToEndOfLine()
410 | {
411 | screen_data()->clearToEndOfLine(m_new_position);
412 | }
413 |
414 | void Cursor::clearToBeginningOfScreen()
415 | {
416 | clearToBeginningOfLine();
417 | if (new_y() > 0)
418 | screen_data()->clearToBeginningOfScreen(m_new_position.y()-1);
419 | }
420 |
421 | void Cursor::clearToEndOfScreen()
422 | {
423 | clearToEndOfLine();
424 | if (new_y() < m_screen->height() -1) {
425 | screen_data()->clearToEndOfScreen(m_new_position.y()+1);
426 | }
427 | }
428 |
429 | void Cursor::clearLine()
430 | {
431 | screen_data()->clearLine(m_new_position);
432 | }
433 |
434 | void Cursor::deleteCharacters(int characters)
435 | {
436 | screen_data()->deleteCharacters(m_new_position, new_x() + characters -1);
437 | }
438 |
439 | void Cursor::setWrapAround(bool wrap)
440 | {
441 | m_wrap_around = wrap;
442 | }
443 |
444 | void Cursor::addAtCursor(const QByteArray &data, bool only_latin)
445 | {
446 | if (m_insert_mode == Replace) {
447 | replaceAtCursor(data, only_latin);
448 | } else {
449 | insertAtCursor(data, only_latin);
450 | }
451 | }
452 |
453 | void Cursor::replaceAtCursor(const QByteArray &data, bool only_latin)
454 | {
455 | const QString text = m_gl_text_codec->toUnicode(data);
456 |
457 | if (!m_wrap_around && new_x() + text.size() > m_screen->width()) {
458 | const int size = m_screen_width - new_x();
459 | QString toBlock = text.mid(0,size);
460 | toBlock.replace(toBlock.size() - 1, 1, text.at(text.size()-1));
461 | screen_data()->replace(m_new_position, toBlock, m_current_text_style, only_latin);
462 | new_rx() += toBlock.size();
463 | } else {
464 | auto diff = screen_data()->replace(m_new_position, text, m_current_text_style, only_latin);
465 | new_rx() += diff.character;
466 | new_ry() += diff.line;
467 | }
468 |
469 | if (new_y() >= m_screen_height) {
470 | new_ry() = m_screen_height - 1;
471 | }
472 |
473 | notifyChanged();
474 | }
475 |
476 | void Cursor::insertAtCursor(const QByteArray &data, bool only_latin)
477 | {
478 | const QString text = m_gl_text_codec->toUnicode(data);
479 | auto diff = screen_data()->insert(m_new_position, text, m_current_text_style, only_latin);
480 | new_rx() += diff.character;
481 | new_ry() += diff.line;
482 | if (new_y() >= m_screen_height)
483 | new_ry() = m_screen_height - 1;
484 | if (new_x() >= m_screen_width)
485 | new_rx() = m_screen_width - 1;
486 | }
487 |
488 | void Cursor::lineFeed()
489 | {
490 | if(new_y() >= bottom()) {
491 | screen_data()->insertLine(bottom(), top());
492 | } else {
493 | new_ry()++;
494 | notifyChanged();
495 | }
496 | }
497 |
498 | void Cursor::reverseLineFeed()
499 | {
500 | if (new_y() == top()) {
501 | scrollUp(1);
502 | } else {
503 | new_ry()--;
504 | notifyChanged();
505 | }
506 | }
507 |
508 | void Cursor::setOriginAtMargin(bool atMargin)
509 | {
510 | m_origin_at_margin = atMargin;
511 | m_new_position = QPoint(0, adjusted_top());
512 | notifyChanged();
513 | }
514 |
515 | void Cursor::setScrollArea(int from, int to)
516 | {
517 | m_top_margin = from;
518 | m_bottom_margin = std::min(to,m_screen_height -1);
519 | m_scroll_margins_set = true;
520 | }
521 |
522 | void Cursor::resetScrollArea()
523 | {
524 | m_top_margin = 0;
525 | m_bottom_margin = 0;
526 | m_scroll_margins_set = false;
527 | }
528 |
529 | void Cursor::dispatchEvents()
530 | {
531 | if (m_new_position != m_position|| m_content_height_changed) {
532 | bool emit_x_changed = m_new_position.x() != m_position.x();
533 | bool emit_y_changed = m_new_position.y() != m_position.y();
534 | m_position = m_new_position;
535 | if (emit_x_changed)
536 | emit xChanged();
537 | if (emit_y_changed || m_content_height_changed)
538 | emit yChanged();
539 | }
540 |
541 | if (m_new_visibillity != m_visible) {
542 | m_visible = m_new_visibillity;
543 | emit visibilityChanged();
544 | }
545 |
546 | if (m_new_blinking != m_blinking) {
547 | m_blinking = m_new_blinking;
548 | emit blinkingChanged();
549 | }
550 | }
551 |
552 | void Cursor::contentHeightChanged()
553 | {
554 | m_content_height_changed = true;
555 | }
556 |
557 |
--------------------------------------------------------------------------------
/backend/character_sets.h:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Copyright (c) 2013 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #include
25 |
26 | static const QChar dec_special_graphics_char_set[] =
27 | {
28 | /*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
29 | /*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
30 | /*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
31 | /*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
32 | /*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
33 | /*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
34 | /*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
35 | /*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
36 | /*0x40*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
37 | /*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
38 | /*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
39 | /*0x58*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0020,
40 | /*0x60*/ 0x25c6,0x2592,0x2409,0x240c,0x240d,0x240a,0x00b0,0x00b1,
41 | /*0x68*/ 0x2424,0x240b,0x2518,0x2510,0x250c,0x2514,0x253c,0x23ba,
42 | /*0x70*/ 0x23bb,0x2500,0x23bc,0x23bd,0x251c,0x2524,0x2534,0x252c,
43 | /*0x78*/ 0x2502,0x2264,0x2265,0x03c0,0x2260,0x00a3,0x00b7,0x0000,
44 | };
45 |
46 | static const QChar nrc_british_char_set[] =
47 | {
48 | /*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
49 | /*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
50 | /*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
51 | /*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
52 | /*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
53 | /*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
54 | /*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
55 | /*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
56 | /*0x40*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
57 | /*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
58 | /*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
59 | /*0x58*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
60 | /*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
61 | /*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
62 | /*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
63 | /*0x78*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
64 | };
65 |
66 | static const QChar nrc_norwegian_danish_char_set[] =
67 | {
68 | /*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
69 | /*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
70 | /*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
71 | /*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
72 | /*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
73 | /*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
74 | /*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
75 | /*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
76 | /*0x40*/ 0x00c4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
77 | /*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
78 | /*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
79 | /*0x58*/ 0x0000,0x0000,0x0000,0x00c6,0x00d8,0x00c5,0x00dc,0x0000,
80 | /*0x60*/ 0x00e4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
81 | /*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
82 | /*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
83 | /*0x78*/ 0x0000,0x0000,0x0000,0x00e6,0x00f8,0x00e5,0x00fc,0x0000,
84 | };
85 |
86 | static const QChar nrc_dutch_char_set[] =
87 | {
88 | /*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
89 | /*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
90 | /*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
91 | /*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
92 | /*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
93 | /*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
94 | /*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
95 | /*0x38*/ 0x0000,0x0000,0x00be,0x0000,0x0000,0x0000,0x0000,0x0000,
96 | /*0x40*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
97 | /*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
98 | /*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
99 | /*0x58*/ 0x0000,0x0000,0x0000,0x0133,0x00bd,0x007c,0x0000,0x0000,
100 | /*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
101 | /*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
102 | /*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
103 | /*0x78*/ 0x0000,0x0000,0x0000,0x00a8,0x0066,0x00bc,0x00b4,0x0000,
104 | };
105 |
106 | static const QChar nrc_finnish_char_set[] =
107 | {
108 | /*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
109 | /*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
110 | /*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
111 | /*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
112 | /*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
113 | /*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
114 | /*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
115 | /*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
116 | /*0x40*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
117 | /*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
118 | /*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
119 | /*0x58*/ 0x0000,0x0000,0x0000,0x00c4,0x00d6,0x00c5,0x00dc,0x0000,
120 | /*0x60*/ 0x00e9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
121 | /*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
122 | /*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
123 | /*0x78*/ 0x0000,0x0000,0x0000,0x00e4,0x00f6,0x00e5,0x00fc,0x0000,
124 | };
125 |
126 | static const QChar nrc_french_char_set[] =
127 | {
128 | /*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
129 | /*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
130 | /*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
131 | /*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
132 | /*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
133 | /*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
134 | /*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
135 | /*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
136 | /*0x40*/ 0x00e0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
137 | /*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
138 | /*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
139 | /*0x58*/ 0x0000,0x0000,0x0000,0x00b0,0x00e7,0x00a7,0x0000,0x0000,
140 | /*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
141 | /*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
142 | /*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
143 | /*0x78*/ 0x0000,0x0000,0x0000,0x00e9,0x00f9,0x00e8,0x00a8,0x0000,
144 | };
145 |
146 | static const QChar nrc_french_canadian_char_set[] =
147 | {
148 | /*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
149 | /*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
150 | /*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
151 | /*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
152 | /*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
153 | /*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
154 | /*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
155 | /*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
156 | /*0x40*/ 0x00e0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
157 | /*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
158 | /*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
159 | /*0x58*/ 0x0000,0x0000,0x0000,0x00e2,0x00e7,0x00ea,0x00ee,0x0000,
160 | /*0x60*/ 0x00f4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
161 | /*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
162 | /*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
163 | /*0x78*/ 0x0000,0x0000,0x0000,0x00e9,0x00f9,0x00e8,0x00fb,0x0000,
164 | };
165 |
166 | static const QChar nrc_german_char_set[] =
167 | {
168 | /*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
169 | /*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
170 | /*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
171 | /*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
172 | /*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
173 | /*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
174 | /*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
175 | /*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
176 | /*0x40*/ 0x00a7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
177 | /*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
178 | /*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
179 | /*0x58*/ 0x0000,0x0000,0x0000,0x00c4,0x00d6,0x00dc,0x0000,0x0000,
180 | /*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
181 | /*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
182 | /*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
183 | /*0x78*/ 0x0000,0x0000,0x0000,0x00e4,0x00f6,0x00fc,0x00df,0x0000,
184 | };
185 |
186 | static const QChar nrc_italian_char_set[] =
187 | {
188 | /*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
189 | /*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
190 | /*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
191 | /*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
192 | /*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
193 | /*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
194 | /*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
195 | /*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
196 | /*0x40*/ 0x00a7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
197 | /*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
198 | /*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
199 | /*0x58*/ 0x0000,0x0000,0x0000,0x00b0,0x00e7,0x00e9,0x0000,0x0000,
200 | /*0x60*/ 0x00f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
201 | /*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
202 | /*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
203 | /*0x78*/ 0x0000,0x0000,0x0000,0x00e0,0x00f2,0x00e8,0x00ec,0x0000,
204 | };
205 |
206 | static const QChar nrc_spanish_char_set[] =
207 | {
208 | /*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
209 | /*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
210 | /*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
211 | /*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
212 | /*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
213 | /*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
214 | /*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
215 | /*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
216 | /*0x40*/ 0x00a7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
217 | /*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
218 | /*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
219 | /*0x58*/ 0x0000,0x0000,0x0000,0x00a1,0x00d1,0x00bf,0x0000,0x0000,
220 | /*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
221 | /*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
222 | /*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
223 | /*0x78*/ 0x0000,0x0000,0x0000,0x00b0,0x00f1,0x00e7,0x0000,0x0000,
224 | };
225 |
226 | static const QChar nrc_swedish_char_set[] =
227 | {
228 | /*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
229 | /*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
230 | /*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
231 | /*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
232 | /*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
233 | /*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
234 | /*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
235 | /*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
236 | /*0x40*/ 0x00c9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
237 | /*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
238 | /*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
239 | /*0x58*/ 0x0000,0x0000,0x0000,0x00c4,0x00d6,0x00c5,0x00dc,0x0000,
240 | /*0x60*/ 0x00e9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
241 | /*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
242 | /*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
243 | /*0x78*/ 0x0000,0x0000,0x0000,0x00e4,0x00f6,0x00e5,0x00fc,0x0000,
244 | };
245 |
246 | static const QChar nrc_swiss_char_set[] =
247 | {
248 | /*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
249 | /*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
250 | /*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
251 | /*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
252 | /*0x20*/ 0x0000,0x0000,0x0000,0x00f9,0x0000,0x0000,0x0000,0x0000,
253 | /*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
254 | /*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
255 | /*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
256 | /*0x40*/ 0x00e0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
257 | /*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
258 | /*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
259 | /*0x58*/ 0x0000,0x0000,0x0000,0x00e9,0x00e7,0x00ea,0x00ee,0x00e8,
260 | /*0x60*/ 0x00f4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
261 | /*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
262 | /*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
263 | /*0x78*/ 0x0000,0x0000,0x0000,0x00e4,0x00f6,0x00fc,0x00fb,0x0000,
264 | };
265 |
266 |
--------------------------------------------------------------------------------
/backend/screen_data.cpp:
--------------------------------------------------------------------------------
1 | /*******************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | *******************************************************************************/
23 |
24 | #include "screen_data.h"
25 |
26 | #include "block.h"
27 | #include "screen.h"
28 | #include "scrollback.h"
29 | #include "cursor.h"
30 |
31 | #include
32 |
33 | #include
34 | #include
35 |
36 | ScreenData::ScreenData(size_t max_scrollback, Screen *screen)
37 | : QObject(screen)
38 | , m_screen(screen)
39 | , m_scrollback(new Scrollback(max_scrollback, this))
40 | , m_screen_height(0)
41 | , m_height(0)
42 | , m_width(0)
43 | , m_block_count(0)
44 | , m_old_total_lines(0)
45 | {
46 | }
47 |
48 | ScreenData::~ScreenData()
49 | {
50 | for (auto it = m_screen_blocks.begin(); it != m_screen_blocks.end(); ++it) {
51 | delete *it;
52 | }
53 | delete m_scrollback;
54 | }
55 |
56 |
57 | int ScreenData::contentHeight() const
58 | {
59 | return m_height + m_scrollback->height();
60 | }
61 |
62 | void ScreenData::setHeight(int height, int currentCursorLine)
63 | {
64 | if (m_screen_height == height)
65 | return;
66 |
67 | m_screen_height = height;
68 |
69 | int removed_beginning = 0;
70 | int removed_end = 0;
71 | int reclaimed = 0;
72 |
73 | if (m_height > height) {
74 | const int to_remove = m_height - height;
75 | const int remove_from_end = std::min(m_height - (currentCursorLine + 1), to_remove);
76 | const int remove_from_start = to_remove - remove_from_end;
77 |
78 | if (remove_from_end) {
79 | removed_end = remove_lines_from_end(remove_from_end);
80 | }
81 | if (remove_from_start) {
82 | removed_beginning = push_at_most_to_scrollback(remove_from_start);
83 | }
84 | } else {
85 | reclaimed = ensure_at_least_height(height);
86 | }
87 |
88 | emit dataHeightChanged(m_screen_height, removed_beginning, reclaimed);
89 | }
90 |
91 | void ScreenData::setWidth(int width)
92 | {
93 | m_width = width;
94 |
95 | for (Block *block : m_screen_blocks) {
96 | int before_count = block->lineCount();
97 | block->setWidth(width);
98 | m_height += block->lineCount() - before_count;
99 | }
100 |
101 | int removed = 0;
102 | int reclaimed = 0;
103 | if (m_height > m_screen_height) {
104 | removed = push_at_most_to_scrollback(m_height - m_screen_height);
105 | } else {
106 | reclaimed = ensure_at_least_height(m_screen_height);
107 | }
108 |
109 | m_scrollback->setWidth(width);
110 |
111 | emit dataWidthChanged(m_width, removed, reclaimed);
112 | }
113 |
114 |
115 | void ScreenData::clearToEndOfLine(const QPoint &point)
116 | {
117 | auto it = it_for_row_ensure_single_line_block(point.y());
118 | (*it)->clearToEnd(point.x());
119 | }
120 |
121 | void ScreenData::clearToEndOfScreen(int y)
122 | {
123 | auto it = it_for_row_ensure_single_line_block(y);
124 | while(it != m_screen_blocks.end()) {
125 | clearBlock(it);
126 | ++it;
127 | }
128 | }
129 |
130 | void ScreenData::clearToBeginningOfLine(const QPoint &point)
131 | {
132 | auto it = it_for_row_ensure_single_line_block(point.y());
133 | (*it)->clearCharacters(0,point.x());
134 | }
135 |
136 | void ScreenData::clearToBeginningOfScreen(int y)
137 | {
138 | auto it = it_for_row_ensure_single_line_block(y);
139 | if (it != m_screen_blocks.end())
140 | (*it)->clear();
141 | while(it != m_screen_blocks.begin()) {
142 | --it;
143 | clearBlock(it);
144 | }
145 | }
146 |
147 | void ScreenData::clearLine(const QPoint &point)
148 | {
149 | (*it_for_row_ensure_single_line_block(point.y()))->clear();
150 | }
151 |
152 | void ScreenData::clear()
153 | {
154 | for (auto it = m_screen_blocks.begin(); it != m_screen_blocks.end(); ++it) {
155 | clearBlock(it);
156 | }
157 | }
158 |
159 | void ScreenData::releaseTextObjects()
160 | {
161 | for (auto it = m_screen_blocks.begin(); it != m_screen_blocks.end(); ++it) {
162 | (*it)->releaseTextObjects();
163 | }
164 | }
165 |
166 | void ScreenData::clearCharacters(const QPoint &point, int to)
167 | {
168 | auto it = it_for_row_ensure_single_line_block(point.y());
169 | (*it)->clearCharacters(point.x(),to);
170 | }
171 |
172 | void ScreenData::deleteCharacters(const QPoint &point, int to)
173 | {
174 | auto it = it_for_row(point.y());
175 | if (it == m_screen_blocks.end())
176 | return;
177 |
178 | int line_in_block = point.y() - (*it)->screenIndex();
179 | int chars_to_line = line_in_block * m_width;
180 |
181 | (*it)->deleteCharacters(chars_to_line + point.x(), chars_to_line + to);
182 | }
183 |
184 | const CursorDiff ScreenData::replace(const QPoint &point, const QString &text, const TextStyle &style, bool only_latin)
185 | {
186 | return modify(point,text,style,true, only_latin);
187 | }
188 |
189 | const CursorDiff ScreenData::insert(const QPoint &point, const QString &text, const TextStyle &style, bool only_latin)
190 | {
191 | return modify(point,text,style,false, only_latin);
192 | }
193 |
194 |
195 | void ScreenData::moveLine(int from, int to)
196 | {
197 | if (from == to)
198 | return;
199 |
200 | const size_t old_content_height = contentHeight();
201 | if (to > from)
202 | to++;
203 | auto from_it = it_for_row_ensure_single_line_block(from);
204 | auto to_it = it_for_row_ensure_single_line_block(to);
205 |
206 | (*from_it)->clear();
207 | m_screen_blocks.splice(to_it, m_screen_blocks, from_it);
208 | emit contentModified(m_scrollback->height() + to, 1, content_height_diff(old_content_height));
209 | }
210 |
211 | void ScreenData::insertLine(int row, int topMargin)
212 | {
213 | auto row_it = it_for_row(row + 1);
214 |
215 | const size_t old_content_height = contentHeight();
216 |
217 | if (!topMargin && m_height >= m_screen_height) {
218 | push_at_most_to_scrollback(1);
219 | } else {
220 | auto row_top_margin = it_for_row_ensure_single_line_block(topMargin);
221 | if (row == topMargin) {
222 | (*row_top_margin)->clear();
223 | return;
224 | }
225 | delete (*row_top_margin);
226 | m_screen_blocks.erase(row_top_margin);
227 | m_height--;
228 | m_block_count--;
229 | }
230 |
231 | Block *block_to_insert = new Block(m_screen);
232 | m_screen_blocks.insert(row_it,block_to_insert);
233 | m_height++;
234 | m_block_count++;
235 |
236 | emit contentModified(m_scrollback->height() + row + 1, 1, content_height_diff(old_content_height));
237 | }
238 |
239 |
240 | void ScreenData::fill(const QChar &character)
241 | {
242 | clear();
243 | auto it = --m_screen_blocks.end();
244 | for (int i = 0; i < m_block_count; --it, i++) {
245 | QString fill_str(m_screen->width(), character);
246 | (*it)->replaceAtPos(0, fill_str, m_screen->defaultTextStyle());
247 | }
248 | }
249 |
250 | void ScreenData::dispatchLineEvents()
251 | {
252 | if (!m_block_count)
253 | return;
254 | const int scrollback_height = m_scrollback->height();
255 | int i = 0;
256 | for (auto it = m_screen_blocks.begin(); it != m_screen_blocks.end(); ++it) {
257 | int line = scrollback_height + i;
258 | (*it)->setLine(line);
259 | //(*it)->setScreenIndex(i);
260 | (*it)->dispatchEvents();
261 | i+= (*it)->lineCount();
262 | }
263 |
264 | if (contentHeight() != m_old_total_lines) {
265 | m_old_total_lines = contentHeight();
266 | emit contentHeightChanged();
267 | }
268 | }
269 |
270 | void ScreenData::printRuler(QDebug &debug) const
271 | {
272 | QString ruler = QString("|----i----").repeated((m_width/10)+1).append("|");
273 | debug << " " << (void *) this << ruler;
274 | }
275 |
276 | void ScreenData::printStyleInformation() const
277 | {
278 | auto it = m_screen_blocks.end();
279 | std::advance(it, -m_block_count);
280 | for (int i = 0; it != m_screen_blocks.end(); ++it, i++) {
281 | if (i % 5 == 0) {
282 | QDebug debug = qDebug();
283 | debug << "Ruler:";
284 | printRuler(debug);
285 | }
286 | QDebug debug = qDebug();
287 | (*it)->printStyleList(debug);
288 | }
289 | qDebug() << "On screen height" << m_height;
290 | }
291 |
292 | Screen *ScreenData::screen() const
293 | {
294 | return m_screen;
295 | }
296 |
297 | void ScreenData::ensureVisiblePages(int top_line)
298 | {
299 | m_scrollback->ensureVisiblePages(top_line);
300 | }
301 |
302 | Scrollback *ScreenData::scrollback() const
303 | {
304 | return m_scrollback;
305 | }
306 |
307 | void ScreenData::sendSelectionToClipboard(const QPoint &start, const QPoint &end, QClipboard::Mode mode)
308 | {
309 | if (start.y() < 0)
310 | return;
311 | if (end.y() >= contentHeight())
312 | return;
313 |
314 | QString to_clip_board_buffer;
315 |
316 | bool started_in_scrollback = false;
317 | if (size_t(start.y()) < m_scrollback->height()) {
318 | started_in_scrollback = true;
319 | QPoint end_scrollback = end;
320 | if (size_t(end.y()) >= m_scrollback->height()) {
321 | end_scrollback = QPoint(m_width, m_scrollback->height() - 1);
322 | }
323 | to_clip_board_buffer = m_scrollback->selection(start, end_scrollback);
324 | }
325 |
326 | if (size_t(end.y()) >= m_scrollback->height()) {
327 | QPoint start_in_screen;
328 | if (started_in_scrollback) {
329 | start_in_screen = QPoint(0,0);
330 | } else {
331 | start_in_screen = start;
332 | start_in_screen.ry() -= m_scrollback->height();
333 | }
334 | QPoint end_in_screen = end;
335 | end_in_screen.ry() -= m_scrollback->height();
336 |
337 | auto it = it_for_row(start_in_screen.y());
338 | size_t screen_index = (*it)->screenIndex();
339 | int start_pos = (start_in_screen.y() - (*it)->screenIndex()) * m_width + start_in_screen.x();
340 | for (; it != m_screen_blocks.end(); ++it, start_pos = 0) {
341 | int end_pos = (*it)->textSize();
342 | bool should_break = false;
343 | if (size_t(screen_index + (*it)->lineCount()) > size_t(end_in_screen.y())) {
344 | end_pos = (end_in_screen.y() - screen_index) * m_width + end_in_screen.x();
345 | should_break = true;
346 | }
347 | if (to_clip_board_buffer.size())
348 | to_clip_board_buffer += '\n';
349 | to_clip_board_buffer += (*it)->textLine().mid(start_pos, end_pos - start_pos);
350 | if (should_break)
351 | break;
352 | screen_index += (*it)->lineCount();
353 | }
354 | }
355 | QGuiApplication::clipboard()->setText(to_clip_board_buffer, mode);
356 | }
357 |
358 | const SelectionRange ScreenData::getDoubleClickSelectionRange(size_t character, size_t line)
359 | {
360 | if (line < m_scrollback->height())
361 | return m_scrollback->getDoubleClickSelectionRange(character, line);
362 | size_t screen_line = line - m_scrollback->height();
363 | auto it = it_for_row(screen_line);
364 | if (it != m_screen_blocks.end())
365 | return Selection::getDoubleClickRange(it, character, line, m_width);
366 | return { QPoint(), QPoint() };
367 | }
368 |
369 | const CursorDiff ScreenData::modify(const QPoint &point, const QString &text, const TextStyle &style, bool replace, bool only_latin)
370 | {
371 | auto it = it_for_row(point.y());
372 | if (it == m_screen_blocks.end())
373 | return { 0, 0 };
374 | Block *block = *it;
375 | const int start_char = (point.y() - block->screenIndex()) * m_width + point.x();
376 | const size_t lines_before = block->lineCount();
377 | const int lines_changed =
378 | block->lineCountAfterModified(start_char, text.size(), replace) - lines_before;
379 | const size_t old_content_height = contentHeight();
380 | m_height += lines_changed;
381 | if (lines_changed > 0) {
382 | int removed = 0;
383 | auto to_merge_inn = it;
384 | ++to_merge_inn;
385 | while(removed < lines_changed && to_merge_inn != m_screen_blocks.end()) {
386 | Block *to_be_reduced = *to_merge_inn;
387 | bool remove_block = removed + to_be_reduced->lineCount() <= lines_changed;
388 | int lines_to_remove = remove_block ? to_be_reduced->lineCount() : to_be_reduced->lineCount() - (lines_changed - removed);
389 | block->moveLinesFromBlock(to_be_reduced, 0, lines_to_remove);
390 | removed += lines_to_remove;
391 | if (remove_block) {
392 | delete to_be_reduced;
393 | to_merge_inn = m_screen_blocks.erase(to_merge_inn);
394 | m_block_count--;
395 | } else {
396 | ++to_merge_inn;
397 | }
398 | }
399 |
400 | m_height -= removed;
401 | }
402 |
403 | if (m_height > m_screen_height)
404 | push_at_most_to_scrollback(m_height - m_screen_height);
405 |
406 | if (replace) {
407 | block->replaceAtPos(start_char, text, style, only_latin);
408 | } else {
409 | block->insertAtPos(start_char, text, style, only_latin);
410 | }
411 | int end_char = (start_char + text.size()) % m_width;
412 | if (end_char == 0)
413 | end_char = m_width -1;
414 |
415 | int end_line = (start_char + text.size()) / m_width;
416 | int line_diff = end_line - (start_char / m_width);
417 | emit contentModified(m_scrollback->height() + point.y(), lines_changed, content_height_diff(old_content_height));
418 | return { line_diff, end_char - point.x()};
419 | }
420 |
421 | void ScreenData::clearBlock(std::list::iterator line)
422 | {
423 | int before_count = (*line)->lineCount();
424 | (*line)->clear();
425 | int diff_line = before_count - (*line)->lineCount();
426 | if (diff_line > 0) {
427 | ++line;
428 | for (int i = 0; i < diff_line; i++) {
429 | m_screen_blocks.insert(line, new Block(m_screen));
430 | }
431 | m_block_count+=diff_line;
432 | }
433 | }
434 |
435 | std::list::iterator ScreenData::it_for_row_ensure_single_line_block(int row)
436 | {
437 | auto it = it_for_row(row);
438 | const int index = (*it)->screenIndex();
439 | const int lines = (*it)->lineCount();
440 |
441 | if (index == row && lines == 1) {
442 | return it;
443 | }
444 |
445 | int line_diff = row - index;
446 | return split_out_row_from_block(it, line_diff);
447 | }
448 |
449 | std::list::iterator ScreenData::split_out_row_from_block(std::list::iterator it, int row_in_block)
450 | {
451 | int lines = (*it)->lineCount();
452 |
453 | if (row_in_block == 0 && lines == 1)
454 | return it;
455 |
456 | if (row_in_block == 0) {
457 | auto insert_before = (*it)->takeLine(0);
458 | insert_before->setScreenIndex(row_in_block);
459 | m_block_count++;
460 | return m_screen_blocks.insert(it,insert_before);
461 | } else if (row_in_block == lines -1) {
462 | auto insert_after = (*it)->takeLine(lines -1);
463 | insert_after->setScreenIndex(row_in_block);
464 | ++it;
465 | m_block_count++;
466 | return m_screen_blocks.insert(it, insert_after);
467 | }
468 |
469 | auto half = (*it)->split(row_in_block);
470 | ++it;
471 | auto it_width_first = m_screen_blocks.insert(it, half);
472 | auto the_one = half->takeLine(0);
473 | m_block_count+=2;
474 | return m_screen_blocks.insert(it_width_first,the_one);
475 | }
476 |
477 | int ScreenData::push_at_most_to_scrollback(int lines)
478 | {
479 | if (lines >= m_height)
480 | lines = m_height - 1;
481 | int pushed = 0;
482 | auto it = m_screen_blocks.begin();
483 | while (it != m_screen_blocks.end() && pushed + (*it)->lineCount() <= lines) {
484 | m_block_count--;
485 | const int block_height = (*it)->lineCount();
486 | m_height -= block_height;
487 | pushed += block_height;
488 | m_scrollback->addBlock(*it);
489 | it = m_screen_blocks.erase(it);
490 | }
491 | return pushed;
492 | }
493 |
494 | int ScreenData::reclaim_at_least(int lines)
495 | {
496 | int lines_reclaimed = 0;
497 | while (m_scrollback->blockCount() && lines_reclaimed < lines) {
498 | Block *block = m_scrollback->reclaimBlock();
499 | m_height += block->lineCount();
500 | lines_reclaimed += block->lineCount();
501 | m_block_count++;
502 | m_screen_blocks.push_front(block);
503 | }
504 | return lines_reclaimed;
505 | }
506 |
507 | int ScreenData::remove_lines_from_end(int lines)
508 | {
509 | int removed = 0;
510 | auto it = m_screen_blocks.end();
511 | while (it != m_screen_blocks.begin() && removed < lines) {
512 | --it;
513 | const int block_height = (*it)->lineCount();
514 | if (removed + block_height <= lines) {
515 | removed += block_height;
516 | m_height -= block_height;
517 | m_block_count--;
518 | delete (*it);
519 | it = m_screen_blocks.erase(it);
520 | } else {
521 | const int to_remove = lines - removed;
522 | removed += to_remove;
523 | m_height -= to_remove;
524 | Block *block = *it;
525 | for (int i = 0; i < to_remove; i++) {
526 | block->removeLine(block->lineCount()-1);
527 | }
528 | }
529 | }
530 | return removed;
531 | }
532 |
533 | int ScreenData::ensure_at_least_height(int height)
534 | {
535 | if (m_height > height)
536 | return 0;
537 |
538 | int to_grow = height - m_height;
539 | int reclaimed = reclaim_at_least(to_grow);
540 |
541 | if (height > m_height) {
542 | int to_insert = height - m_height;
543 | for (int i = 0; i < to_insert; i++) {
544 | m_screen_blocks.push_back(new Block(m_screen));
545 | }
546 | m_height += to_insert;
547 | m_block_count += to_insert;
548 | }
549 | return reclaimed;
550 | }
551 |
552 | int ScreenData::content_height_diff(size_t old_content_height)
553 | {
554 | const size_t content_height = contentHeight();
555 | return old_content_height < content_height ? content_height - old_content_height :
556 | - int(old_content_height - content_height);
557 | }
558 |
--------------------------------------------------------------------------------
/backend/screen.cpp:
--------------------------------------------------------------------------------
1 | /******************************************************************************
2 | * Copyright (c) 2012 Jørgen Lind
3 | *
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy
5 | * of this software and associated documentation files (the "Software"), to deal
6 | * in the Software without restriction, including without limitation the rights
7 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | * copies of the Software, and to permit persons to whom the Software is
9 | * furnished to do so, subject to the following conditions:
10 | *
11 | * The above copyright notice and this permission notice shall be included in
12 | * all copies or substantial portions of the Software.
13 | *
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20 | * SOFTWARE.
21 | *
22 | ******************************************************************************/
23 |
24 | #include "screen.h"
25 |
26 | #include "screen_data.h"
27 | #include "block.h"
28 | #include "cursor.h"
29 | #include "text.h"
30 | #include "scrollback.h"
31 | #include "selection.h"
32 |
33 | #include "controll_chars.h"
34 | #include "character_sets.h"
35 |
36 | #include
37 | #include
38 | #include
39 |
40 | #include
41 |
42 | #include
43 | #include
44 |
45 | Screen::Screen(QObject *parent)
46 | : QObject(parent)
47 | , m_palette(new ColorPalette(this))
48 | , m_parser(this)
49 | , m_timer_event_id(0)
50 | , m_width(1)
51 | , m_height(0)
52 | , m_primary_data(new ScreenData(500, this))
53 | , m_alternate_data(new ScreenData(0, this))
54 | , m_current_data(m_primary_data)
55 | , m_old_current_data(m_primary_data)
56 | , m_selection(new Selection(this))
57 | , m_flash(false)
58 | , m_cursor_changed(false)
59 | , m_application_cursor_key_mode(false)
60 | , m_fast_scroll(true)
61 | , m_default_background(m_palette->normalColor(ColorPalette::DefaultBackground))
62 | {
63 | Cursor *cursor = new Cursor(this);
64 | m_cursor_stack << cursor;
65 | m_new_cursors << cursor;
66 |
67 | connect(m_primary_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
68 | connect(m_primary_data, &ScreenData::contentModified, this, &Screen::contentModified);
69 | connect(m_primary_data, &ScreenData::dataHeightChanged, this, &Screen::dataHeightChanged);
70 | connect(m_primary_data, &ScreenData::dataWidthChanged, this, &Screen::dataWidthChanged);
71 | connect(m_palette, SIGNAL(changed()), this, SLOT(paletteChanged()));
72 |
73 | setHeight(25);
74 | setWidth(80);
75 |
76 | connect(&m_pty, &YatPty::readyRead, this, &Screen::readData);
77 | connect(&m_pty, &YatPty::hangupReceived,this, &Screen::hangup);
78 |
79 | }
80 |
81 | Screen::~Screen()
82 | {
83 |
84 | for(int i = 0; i < m_to_delete.size(); i++) {
85 | delete m_to_delete.at(i);
86 | }
87 | //m_to_delete.clear();
88 |
89 | delete m_primary_data;
90 | delete m_alternate_data;
91 | }
92 |
93 |
94 | QColor Screen::defaultForegroundColor() const
95 | {
96 | return m_palette->normalColor(ColorPalette::DefaultForeground);
97 | }
98 |
99 | QColor Screen::defaultBackgroundColor() const
100 | {
101 | return m_palette->normalColor(ColorPalette::DefaultBackground);
102 | }
103 |
104 | void Screen::emitRequestHeight(int newHeight)
105 | {
106 | emit requestHeightChange(newHeight);
107 | }
108 |
109 | void Screen::setHeight(int height)
110 | {
111 | height = std::max(1, height);
112 | if (height == m_height)
113 | return;
114 |
115 | m_height = height;
116 |
117 | m_primary_data->setHeight(height, currentCursor()->new_y());
118 | m_alternate_data->setHeight(height, currentCursor()->new_y());
119 |
120 | m_pty.setHeight(height, height * 10);
121 |
122 | emit heightChanged();
123 | scheduleEventDispatch();
124 | }
125 |
126 | int Screen::height() const
127 | {
128 | return m_height;
129 | }
130 |
131 | int Screen::contentHeight() const
132 | {
133 | return currentScreenData()->contentHeight();
134 | }
135 |
136 | void Screen::emitRequestWidth(int newWidth)
137 | {
138 | emit requestWidthChange(newWidth);
139 | }
140 |
141 | void Screen::setWidth(int width)
142 | {
143 | width = std::max(1,width);
144 | if (width == m_width)
145 | return;
146 |
147 | emit widthAboutToChange(width);
148 |
149 | m_width = width;
150 |
151 | m_primary_data->setWidth(width);
152 | m_alternate_data->setWidth(width);
153 |
154 | m_pty.setWidth(width, width * 10);
155 |
156 | emit widthChanged();
157 | scheduleEventDispatch();
158 | }
159 |
160 | int Screen::width() const
161 | {
162 | return m_width;
163 | }
164 |
165 | void Screen::useAlternateScreenBuffer()
166 | {
167 | if (m_current_data == m_primary_data) {
168 | disconnect(m_primary_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
169 | disconnect(m_primary_data, &ScreenData::contentModified, this, &Screen::contentModified);
170 | disconnect(m_primary_data, &ScreenData::dataHeightChanged, this, &Screen::dataHeightChanged);
171 | disconnect(m_primary_data, &ScreenData::dataWidthChanged, this, &Screen::dataWidthChanged);
172 | m_current_data = m_alternate_data;
173 | m_current_data->clear();
174 | connect(m_alternate_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
175 | connect(m_alternate_data, &ScreenData::contentModified, this, &Screen::contentModified);
176 | connect(m_alternate_data, &ScreenData::dataHeightChanged, this, &Screen::dataHeightChanged);
177 | connect(m_alternate_data, &ScreenData::dataWidthChanged, this, &Screen::dataWidthChanged);
178 | emit contentHeightChanged();
179 | }
180 | }
181 |
182 | void Screen::useNormalScreenBuffer()
183 | {
184 | if (m_current_data == m_alternate_data) {
185 | disconnect(m_alternate_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
186 | disconnect(m_alternate_data, &ScreenData::contentModified, this, &Screen::contentModified);
187 | disconnect(m_alternate_data, &ScreenData::dataHeightChanged, this, &Screen::dataHeightChanged);
188 | disconnect(m_alternate_data, &ScreenData::dataWidthChanged, this, &Screen::dataWidthChanged);
189 | m_current_data = m_primary_data;
190 | connect(m_primary_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
191 | connect(m_primary_data, &ScreenData::contentModified, this, &Screen::contentModified);
192 | connect(m_primary_data, &ScreenData::dataHeightChanged, this, &Screen::dataHeightChanged);
193 | connect(m_primary_data, &ScreenData::dataWidthChanged, this, &Screen::dataWidthChanged);
194 | emit contentHeightChanged();
195 | }
196 | }
197 |
198 | TextStyle Screen::defaultTextStyle() const
199 | {
200 | TextStyle style;
201 | style.style = TextStyle::Normal;
202 | style.foreground = colorPalette()->defaultForeground().rgb();
203 | style.background = colorPalette()->defaultBackground().rgb();
204 | return style;
205 | }
206 |
207 | void Screen::saveCursor()
208 | {
209 | Cursor *new_cursor = new Cursor(this);
210 | if (m_cursor_stack.size())
211 | m_cursor_stack.last()->setVisible(false);
212 | m_cursor_stack << new_cursor;
213 | m_new_cursors << new_cursor;
214 | }
215 |
216 | void Screen::restoreCursor()
217 | {
218 | if (m_cursor_stack.size() <= 1)
219 | return;
220 |
221 | m_delete_cursors.append(m_cursor_stack.takeLast());
222 | m_cursor_stack.last()->setVisible(true);
223 | }
224 |
225 | void Screen::clearScreen()
226 | {
227 | currentScreenData()->clear();
228 | }
229 |
230 |
231 | ColorPalette *Screen::colorPalette() const
232 | {
233 | return m_palette;
234 | }
235 |
236 | void Screen::fill(const QChar character)
237 | {
238 | currentScreenData()->fill(character);
239 | }
240 |
241 | void Screen::clear()
242 | {
243 | fill(QChar(' '));
244 | }
245 |
246 | void Screen::setFastScroll(bool fast)
247 | {
248 | m_fast_scroll = fast;
249 | }
250 |
251 | bool Screen::fastScroll() const
252 | {
253 | return m_fast_scroll;
254 | }
255 |
256 | Selection *Screen::selection() const
257 | {
258 | return m_selection;
259 | }
260 |
261 | void Screen::doubleClicked(double character, double line)
262 | {
263 | QPoint start, end;
264 | int64_t charInt = std::llround(character);
265 | int64_t lineInt = std::llround(line);
266 | Q_ASSERT(charInt >= 0);
267 | //Q_ASSERT(charInt < std::numeric_limits::max());
268 | Q_ASSERT(lineInt >= 0);
269 | //Q_ASSERT(lineInt < std::numeric_limits::max());
270 | auto selectionRange = currentScreenData()->getDoubleClickSelectionRange(charInt, lineInt);
271 | m_selection->setStartX(selectionRange.start.x());
272 | m_selection->setStartY(selectionRange.start.y());
273 | m_selection->setEndX(selectionRange.end.x());
274 | m_selection->setEndY(selectionRange.end.y());
275 | }
276 |
277 | void Screen::setTitle(const QString &title)
278 | {
279 | m_title = title;
280 | emit screenTitleChanged();
281 | }
282 |
283 | QString Screen::title() const
284 | {
285 | return m_title;
286 | }
287 |
288 | QString Screen::platformName() const
289 | {
290 | return qGuiApp->platformName();
291 | }
292 |
293 | void Screen::scheduleFlash()
294 | {
295 | m_flash = true;
296 | }
297 |
298 | void Screen::printScreen() const
299 | {
300 | currentScreenData()->printStyleInformation();
301 | qDebug() << "Total height: " << currentScreenData()->contentHeight();
302 | }
303 |
304 | void Screen::scheduleEventDispatch()
305 | {
306 | if (!m_timer_event_id) {
307 | m_timer_event_id = startTimer(1);
308 | m_time_since_initiated.restart();
309 | }
310 |
311 | m_time_since_parsed.restart();
312 | }
313 |
314 | void Screen::dispatchChanges()
315 | {
316 | if (m_old_current_data != m_current_data) {
317 | m_old_current_data->releaseTextObjects();
318 | m_old_current_data = m_current_data;
319 | }
320 |
321 | currentScreenData()->dispatchLineEvents();
322 | emit dispatchTextSegmentChanges();
323 |
324 | //be smarter than this
325 | static int max_to_delete_size = 0;
326 | if (max_to_delete_size < m_to_delete.size()) {
327 | max_to_delete_size = m_to_delete.size();
328 | }
329 |
330 | if (m_flash) {
331 | m_flash = false;
332 | emit flash();
333 | }
334 |
335 | for (int i = 0; i < m_delete_cursors.size(); i++) {
336 | int new_index = m_new_cursors.indexOf(m_delete_cursors.at(i));
337 | if (new_index >= 0)
338 | m_new_cursors.remove(new_index);
339 | delete m_delete_cursors.at(i);
340 | }
341 | m_delete_cursors.clear();
342 |
343 | for (int i = 0; i < m_new_cursors.size(); i++) {
344 | emit cursorCreated(m_new_cursors.at(i));
345 | }
346 | m_new_cursors.clear();
347 |
348 | for (int i = 0; i < m_cursor_stack.size(); i++) {
349 | m_cursor_stack[i]->dispatchEvents();
350 | }
351 |
352 | m_selection->dispatchChanges();
353 | }
354 |
355 | void Screen::sendPrimaryDA()
356 | {
357 | m_pty.write(QByteArrayLiteral("\033[?6c"));
358 |
359 | }
360 |
361 | void Screen::sendSecondaryDA()
362 | {
363 | m_pty.write(QByteArrayLiteral("\033[>1;95;0c"));
364 | }
365 |
366 | void Screen::setApplicationCursorKeysMode(bool enable)
367 | {
368 | m_application_cursor_key_mode = enable;
369 | }
370 |
371 | bool Screen::applicationCursorKeyMode() const
372 | {
373 | return m_application_cursor_key_mode;
374 | }
375 |
376 | void Screen::ensureVisiblePages(int top_line)
377 | {
378 | currentScreenData()->ensureVisiblePages(top_line);
379 | }
380 |
381 | static bool hasControll(Qt::KeyboardModifiers modifiers)
382 | {
383 | #ifdef Q_OS_MAC
384 | return modifiers & Qt::MetaModifier;
385 | #else
386 | return modifiers & Qt::ControlModifier;
387 | #endif
388 | }
389 |
390 | static bool hasMeta(Qt::KeyboardModifiers modifiers)
391 | {
392 | #ifdef Q_OS_MAC
393 | return modifiers & Qt::ControlModifier;
394 | #else
395 | return modifiers & Qt::MetaModifier;
396 | #endif
397 | }
398 |
399 | void Screen::sendKey(const QString &text, Qt::Key key, Qt::KeyboardModifiers modifiers)
400 | {
401 |
402 | // if (key == Qt::Key_Control)
403 | // printScreen();
404 | /// UGH, this function should be re-written
405 | char escape = '\0';
406 | char control = '\0';
407 | char code = '\0';
408 | QVector parameters;
409 | bool found = true;
410 |
411 | switch(key) {
412 | case Qt::Key_Up:
413 | escape = C0::ESC;
414 | if (m_application_cursor_key_mode)
415 | control = C1_7bit::SS3;
416 | else
417 | control = C1_7bit::CSI;
418 |
419 | code = 'A';
420 | break;
421 | case Qt::Key_Right:
422 | escape = C0::ESC;
423 | if (m_application_cursor_key_mode)
424 | control = C1_7bit::SS3;
425 | else
426 | control = C1_7bit::CSI;
427 |
428 | code = 'C';
429 | break;
430 | case Qt::Key_Down:
431 | escape = C0::ESC;
432 | if (m_application_cursor_key_mode)
433 | control = C1_7bit::SS3;
434 | else
435 | control = C1_7bit::CSI;
436 |
437 | code = 'B';
438 | break;
439 | case Qt::Key_Left:
440 | escape = C0::ESC;
441 | if (m_application_cursor_key_mode)
442 | control = C1_7bit::SS3;
443 | else
444 | control = C1_7bit::CSI;
445 |
446 | code = 'D';
447 | break;
448 | case Qt::Key_Insert:
449 | escape = C0::ESC;
450 | control = C1_7bit::CSI;
451 | parameters.append(2);
452 | code = '~';
453 | break;
454 | case Qt::Key_Delete:
455 | escape = C0::ESC;
456 | control = C1_7bit::CSI;
457 | parameters.append(3);
458 | code = '~';
459 | break;
460 | case Qt::Key_Home:
461 | escape = C0::ESC;
462 | control = C1_7bit::CSI;
463 | parameters.append(1);
464 | code = '~';
465 | break;
466 | case Qt::Key_End:
467 | escape = C0::ESC;
468 | control = C1_7bit::CSI;
469 | parameters.append(4);
470 | code = '~';
471 | break;
472 | case Qt::Key_PageUp:
473 | escape = C0::ESC;
474 | control = C1_7bit::CSI;
475 | parameters.append(5);
476 | code = '~';
477 | break;
478 | case Qt::Key_PageDown:
479 | escape = C0::ESC;
480 | control = C1_7bit::CSI;
481 | parameters.append(6);
482 | code = '~';
483 | break;
484 | case Qt::Key_F1:
485 | case Qt::Key_F2:
486 | case Qt::Key_F3:
487 | case Qt::Key_F4:
488 | if (m_application_cursor_key_mode) {
489 | parameters.append((key & 0xff) - 37);
490 | escape = C0::ESC;
491 | control = C1_7bit::CSI;
492 | code = '~';
493 | }
494 | break;
495 | case Qt::Key_F5:
496 | case Qt::Key_F6:
497 | case Qt::Key_F7:
498 | case Qt::Key_F8:
499 | case Qt::Key_F9:
500 | case Qt::Key_F10:
501 | case Qt::Key_F11:
502 | case Qt::Key_F12:
503 | if (m_application_cursor_key_mode) {
504 | parameters.append((key & 0xff) - 36);
505 | escape = C0::ESC;
506 | control = C1_7bit::CSI;
507 | code = '~';
508 | }
509 | break;
510 | case Qt::Key_Control:
511 | case Qt::Key_Shift:
512 | case Qt::Key_Alt:
513 | case Qt::Key_AltGr:
514 | return;
515 | break;
516 | default:
517 | found = false;
518 | }
519 |
520 | if (found) {
521 | int term_mods = 0;
522 | if (modifiers & Qt::ShiftModifier)
523 | term_mods |= 1;
524 | if (modifiers & Qt::AltModifier)
525 | term_mods |= 2;
526 | if (modifiers & Qt::ControlModifier)
527 | term_mods |= 4;
528 |
529 | QByteArray toPty;
530 |
531 | if (term_mods) {
532 | term_mods++;
533 | parameters.append(term_mods);
534 | }
535 | if (escape)
536 | toPty.append(escape);
537 | if (control)
538 | toPty.append(control);
539 | if (parameters.size()) {
540 | for (int i = 0; i < parameters.size(); i++) {
541 | if (i)
542 | toPty.append(';');
543 | toPty.append(QByteArray::number(parameters.at(i)));
544 | }
545 | }
546 | if (code)
547 | toPty.append(code);
548 | m_pty.write(toPty);
549 |
550 | } else {
551 | QString verifiedText = text.simplified();
552 | if (verifiedText.isEmpty()) {
553 | switch (key) {
554 | case Qt::Key_Return:
555 | case Qt::Key_Enter:
556 | verifiedText = "\r";
557 | break;
558 | case Qt::Key_Backspace:
559 | verifiedText = "\010";
560 | break;
561 | case Qt::Key_Tab:
562 | verifiedText = "\t";
563 | break;
564 | case Qt::Key_Control:
565 | case Qt::Key_Meta:
566 | case Qt::Key_Alt:
567 | case Qt::Key_Shift:
568 | return;
569 | case Qt::Key_Space:
570 | verifiedText = " ";
571 | break;
572 | default:
573 | return;
574 | }
575 | }
576 | QByteArray to_pty;
577 | QByteArray key_text;
578 | if (hasControll(modifiers)) {
579 | char key_char = verifiedText.toLocal8Bit().at(0);
580 | key_text.append(key_char & 0x1F);
581 | } else {
582 | key_text = verifiedText.toUtf8();
583 | }
584 |
585 | if (modifiers & Qt::AltModifier) {
586 | to_pty.append(C0::ESC);
587 | }
588 |
589 | if (hasMeta(modifiers)) {
590 | to_pty.append(C0::ESC);
591 | to_pty.append('@');
592 | to_pty.append(FinalBytesNoIntermediate::Reserved3);
593 | }
594 |
595 | to_pty.append(key_text);
596 | m_pty.write(to_pty);
597 | }
598 | }
599 |
600 | YatPty *Screen::pty()
601 | {
602 | return &m_pty;
603 | }
604 |
605 | Text *Screen::createTextSegment(const TextStyleLine &style_line)
606 | {
607 | Q_UNUSED(style_line);
608 | Text *to_return;
609 | if (m_to_delete.size()) {
610 | to_return = m_to_delete.takeLast();
611 | to_return->setVisible(true);
612 | } else {
613 | to_return = new Text(this);
614 | emit textCreated(to_return);
615 | }
616 |
617 | return to_return;
618 | }
619 |
620 | void Screen::releaseTextSegment(Text *text)
621 | {
622 | m_to_delete.append(text);
623 | }
624 |
625 | void Screen::readData(const QByteArray &data)
626 | {
627 | m_parser.addData(data);
628 |
629 | scheduleEventDispatch();
630 | }
631 |
632 | void Screen::paletteChanged()
633 | {
634 | QColor new_default = m_palette->normalColor(ColorPalette::DefaultBackground);
635 | if (new_default != m_default_background) {
636 | m_default_background = new_default;
637 | emit defaultBackgroundColorChanged();
638 | }
639 | }
640 |
641 | void Screen::timerEvent(QTimerEvent *)
642 | {
643 | if (m_timer_event_id && (m_time_since_parsed.elapsed() > 3 || m_time_since_initiated.elapsed() > 25)) {
644 | killTimer(m_timer_event_id);
645 | m_timer_event_id = 0;
646 | dispatchChanges();
647 | }
648 | }
649 |
--------------------------------------------------------------------------------