Moved to new version of yat. Yat is no longer a submodule but is now integrated.

This commit is contained in:
Filippo Scognamiglio
2013-12-27 00:31:43 +01:00
parent bd39a63a64
commit 6b4b187df5
62 changed files with 14743 additions and 125 deletions

41
yat/backend/backend.pri Normal file
View File

@@ -0,0 +1,41 @@
DEPENDPATH += $$PWD
INCLUDEPATH += $$PWD
LIBS += -lutil
CONFIG += c++11
MOC_DIR = .moc
OBJECTS_DIR = .obj
HEADERS += \
$$PWD/yat_pty.h \
$$PWD/text.h \
$$PWD/controll_chars.h \
$$PWD/parser.h \
$$PWD/screen.h \
$$PWD/block.h \
$$PWD/color_palette.h \
$$PWD/text_style.h \
$$PWD/screen_data.h \
$$PWD/cursor.h \
$$PWD/nrc_text_codec.h \
$$PWD/scrollback.h \
$$PWD/utf8_decoder.h \
$$PWD/selection.h
SOURCES += \
$$PWD/yat_pty.cpp \
$$PWD/text.cpp \
$$PWD/controll_chars.cpp \
$$PWD/parser.cpp \
$$PWD/screen.cpp \
$$PWD/block.cpp \
$$PWD/color_palette.cpp \
$$PWD/text_style.cpp \
$$PWD/screen_data.cpp \
$$PWD/cursor.cpp \
$$PWD/nrc_text_codec.cpp \
$$PWD/scrollback.cpp \
$$PWD/selection.cpp

557
yat/backend/block.cpp Normal file
View File

@@ -0,0 +1,557 @@
/*******************************************************************************
* Copyright (c) 2012 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
******************************************************************************/
#include "block.h"
#include "text.h"
#include "screen.h"
#include <QtQuick/QQuickView>
#include <QtQuick/QQuickItem>
#include <QtCore/QDebug>
#include <algorithm>
Block::Block(Screen *screen)
: m_screen(screen)
, m_line(0)
, m_new_line(-1)
, m_screen_index(0)
, m_width(m_screen->width())
, m_visible(true)
, m_changed(true)
, m_only_latin(true)
{
clear();
}
Block::~Block()
{
for (int i = 0; i < m_style_list.size(); i++) {
m_style_list[i].releaseTextSegment(m_screen);
}
}
Screen *Block::screen() const
{
return m_screen;
}
void Block::clear()
{
m_text_line.clear();
for (int i = 0; i < m_style_list.size(); i++) {
m_style_list[i].releaseTextSegment(m_screen);
}
m_style_list.clear();
m_only_latin = true;
m_changed = true;
}
void Block::clearToEnd(int from)
{
clearCharacters(from, m_text_line.size() - 1);
}
void Block::clearCharacters(int from, int to)
{
if (from > m_text_line.size())
return;
QString empty(to+1-from, QChar(' '));
const TextStyle &defaultTextStyle = m_screen->defaultTextStyle();
replaceAtPos(from, empty, defaultTextStyle);
}
void Block::deleteCharacters(int from, int to)
{
m_changed = true;
int removed = 0;
const int size = (to + 1) - from;
bool found = false;
int last_index = -1;
for (int i = 0; i < m_style_list.size(); i++) {
TextStyleLine &current_style = m_style_list[i];
last_index = i;
if (found) {
current_style.start_index -= removed;
current_style.end_index -= removed;
current_style.index_dirty = true;
if (removed != size) {
int current_style_size = current_style.end_index + 1 - current_style.start_index;
if (current_style_size <= size - removed) {
removed += current_style.end_index + 1 - current_style.start_index;
current_style.releaseTextSegment(m_screen);
m_style_list.remove(i);
i--;
} else {
current_style.end_index -= size - removed;
removed = size;
}
}
} else {
if (current_style.start_index <= from && current_style.end_index >= from) {
found = true;
int left_in_style = (current_style.end_index + 1) - from;
int subtract = std::min(left_in_style, size);
current_style.end_index -= subtract;
current_style.text_dirty = true;
removed = subtract;
if (current_style.end_index < current_style.start_index) {
current_style.releaseTextSegment(m_screen);
m_style_list.remove(i);
i--;
}
}
}
}
if (last_index >= 0) {
TextStyleLine &last_modified = m_style_list[last_index];
TextStyle defaultStyle = m_screen->defaultTextStyle();
if (last_modified.isCompatible(defaultStyle)) {
last_modified.end_index += size;
last_modified.text_dirty = true;
} else {
m_style_list.insert(last_index + 1, TextStyleLine(defaultStyle,
last_modified.end_index + 1, last_modified.end_index + size));
}
}
m_text_line.remove(from, size);
}
void Block::deleteToEnd(int from)
{
deleteCharacters(from, m_text_line.size() - 1);
}
void Block::deleteLines(int from)
{
if (from > lineCount())
return;
}
void Block::replaceAtPos(int pos, const QString &text, const TextStyle &style, bool only_latin)
{
m_changed = true;
m_only_latin = m_only_latin && only_latin;
if (pos >= m_text_line.size()) {
if (pos > m_text_line.size()) {
int old_size = m_text_line.size();
QString filling(pos - m_text_line.size(), QChar(' '));
m_text_line.append(filling);
m_style_list.append(TextStyleLine(m_screen->defaultTextStyle(), old_size, old_size + filling.size() -1));
}
m_text_line.append(text);
m_style_list.append(TextStyleLine(style, pos, pos + text.size()-1));
return;
} else if (pos + text.size() > m_text_line.size()) {
m_style_list.append(TextStyleLine(m_screen->defaultTextStyle(), pos + text.size() - m_text_line.size(), pos + text.size() -1));
}
m_text_line.replace(pos,text.size(),text);
bool found = false;
for (int i = 0; i < m_style_list.size(); i++) {
TextStyleLine &current_style = m_style_list[i];
if (found) {
if (current_style.end_index <= pos + text.size() - 1) {
current_style.releaseTextSegment(m_screen);
m_style_list.remove(i);
i--;
} else if (current_style.start_index <= pos + text.size()) {
current_style.start_index = pos + text.size();
current_style.style_dirty = true;
current_style.text_dirty = true;
current_style.index_dirty = true;
} else {
break;
}
} else if (pos >= current_style.start_index && pos <= current_style.end_index) {
found = true;
if (pos + text.size() -1 <= current_style.end_index) {
if (current_style.isCompatible(style)) {
current_style.text_dirty = true;
} else {
if (current_style.start_index == pos && current_style.end_index == pos + text.size() - 1) {
current_style.setStyle(style);
current_style.text_dirty = true;
current_style.style_dirty = true;
} else if (current_style.start_index == pos) {
current_style.start_index = pos + text.size();
current_style.text_dirty = true;
m_style_list.insert(i, TextStyleLine(style,pos, pos+text.size() -1));
} else if (current_style.end_index == pos + text.size() - 1) {
current_style.end_index = pos - 1;
current_style.text_dirty = true;
m_style_list.insert(i+1, TextStyleLine(style,pos, pos + text.size() - 1));
} else {
int old_end = current_style.end_index;
current_style.end_index = pos - 1;
current_style.text_dirty = true;
m_style_list.insert(i+1, TextStyleLine(style,pos, pos + text.size() - 1));
if (pos + text.size() < m_text_line.size()) {
m_style_list.insert(i+2, TextStyleLine(current_style,pos + text.size(), old_end));
}
}
}
break;
} else {
if (current_style.isCompatible(style)) {
current_style.end_index = pos + text.size() - 1;
current_style.text_dirty = true;
} else {
if (current_style.start_index == pos) {
if (i > 0 && m_style_list.at(i-1).isCompatible(style)) {
TextStyleLine &previous_style = m_style_list[i -1];
previous_style.end_index+= text.size();
previous_style.text_dirty = true;
current_style.releaseTextSegment(m_screen);
m_style_list.remove(i);
i--;
} else {
current_style.end_index = pos + text.size() - 1;
current_style.style = style.style;
current_style.forground = style.forground;
current_style.background = style.background;
current_style.text_dirty = true;
current_style.style_dirty = true;
current_style.index_dirty = true;
}
} else {
current_style.end_index = pos - 1;
current_style.text_dirty = true;
m_style_list.insert(i+1, TextStyleLine(style, pos, pos + text.size() -1));
i++;
}
}
}
}
}
}
void Block::insertAtPos(int pos, const QString &text, const TextStyle &style, bool only_latin)
{
m_changed = true;
m_only_latin = m_only_latin && only_latin;
m_text_line.insert(pos,text);
bool found = false;
for (int i = 0; i < m_style_list.size(); i++) {
TextStyleLine &current_style = m_style_list[i];
if (found) {
current_style.start_index += text.size();
current_style.end_index += text.size();
current_style.index_dirty = true;
if (current_style.start_index >= m_text_line.size()) {
current_style.releaseTextSegment(m_screen);
m_style_list.remove(i);
i--;
} else if (current_style.end_index >= m_text_line.size()) {
current_style.end_index = m_text_line.size()-1;
}
} else if (pos >= current_style.start_index && pos <= current_style.end_index) {
found = true;
if (current_style.start_index == pos) {
current_style.start_index += text.size();
current_style.end_index += text.size();
current_style.index_dirty = true;
m_style_list.insert(i, TextStyleLine(style, pos, pos+ text.size() - 1));
i++;
} else if (current_style.end_index == pos) {
current_style.end_index--;
current_style.text_dirty = true;
m_style_list.insert(i+1, TextStyleLine(style, pos, pos+ text.size() - 1));
i++;
} else {
int old_end = current_style.end_index;
current_style.end_index = pos -1;
current_style.text_dirty = true;
m_style_list.insert(i+1, TextStyleLine(style, pos, pos + text.size() - 1));
if (pos + text.size() < m_text_line.size()) {
int segment_end = std::min(m_text_line.size() -1, old_end + text.size());
m_style_list.insert(i+2, TextStyleLine(current_style, pos + text.size(), segment_end));
i+=2;
} else {
i++;
}
}
}
}
}
QString *Block::textLine()
{
return &m_text_line;
}
void Block::setVisible(bool visible)
{
if (visible != m_visible) {
m_changed = true;
m_visible = visible;
for (int i = 0; i < m_style_list.size(); i++) {
if (m_style_list.at(i).text_segment) {
m_style_list.at(i).text_segment->setVisible(visible);
}
}
}
}
bool Block::visible() const
{
return m_visible;
}
Block *Block::split(int line)
{
if (line >= lineCount())
return nullptr;
m_changed = true;
Block *to_return = new Block(m_screen);
int start_index = line * m_width;
for (int i = 0; i < m_style_list.size(); i++) {
ensureStyleAlignWithLines(i);
TextStyleLine &current_style = m_style_list[i];
if (current_style.start_index >= start_index) {
current_style.start_index -= start_index;
current_style.old_index = current_style.start_index - 1;
current_style.end_index -= start_index;
current_style.index_dirty = true;
current_style.text_dirty = true;
current_style.index_dirty = true;
to_return->m_style_list.append(TextStyleLine(current_style, current_style.start_index,
current_style.end_index));
m_style_list.remove(i);
i--;
}
}
to_return->m_text_line = m_text_line.mid(start_index, m_text_line.size() - start_index);
m_text_line.remove(start_index, m_text_line.size() - start_index);
return to_return;
}
Block *Block::takeLine(int line)
{
if (line >= lineCount())
return nullptr;
m_changed = true;
Block *to_return = new Block(m_screen);
int start_index = line * m_width;
int end_index = start_index + (m_width - 1);
for (int i = 0; i < m_style_list.size(); i++) {
ensureStyleAlignWithLines(i);
TextStyleLine &current_style = m_style_list[i];
if (current_style.start_index >= start_index && current_style.end_index <= end_index) {
current_style.releaseTextSegment(m_screen);
current_style.start_index -= start_index;
current_style.end_index -= start_index;
current_style.index_dirty = true;
to_return->m_style_list.append(TextStyleLine(current_style, current_style.start_index,
current_style.end_index));
m_style_list.remove(i);
i--;
} else if (current_style.start_index > end_index) {
current_style.start_index -= (end_index + 1) - start_index;
current_style.end_index -= (end_index + 1) - start_index;
current_style.index_dirty = true;
current_style.text_dirty = true;
}
}
to_return->m_text_line = m_text_line.mid(start_index, m_width);
m_text_line.remove(start_index, m_width);
return to_return;
}
void Block::removeLine(int line)
{
if (line >= lineCount())
return;
m_changed = true;
int start_index = line * m_width;
int end_index = start_index + (m_width - 1);
for (int i = 0; i < m_style_list.size(); i++) {
ensureStyleAlignWithLines(i);
TextStyleLine &current_style = m_style_list[i];
if (current_style.start_index >= start_index && current_style.end_index <= end_index) {
current_style.releaseTextSegment(m_screen);
m_style_list.remove(i);
i--;
} else if (current_style.start_index > end_index) {
current_style.start_index -= (end_index + 1) - start_index;
current_style.end_index -= (end_index + 1) - start_index;
current_style.index_dirty = true;
current_style.text_dirty = true;
}
}
m_text_line.remove(start_index, m_width);
}
void Block::moveLinesFromBlock(Block *block, int start_line, int count)
{
Q_ASSERT(block);
Q_ASSERT(block->lineCount() >= start_line + count);
int start_char = block->width() * start_line;
int end_char = (block->width() * (start_line + count)) - 1;
for (int i = 0; i < block->m_style_list.size(); i++) {
TextStyleLine &current_style = block->m_style_list[i];
if (current_style.start_index >= start_char && current_style.end_index <= end_char) {
current_style.start_index += (-start_char + m_text_line.size());
current_style.end_index += (-start_char + m_text_line.size());
current_style.releaseTextSegment(m_screen);
m_style_list.append(TextStyleLine(current_style, current_style.start_index,
current_style.end_index));
block->m_style_list.remove(i);
i--;
} else if (current_style.start_index > end_char) {
current_style.start_index -= (end_char + 1) - start_char;
current_style.end_index -= (end_char + 1) - start_char;
current_style.index_dirty = true;
current_style.text_dirty = true;
}
}
m_text_line.append(block->m_text_line.mid(start_char, (end_char + 1) - start_char));
block->m_text_line.remove(start_char, (end_char + 1) - start_char);
m_changed = true;
block->m_changed = true;
}
void Block::dispatchEvents()
{
if (!m_changed) {
return;
}
mergeCompatibleStyles();
for (int i = 0; i < m_style_list.size(); i++) {
ensureStyleAlignWithLines(i);
TextStyleLine &current_style = m_style_list[i];
if (current_style.text_segment == 0) {
current_style.text_segment = m_screen->createTextSegment(current_style);
current_style.text_segment->setLine(m_new_line, m_width, &m_text_line);
} else if (m_new_line != m_line) {
current_style.text_segment->setLine(m_new_line, m_width, &m_text_line);
}
if (current_style.style_dirty) {
current_style.text_segment->setTextStyle(current_style);
current_style.style_dirty = false;
}
if (current_style.index_dirty || current_style.text_dirty) {
current_style.text_segment->setStringSegment(current_style.start_index, current_style.end_index, current_style.text_dirty);
current_style.index_dirty = false;
current_style.text_dirty = false;
}
current_style.text_segment->setLatin(m_only_latin);
current_style.text_segment->dispatchEvents();
}
m_changed = false;
m_line = m_new_line;
}
void Block::releaseTextObjects()
{
m_changed = true;
for (int i = 0; i < m_style_list.size(); i++) {
TextStyleLine &currentStyleLine = m_style_list[i];
currentStyleLine.releaseTextSegment(m_screen);
currentStyleLine.text_dirty = true;
currentStyleLine.style_dirty = true;
}
}
QVector<TextStyleLine> Block::style_list()
{
return m_style_list;
}
void Block::printStyleList() const
{
QDebug debug = qDebug();
printStyleList(debug);
}
void Block::printStyleList(QDebug &debug) const
{
QString text_line = m_text_line;
debug << " " << m_line << lineCount() << m_text_line.size() << (void *) this << text_line << "\n"; debug << "\t";
for (int i= 0; i < m_style_list.size(); i++) {
debug << m_style_list.at(i);
}
}
void Block::printStyleListWidthText() const
{
QString text_line = m_text_line;
for (int i= 0; i < m_style_list.size(); i++) {
const TextStyleLine &currentStyle = m_style_list.at(i);
QDebug debug = qDebug();
debug << m_text_line.mid(currentStyle.start_index, (currentStyle.end_index + 1) - currentStyle.start_index) << currentStyle;
}
}
void Block::mergeCompatibleStyles()
{
for (int i = 1; i < m_style_list.size(); i++) {
TextStyleLine &current = m_style_list[i];
if (m_style_list.at(i - 1).isCompatible(current) &&
current.start_index % m_width != 0) {
TextStyleLine &prev = m_style_list[i-1];
prev.end_index = current.end_index;
prev.text_dirty = true;
current.releaseTextSegment(m_screen);
m_style_list.remove(i);
i--;
}
}
}
void Block::ensureStyleAlignWithLines(int i)
{
int start_line = m_style_list[i].start_index / m_width;
int end_line = m_style_list[i].end_index / m_width;
if (start_line != end_line) {
int remainder_start_line = ((m_width * (start_line + 1))-1) - m_style_list[i].start_index;
int next_line_end_index = m_style_list[i].end_index;
m_style_list[i].end_index = m_style_list[i].start_index + remainder_start_line;
m_style_list.insert(i + 1, TextStyleLine(m_style_list[i], m_style_list[i].end_index + 1, next_line_end_index));
}
}

109
yat/backend/block.h Normal file
View File

@@ -0,0 +1,109 @@
/*******************************************************************************
* Copyright (c) 2012 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#ifndef BLOCK_H
#define BLOCK_H
#include <QtCore/QObject>
#include "text_style.h"
class Text;
class Screen;
class Block
{
public:
Block(Screen *screen);
~Block();
Q_INVOKABLE Screen *screen() const;
void clear();
void clearToEnd(int from);
void clearCharacters(int from, int to);
void deleteCharacters(int from, int to);
void deleteToEnd(int from);
void deleteLines(int from);
void replaceAtPos(int i, const QString &text, const TextStyle &style, bool only_latin = true);
void insertAtPos(int i, const QString &text, const TextStyle &style, bool only_latin = true);
void setScreenIndex(int index) { m_screen_index = index; }
int screenIndex() const { return m_screen_index; }
size_t line() { return m_new_line; }
void setLine(size_t line) {
if (line != m_new_line) {
m_changed = true;
m_new_line = line;
}
}
QString *textLine();
int textSize() { return m_text_line.size(); }
int width() const { return m_width; }
void setWidth(int width) { m_changed = true; m_width = width; }
int lineCount() const { return (std::max((m_text_line.size() - 1),0) / m_width) + 1; }
int lineCountAfterModified(int from_char, int text_size, bool replace) {
int new_size = replace ? std::max(from_char + text_size, m_text_line.size())
: std::max(from_char, m_text_line.size()) + text_size;
return ((new_size - 1) / m_width) + 1;
}
void setVisible(bool visible);
bool visible() const;
Block *split(int line);
Block *takeLine(int line);
void removeLine(int line);
void moveLinesFromBlock(Block *block, int start_line, int count);
void dispatchEvents();
void releaseTextObjects();
QVector<TextStyleLine> style_list();
void printStyleList() const;
void printStyleList(QDebug &debug) const;
void printStyleListWidthText() const;
private:
void mergeCompatibleStyles();
void ensureStyleAlignWithLines(int i);
Screen *m_screen;
QString m_text_line;
QVector<TextStyleLine> m_style_list;
size_t m_line;
size_t m_new_line;
int m_screen_index;
int m_width;
bool m_visible;
bool m_changed;
bool m_only_latin;
};
#endif // BLOCK_H

View File

@@ -0,0 +1,265 @@
/******************************************************************************
* Copyright (c) 2013 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#include <QtCore/QString>
static const QChar dec_special_graphics_char_set[] =
{
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x40*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x58*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0020,
/*0x60*/ 0x25c6,0x2592,0x2409,0x240c,0x240d,0x240a,0x00b0,0x00b1,
/*0x68*/ 0x2424,0x240b,0x2518,0x2510,0x250c,0x2514,0x253c,0x23ba,
/*0x70*/ 0x23bb,0x2500,0x23bc,0x23bd,0x251c,0x2524,0x2534,0x252c,
/*0x78*/ 0x2502,0x2264,0x2265,0x03c0,0x2260,0x00a3,0x00b7,0x0000,
};
static const QChar nrc_british_char_set[] =
{
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x40*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x58*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x78*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
};
static const QChar nrc_norwegian_danish_char_set[] =
{
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x40*/ 0x00c4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x58*/ 0x0000,0x0000,0x0000,0x00c6,0x00d8,0x00c5,0x00dc,0x0000,
/*0x60*/ 0x00e4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x78*/ 0x0000,0x0000,0x0000,0x00e6,0x00f8,0x00e5,0x00fc,0x0000,
};
static const QChar nrc_dutch_char_set[] =
{
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x38*/ 0x0000,0x0000,0x00be,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x40*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x58*/ 0x0000,0x0000,0x0000,0x0133,0x00bd,0x007c,0x0000,0x0000,
/*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x78*/ 0x0000,0x0000,0x0000,0x00a8,0x0066,0x00bc,0x00b4,0x0000,
};
static const QChar nrc_finnish_char_set[] =
{
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x40*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x58*/ 0x0000,0x0000,0x0000,0x00c4,0x00d6,0x00c5,0x00dc,0x0000,
/*0x60*/ 0x00e9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x78*/ 0x0000,0x0000,0x0000,0x00e4,0x00f6,0x00e5,0x00fc,0x0000,
};
static const QChar nrc_french_char_set[] =
{
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x40*/ 0x00e0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x58*/ 0x0000,0x0000,0x0000,0x00b0,0x00e7,0x00a7,0x0000,0x0000,
/*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x78*/ 0x0000,0x0000,0x0000,0x00e9,0x00f9,0x00e8,0x00a8,0x0000,
};
static const QChar nrc_french_canadian_char_set[] =
{
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x40*/ 0x00e0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x58*/ 0x0000,0x0000,0x0000,0x00e2,0x00e7,0x00ea,0x00ee,0x0000,
/*0x60*/ 0x00f4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x78*/ 0x0000,0x0000,0x0000,0x00e9,0x00f9,0x00e8,0x00fb,0x0000,
};
static const QChar nrc_german_char_set[] =
{
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x40*/ 0x00a7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x58*/ 0x0000,0x0000,0x0000,0x00c4,0x00d6,0x00dc,0x0000,0x0000,
/*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x78*/ 0x0000,0x0000,0x0000,0x00e4,0x00f6,0x00fc,0x00df,0x0000,
};
static const QChar nrc_italian_char_set[] =
{
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x40*/ 0x00a7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x58*/ 0x0000,0x0000,0x0000,0x00b0,0x00e7,0x00e9,0x0000,0x0000,
/*0x60*/ 0x00f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x78*/ 0x0000,0x0000,0x0000,0x00e0,0x00f2,0x00e8,0x00ec,0x0000,
};
static const QChar nrc_spanish_char_set[] =
{
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x40*/ 0x00a7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x58*/ 0x0000,0x0000,0x0000,0x00a1,0x00d1,0x00bf,0x0000,0x0000,
/*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x78*/ 0x0000,0x0000,0x0000,0x00b0,0x00f1,0x00e7,0x0000,0x0000,
};
static const QChar nrc_swedish_char_set[] =
{
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x40*/ 0x00c9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x58*/ 0x0000,0x0000,0x0000,0x00c4,0x00d6,0x00c5,0x00dc,0x0000,
/*0x60*/ 0x00e9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x78*/ 0x0000,0x0000,0x0000,0x00e4,0x00f6,0x00e5,0x00fc,0x0000,
};
static const QChar nrc_swiss_char_set[] =
{
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x20*/ 0x0000,0x0000,0x0000,0x00f9,0x0000,0x0000,0x0000,0x0000,
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x40*/ 0x00e0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x58*/ 0x0000,0x0000,0x0000,0x00e9,0x00e7,0x00ea,0x00ee,0x00e8,
/*0x60*/ 0x00f4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
/*0x78*/ 0x0000,0x0000,0x0000,0x00e4,0x00f6,0x00fc,0x00fb,0x0000,
};

View File

@@ -0,0 +1,66 @@
#include "color_palette.h"
#include <QDebug>
ColorPalette::ColorPalette(QObject *parent)
: QObject(parent)
, m_normalColors(numberOfColors)
, m_lightColors(numberOfColors)
, m_intenseColors(numberOfColors)
, m_inverse_default(false)
{
m_normalColors[0].setRgb(0,0,0);
m_normalColors[1].setRgb(194,54,33);
m_normalColors[2].setRgb(37,188,36);
m_normalColors[3].setRgb(173,173,39);
m_normalColors[4].setRgb(63,84,255);
m_normalColors[5].setRgb(211,56,211);
m_normalColors[6].setRgb(51,187,199);
m_normalColors[7].setRgb(229,229,229);
m_normalColors[8].setRgb(178,178,178);
m_normalColors[9].setRgb(0,0,0);
m_lightColors[0].setRgb(129,131,131);
m_lightColors[1].setRgb(252,57,31);
m_lightColors[2].setRgb(49,231,34);
m_lightColors[3].setRgb(234,236,35);
m_lightColors[4].setRgb(88,51,255);
m_lightColors[5].setRgb(249,53,248);
m_lightColors[6].setRgb(20,240,240);
m_lightColors[7].setRgb(233,233,233);
m_lightColors[8].setRgb(220,220,220);
m_lightColors[9].setRgb(50,50,50);
}
QColor ColorPalette::color(ColorPalette::Color color, bool bold) const
{
if (m_inverse_default) {
if (color == DefaultForground)
color = DefaultBackground;
else if (color == DefaultBackground)
color = DefaultForground;
}
if (bold)
return m_lightColors.at(color);
return m_normalColors.at(color);
}
QColor ColorPalette::normalColor(ColorPalette::Color color) const
{
return this->color(color, false);
}
QColor ColorPalette::lightColor(ColorPalette::Color color) const
{
return this->color(color,true);
}
void ColorPalette::setInverseDefaultColors(bool inverse)
{
bool emit_changed = inverse != m_inverse_default;
if (emit_changed) {
m_inverse_default = inverse;
emit changed();
}
}

View File

@@ -0,0 +1,43 @@
#ifndef COLOR_PALETTE_H
#define COLOR_PALETTE_H
#include <QtCore/QVector>
#include <QtGui/QColor>
class ColorPalette : public QObject
{
Q_OBJECT
public:
ColorPalette(QObject *parent = 0);
enum Color {
Black,
Red,
Green,
Yellow,
Blue,
Magenta,
Cyan,
White,
DefaultForground,
DefaultBackground,
numberOfColors
};
QColor color(Color color, bool bold) const;
QColor normalColor(Color color) const;
QColor lightColor(Color color) const;
void setInverseDefaultColors(bool inverse);
signals:
void changed();
private:
QVector<QColor> m_normalColors;
QVector<QColor> m_lightColors;
QVector<QColor> m_intenseColors;
bool m_inverse_default;
};
#endif // COLOR_PALETTE_H

View File

@@ -0,0 +1,798 @@
/*******************************************************************************
* Copyright (c) 2013 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#include "controll_chars.h"
namespace C0 {
QDebug operator<<(QDebug debug, C0 character) {
bool insert_space = debug.autoInsertSpaces();
debug.setAutoInsertSpaces(false);
debug << "C0::";
switch (character) {
case NUL:
debug << "NUL";
break;
case SOH:
debug << "SOH";
break;
case STX:
debug << "STX";
break;
case ETX:
debug << "ETX";
break;
case EOT:
debug << "EOT";
break;
case ENQ:
debug << "ENQ";
break;
case ACK:
debug << "ACK";
break;
case BEL:
debug << "BEL";
break;
case BS:
debug << "BS";
break;
case HT:
debug << "HT";
break;
case LF:
debug << "LF";
break;
case VT:
debug << "VT";
break;
case FF:
debug << "FF";
break;
case CR:
debug << "CR";
break;
case SOorLS1:
debug << "SOorLS1";
break;
case SIorLS0:
debug << "SIorLS0";
break;
case DLE:
debug << "DLE";
break;
case DC1:
debug << "DC1";
break;
case DC2:
debug << "DC2";
break;
case DC3:
debug << "DC3";
break;
case DC4:
debug << "DC4";
break;
case NAK:
debug << "NAK";
break;
case SYN:
debug << "SYN";
break;
case ETB:
debug << "ETB";
break;
case CAN:
debug << "CAN";
break;
case EM:
debug << "EM";
break;
case SUB:
debug << "SUB";
break;
case ESC:
debug << "ESC";
break;
case IS4:
debug << "IS4";
break;
case IS3:
debug << "IS3";
break;
case IS2:
debug << "IS2";
break;
case IS1:
debug << "IS1";
break;
case C0_END:
debug << "C0_END";
break;
default:
debug << qPrintable(QString("0x%1").arg(character,0,16));
break;
}
debug.setAutoInsertSpaces(insert_space);
return debug;
}
}
namespace C1_7bit {
QDebug operator<<(QDebug debug, C1_7bit character) {
bool insert_space = debug.autoInsertSpaces();
debug.setAutoInsertSpaces(false);
debug << "C1_7bit::";
switch(character) {
case ESC:
debug << "ESC";
break;
case SCS_G0:
debug << "SCS_G0";
break;
case SCS_G1:
debug << "SCS_G1";
break;
case SCS_G2:
debug << "SCS_G2";
break;
case SCS_G3:
debug << "SCS_G3";
break;
case DECSC:
debug << "DECSC";
break;
case DECRC:
debug << "DECRC";
break;
case NOT_DEFINED:
debug << "NOT_DEFINED";
break;
case NOT_DEFINED1:
debug << "NOT_DEFINED1";
break;
case BPH:
debug << "BPH";
break;
case NBH:
debug << "NBH";
break;
case IND:
debug << "IND";
break;
case NEL:
debug << "NEL";
break;
case SSA:
debug << "SSA";
break;
case ESA:
debug << "ESA";
break;
case HTS:
debug << "HTS";
break;
case HTJ:
debug << "HTJ";
break;
case VTS:
debug << "VTS";
break;
case PLD:
debug << "PLD";
break;
case PLU:
debug << "PLU";
break;
case RI :
debug << "RI ";
break;
case SS2:
debug << "SS2";
break;
case SS3:
debug << "SS3";
break;
case DCS:
debug << "DCS";
break;
case PU1:
debug << "PU1";
break;
case PU2:
debug << "PU2";
break;
case STS:
debug << "STS";
break;
case CCH:
debug << "CCH";
break;
case MW :
debug << "MW ";
break;
case SPA:
debug << "SPA";
break;
case EPA:
debug << "EPA";
break;
case SOS:
debug << "SOS";
break;
case NOT_DEFINED3:
debug << "NOT_DEFINED3";
break;
case SCI:
debug << "SCI";
break;
case CSI:
debug << "CSI";
break;
case ST :
debug << "ST ";
break;
case OSC:
debug << "OSC";
break;
case PM :
debug << "PM ";
break;
case APC:
debug << "APC";
break;
case C1_7bit_Stop:
debug << "C1_7bit_Stop";
break;
default:
debug << qPrintable(QString("0x%1").arg(character,0,16));
break;
}
debug.setAutoInsertSpaces(insert_space);
return debug;
}
}
namespace C1_8bit {
QDebug operator<<(QDebug debug, C1_8bit character) {
bool insert_space = debug.autoInsertSpaces();
debug.setAutoInsertSpaces(false);
debug << "C1_8bit::";
switch(character) {
case NOT_DEFINED:
debug << "NOT_DEFINED";
break;
case NOT_DEFINED1:
debug << "NOT_DEFINED1";
break;
case BPH:
debug << "BPH";
break;
case NBH:
debug << "NBH";
break;
case NOT_DEFINED2:
debug << "NOT_DEFINED2";
break;
case NEL:
debug << "NEL";
break;
case SSA:
debug << "SSA";
break;
case ESA:
debug << "ESA";
break;
case HTS:
debug << "HTS";
break;
case HTJ:
debug << "HTJ";
break;
case VTS:
debug << "VTS";
break;
case PLD:
debug << "PLD";
break;
case PLU:
debug << "PLU";
break;
case RI :
debug << "RI ";
break;
case SS2:
debug << "SS2";
break;
case SS3:
debug << "SS3";
break;
case DCS:
debug << "DCS";
break;
case PU1:
debug << "PU1";
break;
case PU2C1_7bit:
debug << "PU2C1_7bit";
break;
case STS:
debug << "STS";
break;
case CCH:
debug << "CCH";
break;
case MW :
debug << "MW ";
break;
case SPA:
debug << "SPA";
break;
case EPA:
debug << "EPA";
break;
case SOS:
debug << "SOS";
break;
case NOT_DEFINED3:
debug << "NOT_DEFINED3";
break;
case SCI:
debug << "SCI";
break;
case CSI:
debug << "CSI";
break;
case ST :
debug << "ST ";
break;
case OSC:
debug << "OSC";
break;
case PM :
debug << "PM ";
break;
case APC:
debug << "APC";
break;
case C1_8bit_Stop:
debug << "C1_8bit_Stop";
break;
default:
debug << qPrintable(QString("0x%1").arg(character,0,16));
break;
}
debug.setAutoInsertSpaces(insert_space);
return debug;
}
}
namespace FinalBytesNoIntermediate {
QDebug operator<<(QDebug debug, FinalBytesNoIntermediate character) {
bool insert_space = debug.autoInsertSpaces();
debug.setAutoInsertSpaces(false);
debug << "FinalBytesNoIntermediate::";
switch(character) {
case ICH:
debug << "ICH";
break;
case CUU:
debug << "CUU";
break;
case CUD:
debug << "CUD";
break;
case CUF:
debug << "CUF";
break;
case CUB:
debug << "CUB";
break;
case CNL:
debug << "CNL";
break;
case CPL:
debug << "CPL";
break;
case CHA:
debug << "CHA";
break;
case CUP:
debug << "CUP";
break;
case CHT:
debug << "CHT";
break;
case ED:
debug << "ED";
break;
case EL:
debug << "EL";
break;
case IL:
debug << "IL";
break;
case DL:
debug << "DL";
break;
case EF:
debug << "EF";
break;
case EA:
debug << "EA";
break;
case DCH:
debug << "DCH";
break;
case SSE:
debug << "SSE";
break;
case CPR:
debug << "CPR";
break;
case SU:
debug << "SU";
break;
case SD:
debug << "SD";
break;
case NP:
debug << "NP";
break;
case PP:
debug << "PP";
break;
case CTC:
debug << "CTC";
break;
case ECH:
debug << "ECH";
break;
case CVT:
debug << "CVT";
break;
case CBT:
debug << "CBT";
break;
case SRS:
debug << "SRS";
break;
case PTX:
debug << "PTX";
break;
case SDS:
debug << "SDS";
break;
case SIMD:
debug << "SIMD";
break;
case NOT_DEFINED:
debug << "NOT_DEFINED";
break;
case HPA:
debug << "HPA";
break;
case HPR:
debug << "HPR";
break;
case REP:
debug << "REP";
break;
case DA:
debug << "DA";
break;
case VPA:
debug << "VPA";
break;
case VPR:
debug << "VPR";
break;
case HVP:
debug << "HVP";
break;
case TBC:
debug << "TBC";
break;
case SM:
debug << "SM";
break;
case MC:
debug << "MC";
break;
case HPB:
debug << "HPB";
break;
case VPB:
debug << "VPB";
break;
case RM:
debug << "RM";
break;
case SGR:
debug << "SGR";
break;
case DSR:
debug << "DSR";
break;
case DAQ:
debug << "DAQ";
break;
case Reserved0:
debug << "Reserved0";
break;
case Reserved1:
debug << "Reserved1";
break;
case DECSTBM:
debug << "DECSTBM";
break;
case Reserved3:
debug << "Reserved3";
break;
case Reserved4:
debug << "Reserved4";
break;
case Reserved5:
debug << "Reserved5";
break;
case Reserved6:
debug << "Reserved6";
break;
case Reserved7:
debug << "Reserved7";
break;
case Reserved8:
debug << "Reserved8";
break;
case Reserved9:
debug << "Reserved9";
break;
case Reserveda:
debug << "Reserveda";
break;
case Reservedb:
debug << "Reservedb";
break;
case Reservedc:
debug << "Reservedc";
break;
case Reservedd:
debug << "Reservedd";
break;
case Reservede:
debug << "Reservede";
break;
case Reservedf:
debug << "Reservedf";
break;
default:
debug << qPrintable(QString("0x%1").arg(character,0,16));
break;
}
debug.setAutoInsertSpaces(insert_space);
return debug;
}
}
namespace FinalBytesSingleIntermediate {
QDebug operator<<(QDebug debug, FinalBytesSingleIntermediate character)
{
bool insert_space = debug.autoInsertSpaces();
debug.setAutoInsertSpaces(false);
debug << "FinalBytesSingleIntermediate::";
switch(character) {
case SL:
debug << "SL";
break;
case SR:
debug << "SR";
break;
case GSM:
debug << "GSM";
break;
case GSS:
debug << "GSS";
break;
case FNT:
debug << "FNT";
break;
case TSS:
debug << "TSS";
break;
case JFY:
debug << "JFY";
break;
case SPI:
debug << "SPI";
break;
case QUAD:
debug << "QUAD";
break;
case SSU:
debug << "SSU";
break;
case PFS:
debug << "PFS";
break;
case SHS:
debug << "SHS";
break;
case SVS:
debug << "SVS";
break;
case IGS:
debug << "IGS";
break;
case NOT_DEFINED:
debug << "NOT_DEFINED";
break;
case IDCS:
debug << "IDCS";
break;
case PPA:
debug << "PPA";
break;
case PPR:
debug << "PPR";
break;
case PPB:
debug << "PPB";
break;
case SPD:
debug << "SPD";
break;
case DTA:
debug << "DTA";
break;
case SHL:
debug << "SHL";
break;
case SLL:
debug << "SLL";
break;
case FNK:
debug << "FNK";
break;
case SPQR:
debug << "SPQR";
break;
case SEF:
debug << "SEF";
break;
case PEC:
debug << "PEC";
break;
case SSW:
debug << "SSW";
break;
case SACS:
debug << "SACS";
break;
case SAPV:
debug << "SAPV";
break;
case STAB:
debug << "STAB";
break;
case GCC:
debug << "GCC";
break;
case TATE:
debug << "TATE";
break;
case TALE:
debug << "TALE";
break;
case TAC:
debug << "TAC";
break;
case TCC:
debug << "TCC";
break;
case TSR:
debug << "TSR";
break;
case SCO:
debug << "SCO";
break;
case SRCS:
debug << "SRCS";
break;
case SCS:
debug << "SCS";
break;
case SLS:
debug << "SLS";
break;
case NOT_DEFINED2:
debug << "NOT_DEFINED2";
break;
case NOT_DEFINED3:
debug << "NOT_DEFINED3";
break;
case SCP:
debug << "SCP";
break;
case NOT_DEFINED4:
debug << "NOT_DEFINED4";
break;
case NOT_DEFINED5:
debug << "NOT_DEFINED5";
break;
case NOT_DEFINED6:
debug << "NOT_DEFINED6";
break;
case NOT_DEFINED7:
debug << "NOT_DEFINED7";
break;
case Reserved0:
debug << "Reserved0";
break;
case Reserved1:
debug << "Reserved1";
break;
case Reserved2:
debug << "Reserved2";
break;
case Reserved3:
debug << "Reserved3";
break;
case Reserved4:
debug << "Reserved4";
break;
case Reserved5:
debug << "Reserved5";
break;
case Reserved6:
debug << "Reserved6";
break;
case Reserved7:
debug << "Reserved7";
break;
case Reserved8:
debug << "Reserved8";
break;
case Reserved9:
debug << "Reserved9";
break;
case Reserveda:
debug << "Reserveda";
break;
case Reservedb:
debug << "Reservedb";
break;
case Reservedc:
debug << "Reservedc";
break;
case Reservedd:
debug << "Reservedd";
break;
case Reservedf:
debug << "Reservedf";
break;
default:
debug << qPrintable(QString("0x%1").arg(character,0,16));
break;
}
debug.setAutoInsertSpaces(insert_space);
return debug;
}
}

View File

@@ -0,0 +1,299 @@
/******************************************************************************
* Copyright (c) 2012 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#ifndef CONTROLL_CHARS_H
#define CONTROLL_CHARS_H
//This is taken largely from Standard ECMA-48
//http://www.ecma-international.org/publications/standards/Ecma-048.htm
//Also to heres a few handy references
//http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
//http://www.vt100.net/docs/vt100-ug/chapter3.html
#include <QtCore/QDebug>
namespace C0 {
enum C0 {
NUL = 0x00,
SOH = 0x01,
STX = 0x02,
ETX = 0x03,
EOT = 0x04,
ENQ = 0x05,
ACK = 0x06,
BEL = 0x07,
BS = 0x08,
HT = 0x09,
LF = 0x0a,
VT = 0x0b,
FF = 0x0c,
CR = 0x0d,
SOorLS1 = 0x0e,
SIorLS0 = 0x0f,
DLE = 0x10,
DC1 = 0x11,
DC2 = 0x12,
DC3 = 0x13,
DC4 = 0x14,
NAK = 0x15,
SYN = 0x16,
ETB = 0x17,
CAN = 0x18,
EM = 0x19,
SUB = 0x1a,
ESC = 0x1b,
IS4 = 0x1c,
IS3 = 0x1d,
IS2 = 0x1e,
IS1 = 0x1f,
C0_END = 0x20
};
QDebug operator<<(QDebug debug, C0 character);
}
namespace C1_7bit {
enum C1_7bit {
C1_7bit_Start = 0x1b,
ESC = 0x1b,
SCS_G0 = 0x28,
SCS_G1 = 0x29,
SCS_G2 = 0x2a,
SCS_G3 = 0x2b,
DECSC = 0x37,
DECRC = 0x38,
NOT_DEFINED = 0x40,
NOT_DEFINED1 = 0x41,
BPH = 0x42,
NBH = 0x43,
IND = 0x44,
NEL = 0x45,
SSA = 0x46,
ESA = 0x47,
HTS = 0x48,
HTJ = 0x49,
VTS = 0x4a,
PLD = 0x4b,
PLU = 0x4c,
RI = 0x4d,
SS2 = 0x4e,
SS3 = 0x4f,
DCS = 0x50,
PU1 = 0x51,
PU2 = 0x52,
STS = 0x53,
CCH = 0x54,
MW = 0x55,
SPA = 0x56,
EPA = 0x57,
SOS = 0x58,
NOT_DEFINED3 = 0x59,
SCI = 0x5a,
CSI = 0x5b,
ST = 0x5c,
OSC = 0x5d,
PM = 0x5e,
APC = 0x5f,
C1_7bit_Stop = 0x60
};
QDebug operator<<(QDebug debug, C1_7bit character);
}
namespace C1_8bit {
enum C1_8bit {
C1_8bit_Start = 0x80,
NOT_DEFINED = C1_8bit_Start,
NOT_DEFINED1 = 0x81,
BPH = 0x82,
NBH = 0x83,
NOT_DEFINED2 = 0x84,
NEL = 0x85,
SSA = 0x86,
ESA = 0x87,
HTS = 0x88,
HTJ = 0x89,
VTS = 0x8a,
PLD = 0x8b,
PLU = 0x8c,
RI = 0x8d,
SS2 = 0x8e,
SS3 = 0x8f,
DCS = 0x90,
PU1 = 0x91,
PU2C1_7bit = 0x92,
STS = 0x93,
CCH = 0x94,
MW = 0x95,
SPA = 0x96,
EPA = 0x97,
SOS = 0x98,
NOT_DEFINED3 = 0x99,
SCI = 0x9a,
CSI = 0x9b,
ST = 0x9c,
OSC = 0x9d,
PM = 0x9e,
APC = 0x9f,
C1_8bit_Stop = 0xa0
};
QDebug operator<<(QDebug debug, C1_8bit character);
}
namespace FinalBytesNoIntermediate {
enum FinalBytesNoIntermediate {
ICH = 0x40,
CUU = 0x41,
CUD = 0x42,
CUF = 0x43,
CUB = 0x44,
CNL = 0x45,
CPL = 0x46,
CHA = 0x47,
CUP = 0x48,
CHT = 0x49,
ED = 0x4a,
EL = 0x4b,
IL = 0x4c,
DL = 0x4d,
EF = 0x4e,
EA = 0x4f,
DCH = 0x50,
SSE = 0x51,
CPR = 0x52,
SU = 0x53,
SD = 0x54,
NP = 0x55,
PP = 0x56,
CTC = 0x57,
ECH = 0x58,
CVT = 0x59,
CBT = 0x5a,
SRS = 0x5b,
PTX = 0x5c,
SDS = 0x5d,
SIMD = 0x5e,
NOT_DEFINED = 0x5f,
HPA = 0x60,
HPR = 0x61,
REP = 0x62,
DA = 0x63,
VPA = 0x64,
VPR = 0x65,
HVP = 0x66,
TBC = 0x67,
SM = 0x68,
MC = 0x69,
HPB = 0x6a,
VPB = 0x6b,
RM = 0x6c,
SGR = 0x6d,
DSR = 0x6e,
DAQ = 0x6f,
Reserved0 = 0x70,
Reserved1 = 0x71,
DECSTBM = 0x72,
Reserved3 = 0x73,
Reserved4 = 0x74,
Reserved5 = 0x75,
Reserved6 = 0x76,
Reserved7 = 0x77,
Reserved8 = 0x78,
Reserved9 = 0x79,
Reserveda = 0x7a,
Reservedb = 0x7b,
Reservedc = 0x7c,
Reservedd = 0x7d,
Reservede = 0x7e,
Reservedf = 0x7f
};
QDebug operator<<(QDebug debug, FinalBytesNoIntermediate character);
}
namespace FinalBytesSingleIntermediate {
enum FinalBytesSingleIntermediate {
SL = 0x40,
SR = 0x41,
GSM = 0x42,
GSS = 0x43,
FNT = 0x44,
TSS = 0x45,
JFY = 0x46,
SPI = 0x47,
QUAD = 0x48,
SSU = 0x49,
PFS = 0x4a,
SHS = 0x4b,
SVS = 0x4c,
IGS = 0x4d,
NOT_DEFINED = 0x4e,
IDCS = 0x4f,
PPA = 0x50,
PPR = 0x51,
PPB = 0x52,
SPD = 0x53,
DTA = 0x54,
SHL = 0x55,
SLL = 0x56,
FNK = 0x57,
SPQR = 0x58,
SEF = 0x59,
PEC = 0x5a,
SSW = 0x5b,
SACS = 0x5c,
SAPV = 0x5d,
STAB = 0x5e,
GCC = 0x5f,
TATE = 0x60,
TALE = 0x61,
TAC = 0x62,
TCC = 0x63,
TSR = 0x64,
SCO = 0x65,
SRCS = 0x66,
SCS = 0x67,
SLS = 0x68,
NOT_DEFINED2 = 0x69,
NOT_DEFINED3 = 0x6a,
SCP = 0x6b,
NOT_DEFINED4 = 0x6c,
NOT_DEFINED5 = 0x6d,
NOT_DEFINED6 = 0x6e,
NOT_DEFINED7 = 0x6f,
Reserved0 = 0x70,
Reserved1 = 0x71,
Reserved2 = 0x72,
Reserved3 = 0x73,
Reserved4 = 0x74,
Reserved5 = 0x75,
Reserved6 = 0x76,
Reserved7 = 0x77,
Reserved8 = 0x78,
Reserved9 = 0x79,
Reserveda = 0x7a,
Reservedb = 0x7b,
Reservedc = 0x7c,
Reservedd = 0x7d,
Reservedf = 0x7f
};
QDebug operator<<(QDebug debug, FinalBytesSingleIntermediate character);
}
#endif // CONTROLL_CHARS_H

542
yat/backend/cursor.cpp Normal file
View File

@@ -0,0 +1,542 @@
/******************************************************************************
* Copyright (c) 2013 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#include "cursor.h"
#include "block.h"
#include "screen_data.h"
#include <QTextCodec>
Cursor::Cursor(Screen* screen)
: QObject(screen)
, m_screen(screen)
, m_current_text_style(screen->defaultTextStyle())
, m_position(0,0)
, m_new_position(0,0)
, m_document_width(screen->width())
, m_document_height(screen->height())
, m_top_margin(0)
, m_bottom_margin(0)
, m_scroll_margins_set(false)
, m_origin_at_margin(false)
, m_notified(false)
, m_visible(true)
, m_new_visibillity(true)
, m_blinking(false)
, m_new_blinking(false)
, m_wrap_around(true)
, m_content_height_changed(false)
, m_insert_mode(Replace)
{
connect(screen, SIGNAL(widthAboutToChange(int)), this, SLOT(setDocumentWidth(int)));
connect(screen, SIGNAL(heightAboutToChange(int, int, int)), this, SLOT(setDocumentHeight(int, int, int)));
connect(screen, SIGNAL(contentHeightChanged()), this, SLOT(contentHeightChanged()));
m_gl_text_codec = QTextCodec::codecForName("utf-8")->makeDecoder();
m_gr_text_codec = QTextCodec::codecForName("utf-8")->makeDecoder();
for (int i = 0; i < m_document_width; i++) {
if (i % 8 == 0) {
m_tab_stops.append(i);
}
}
}
Cursor::~Cursor()
{
}
void Cursor::setDocumentWidth(int width)
{
if (width > m_document_width) {
for (int i = m_document_width -1; i < width; i++) {
if (i % 8 == 0) {
m_tab_stops.append(i);
}
}
}
m_document_width = width;
if (new_x() >= width) {
new_rx() = width - 1;
notifyChanged();
}
}
void Cursor::setDocumentHeight(int height, int currentCursorBlock, int currentScrollBackHeight)
{
Q_UNUSED(currentCursorBlock);
resetScrollArea();
if (m_document_height > height) {
const int to_remove = m_document_height - height;
const int removeLinesBelowCursor =
std::min(m_document_height - new_y(), to_remove);
const int removeLinesAtTop = to_remove - removeLinesBelowCursor;
if (!removeLinesAtTop) {
new_ry() -= removeLinesAtTop;
notifyChanged();
}
} else {
int height_diff = height - m_document_height;
if (currentScrollBackHeight >= height_diff) {
new_ry() += height_diff;
} else if (currentScrollBackHeight > 0) {
const int move = height_diff - currentScrollBackHeight;
new_ry() += move;
}
}
m_document_height = height;
if (new_y() >= height) {
new_ry() = height - 1;
notifyChanged();
}
if (new_y() <= 0) {
new_ry() = 0;
}
}
bool Cursor::visible() const
{
return m_visible;
}
void Cursor::setVisible(bool visible)
{
m_new_visibillity = visible;
}
bool Cursor::blinking() const
{
return m_blinking;
}
void Cursor::setBlinking(bool blinking)
{
m_new_blinking = blinking;
}
void Cursor::setTextStyle(TextStyle::Style style, bool add)
{
if (add) {
m_current_text_style.style |= style;
} else {
m_current_text_style.style &= !style;
}
}
void Cursor::resetStyle()
{
m_current_text_style.background = ColorPalette::DefaultBackground;
m_current_text_style.forground = ColorPalette::DefaultForground;
m_current_text_style.style = TextStyle::Normal;
}
void Cursor::scrollUp(int lines)
{
if (new_y() < top() || new_y() > bottom())
return;
for (int i = 0; i < lines; i++) {
screen_data()->moveLine(bottom(), top());
}
}
void Cursor::scrollDown(int lines)
{
if (new_y() < top() || new_y() > bottom())
return;
for (int i = 0; i < lines; i++) {
screen_data()->moveLine(top(), bottom());
}
}
void Cursor::setTextCodec(QTextCodec *codec)
{
m_gl_text_codec = codec->makeDecoder();
}
void Cursor::setInsertMode(InsertMode mode)
{
m_insert_mode = mode;
}
TextStyle Cursor::currentTextStyle() const
{
return m_current_text_style;
}
void Cursor::setTextStyleColor(ushort color)
{
Q_ASSERT(color >= 30 && color < 50);
if (color < 38) {
m_current_text_style.forground = ColorPalette::Color(color - 30);
} else if (color == 39) {
m_current_text_style.forground = ColorPalette::DefaultForground;
} else if (color >= 40 && color < 48) {
m_current_text_style.background = ColorPalette::Color(color - 40);
} else if (color == 49) {
m_current_text_style.background = ColorPalette::DefaultBackground;
} else {
qDebug() << "Failed to set color";
}
}
ColorPalette *Cursor::colorPalette() const
{
return m_screen->colorPalette();
}
QPoint Cursor::position() const
{
return m_position;
}
int Cursor::x() const
{
return m_position.x();
}
int Cursor::y() const
{
return (m_screen->currentScreenData()->contentHeight() - m_screen->height()) + m_position.y();
}
void Cursor::moveOrigin()
{
m_new_position = QPoint(0,adjusted_top());
notifyChanged();
}
void Cursor::moveBeginningOfLine()
{
new_rx() = 0;
notifyChanged();
}
void Cursor::moveUp(int lines)
{
int adjusted_new_y = this->adjusted_new_y();
if (!adjusted_new_y || !lines)
return;
if (lines < adjusted_new_y) {
new_ry() -= lines;
} else {
new_ry() = adjusted_top();
}
notifyChanged();
}
void Cursor::moveDown(int lines)
{
int bottom = adjusted_bottom();
if (new_y() == bottom || !lines)
return;
if (new_y() + lines <= bottom) {
new_ry() += lines;
} else {
new_ry() = bottom;
}
notifyChanged();
}
void Cursor::moveLeft(int positions)
{
if (!new_x() || !positions)
return;
if (positions < new_x()) {
new_rx() -= positions;
} else {
new_rx() = 0;
}
notifyChanged();
}
void Cursor::moveRight(int positions)
{
int width = m_screen->width();
if (new_x() == width -1 || !positions)
return;
if (positions < width - new_x()) {
new_rx() += positions;
} else {
new_rx() = width -1;
}
notifyChanged();
}
void Cursor::move(int new_x, int new_y)
{
int width = m_screen->width();
if (m_origin_at_margin) {
new_y += m_top_margin;
}
if (new_x < 0) {
new_x = 0;
} else if (new_x >= width) {
new_x = width - 1;
}
if (new_y < adjusted_top()) {
new_y = adjusted_top();
} else if (new_y > adjusted_bottom()) {
new_y = adjusted_bottom();
}
if (this->new_y() != new_y || this->new_x() != new_x) {
m_new_position = QPoint(new_x, new_y);
notifyChanged();
}
}
void Cursor::moveToLine(int line)
{
const int height = m_screen->height();
if (line < adjusted_top()) {
line = 0;
} else if (line > adjusted_bottom()) {
line = height -1;
}
if (line != new_y()) {
new_rx() = line;
notifyChanged();
}
}
void Cursor::moveToCharacter(int character)
{
const int width = m_screen->width();
if (character < 0) {
character = 1;
} else if (character > width) {
character = width;
}
if (character != new_x()) {
new_rx() = character;
notifyChanged();
}
}
void Cursor::moveToNextTab()
{
for (int i = 0; i < m_tab_stops.size(); i++) {
if (new_x() < m_tab_stops.at(i)) {
moveToCharacter(std::min(m_tab_stops.at(i), m_document_width -1));
return;
}
}
moveToCharacter(m_document_width - 1);
}
void Cursor::setTabStop()
{
int i;
for (i = 0; i < m_tab_stops.size(); i++) {
if (new_x() == m_tab_stops.at(i))
return;
if (new_x() > m_tab_stops.at(i)) {
continue;
} else {
break;
}
}
m_tab_stops.insert(i,new_x());
}
void Cursor::removeTabStop()
{
for (int i = 0; i < m_tab_stops.size(); i++) {
if (new_x() == m_tab_stops.at(i)) {
m_tab_stops.remove(i);
return;
} else if (new_x() < m_tab_stops.at(i)) {
return;
}
}
}
void Cursor::clearTabStops()
{
m_tab_stops.clear();
}
void Cursor::clearToBeginningOfLine()
{
screen_data()->clearToBeginningOfLine(m_new_position);
}
void Cursor::clearToEndOfLine()
{
screen_data()->clearToEndOfLine(m_new_position);
}
void Cursor::clearToBeginningOfScreen()
{
clearToBeginningOfLine();
if (new_y() > 0)
screen_data()->clearToBeginningOfScreen(m_new_position.y()-1);
}
void Cursor::clearToEndOfScreen()
{
clearToEndOfLine();
if (new_y() < m_screen->height() -1) {
screen_data()->clearToEndOfScreen(m_new_position.y()+1);
}
}
void Cursor::clearLine()
{
screen_data()->clearLine(m_new_position);
}
void Cursor::deleteCharacters(int characters)
{
screen_data()->deleteCharacters(m_new_position, new_x() + characters -1);
}
void Cursor::setWrapAround(bool wrap)
{
m_wrap_around = wrap;
}
void Cursor::addAtCursor(const QByteArray &data, bool only_latin)
{
if (m_insert_mode == Replace) {
replaceAtCursor(data, only_latin);
} else {
insertAtCursor(data, only_latin);
}
}
void Cursor::replaceAtCursor(const QByteArray &data, bool only_latin)
{
const QString text = m_gl_text_codec->toUnicode(data);
if (!m_wrap_around && new_x() + text.size() > m_screen->width()) {
const int size = m_document_width - new_x();
QString toBlock = text.mid(0,size);
toBlock.replace(toBlock.size() - 1, 1, text.at(text.size()-1));
screen_data()->replace(m_new_position, toBlock, m_current_text_style, only_latin);
new_rx() += toBlock.size();
} else {
auto diff = screen_data()->replace(m_new_position, text, m_current_text_style, only_latin);
new_rx() += diff.character;
new_ry() += diff.line;
}
if (new_y() >= m_document_height)
new_ry() = m_document_height - 1;
notifyChanged();
}
void Cursor::insertAtCursor(const QByteArray &data, bool only_latin)
{
const QString text = m_gl_text_codec->toUnicode(data);
auto diff = screen_data()->insert(m_new_position, text, m_current_text_style, only_latin);
new_rx() += diff.character;
new_ry() += diff.line;
if (new_y() >= m_document_height)
new_ry() = m_document_height - 1;
if (new_x() >= m_document_width)
new_rx() = m_document_width - 1;
}
void Cursor::lineFeed()
{
if(new_y() >= bottom()) {
screen_data()->insertLine(bottom(), top());
} else {
new_ry()++;
notifyChanged();
}
}
void Cursor::reverseLineFeed()
{
if (new_y() == top()) {
scrollUp(1);
} else {
new_ry()--;
notifyChanged();
}
}
void Cursor::setOriginAtMargin(bool atMargin)
{
m_origin_at_margin = atMargin;
m_new_position = QPoint(0, adjusted_top());
notifyChanged();
}
void Cursor::setScrollArea(int from, int to)
{
m_top_margin = from;
m_bottom_margin = std::min(to,m_document_height -1);
m_scroll_margins_set = true;
}
void Cursor::resetScrollArea()
{
m_top_margin = 0;
m_bottom_margin = 0;
m_scroll_margins_set = false;
}
void Cursor::dispatchEvents()
{
if (m_new_position != m_position|| m_content_height_changed) {
bool emit_x_changed = m_new_position.x() != m_position.x();
bool emit_y_changed = m_new_position.y() != m_position.y();
m_position = m_new_position;
if (emit_x_changed)
emit xChanged();
if (emit_y_changed || m_content_height_changed)
emit yChanged();
}
if (m_new_visibillity != m_visible) {
m_visible = m_new_visibillity;
emit visibilityChanged();
}
if (m_new_blinking != m_blinking) {
m_blinking = m_new_blinking;
emit blinkingChanged();
}
}
void Cursor::contentHeightChanged()
{
m_content_height_changed = true;
}

175
yat/backend/cursor.h Normal file
View File

@@ -0,0 +1,175 @@
/******************************************************************************
* Copyright (c) 2013 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#ifndef CURSOR_H
#define CURSOR_H
#include "text_style.h"
#include "screen.h"
#include <QtCore/QObject>
class Cursor : public QObject
{
Q_OBJECT
Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibilityChanged)
Q_PROPERTY(bool blinking READ blinking WRITE setBlinking NOTIFY blinkingChanged)
Q_PROPERTY(int x READ x NOTIFY xChanged)
Q_PROPERTY(int y READ y NOTIFY yChanged)
public:
enum InsertMode {
Insert,
Replace
};
Cursor(Screen *screen);
~Cursor();
bool visible() const;
void setVisible(bool visible);
bool blinking() const;
void setBlinking(bool blinking);
void setTextStyle(TextStyle::Style style, bool add = true);
void resetStyle();
TextStyle currentTextStyle() const;
void setTextStyleColor(ushort color);
ColorPalette *colorPalette() const;
QPoint position() const;
int x() const;
int y() const;
int new_x() const { return m_new_position.x(); }
int new_y() const { return m_new_position.y(); }
void moveOrigin();
void moveBeginningOfLine();
void moveUp(int lines = 1);
void moveDown(int lines = 1);
void moveLeft(int positions = 1);
void moveRight(int positions = 1);
void move(int new_x, int new_y);
void moveToLine(int line);
void moveToCharacter(int character);
void moveToNextTab();
void setTabStop();
void removeTabStop();
void clearTabStops();
void clearToBeginningOfLine();
void clearToEndOfLine();
void clearToBeginningOfScreen();
void clearToEndOfScreen();
void clearLine();
void deleteCharacters(int characters);
void setWrapAround(bool wrap);
void addAtCursor(const QByteArray &text, bool only_latin = true);
void insertAtCursor(const QByteArray &text, bool only_latin = true);
void replaceAtCursor(const QByteArray &text, bool only_latin = true);
void lineFeed();
void reverseLineFeed();
void setOriginAtMargin(bool atMargin);
void setScrollArea(int from, int to);
void resetScrollArea();
void scrollUp(int lines);
void scrollDown(int lines);
void setTextCodec(QTextCodec *codec);
void setInsertMode(InsertMode mode);
inline void notifyChanged();
void dispatchEvents();
public slots:
void setDocumentWidth(int width);
void setDocumentHeight(int height, int currentCursorBlock, int currentScrollBackHeight);
signals:
void xChanged();
void yChanged();
void visibilityChanged();
void blinkingChanged();
private slots:
void contentHeightChanged();
private:
ScreenData *screen_data() const { return m_screen->currentScreenData(); }
int &new_rx() { return m_new_position.rx(); }
int &new_ry() { return m_new_position.ry(); }
int adjusted_new_x() const { return m_origin_at_margin ?
m_new_position.x() - m_top_margin : m_new_position.x(); }
int adjusted_new_y() const { return m_origin_at_margin ?
m_new_position.y() - m_top_margin : m_new_position.y(); }
int adjusted_top() const { return m_origin_at_margin ? m_top_margin : 0; }
int adjusted_bottom() const { return m_origin_at_margin ? m_bottom_margin : m_document_height - 1; }
int top() const { return m_scroll_margins_set ? m_top_margin : 0; }
int bottom() const { return m_scroll_margins_set ? m_bottom_margin : m_document_height - 1; }
Screen *m_screen;
TextStyle m_current_text_style;
QPoint m_position;
QPoint m_new_position;
int m_document_width;
int m_document_height;
int m_top_margin;
int m_bottom_margin;
bool m_scroll_margins_set;
bool m_origin_at_margin;
QVector<int> m_tab_stops;
bool m_notified;
bool m_visible;
bool m_new_visibillity;
bool m_blinking;
bool m_new_blinking;
bool m_wrap_around;
bool m_content_height_changed;
QTextDecoder *m_gl_text_codec;
QTextDecoder *m_gr_text_codec;
InsertMode m_insert_mode;
};
void Cursor::notifyChanged()
{
if (!m_notified) {
m_notified = true;
m_screen->scheduleEventDispatch();
}
}
#endif //CUROSOR_H

32
yat/backend/main.cpp Normal file
View File

@@ -0,0 +1,32 @@
/**************************************************************************************************
* Copyright (c) 2012 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
* OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
***************************************************************************************************/
#include "terminal_state.h"
#include <QtGui/QGuiApplication>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
TerminalState state;
return app.exec();
}

View File

@@ -0,0 +1,124 @@
/******************************************************************************
* Copyright (c) 2013 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#include "nrc_text_codec.h"
static bool nrc_text_codec_init = false;
void NrcTextCodec::initialize()
{
if (!nrc_text_codec_init) {
nrc_text_codec_init = true;
new NrcTextCodec("dec_special_graphics", 500001, dec_special_graphics_char_set);
new NrcTextCodec("nrc_british", 500002, nrc_british_char_set);
new NrcTextCodec("nrc_norwegian_danish", 5002, nrc_norwegian_danish_char_set);
new NrcTextCodec("nrc_dutch", 5002, nrc_dutch_char_set);
new NrcTextCodec("nrc_finnish", 5002, nrc_finnish_char_set);
new NrcTextCodec("nrc_french", 5002, nrc_french_char_set);
new NrcTextCodec("nrc_french_canadian", 5002, nrc_french_canadian_char_set);
new NrcTextCodec("nrc_german", 5002, nrc_german_char_set);
new NrcTextCodec("nrc_italian", 5002, nrc_italian_char_set);
new NrcTextCodec("nrc_spanish", 5002, nrc_spanish_char_set);
new NrcTextCodec("nrc_swedish", 5002, nrc_swedish_char_set);
new NrcTextCodec("nrc_swiss", 5002, nrc_swiss_char_set);
}
}
NrcTextCodec::NrcTextCodec(const QByteArray &name, int mib, const QChar character_set[])
: QTextCodec()
, m_name(name)
, m_mib(mib)
, m_character_set(character_set)
{
}
QByteArray NrcTextCodec::name() const
{
return m_name;
}
int NrcTextCodec::mibEnum() const
{
return m_mib;
}
QString NrcTextCodec::convertToUnicode(const char *in, int length, QTextCodec::ConverterState *state) const
{
QString ret_str;
ret_str.reserve(length);
for (int i = 0; i < length; i++) {
uchar in_char = *(in + i);
if (in_char < 128) {
QChar unicode = m_character_set[in_char];
if (unicode.isNull())
unicode = QChar(in_char);
ret_str.append(unicode);
} else {
if (state) {
if (state->flags & QTextCodec::ConvertInvalidToNull) {
state->invalidChars++;
ret_str.append(0);
} else {
state->invalidChars++;
state->remainingChars = length - i;
return ret_str;
}
}
}
}
return ret_str;
}
QByteArray NrcTextCodec::convertFromUnicode(const QChar *in, int length, ConverterState *state) const
{
QByteArray ret_array;
ret_array.reserve(length);
for (int i = 0; i < length; i++) {
QChar out_char = *(in + i);
if (out_char.unicode() < 128) {
uchar out = out_char.unicode();
ret_array.append(out);
} else {
bool found = false;
for (uchar n = 0; n < 128; n++) {
if (m_character_set[n] == out_char) {
ret_array.append(n);
found = true;
break;
}
}
if (!found && state) {
if (state->flags & QTextCodec::ConvertInvalidToNull) {
state->invalidChars++;
ret_array.append(char(0));
} else {
state->invalidChars++;
state->remainingChars = length - i;
return ret_array;
}
}
}
}
return ret_array;
}

View File

@@ -0,0 +1,45 @@
/******************************************************************************
* Copyright (c) 2013 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#include "character_sets.h"
#include <QtCore/QString>
#include <QtCore/QTextCodec>
class NrcTextCodec : public QTextCodec
{
public:
NrcTextCodec(const QByteArray &name, int mib, const QChar character_set[]);
QByteArray name() const;
int mibEnum() const;
static void initialize();
protected:
QString convertToUnicode(const char *in, int length, ConverterState *state) const;
QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const;
private:
const QByteArray m_name;
const int m_mib;
const QChar *m_character_set;
};

1329
yat/backend/parser.cpp Normal file

File diff suppressed because it is too large Load Diff

110
yat/backend/parser.h Normal file
View File

@@ -0,0 +1,110 @@
/*******************************************************************************
* Copyright (c) 2012 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#ifndef PARSER_H
#define PARSER_H
#include <QtCore/QString>
#include <QtCore/QVector>
#include <QtCore/QLinkedList>
#include "controll_chars.h"
#include "utf8_decoder.h"
class Screen;
class Parser
{
public:
Parser(Screen *screen);
void addData(const QByteArray &data);
private:
enum DecodeState {
PlainText,
DecodeC0,
DecodeC1_7bit,
DecodeCSI,
DecodeOSC,
DecodeCharacterSet,
DecodeFontSize
};
enum DecodeOSCState {
None,
ChangeWindowAndIconName,
ChangeIconTitle,
ChangeWindowTitle,
Unknown
};
void decodeC0(uchar character);
void decodeC1_7bit(uchar character);
void decodeParameters(uchar character);
void decodeCSI(uchar character);
void decodeOSC(uchar character);
void decodeCharacterSet(uchar character);
void decodeFontSize(uchar character);
void setMode(int mode);
void setDecMode(int mode);
void resetMode(int mode);
void resetDecMode(int mode);
void handleSGR();
void tokenFinished();
void appendParameter();
void handleDefaultParameters(int defaultValue);
DecodeState m_decode_state;
DecodeOSCState m_decode_osc_state;
QByteArray m_current_data;
int m_current_token_start;
int m_current_position;
QChar m_intermediate_char;
QByteArray m_parameter_string;
QVector<int> m_parameters;
bool m_parameters_expecting_more;
bool m_dec_mode;
bool m_gt_param;
bool m_lnm_mode_set;
bool m_contains_only_latin;
int m_decode_graphics_set;
QTextCodec *m_graphic_codecs[4];
Utf8Decoder m_utf8_decoder;
Screen *m_screen;
friend QDebug operator<<(QDebug debug, DecodeState decodeState);
};
QDebug operator<<(QDebug debug, Parser::DecodeState decodeState);
#endif // PARSER_H

620
yat/backend/screen.cpp Normal file
View File

@@ -0,0 +1,620 @@
/******************************************************************************
* Copyright (c) 2012 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
******************************************************************************/
#include "screen.h"
#include "screen_data.h"
#include "block.h"
#include "cursor.h"
#include "text.h"
#include "scrollback.h"
#include "selection.h"
#include "controll_chars.h"
#include "character_sets.h"
#include <QtCore/QTimer>
#include <QtCore/QSocketNotifier>
#include <QtGui/QGuiApplication>
#include <QtCore/QDebug>
#include <float.h>
Screen::Screen(QObject *parent)
: QObject(parent)
, m_palette(new ColorPalette(this))
, m_parser(this)
, m_timer_event_id(0)
, m_width(1)
, m_height(0)
, m_primary_data(new ScreenData(500, this))
, m_alternate_data(new ScreenData(0, this))
, m_current_data(m_primary_data)
, m_old_current_data(m_primary_data)
, m_selection(new Selection(this))
, m_flash(false)
, m_cursor_changed(false)
, m_application_cursor_key_mode(false)
, m_fast_scroll(true)
, m_default_background(m_palette->normalColor(ColorPalette::DefaultBackground))
{
Cursor *cursor = new Cursor(this);
m_cursor_stack << cursor;
m_new_cursors << cursor;
connect(m_primary_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
connect(m_primary_data, &ScreenData::contentModified,
this, &Screen::contentModified);
connect(m_palette, SIGNAL(changed()), this, SLOT(paletteChanged()));
setHeight(25);
setWidth(80);
connect(&m_pty, &YatPty::readyRead, this, &Screen::readData);
connect(&m_pty, SIGNAL(hangupReceived()),qGuiApp, SLOT(quit()));
}
Screen::~Screen()
{
for(int i = 0; i < m_to_delete.size(); i++) {
delete m_to_delete.at(i);
}
//m_to_delete.clear();
delete m_primary_data;
delete m_alternate_data;
}
QColor Screen::defaultForgroundColor() const
{
return m_palette->normalColor(ColorPalette::DefaultForground);
}
QColor Screen::defaultBackgroundColor() const
{
return m_palette->normalColor(ColorPalette::DefaultBackground);
}
void Screen::emitRequestHeight(int newHeight)
{
emit requestHeightChange(newHeight);
}
void Screen::setHeight(int height)
{
if (height == m_height)
return;
emit heightAboutToChange(height, currentCursor()->new_y(), currentScreenData()->scrollback()->height());
m_height = height;
m_pty.setHeight(height, height * 10);
emit heightChanged();
}
int Screen::height() const
{
return m_height;
}
int Screen::contentHeight() const
{
return currentScreenData()->contentHeight();
}
void Screen::emitRequestWidth(int newWidth)
{
emit requestWidthChange(newWidth);
}
void Screen::setWidth(int width)
{
if (width == m_width)
return;
emit widthAboutToChange(width);
m_width = width;
m_pty.setWidth(width, width * 10);
emit widthChanged();
}
int Screen::width() const
{
return m_width;
}
void Screen::useAlternateScreenBuffer()
{
if (m_current_data == m_primary_data) {
disconnect(m_primary_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
disconnect(m_primary_data, &ScreenData::contentModified, this, &Screen::contentModified);
m_current_data = m_alternate_data;
m_current_data->clear();
connect(m_alternate_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
connect(m_primary_data, &ScreenData::contentModified, this, &Screen::contentModified);
emit contentHeightChanged();
}
}
void Screen::useNormalScreenBuffer()
{
if (m_current_data == m_alternate_data) {
disconnect(m_alternate_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
disconnect(m_alternate_data, &ScreenData::contentModified, this, &Screen::contentModified);
m_current_data = m_primary_data;
connect(m_primary_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
connect(m_alternate_data, &ScreenData::contentModified, this, &Screen::contentModified);
emit contentHeightChanged();
}
}
TextStyle Screen::defaultTextStyle() const
{
TextStyle style;
style.style = TextStyle::Normal;
style.forground = ColorPalette::DefaultForground;
style.background = ColorPalette::DefaultBackground;
return style;
}
void Screen::saveCursor()
{
Cursor *new_cursor = new Cursor(this);
if (m_cursor_stack.size())
m_cursor_stack.last()->setVisible(false);
m_cursor_stack << new_cursor;
m_new_cursors << new_cursor;
}
void Screen::restoreCursor()
{
if (m_cursor_stack.size() <= 1)
return;
m_delete_cursors.append(m_cursor_stack.takeLast());
m_cursor_stack.last()->setVisible(true);
}
void Screen::clearScreen()
{
currentScreenData()->clear();
}
ColorPalette *Screen::colorPalette() const
{
return m_palette;
}
void Screen::fill(const QChar character)
{
currentScreenData()->fill(character);
}
void Screen::clear()
{
fill(QChar(' '));
}
void Screen::setFastScroll(bool fast)
{
m_fast_scroll = fast;
}
bool Screen::fastScroll() const
{
return m_fast_scroll;
}
Selection *Screen::selection() const
{
return m_selection;
}
void Screen::doubleClicked(const QPointF &clicked)
{
Q_UNUSED(clicked);
//int start, end;
//currentScreenData()->getDoubleClickSelectionArea(clicked, &start, &end);
//setSelectionAreaStart(QPointF(start,clicked.y()));
//setSelectionAreaEnd(QPointF(end,clicked.y()));
}
void Screen::setTitle(const QString &title)
{
m_title = title;
emit screenTitleChanged();
}
QString Screen::title() const
{
return m_title;
}
void Screen::scheduleFlash()
{
m_flash = true;
}
void Screen::printScreen() const
{
currentScreenData()->printStyleInformation();
qDebug() << "Total height: " << currentScreenData()->contentHeight();
}
void Screen::scheduleEventDispatch()
{
if (!m_timer_event_id) {
m_timer_event_id = startTimer(1);
m_time_since_initiated.restart();
}
m_time_since_parsed.restart();
}
void Screen::dispatchChanges()
{
if (m_old_current_data != m_current_data) {
m_old_current_data->releaseTextObjects();
m_old_current_data = m_current_data;
}
currentScreenData()->dispatchLineEvents();
emit dispatchTextSegmentChanges();
static int max_to_delete_size = 0;
if (max_to_delete_size < m_to_delete.size()) {
max_to_delete_size = m_to_delete.size();
qDebug() << "TO DELETE SIZE :" << max_to_delete_size;
}
if (m_flash) {
m_flash = false;
emit flash();
}
for (int i = 0; i < m_delete_cursors.size(); i++) {
int new_index = m_new_cursors.indexOf(m_delete_cursors.at(i));
if (new_index >= 0)
m_new_cursors.remove(new_index);
delete m_delete_cursors.at(i);
}
m_delete_cursors.clear();
for (int i = 0; i < m_new_cursors.size(); i++) {
emit cursorCreated(m_new_cursors.at(i));
}
m_new_cursors.clear();
for (int i = 0; i < m_cursor_stack.size(); i++) {
m_cursor_stack[i]->dispatchEvents();
}
m_selection->dispatchChanges();
}
void Screen::sendPrimaryDA()
{
m_pty.write(QByteArrayLiteral("\033[?6c"));
}
void Screen::sendSecondaryDA()
{
m_pty.write(QByteArrayLiteral("\033[>1;95;0c"));
}
void Screen::setApplicationCursorKeysMode(bool enable)
{
m_application_cursor_key_mode = enable;
}
bool Screen::applicationCursorKeyMode() const
{
return m_application_cursor_key_mode;
}
void Screen::ensureVisiblePages(int top_line)
{
currentScreenData()->ensureVisiblePages(top_line);
}
static bool hasControll(Qt::KeyboardModifiers modifiers)
{
#ifdef Q_OS_MAC
return modifiers & Qt::MetaModifier;
#else
return modifiers & Qt::ControlModifier;
#endif
}
static bool hasMeta(Qt::KeyboardModifiers modifiers)
{
#ifdef Q_OS_MAC
return modifiers & Qt::ControlModifier;
#else
return modifiers & Qt::MetaModifier;
#endif
}
void Screen::sendKey(const QString &text, Qt::Key key, Qt::KeyboardModifiers modifiers)
{
// if (key == Qt::Key_Control)
// printScreen();
/// UGH, this function should be re-written
char escape = '\0';
char control = '\0';
char code = '\0';
QVector<ushort> parameters;
bool found = true;
switch(key) {
case Qt::Key_Up:
escape = C0::ESC;
if (m_application_cursor_key_mode)
control = C1_7bit::SS3;
else
control = C1_7bit::CSI;
code = 'A';
break;
case Qt::Key_Right:
escape = C0::ESC;
if (m_application_cursor_key_mode)
control = C1_7bit::SS3;
else
control = C1_7bit::CSI;
code = 'C';
break;
case Qt::Key_Down:
escape = C0::ESC;
if (m_application_cursor_key_mode)
control = C1_7bit::SS3;
else
control = C1_7bit::CSI;
code = 'B';
break;
case Qt::Key_Left:
escape = C0::ESC;
if (m_application_cursor_key_mode)
control = C1_7bit::SS3;
else
control = C1_7bit::CSI;
code = 'D';
break;
case Qt::Key_Insert:
escape = C0::ESC;
control = C1_7bit::CSI;
parameters.append(2);
code = '~';
break;
case Qt::Key_Delete:
escape = C0::ESC;
control = C1_7bit::CSI;
parameters.append(3);
code = '~';
break;
case Qt::Key_Home:
escape = C0::ESC;
control = C1_7bit::CSI;
parameters.append(1);
code = '~';
break;
case Qt::Key_End:
escape = C0::ESC;
control = C1_7bit::CSI;
parameters.append(4);
code = '~';
break;
case Qt::Key_PageUp:
escape = C0::ESC;
control = C1_7bit::CSI;
parameters.append(5);
code = '~';
break;
case Qt::Key_PageDown:
escape = C0::ESC;
control = C1_7bit::CSI;
parameters.append(6);
code = '~';
break;
case Qt::Key_F1:
case Qt::Key_F2:
case Qt::Key_F3:
case Qt::Key_F4:
if (m_application_cursor_key_mode) {
parameters.append((key & 0xff) - 37);
escape = C0::ESC;
control = C1_7bit::CSI;
code = '~';
}
break;
case Qt::Key_F5:
case Qt::Key_F6:
case Qt::Key_F7:
case Qt::Key_F8:
case Qt::Key_F9:
case Qt::Key_F10:
case Qt::Key_F11:
case Qt::Key_F12:
if (m_application_cursor_key_mode) {
parameters.append((key & 0xff) - 36);
escape = C0::ESC;
control = C1_7bit::CSI;
code = '~';
}
break;
case Qt::Key_Control:
case Qt::Key_Shift:
case Qt::Key_Alt:
case Qt::Key_AltGr:
return;
break;
default:
found = false;
}
if (found) {
int term_mods = 0;
if (modifiers & Qt::ShiftModifier)
term_mods |= 1;
if (modifiers & Qt::AltModifier)
term_mods |= 2;
if (modifiers & Qt::ControlModifier)
term_mods |= 4;
QByteArray toPty;
if (term_mods) {
term_mods++;
parameters.append(term_mods);
}
if (escape)
toPty.append(escape);
if (control)
toPty.append(control);
if (parameters.size()) {
for (int i = 0; i < parameters.size(); i++) {
if (i)
toPty.append(';');
toPty.append(QByteArray::number(parameters.at(i)));
}
}
if (code)
toPty.append(code);
m_pty.write(toPty);
} else {
QString verifiedText = text.simplified();
if (verifiedText.isEmpty()) {
switch (key) {
case Qt::Key_Return:
case Qt::Key_Enter:
verifiedText = "\r";
break;
case Qt::Key_Backspace:
verifiedText = "\010";
break;
case Qt::Key_Tab:
verifiedText = "\t";
break;
case Qt::Key_Control:
case Qt::Key_Meta:
case Qt::Key_Alt:
case Qt::Key_Shift:
return;
case Qt::Key_Space:
verifiedText = " ";
break;
default:
return;
}
}
QByteArray to_pty;
QByteArray key_text;
if (hasControll(modifiers)) {
char key_char = verifiedText.toLocal8Bit().at(0);
key_text.append(key_char & 0x1F);
} else {
key_text = verifiedText.toUtf8();
}
if (modifiers & Qt::AltModifier) {
to_pty.append(C0::ESC);
}
if (hasMeta(modifiers)) {
to_pty.append(C0::ESC);
to_pty.append('@');
to_pty.append(FinalBytesNoIntermediate::Reserved3);
}
to_pty.append(key_text);
m_pty.write(to_pty);
}
}
YatPty *Screen::pty()
{
return &m_pty;
}
Text *Screen::createTextSegment(const TextStyleLine &style_line)
{
Q_UNUSED(style_line);
Text *to_return;
if (m_to_delete.size()) {
to_return = m_to_delete.takeLast();
to_return->setVisible(true);
} else {
to_return = new Text(this);
emit textCreated(to_return);
}
return to_return;
}
void Screen::releaseTextSegment(Text *text)
{
m_to_delete.append(text);
}
void Screen::readData(const QByteArray &data)
{
m_parser.addData(data);
scheduleEventDispatch();
}
void Screen::paletteChanged()
{
QColor new_default = m_palette->normalColor(ColorPalette::DefaultBackground);
if (new_default != m_default_background) {
m_default_background = new_default;
emit defaultBackgroundColorChanged();
}
}
void Screen::timerEvent(QTimerEvent *)
{
if (m_timer_event_id && (m_time_since_parsed.elapsed() > 3 || m_time_since_initiated.elapsed() > 8)) {
killTimer(m_timer_event_id);
m_timer_event_id = 0;
dispatchChanges();
}
}

188
yat/backend/screen.h Normal file
View File

@@ -0,0 +1,188 @@
/*******************************************************************************
* Copyright (c) 2012 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#ifndef TERMINALSCREEN_H
#define TERMINALSCREEN_H
#include <QObject>
#include "color_palette.h"
#include "parser.h"
#include "yat_pty.h"
#include "text_style.h"
#include <QtCore/QPoint>
#include <QtCore/QSize>
#include <QtCore/QStack>
#include <QtCore/QElapsedTimer>
class Block;
class Cursor;
class Text;
class ScreenData;
class Selection;
class Screen : public QObject
{
Q_OBJECT
Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged)
Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged)
Q_PROPERTY(int contentHeight READ contentHeight NOTIFY contentHeightChanged)
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY screenTitleChanged)
Q_PROPERTY(Selection *selection READ selection CONSTANT)
Q_PROPERTY(QColor defaultBackgroundColor READ defaultBackgroundColor NOTIFY defaultBackgroundColorChanged)
public:
explicit Screen(QObject *parent = 0);
~Screen();
void emitRequestHeight(int newHeight);
void setHeight(int height);
int height() const;
int contentHeight() const;
void emitRequestWidth(int newWidth);
void setWidth(int width);
int width() const;
ScreenData *currentScreenData() const { return m_current_data; }
void useAlternateScreenBuffer();
void useNormalScreenBuffer();
Cursor *currentCursor() const { return m_cursor_stack.last(); }
void saveCursor();
void restoreCursor();
TextStyle defaultTextStyle() const;
QColor defaultForgroundColor() const;
QColor defaultBackgroundColor() const;
ColorPalette *colorPalette() const;
void clearScreen();
void fill(const QChar character);
void clear();
void setFastScroll(bool fast);
bool fastScroll() const;
Selection *selection() const;
Q_INVOKABLE void doubleClicked(const QPointF &clicked);
void setTitle(const QString &title);
QString title() const;
void scheduleFlash();
Q_INVOKABLE void printScreen() const;
void scheduleEventDispatch();
void dispatchChanges();
void sendPrimaryDA();
void sendSecondaryDA();
void setApplicationCursorKeysMode(bool enable);
bool applicationCursorKeyMode() const;
Q_INVOKABLE void sendKey(const QString &text, Qt::Key key, Qt::KeyboardModifiers modifiers);
YatPty *pty();
Q_INVOKABLE void ensureVisiblePages(int top_line);
Text *createTextSegment(const TextStyleLine &style_line);
void releaseTextSegment(Text *text);
public slots:
void readData(const QByteArray &data);
void paletteChanged();
signals:
void reset();
void flash();
void dispatchLineChanges();
void dispatchTextSegmentChanges();
void screenTitleChanged();
void textCreated(Text *text);
void cursorCreated(Cursor *cursor);
void requestHeightChange(int newHeight);
void heightAboutToChange(int height, int currentCursorLine, int currentScrollBackHeight);
void heightChanged();
void contentHeightChanged();
void requestWidthChange(int newWidth);
void widthAboutToChange(int width);
void widthChanged();
void defaultBackgroundColorChanged();
void contentModified(size_t lineModified, int lineDiff, int contentDiff);
protected:
void timerEvent(QTimerEvent *);
private:
ColorPalette *m_palette;
YatPty m_pty;
Parser m_parser;
QElapsedTimer m_time_since_parsed;
QElapsedTimer m_time_since_initiated;
int m_timer_event_id;
int m_width;
int m_height;
ScreenData *m_primary_data;
ScreenData *m_alternate_data;
ScreenData *m_current_data;
ScreenData *m_old_current_data;
QVector<Cursor *> m_cursor_stack;
QVector<Cursor *> m_new_cursors;
QVector<Cursor *> m_delete_cursors;
QString m_title;
Selection *m_selection;
bool m_flash;
bool m_cursor_changed;
bool m_application_cursor_key_mode;
bool m_fast_scroll;
QVector<Text *> m_to_delete;
QColor m_default_background;
friend class ScreenData;
};
#endif // TERMINALSCREEN_H

530
yat/backend/screen_data.cpp Normal file
View File

@@ -0,0 +1,530 @@
/*******************************************************************************
* Copyright (c) 2012 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#include "screen_data.h"
#include "block.h"
#include "screen.h"
#include "scrollback.h"
#include "cursor.h"
#include <stdio.h>
#include <QtGui/QGuiApplication>
#include <QtCore/QDebug>
ScreenData::ScreenData(size_t max_scrollback, Screen *screen)
: QObject(screen)
, m_screen(screen)
, m_scrollback(new Scrollback(max_scrollback, this))
, m_screen_height(0)
, m_height(0)
, m_width(0)
, m_block_count(0)
, m_old_total_lines(0)
{
connect(screen, SIGNAL(heightAboutToChange(int, int, int)), this, SLOT(setHeight(int, int, int)));
connect(screen, SIGNAL(widthAboutToChange(int)), this, SLOT(setWidth(int)));
}
ScreenData::~ScreenData()
{
for (auto it = m_screen_blocks.begin(); it != m_screen_blocks.end(); ++it) {
delete *it;
}
delete m_scrollback;
}
int ScreenData::contentHeight() const
{
return m_height + m_scrollback->height();
}
void ScreenData::setHeight(int height, int currentCursorLine, int currentContentHeight)
{
Q_UNUSED(currentContentHeight);
m_screen_height = height;
if (height == m_height)
return;
if (m_height > height) {
const int to_remove = m_height - height;
const int remove_from_end = std::min((m_height -1) - currentCursorLine, to_remove);
const int remove_from_start = to_remove - remove_from_end;
if (remove_from_end) {
remove_lines_from_end(remove_from_end);
}
if (remove_from_start) {
push_at_most_to_scrollback(remove_from_start);
}
} else {
ensure_at_least_height(height);
}
}
void ScreenData::setWidth(int width)
{
m_width = width;
for (Block *block : m_screen_blocks) {
int before_count = block->lineCount();
block->setWidth(width);
m_height += block->lineCount() - before_count;
}
if (m_height > m_screen_height) {
push_at_most_to_scrollback(m_height - m_screen_height);
} else {
ensure_at_least_height(m_screen_height);
}
m_scrollback->setWidth(width);
}
void ScreenData::clearToEndOfLine(const QPoint &point)
{
auto it = it_for_row_ensure_single_line_block(point.y());
(*it)->clearToEnd(point.x());
}
void ScreenData::clearToEndOfScreen(int y)
{
auto it = it_for_row_ensure_single_line_block(y);
while(it != m_screen_blocks.end()) {
clearBlock(it);
++it;
}
}
void ScreenData::clearToBeginningOfLine(const QPoint &point)
{
auto it = it_for_row_ensure_single_line_block(point.y());
(*it)->clearCharacters(0,point.x());
}
void ScreenData::clearToBeginningOfScreen(int y)
{
auto it = it_for_row_ensure_single_line_block(y);
if (it != m_screen_blocks.end())
(*it)->clear();
while(it != m_screen_blocks.begin()) {
--it;
clearBlock(it);
}
}
void ScreenData::clearLine(const QPoint &point)
{
(*it_for_row_ensure_single_line_block(point.y()))->clear();
}
void ScreenData::clear()
{
for (auto it = m_screen_blocks.begin(); it != m_screen_blocks.end(); ++it) {
clearBlock(it);
}
}
void ScreenData::releaseTextObjects()
{
for (auto it = m_screen_blocks.begin(); it != m_screen_blocks.end(); ++it) {
(*it)->releaseTextObjects();
}
}
void ScreenData::clearCharacters(const QPoint &point, int to)
{
auto it = it_for_row_ensure_single_line_block(point.y());
(*it)->clearCharacters(point.x(),to);
}
void ScreenData::deleteCharacters(const QPoint &point, int to)
{
auto it = it_for_row(point.y());
if (it == m_screen_blocks.end())
return;
int line_in_block = point.y() - (*it)->screenIndex();
int chars_to_line = line_in_block * m_width;
(*it)->deleteCharacters(chars_to_line + point.x(), chars_to_line + to);
}
CursorDiff ScreenData::replace(const QPoint &point, const QString &text, const TextStyle &style, bool only_latin)
{
return modify(point,text,style,true, only_latin);
}
CursorDiff ScreenData::insert(const QPoint &point, const QString &text, const TextStyle &style, bool only_latin)
{
return modify(point,text,style,false, only_latin);
}
void ScreenData::moveLine(int from, int to)
{
if (from == to)
return;
const size_t old_content_height = contentHeight();
const int orig_to = to;
if (to > from)
to++;
auto from_it = it_for_row_ensure_single_line_block(from);
auto to_it = it_for_row_ensure_single_line_block(to);
(*from_it)->clear();
m_screen_blocks.splice(to_it, m_screen_blocks, from_it);
qDebug() << Q_FUNC_INFO << to;
emit contentModified(m_scrollback->height() + to, 1, content_height_diff(old_content_height));
}
void ScreenData::insertLine(int row, int topMargin)
{
auto row_it = it_for_row(row + 1);
const size_t old_content_height = contentHeight();
if (!topMargin && m_height >= m_screen_height) {
push_at_most_to_scrollback(1);
} else {
auto row_top_margin = it_for_row_ensure_single_line_block(topMargin);
if (row == topMargin) {
(*row_top_margin)->clear();
return;
}
delete (*row_top_margin);
m_screen_blocks.erase(row_top_margin);
m_height--;
m_block_count--;
}
Block *block_to_insert = new Block(m_screen);
m_screen_blocks.insert(row_it,block_to_insert);
m_height++;
m_block_count++;
emit contentModified(m_scrollback->height() + row + 1, 1, content_height_diff(old_content_height));
}
void ScreenData::fill(const QChar &character)
{
clear();
auto it = --m_screen_blocks.end();
for (int i = 0; i < m_block_count; --it, i++) {
QString fill_str(m_screen->width(), character);
(*it)->replaceAtPos(0, fill_str, m_screen->defaultTextStyle());
}
}
void ScreenData::dispatchLineEvents()
{
if (!m_block_count)
return;
const int scrollback_height = m_scrollback->height();
int i = 0;
for (auto it = m_screen_blocks.begin(); it != m_screen_blocks.end(); ++it) {
int line = scrollback_height + i;
(*it)->setLine(line);
//(*it)->setScreenIndex(i);
(*it)->dispatchEvents();
i+= (*it)->lineCount();
}
if (contentHeight() != m_old_total_lines) {
m_old_total_lines = contentHeight();
emit contentHeightChanged();
}
}
void ScreenData::printRuler(QDebug &debug) const
{
QString ruler = QString("|----i----").repeated((m_width/10)+1).append("|");
debug << " " << (void *) this << ruler;
}
void ScreenData::printStyleInformation() const
{
auto it = m_screen_blocks.end();
std::advance(it, -m_block_count);
for (int i = 0; it != m_screen_blocks.end(); ++it, i++) {
if (i % 5 == 0) {
QDebug debug = qDebug();
debug << "Ruler:";
printRuler(debug);
}
QDebug debug = qDebug();
(*it)->printStyleList(debug);
}
qDebug() << "On screen height" << m_height;
}
Screen *ScreenData::screen() const
{
return m_screen;
}
void ScreenData::ensureVisiblePages(int top_line)
{
m_scrollback->ensureVisiblePages(top_line);
}
Scrollback *ScreenData::scrollback() const
{
return m_scrollback;
}
void ScreenData::sendSelectionToClipboard(const QPoint &start, const QPoint &end, QClipboard::Mode mode)
{
if (start.y() < 0)
return;
if (end.y() >= contentHeight())
return;
QString to_clip_board_buffer;
bool started_in_scrollback = false;
if (size_t(start.y()) < m_scrollback->height()) {
started_in_scrollback = true;
QPoint end_scrollback = end;
if (size_t(end.y()) >= m_scrollback->height()) {
end_scrollback = QPoint(m_width, m_scrollback->height() - 1);
}
to_clip_board_buffer = m_scrollback->selection(start, end_scrollback);
}
if (size_t(end.y()) >= m_scrollback->height()) {
QPoint start_in_screen;
if (started_in_scrollback) {
start_in_screen = QPoint(0,0);
} else {
start_in_screen = start;
start_in_screen.ry() -= m_scrollback->height();
}
QPoint end_in_screen = end;
end_in_screen.ry() -= m_scrollback->height();
auto it = it_for_row(start_in_screen.y());
size_t screen_index = (*it)->screenIndex();
int start_pos = (start_in_screen.y() - (*it)->screenIndex()) * m_width + start.x();
for (; it != m_screen_blocks.end(); ++it, start_pos = 0) {
int end_pos = (*it)->textSize();
bool should_break = false;
if (size_t(screen_index + (*it)->lineCount()) > size_t(end_in_screen.y())) {
end_pos = (end_in_screen.y() - screen_index) * m_width + end_in_screen.x();
should_break = true;
}
if (to_clip_board_buffer.size())
to_clip_board_buffer += '\n';
to_clip_board_buffer += (*it)->textLine()->mid(start_pos, end_pos - start_pos);
if (should_break)
break;
screen_index += (*it)->lineCount();
}
}
QGuiApplication::clipboard()->setText(to_clip_board_buffer, mode);
}
CursorDiff ScreenData::modify(const QPoint &point, const QString &text, const TextStyle &style, bool replace, bool only_latin)
{
auto it = it_for_row(point.y());
Block *block = *it;
const int start_char = (point.y() - block->screenIndex()) * m_width + point.x();
const size_t lines_before = block->lineCount();
const int lines_changed =
block->lineCountAfterModified(start_char, text.size(), replace) - lines_before;
const size_t old_content_height = contentHeight();
m_height += lines_changed;
if (lines_changed > 0) {
int removed = 0;
auto to_merge_inn = it;
++to_merge_inn;
while(removed < lines_changed && to_merge_inn != m_screen_blocks.end()) {
Block *to_be_reduced = *to_merge_inn;
bool remove_block = removed + to_be_reduced->lineCount() <= lines_changed;
int lines_to_remove = remove_block ? to_be_reduced->lineCount() : to_be_reduced->lineCount() - (lines_changed - removed);
block->moveLinesFromBlock(to_be_reduced, 0, lines_to_remove);
removed += lines_to_remove;
if (remove_block) {
delete to_be_reduced;
to_merge_inn = m_screen_blocks.erase(to_merge_inn);
m_block_count--;
} else {
++to_merge_inn;
}
}
m_height -= removed;
}
if (m_height > m_screen_height)
push_at_most_to_scrollback(m_height - m_screen_height);
if (replace) {
block->replaceAtPos(start_char, text, style, only_latin);
} else {
block->insertAtPos(start_char, text, style, only_latin);
}
int end_char = (start_char + text.size()) % m_width;
if (end_char == 0)
end_char = m_width -1;
emit contentModified(m_scrollback->height() + point.y(), lines_changed, content_height_diff(old_content_height));
return { lines_changed, end_char - point.x()};
}
void ScreenData::clearBlock(std::list<Block *>::iterator line)
{
int before_count = (*line)->lineCount();
(*line)->clear();
int diff_line = before_count - (*line)->lineCount();
if (diff_line > 0) {
++line;
for (int i = 0; i < diff_line; i++) {
m_screen_blocks.insert(line, new Block(m_screen));
}
m_block_count+=diff_line;
}
}
std::list<Block *>::iterator ScreenData::it_for_row_ensure_single_line_block(int row)
{
auto it = it_for_row(row);
const int index = (*it)->screenIndex();
const int lines = (*it)->lineCount();
if (index == row && lines == 1) {
return it;
}
int line_diff = row - index;
return split_out_row_from_block(it, line_diff);
}
std::list<Block *>::iterator ScreenData::split_out_row_from_block(std::list<Block *>::iterator it, int row_in_block)
{
int lines = (*it)->lineCount();
if (row_in_block == 0 && lines == 1)
return it;
if (row_in_block == 0) {
auto insert_before = (*it)->takeLine(0);
insert_before->setScreenIndex(row_in_block);
m_block_count++;
return m_screen_blocks.insert(it,insert_before);
} else if (row_in_block == lines -1) {
auto insert_after = (*it)->takeLine(lines -1);
insert_after->setScreenIndex(row_in_block);
++it;
m_block_count++;
return m_screen_blocks.insert(it, insert_after);
}
auto half = (*it)->split(row_in_block);
++it;
auto it_width_first = m_screen_blocks.insert(it, half);
auto the_one = half->takeLine(0);
m_block_count+=2;
return m_screen_blocks.insert(it_width_first,the_one);
}
void ScreenData::push_at_most_to_scrollback(int lines)
{
int pushed = 0;
auto it = m_screen_blocks.begin();
while (it != m_screen_blocks.end() && pushed + (*it)->lineCount() <= lines) {
m_block_count--;
const int block_height = (*it)->lineCount();
m_height -= block_height;
pushed += block_height;
m_scrollback->addBlock(*it);
it = m_screen_blocks.erase(it);
}
}
void ScreenData::reclaim_at_least(int lines)
{
int lines_reclaimed = 0;
while (m_scrollback->blockCount() && lines_reclaimed < lines) {
Block *block = m_scrollback->reclaimBlock();
m_height += block->lineCount();
lines_reclaimed += block->lineCount();
m_block_count++;
m_screen_blocks.push_front(block);
}
}
void ScreenData::remove_lines_from_end(int lines)
{
int removed = 0;
auto it = m_screen_blocks.end();
while (it != m_screen_blocks.begin() && removed < lines) {
--it;
const int block_height = (*it)->lineCount();
if (removed + block_height <= lines) {
removed += block_height;
m_height -= block_height;
m_block_count--;
delete (*it);
it = m_screen_blocks.erase(it);
} else {
const int to_remove = lines - removed;
removed += to_remove;
m_height -= to_remove;
Block *block = *it;
for (int i = 0; i < to_remove; i++) {
block->removeLine(block->lineCount()-1);
}
}
}
}
void ScreenData::ensure_at_least_height(int height)
{
if (m_height > height)
return;
int to_grow = height - m_height;
reclaim_at_least(to_grow);
if (height > m_height) {
int to_insert = height - m_height;
for (int i = 0; i < to_insert; i++) {
m_screen_blocks.push_back(new Block(m_screen));
}
m_height += to_insert;
m_block_count += to_insert;
}
}
int ScreenData::content_height_diff(size_t old_content_height)
{
const size_t content_height = contentHeight();
return old_content_height < content_height ? content_height - old_content_height :
- int(old_content_height - content_height);
}

138
yat/backend/screen_data.h Normal file
View File

@@ -0,0 +1,138 @@
/*******************************************************************************
* Copyright (c) 2012 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#ifndef SCREENDATA_H
#define SCREENDATA_H
#include "text_style.h"
#include "block.h"
#include <QtCore/QVector>
#include <QtCore/QPoint>
#include <QtCore/QObject>
#include <QtGui/QClipboard>
#include <QtCore/QDebug>
class Screen;
class Scrollback;
class CursorDiff
{
public:
int line;
int character;
};
class ScreenData : public QObject
{
Q_OBJECT
public:
ScreenData(size_t max_scrollback, Screen *screen);
~ScreenData();
int contentHeight() const;
void clearToEndOfLine(const QPoint &pos);
void clearToEndOfScreen(int y);
void clearToBeginningOfLine(const QPoint &pos);
void clearToBeginningOfScreen(int y);
void clearLine(const QPoint &pos);
void clear();
void releaseTextObjects();
void clearCharacters(const QPoint &pos, int to);
void deleteCharacters(const QPoint &pos, int to);
CursorDiff replace(const QPoint &pos, const QString &text, const TextStyle &style, bool only_latin);
CursorDiff insert(const QPoint &pos, const QString &text, const TextStyle &style, bool only_latin);
void moveLine(int from, int to);
void insertLine(int insertAt, int topMargin);
void fill(const QChar &character);
void dispatchLineEvents();
void printRuler(QDebug &debug) const;
void printStyleInformation() const;
Screen *screen() const;
void ensureVisiblePages(int top_line);
Scrollback *scrollback() const;
void sendSelectionToClipboard(const QPoint &start, const QPoint &end, QClipboard::Mode mode);
inline std::list<Block *>::iterator it_for_row(int row);
public slots:
void setHeight(int height, int currentCursorLine, int currentContentHeight);
void setWidth(int width);
signals:
void contentHeightChanged();
void contentModified(size_t lineModified, int lineDiff, int contentDiff);
private:
CursorDiff modify(const QPoint &pos, const QString &text, const TextStyle &style, bool replace, bool only_latin);
void clearBlock(std::list<Block *>::iterator line);
std::list<Block *>::iterator it_for_row_ensure_single_line_block(int row);
std::list<Block *>::iterator split_out_row_from_block(std::list<Block *>::iterator block_it, int row_in_block);
void push_at_most_to_scrollback(int lines);
void reclaim_at_least(int lines);
void remove_lines_from_end(int lines);
void ensure_at_least_height(int height);
int content_height_diff(size_t old_content_height);
Screen *m_screen;
Scrollback *m_scrollback;
int m_screen_height;
int m_height;
int m_width;
int m_block_count;
int m_old_total_lines;
std::list<Block *> m_screen_blocks;
};
std::list<Block *>::iterator ScreenData::it_for_row(int row)
{
if (row >= m_screen_height) {
return m_screen_blocks.end();
}
auto it = m_screen_blocks.end();
int line_for_block = m_screen_height;
size_t abs_line = contentHeight();
while (it != m_screen_blocks.begin()) {
--it;
line_for_block -= (*it)->lineCount();
abs_line -= (*it)->lineCount();
if (line_for_block <= row) {
(*it)->setScreenIndex(line_for_block);
(*it)->setLine(abs_line);
return it;
}
}
return m_screen_blocks.end();
}
#endif // SCREENDATA_H

215
yat/backend/scrollback.cpp Normal file
View File

@@ -0,0 +1,215 @@
/******************************************************************************
* Copyright (c) 2013 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
******************************************************************************/
#include "scrollback.h"
#include "screen_data.h"
#include "screen.h"
#include "block.h"
#define P_VAR(variable) \
#variable ":" << variable
Scrollback::Scrollback(size_t max_size, ScreenData *screen_data)
: m_screen_data(screen_data)
, m_height(0)
, m_width(0)
, m_block_count(0)
, m_max_size(max_size)
, m_adjust_visible_pages(0)
{
}
void Scrollback::addBlock(Block *block)
{
if (!m_max_size) {
delete block;
return;
}
m_blocks.push_back(block);
block->releaseTextObjects();
m_block_count++;
m_height += m_blocks.back()->lineCount();
while (m_height - m_blocks.front()->lineCount() >= m_max_size) {
m_block_count--;
m_height -= m_blocks.front()->lineCount();
delete m_blocks.front();
m_blocks.pop_front();
m_adjust_visible_pages++;
}
m_visible_pages.clear();
}
Block *Scrollback::reclaimBlock()
{
if (m_blocks.empty())
return nullptr;
Block *last = m_blocks.back();
last->setWidth(m_width);
m_block_count--;
m_height -= last->lineCount();
m_blocks.pop_back();
m_visible_pages.clear();
return last;
}
void Scrollback::ensureVisiblePages(int top_line)
{
if (top_line < 0)
return;
if (size_t(top_line) >= m_height)
return;
uint height = std::max(m_screen_data->screen()->height(), 1);
int complete_pages = m_height / height;
int remainder = m_height - (complete_pages * height);
int top_page = top_line / height;
int bottom_page = top_page + 1;
std::set<int> pages_to_update;
pages_to_update.insert(top_page);
if (bottom_page * height < m_height)
pages_to_update.insert(bottom_page);
for (auto it = m_visible_pages.begin(); it != m_visible_pages.end(); ++it) {
Page &page = *it;
if (pages_to_update.count(page.page_no) != 0) {
if (page.page_no < complete_pages) {
ensurePageVisible(page, height);
} else if (page.page_no == complete_pages) {
ensurePageVisible(page, remainder);
}
pages_to_update.erase(page.page_no);
} else {
ensurePageNotVisible(page);
auto to_remove = it;
--it;
m_visible_pages.erase(to_remove);
}
}
for (auto it = pages_to_update.begin(); it != pages_to_update.end(); ++it) {
auto page_it = findIteratorForPage(*it);
m_visible_pages.push_back( { *it, 0, page_it } );
if (*it < complete_pages) {
ensurePageVisible(m_visible_pages.back(), height);
} else if (*it == complete_pages) {
ensurePageVisible(m_visible_pages.back(), remainder);
}
}
}
void Scrollback::ensurePageVisible(Page &page, int new_height)
{
if (page.size == new_height || !m_block_count)
return;
int line_no = page.page_no * m_screen_data->screen()->height();
auto it = page.it;
std::advance(it, page.size);
for (int i = page.size; i < new_height; ++it, i++) {
(*it)->setLine(line_no + i);
(*it)->dispatchEvents();
}
page.size = new_height;
}
void Scrollback::ensurePageNotVisible(Page &page)
{
auto it = page.it;
for (int i = 0; i < page.size; ++it, i++) {
(*it)->releaseTextObjects();
}
page.size = 0;
}
std::list<Block *>::iterator Scrollback::findIteratorForPage(int page_no)
{
uint line = page_no * m_screen_data->screen()->height();
Q_ASSERT(line < m_height);
for (auto it = m_visible_pages.begin(); it != m_visible_pages.end(); ++it) {
Page &page = *it;
int diff = page_no - page.page_no;
if (diff < 5 && diff > 5) {
auto to_return = page.it;
int advance = diff * m_screen_data->screen()->height();
std::advance(to_return, advance);
return to_return;
}
}
if (line > m_height / 2) {
auto to_return = m_blocks.end();
std::advance(to_return, line - m_height);
return to_return;
}
auto to_return = m_blocks.begin();
std::advance(to_return, line);
return to_return;
}
void Scrollback::adjustVisiblePages()
{
if (!m_adjust_visible_pages)
return;
for (auto it = m_visible_pages.begin(); it != m_visible_pages.end(); ++it) {
Page &page = *it;
const size_t line_for_page = page.page_no * m_screen_data->screen()->height();
if (line_for_page < m_adjust_visible_pages) {
auto to_remove = it;
--it;
m_visible_pages.erase(to_remove);
} else {
page.size = 0;
std::advance(page.it, m_adjust_visible_pages);
}
}
m_adjust_visible_pages = 0;
}
size_t Scrollback::height() const
{
return m_height;
}
void Scrollback::setWidth(int width)
{
m_width = width;
}
QString Scrollback::selection(const QPoint &start, const QPoint &end) const
{
Q_UNUSED(start);
Q_UNUSED(end);
return QString();
}

73
yat/backend/scrollback.h Normal file
View File

@@ -0,0 +1,73 @@
/******************************************************************************
* Copyright (c) 2013 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
******************************************************************************/
#ifndef SCROLLBACK_H
#define SCROLLBACK_H
#include <set>
#include <list>
#include <QtCore/qglobal.h>
#include <QtCore/QPoint>
class ScreenData;
class Block;
struct Page {
int page_no;
int size;
std::list<Block *>::iterator it;
};
class Scrollback
{
public:
Scrollback(size_t max_size, ScreenData *screen_data);
void addBlock(Block *block);
Block *reclaimBlock();
void ensureVisiblePages(int top_line);
size_t height() const;
void setWidth(int width);
size_t blockCount() { return m_block_count; }
QString selection(const QPoint &start, const QPoint &end) const;
private:
void ensurePageVisible(Page &page, int new_height);
void ensurePageNotVisible(Page &page);
std::list<Block *>::iterator findIteratorForPage(int page_no);
void adjustVisiblePages();
ScreenData *m_screen_data;
std::list<Block *> m_blocks;
std::list<Page> m_visible_pages;
size_t m_height;
size_t m_width;
size_t m_block_count;
size_t m_max_size;
size_t m_adjust_visible_pages;
};
#endif //SCROLLBACK_H

197
yat/backend/selection.cpp Normal file
View File

@@ -0,0 +1,197 @@
/*******************************************************************************
* Copyright (c) 2013 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#include "selection.h"
#include "screen.h"
#include "screen_data.h"
#include <QtGui/QGuiApplication>
Selection::Selection(Screen *screen)
: QObject(screen)
, m_screen(screen)
, m_new_start_x(0)
, m_start_x(0)
, m_new_start_y(0)
, m_start_y(0)
, m_new_end_x(0)
, m_end_x(0)
, m_new_end_y(0)
, m_end_y(0)
, m_new_enable(false)
{
connect(screen, &Screen::contentModified, this, &Selection::screenContentModified);
}
void Selection::setStartX(int x)
{
if (x != m_new_start_x) {
m_new_start_x = x;
setValidity();
m_screen->scheduleEventDispatch();
}
}
int Selection::startX() const
{
return m_start_x;
}
void Selection::setStartY(int y)
{
if (y != m_new_start_y) {
m_new_start_y = y;
setValidity();
m_screen->scheduleEventDispatch();
}
}
int Selection::startY() const
{
return m_start_y;
}
void Selection::setEndX(int x)
{
if (m_new_end_x != x) {
m_new_end_x = x;
setValidity();
m_screen->scheduleEventDispatch();
}
}
int Selection::endX() const
{
return m_end_x;
}
void Selection::setEndY(int y)
{
if (m_new_end_y != y) {
m_new_end_y = y;
setValidity();
m_screen->scheduleEventDispatch();
}
}
int Selection::endY() const
{
return m_end_y;
}
void Selection::setEnable(bool enable)
{
if (m_new_enable != enable) {
m_new_enable = enable;
m_screen->scheduleEventDispatch();
}
}
void Selection::screenContentModified(size_t lineModified, int lineDiff, int contentDiff)
{
if (!m_new_enable)
return;
if (lineModified >= size_t(m_new_start_y) && lineModified <= size_t(m_new_end_y)) {
setEnable(false);
return;
}
if (size_t(m_new_end_y) < lineModified && lineModified != contentDiff) {
m_new_end_y -= lineDiff - contentDiff;
m_new_start_y -= lineDiff - contentDiff;
if (m_new_end_y < 0) {
setEnable(false);
return;
}
if (m_new_start_y < 0) {
m_new_start_y = 0;
}
m_screen->scheduleEventDispatch();
}
}
void Selection::setValidity()
{
if (m_new_end_y > m_new_start_y ||
(m_new_end_y == m_new_start_y &&
m_new_end_x > m_new_start_x)) {
setEnable(true);
} else {
setEnable(false);
}
}
void Selection::sendToClipboard() const
{
m_screen->currentScreenData()->sendSelectionToClipboard(start_new_point(), end_new_point(), QClipboard::Clipboard);
}
void Selection::sendToSelection() const
{
m_screen->currentScreenData()->sendSelectionToClipboard(start_new_point(), end_new_point(), QClipboard::Selection);
}
void Selection::pasteFromSelection()
{
m_screen->pty()->write(QGuiApplication::clipboard()->text(QClipboard::Selection).toUtf8());
}
void Selection::pasteFromClipboard()
{
m_screen->pty()->write(QGuiApplication::clipboard()->text(QClipboard::Clipboard).toUtf8());
}
void Selection::dispatchChanges()
{
if (!m_new_enable && !m_enable)
return;
if (m_new_start_y != m_start_y) {
m_start_y = m_new_start_y;
emit startYChanged();
}
if (m_new_start_x != m_start_x) {
m_start_x = m_new_start_x;
emit startXChanged();
}
if (m_new_end_y != m_end_y) {
m_end_y = m_new_end_y;
emit endYChanged();
}
if (m_new_end_x != m_end_x) {
m_end_x = m_new_end_x;
emit endXChanged();
}
if (m_new_enable != m_enable) {
m_enable = m_new_enable;
emit enableChanged();
}
}
bool Selection::enable() const
{
return m_enable;
}

93
yat/backend/selection.h Normal file
View File

@@ -0,0 +1,93 @@
/*******************************************************************************
* Copyright (c) 2013 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#ifndef SELECTION_H
#define SELECTION_H
#include <QtCore/QObject>
#include <QtCore/QPoint>
class Screen;
class Selection : public QObject
{
Q_OBJECT
Q_PROPERTY(int startX READ startX WRITE setStartX NOTIFY startXChanged)
Q_PROPERTY(int startY READ startY WRITE setStartY NOTIFY startYChanged)
Q_PROPERTY(int endX READ endX WRITE setEndX NOTIFY endXChanged)
Q_PROPERTY(int endY READ endY WRITE setEndY NOTIFY endYChanged)
Q_PROPERTY(bool enable READ enable WRITE setEnable NOTIFY enableChanged)
public:
explicit Selection(Screen *screen);
void setStartX(int x);
int startX() const;
void setStartY(int y);
int startY() const;
void setEndX(int x);
int endX() const;
void setEndY(int y);
int endY() const;
void setEnable(bool enabled);
bool enable() const;
Q_INVOKABLE void sendToClipboard() const;
Q_INVOKABLE void sendToSelection() const;
Q_INVOKABLE void pasteFromSelection();
Q_INVOKABLE void pasteFromClipboard();
void dispatchChanges();
signals:
void startXChanged();
void startYChanged();
void endXChanged();
void endYChanged();
void enableChanged();
private slots:
void screenContentModified(size_t lineModified, int lineDiff, int contentDiff);
private:
void setValidity();
QPoint start_new_point() const { return QPoint(m_new_start_x, m_new_start_y); }
QPoint end_new_point() const { return QPoint(m_new_end_x, m_new_end_y); }
Screen *m_screen;
int m_new_start_x;
int m_start_x;
int m_new_start_y;
int m_start_y;
int m_new_end_x;
int m_end_x;
int m_new_end_y;
int m_end_y;
bool m_new_enable;
bool m_enable;
};
#endif

255
yat/backend/text.cpp Normal file
View File

@@ -0,0 +1,255 @@
/**************************************************************************************************
* Copyright (c) 2012 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
* OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
***************************************************************************************************/
#include "text.h"
#include "screen.h"
#include "block.h"
#include <QtQuick/QQuickItem>
#include <QtCore/QDebug>
Text::Text(Screen *screen)
: QObject(screen)
, m_screen(screen)
, m_text_line(0)
, m_start_index(0)
, m_old_start_index(0)
, m_end_index(0)
, m_line(0)
, m_old_line(0)
, m_width(1)
, m_style_dirty(true)
, m_text_dirty(true)
, m_visible(true)
, m_visible_old(true)
, m_latin(true)
, m_latin_old(true)
, m_forgroundColor(m_screen->defaultForgroundColor())
, m_backgroundColor(m_screen->defaultBackgroundColor())
{
connect(m_screen->colorPalette(), SIGNAL(changed()), this, SLOT(paletteChanged()));
connect(m_screen, SIGNAL(dispatchTextSegmentChanges()), this, SLOT(dispatchEvents()));
}
Text::~Text()
{
}
int Text::index() const
{
return m_start_index % m_width;
}
int Text::line() const
{
return m_line + (m_start_index / m_width);
}
void Text::setLine(int line, int width, const QString *textLine)
{
m_line = line;
m_width = width;
m_text_dirty = true;
m_text_line = textLine;
}
bool Text::visible() const
{
return m_visible;
}
void Text::setVisible(bool visible)
{
m_visible = visible;
}
QString Text::text() const
{
return m_text;
}
QColor Text::foregroundColor() const
{
return m_forgroundColor;
}
QColor Text::backgroundColor() const
{
return m_backgroundColor;
}
void Text::setStringSegment(int start_index, int end_index, bool text_changed)
{
m_start_index = start_index;
m_end_index = end_index;
m_text_dirty = text_changed;
}
void Text::setTextStyle(const TextStyle &style)
{
m_new_style = style;
m_style_dirty = true;
}
bool Text::bold() const
{
return m_style.style & TextStyle::Bold;
}
bool Text::blinking() const
{
return m_style.style & TextStyle::Blinking;
}
bool Text::underline() const
{
return m_style.style & TextStyle::Underlined;
}
void Text::setLatin(bool latin)
{
m_latin = latin;
}
bool Text::latin() const
{
return m_latin_old;
}
static bool differentStyle(TextStyle::Styles a, TextStyle::Styles b, TextStyle::Style style)
{
return (a & style) != (b & style);
}
void Text::dispatchEvents()
{
int old_line = m_old_line + (m_old_start_index / m_width);
int new_line = m_line + (m_start_index / m_width);
if (old_line != new_line) {
m_old_line = m_line;
emit lineChanged();
}
if (m_latin != m_latin_old) {
m_latin_old = m_latin;
emit latinChanged();
}
if (m_old_start_index != m_start_index
|| m_text_dirty) {
m_text_dirty = false;
QString old_text = m_text;
m_text = m_text_line->mid(m_start_index, m_end_index - m_start_index + 1);
if (m_old_start_index != m_start_index) {
m_old_start_index = m_start_index;
emit indexChanged();
}
emit textChanged();
}
if (m_style_dirty) {
m_style_dirty = false;
bool emit_forground = m_new_style.forground != m_style.forground;
bool emit_background = m_new_style.background != m_style.background;
TextStyle::Styles new_style = m_new_style.style;
TextStyle::Styles old_style = m_style.style;
bool emit_bold = false;
bool emit_blink = false;
bool emit_underline = false;
bool emit_inverse = false;
if (new_style != old_style) {
emit_bold = differentStyle(new_style, old_style, TextStyle::Bold);
emit_blink = differentStyle(new_style, old_style, TextStyle::Blinking);
emit_underline = differentStyle(new_style, old_style, TextStyle::Underlined);
emit_inverse = differentStyle(new_style, old_style, TextStyle::Inverse);
}
m_style = m_new_style;
if (emit_inverse) {
setForgroundColor();
setBackgroundColor();
} else {
if (emit_forground || emit_bold) {
setForgroundColor();
}
if (emit_background) {
setBackgroundColor();
}
}
if (emit_bold) {
emit boldChanged();
}
if (emit_blink) {
emit blinkingChanged();
}
if (emit_underline) {
emit underlineChanged();
}
}
if (m_visible_old != m_visible) {
m_visible_old = m_visible;
emit visibleChanged();
}
}
void Text::paletteChanged()
{
setBackgroundColor();
setForgroundColor();
}
void Text::setBackgroundColor()
{
QColor new_background;
if (m_style.style & TextStyle::Inverse) {
new_background = m_screen->colorPalette()->color(m_style.forground, false);
} else {
new_background = m_screen->colorPalette()->color(m_style.background, false);
}
if (new_background != m_backgroundColor) {
m_backgroundColor = new_background;
emit backgroundColorChanged();
}
}
void Text::setForgroundColor()
{
QColor new_forground;
if (m_style.style & TextStyle::Inverse) {
new_forground = m_screen->colorPalette()->color(m_style.background, false);
} else {
new_forground = m_screen->colorPalette()->color(m_style.forground, false);
}
if (new_forground != m_forgroundColor) {
m_forgroundColor = new_forground;
emit forgroundColorChanged();
}
}

121
yat/backend/text.h Normal file
View File

@@ -0,0 +1,121 @@
/**************************************************************************************************
* Copyright (c) 2012 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
* OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
***************************************************************************************************/
#ifndef TEXT_SEGMENT_H
#define TEXT_SEGMENT_H
#include <QtCore/QString>
#include <QtGui/QColor>
#include <QtCore/QObject>
#include <QtCore/QSize>
#include "text_style.h"
class Screen;
class QQuickItem;
class Text : public QObject
{
Q_OBJECT
Q_PROPERTY(int index READ index NOTIFY indexChanged)
Q_PROPERTY(int line READ line NOTIFY lineChanged)
Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged)
Q_PROPERTY(QString text READ text NOTIFY textChanged)
Q_PROPERTY(QColor foregroundColor READ foregroundColor NOTIFY forgroundColorChanged)
Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY backgroundColorChanged)
Q_PROPERTY(bool bold READ bold NOTIFY boldChanged)
Q_PROPERTY(bool blinking READ blinking NOTIFY blinkingChanged)
Q_PROPERTY(bool underline READ underline NOTIFY underlineChanged)
Q_PROPERTY(bool latin READ latin NOTIFY latinChanged)
public:
Text(Screen *screen);
~Text();
int index() const;
int line() const;
void setLine(int line, int width, const QString *textLine);
bool visible() const;
void setVisible(bool visible);
QString text() const;
QColor foregroundColor() const;
QColor backgroundColor() const;
void setStringSegment(int start_index, int end_index, bool textChanged);
void setTextStyle(const TextStyle &style);
bool bold() const;
bool blinking() const;
bool underline() const;
void setLatin(bool latin);
bool latin() const;
QObject *item() const;
public slots:
void dispatchEvents();
signals:
void indexChanged();
void lineChanged();
void visibleChanged();
void textChanged();
void forgroundColorChanged();
void backgroundColorChanged();
void boldChanged();
void blinkingChanged();
void underlineChanged();
void latinChanged();
private slots:
void paletteChanged();
private:
void setBackgroundColor();
void setForgroundColor();
Screen *m_screen;
QString m_text;
const QString *m_text_line;
int m_start_index;
int m_old_start_index;
int m_end_index;
int m_line;
int m_old_line;
int m_width;
TextStyle m_style;
TextStyle m_new_style;
bool m_style_dirty;
bool m_text_dirty;
bool m_visible;
bool m_visible_old;
bool m_latin;
bool m_latin_old;
QColor m_forgroundColor;
QColor m_backgroundColor;
};
#endif // TEXT_SEGMENT_H

View File

@@ -0,0 +1,36 @@
#include "text_style.h"
#include "screen.h"
#include "text.h"
#include <QtCore/QDebug>
TextStyle::TextStyle()
: style(Normal)
, forground(ColorPalette::DefaultForground)
, background(ColorPalette::DefaultBackground)
{
}
bool TextStyle::isCompatible(const TextStyle &other) const
{
return forground == other.forground
&& background == other.background
&& style == other.style;
}
QDebug operator<<(QDebug debug, TextStyleLine line)
{
debug << "[" << line.start_index << "(" << line.style << ":" << line.forground << ":" << line.background << ")" << line.end_index << "]";
return debug;
}
void TextStyleLine::releaseTextSegment(Screen *screen)
{
if (text_segment) {
text_segment->setVisible(false);
screen->releaseTextSegment(text_segment);
text_segment = 0;
}
}

85
yat/backend/text_style.h Normal file
View File

@@ -0,0 +1,85 @@
#ifndef TEXT_STYLE_H
#define TEXT_STYLE_H
#include <QtGui/QColor>
#include "color_palette.h"
class Screen;
class TextStyle
{
public:
enum Style {
Normal = 0x0000,
Italic = 0x0001,
Bold = 0x0002,
Underlined = 0x0004,
Blinking = 0x0008,
FastBlinking = 0x0010,
Gothic = 0x0020,
DoubleUnderlined = 0x0040,
Framed = 0x0080,
Overlined = 0x0100,
Encircled = 0x0200,
Inverse = 0x0400
};
Q_DECLARE_FLAGS(Styles, Style)
TextStyle();
Styles style;
ColorPalette::Color forground;
ColorPalette::Color background;
bool isCompatible(const TextStyle &other) const;
};
class Text;
class TextStyleLine : public TextStyle {
public:
TextStyleLine(const TextStyle &style, int start_index, int end_index)
: TextStyle(style)
, start_index(start_index)
, end_index(end_index)
, old_index(-1)
, text_segment(0)
, style_dirty(true)
, index_dirty(true)
, text_dirty(true)
{
}
TextStyleLine()
: start_index(0)
, end_index(0)
, old_index(-1)
, text_segment(0)
, style_dirty(false)
, index_dirty(false)
, text_dirty(false)
{
}
void releaseTextSegment(Screen *screen);
int start_index;
int end_index;
int old_index;
Text *text_segment;
bool style_dirty;
bool index_dirty;
bool text_dirty;
void setStyle(const TextStyle &style) {
forground = style.forground;
background = style.background;
this->style = style.style;
}
};
QDebug operator<<(QDebug debug, TextStyleLine line);
#endif // TEXT_STYLE_H

109
yat/backend/utf8_decoder.h Normal file
View File

@@ -0,0 +1,109 @@
/*******************************************************************************
* Copyright (c) 2013 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*******************************************************************************/
#ifndef UTF8_DECODER
#define UTF8_DECODER
#include "controll_chars.h"
class Utf8Decoder
{
public:
inline Utf8Decoder();
inline void addChar(uchar character);
inline bool isLatin() const;
inline bool isC1() const;
inline void clear();
private:
short m_expected_length;
short m_length;
uint32_t m_unicode;
};
Utf8Decoder::Utf8Decoder()
{
clear();
}
void Utf8Decoder::addChar(uchar character)
{
if (m_length && m_length == m_expected_length) {
clear();
}
if (character < 0x80)
return;
fprintf(stderr, "Character: 0x%x\n", character);
if (m_expected_length == 0) {
//this is naive. There must be a faster way.
if ((character & 0xfc) == 0xfc) {
m_expected_length = 5;
m_unicode = character & 0x01;
} else if ((character & 0xf8) == 0xf8) {
m_expected_length = 4;
m_unicode = character & 0x03;
} else if ((character & 0xf0) == 0xf0) {
m_expected_length = 3;
m_unicode = character & 0x07;
} else if ((character & 0xe0) == 0xe0) {
m_expected_length = 2;
m_unicode = character & 0x0f;
} else if ((character & 0xc0) == 0xc0) {
m_expected_length = 1;
m_unicode = character & 0x1f;
} else {
m_expected_length = 0;
m_unicode = 0;
qWarning("Utf8Decoder: invalid decoder character");
}
} else {
fprintf(stderr, "Before 0x%x adding 0x%x pure 0x%x\n", m_unicode,(character & 0x3f), character);
m_unicode = (m_unicode << 6) | (character & 0x3f);
fprintf(stderr, "After 0x%x\n", m_unicode);
m_length++;
}
}
bool Utf8Decoder::isLatin() const
{
return m_expected_length < 2 && m_unicode < 0xff;
}
bool Utf8Decoder::isC1() const
{
return m_expected_length == 2 && m_length == m_expected_length &&
(m_unicode >= C1_8bit::C1_8bit_Start && m_unicode <= C1_8bit::C1_8bit_Stop);
}
void Utf8Decoder::clear()
{
m_expected_length = 0;
m_length = 0;
m_unicode = 0;
}
#endif

139
yat/backend/yat_pty.cpp Normal file
View File

@@ -0,0 +1,139 @@
/**************************************************************************************************
* Copyright (c) 2012 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
* OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
***************************************************************************************************/
#include "yat_pty.h"
#include <fcntl.h>
#include <poll.h>
#ifdef LINUX
#include <sys/epoll.h>
#endif
#include <sys/ioctl.h>
#ifdef Q_OS_MAC
#include <util.h>
#else
#include <pty.h>
#endif
#include <utmp.h>
#include <QtCore/QSize>
#include <QtCore/QString>
#include <QtCore/QThread>
#include <QtCore/QSocketNotifier>
#include <QtCore/QDebug>
static char env_variables[][255] = {
"TERM=xterm-color",
"COLORTERM=xterm",
"COLORFGBG=15;0",
"LINES",
"COLUMNS",
"TERMCAP"
};
static int env_variables_size = sizeof(env_variables) / sizeof(env_variables[0]);
YatPty::YatPty()
: m_winsize(0)
{
m_terminal_pid = forkpty(&m_master_fd,
NULL,
NULL,
NULL);
if (m_terminal_pid == 0) {
for (int i = 0; i < env_variables_size; i++) {
::putenv(env_variables[i]);
}
::execl("/bin/bash", "/bin/bash", "--login", (const char *) 0);
exit(0);
}
QSocketNotifier *reader = new QSocketNotifier(m_master_fd,QSocketNotifier::Read,this);
connect(reader, &QSocketNotifier::activated, this, &YatPty::readData);
}
YatPty::~YatPty()
{
}
void YatPty::write(const QByteArray &data)
{
if (::write(m_master_fd, data.constData(), data.size()) < 0) {
qDebug() << "Something whent wrong when writing to m_master_fd";
}
}
void YatPty::setWidth(int width, int pixelWidth)
{
if (!m_winsize) {
m_winsize = new struct winsize;
m_winsize->ws_row = 25;
m_winsize->ws_ypixel = 0;
}
m_winsize->ws_col = width;
m_winsize->ws_xpixel = pixelWidth;
ioctl(m_master_fd, TIOCSWINSZ, m_winsize);
}
void YatPty::setHeight(int height, int pixelHeight)
{
if (!m_winsize) {
m_winsize = new struct winsize;
m_winsize->ws_col = 80;
m_winsize->ws_xpixel = 0;
}
m_winsize->ws_row = height;
m_winsize->ws_ypixel = pixelHeight;
ioctl(m_master_fd, TIOCSWINSZ, m_winsize);
}
QSize YatPty::size() const
{
if (!m_winsize) {
YatPty *that = const_cast<YatPty *>(this);
that->m_winsize = new struct winsize;
ioctl(m_master_fd, TIOCGWINSZ, m_winsize);
}
return QSize(m_winsize->ws_col, m_winsize->ws_row);
}
int YatPty::masterDevice() const
{
return m_master_fd;
}
void YatPty::readData()
{
int size_of_buffer = sizeof m_data_buffer / sizeof *m_data_buffer;
ssize_t read_size = ::read(m_master_fd,m_data_buffer,size_of_buffer);
if (read_size > 0) {
QByteArray to_return = QByteArray::fromRawData(m_data_buffer,read_size);
emit readyRead(to_return);
} else if (read_size < 0) {
emit hangupReceived();
} else {
emit hangupReceived();
}
}

59
yat/backend/yat_pty.h Normal file
View File

@@ -0,0 +1,59 @@
/**************************************************************************************************
* Copyright (c) 2012 Jørgen Lind
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
* associated documentation files (the "Software"), to deal in the Software without restriction,
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
* OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
***************************************************************************************************/
#ifndef YAT_PTY_H
#define YAT_PTY_H
#include <unistd.h>
#include <QtCore/QObject>
#include <QtCore/QLinkedList>
#include <QtCore/QMutex>
class YatPty : public QObject
{
Q_OBJECT
public:
YatPty();
~YatPty();
void write(const QByteArray &data);
void setWidth(int width, int pixelWidth = 0);
void setHeight(int height, int pixelHeight = 0);
QSize size() const;
int masterDevice() const;
signals:
void hangupReceived();
void readyRead(const QByteArray &data);
private:
void readData();
pid_t m_terminal_pid;
int m_master_fd;
char m_slave_file_name[PATH_MAX];
struct winsize *m_winsize;
char m_data_buffer[1024];
};
#endif //YAT_PTY_H