1
0
mirror of https://github.com/Swordfish90/cool-retro-term.git synced 2025-01-18 12:15:27 +00:00

Switched to my version of yat

This commit is contained in:
Filippo Scognamiglio 2013-11-23 13:59:05 +01:00
parent c8cb00d240
commit 735d1e5dbb
45 changed files with 11110 additions and 0 deletions

10
yat/.gitignore vendored Normal file
View File

@ -0,0 +1,10 @@
Makefile
.moc
.obj
yat
yat.pro.user
yat.pro.user.1.3
yat.pro.user.2.6pre1
yat_declarative/qrc_qml_sources.cpp

6
yat/README Normal file
View File

@ -0,0 +1,6 @@
YAT is a terminal emulator written in qml and c++
The main goal of the project was to find out if it was possible to use qml to
write a terminal emulator which performed on par with xterm and konsole.
Turns out, it's possible.

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

@ -0,0 +1,31 @@
DEPENDPATH += $$PWD
INCLUDEPATH += $$PWD
LIBS += -lutil -L/home/jlind/install/lib
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/line.h \
$$PWD/color_palette.h \
$$PWD/text_style.h \
$$PWD/update_action.h \
$$PWD/screen_data.h
SOURCES += \
$$PWD/yat_pty.cpp \
$$PWD/text.cpp \
$$PWD/controll_chars.cpp \
$$PWD/parser.cpp \
$$PWD/screen.cpp \
$$PWD/line.cpp \
$$PWD/color_palette.cpp \
$$PWD/text_style.cpp \
$$PWD/update_action.cpp \
$$PWD/screen_data.cpp

View File

@ -0,0 +1,49 @@
#include "color_palette.h"
ColorPalette::ColorPalette()
: m_normalColors(numberOfColors)
, m_lightColors(numberOfColors)
, m_intenseColors(numberOfColors)
{
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].setAlpha(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 (bold)
return m_lightColors.at(color);
return m_normalColors.at(color);
}
QColor ColorPalette::normalColor(ColorPalette::Color color) const
{
return m_normalColors.at(color);
}
QColor ColorPalette::lightColor(ColorPalette::Color color) const
{
return m_lightColors.at(color);
}

View File

@ -0,0 +1,38 @@
#ifndef COLOR_PALETTE_H
#define COLOR_PALETTE_H
#include <QtCore/QVector>
#include <QtGui/QColor>
class ColorPalette
{
public:
ColorPalette();
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;
private:
QVector<QColor> m_normalColors;
QVector<QColor> m_lightColors;
QVector<QColor> m_intenseColors;
};
#endif // COLOR_PALETTE_H

View File

@ -0,0 +1,776 @@
/*******************************************************************************
* 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 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 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 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 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,289 @@
/**************************************************************************************************
* 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 = 0x80,
NOT_DEFINED = C1_7bit_Start,
NOT_DEFINED1 = 0x81,
BPH = 0x42,
NBH = 0x43,
NOT_DEFINED2 = 0x82,
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 = 0x99,
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,
Reserved2 = 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

437
yat/backend/line.cpp Normal file
View File

@ -0,0 +1,437 @@
/**************************************************************************************************
* 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 "line.h"
#include "text.h"
#include "screen.h"
#include <QtQuick/QQuickView>
#include <QtQuick/QQuickItem>
#include <QtCore/QDebug>
#include <algorithm>
QDebug operator<<(QDebug debug, TextStyleLine line)
{
debug << "TextStyleLine: [" << line.start_index << ":" << line.end_index << "] : style:" << line.style;
return debug;
}
Line::Line(Screen *screen)
: QObject(screen)
, m_screen(screen)
, m_index(0)
, m_old_index(-1)
, m_visible(true)
, m_changed(true)
{
m_text_line.resize(screen->width());
m_style_list.reserve(25);
clear();
}
Line::~Line()
{
releaseTextObjects();
}
Screen *Line::screen() const
{
return m_screen;
}
void Line::releaseTextObjects()
{
m_changed = true;
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(false);
delete m_style_list.at(i).text_segment;
m_style_list[i].text_segment = 0;
}
}
}
void Line::clear()
{
m_text_line.fill(QChar(' '));
for (int i = 0; i < m_style_list.size(); i++) {
if (m_style_list.at(i).text_segment)
releaseTextSegment(m_style_list.at(i).text_segment);
}
m_style_list.clear();
m_style_list.append(TextStyleLine(m_screen->defaultTextStyle(),0,m_text_line.size() -1));
m_changed = true;
}
void Line::clearToEndOfLine(int index)
{
m_changed = true;
QString empty(m_text_line.size() - index, QChar(' '));
m_text_line.replace(index, m_text_line.size()-index,empty);
bool found = false;
for (int i = 0; i < m_style_list.size(); i++) {
const TextStyleLine current_style = m_style_list.at(i);
if (found) {
if (current_style.text_segment)
releaseTextSegment(current_style.text_segment);
m_style_list.remove(i);
i--;
} else {
if (index <= current_style.end_index) {
found = true;
if (current_style.start_index == index) {
if (current_style.text_segment)
releaseTextSegment(current_style.text_segment);
m_style_list.remove(i);
i--;
} else {
m_style_list[i].end_index = index - 1;
m_style_list[i].text_dirty = true;
}
}
}
}
if (m_style_list.size() && m_style_list.last().isCompatible(m_screen->defaultTextStyle())) {
m_style_list.last().end_index = m_text_line.size() -1;
} else {
m_style_list.append(TextStyleLine(m_screen->defaultTextStyle(),index, m_text_line.size() -1));
}
}
void Line::clearCharacters(int from, int to)
{
QString empty(to-from, QChar(' '));
const TextStyle &defaultTextStyle = m_screen->defaultTextStyle();
replaceAtPos(from, empty, defaultTextStyle);
}
void Line::deleteCharacters(int from, int to)
{
m_changed = true;
int removed = 0;
const int size = (to + 1) - from;
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 -= 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;
if (current_style.text_segment)
releaseTextSegment(current_style.text_segment);
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) {
if (current_style.text_segment)
releaseTextSegment(current_style.text_segment);
m_style_list.remove(i);
i--;
}
}
}
}
TextStyle defaultStyle = m_screen->defaultTextStyle();
if (m_style_list.last().isCompatible(defaultStyle)) {
m_style_list.last().end_index += size;
m_style_list.last().text_dirty = true;
} else {
m_style_list.append(TextStyleLine(defaultStyle, m_style_list.last().end_index + 1,
m_style_list.last().end_index + size));
}
m_text_line.remove(from, size);
QString empty(size,' ');
m_text_line.append(empty);
}
void Line::setWidth(int width)
{
bool emit_changed = m_text_line.size() != width;
if (m_text_line.size() > width) {
m_text_line.chop(m_text_line.size() - width);
} else if (m_text_line.size() < width) {
m_text_line.append(QString(width - m_text_line.size(), QChar(' ')));
}
if (emit_changed)
emit widthChanged();
}
int Line::width() const
{
return m_style_list.size();
}
void Line::replaceAtPos(int pos, const QString &text, const TextStyle &style)
{
Q_ASSERT(pos + text.size() <= m_text_line.size());
m_changed = true;
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()) {
if (current_style.text_segment)
releaseTextSegment(current_style.text_segment);
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);
} 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()) {
current_style.end_index = pos - 1;
current_style.text_dirty = true;
m_style_list.insert(i+1, TextStyleLine(style,pos, pos+text.size()));
} 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) {
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;
} 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 Line::insertAtPos(int pos, const QString &text, const TextStyle &style)
{
m_changed = true;
m_text_line.insert(pos,text);
m_text_line.chop(text.size());
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()) {
releaseTextSegment(current_style.text_segment);
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++;
}
}
}
}
}
int Line::index() const
{
return m_index;
}
void Line::setIndex(int index)
{
m_index = index;
}
QString *Line::textLine()
{
return &m_text_line;
}
void Line::setVisible(bool visible)
{
if (visible != m_visible) {
m_visible = visible;
emit visibleChanged();
}
}
bool Line::visible() const
{
return m_visible;
}
void Line::dispatchEvents()
{
if (m_index != m_old_index) {
m_old_index = m_index;
emit indexChanged();
}
if (!m_changed) {
return;
}
for (int i = 0; i < m_style_list.size(); i++) {
TextStyleLine &current_style = m_style_list[i];
if (current_style.text_segment == 0) {
current_style.text_segment = createTextSegment(current_style);
}
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;
}
m_style_list.at(i).text_segment->dispatchEvents();
}
m_changed = false;
for (int i = 0; i< m_to_delete.size(); i++) {
delete m_to_delete[i];
}
m_to_delete.clear();
}
QVector<TextStyleLine> Line::style_list()
{
return m_style_list;
}
Text *Line::createTextSegment(const TextStyleLine &style_line)
{
Text *to_return;
if (m_to_delete.size()) {
to_return = m_to_delete.takeLast();
} else {
to_return = new Text(screen());
to_return->setLine(this);
emit textCreated(to_return);
}
to_return->setVisible(true);
return to_return;
}
void Line::releaseTextSegment(Text *text)
{
text->setVisible(false);
m_to_delete.append(text);
}
void Line::printStyleList() const
{
for (int i= 0; i < m_style_list.size(); i++) {
qDebug() << "i" << m_style_list.at(i);
}
}

137
yat/backend/line.h Normal file
View File

@ -0,0 +1,137 @@
/**************************************************************************************************
* 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_LINE_H
#define TEXT_SEGMENT_LINE_H
#include <QtCore/QObject>
#include "text.h"
class Screen;
class QQuickItem;
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)
{
}
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);
class Line : public QObject
{
Q_OBJECT
Q_PROPERTY(int index READ index NOTIFY indexChanged)
Q_PROPERTY(Screen *screen READ screen CONSTANT)
Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibleChanged)
Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged)
public:
Line(Screen *screen);
~Line();
Q_INVOKABLE Screen *screen() const;
void releaseTextObjects();
void clear();
void clearToEndOfLine(int index);
void clearCharacters(int from, int to);
void deleteCharacters(int from, int to);
void setWidth(int width);
int width() const;
void replaceAtPos(int i, const QString &text, const TextStyle &style);
void insertAtPos(int i, const QString &text, const TextStyle &style);
int index() const;
void setIndex(int index);
QString *textLine();
void setVisible(bool visible);
bool visible() const;
void dispatchEvents();
QVector<TextStyleLine> style_list();
void printStyleList() const;
signals:
void indexChanged();
void visibleChanged();
void widthChanged();
void textCreated(Text *text);
private:
Text *createTextSegment(const TextStyleLine &style_line);
void releaseTextSegment(Text *text);
Screen *m_screen;
QString m_text_line;
QVector<TextStyleLine> m_style_list;
int m_index;
int m_old_index;
bool m_visible;
QVector<Text *> m_to_delete;
bool m_changed;
bool m_delete_handle;
};
#endif // TEXT_SEGMENT_LINE_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();
}

793
yat/backend/parser.cpp Normal file
View File

@ -0,0 +1,793 @@
/**************************************************************************************************
* 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 "parser.h"
#include "controll_chars.h"
#include "screen.h"
#include <QtCore/QDebug>
static bool yat_parser_debug = qEnvironmentVariableIsSet("YAT_PARSER_DEBUG");
Parser::Parser(Screen *screen)
: m_decode_state(PlainText)
, m_current_token_start(0)
, m_currrent_position(0)
, m_intermediate_char(QChar())
, m_parameters(10)
, m_screen(screen)
{
}
void Parser::addData(const QByteArray &data)
{
m_current_token_start = 0;
m_current_data = data;
for (m_currrent_position = 0; m_currrent_position < data.size(); m_currrent_position++) {
uchar character = data.at(m_currrent_position);
switch (m_decode_state) {
case PlainText:
//UTF-8
if (character > 127)
continue;
if (character < C0::C0_END ||
(character >= C1_8bit::C1_8bit_Start &&
character <= C1_8bit::C1_8bit_Stop)) {
if (m_currrent_position != m_current_token_start) {
m_screen->replaceAtCursor(QString::fromUtf8(data.mid(m_current_token_start,
m_currrent_position - m_current_token_start)));
tokenFinished();
m_current_token_start--;
}
m_decode_state = DecodeC0;
decodeC0(data.at(m_currrent_position));
}
break;
case DecodeC0:
decodeC0(character);
break;
case DecodeC1_7bit:
decodeC1_7bit(character);
break;
case DecodeCSI:
decodeCSI(character);
break;
case DecodeOSC:
decodeOSC(character);
break;
case DecodeOtherEscape:
decodeOtherEscape(character);
break;
}
}
if (m_decode_state == PlainText) {
QByteArray text = data.mid(m_current_token_start);
if (text.size()) {
m_screen->replaceAtCursor(QString::fromUtf8(text));
tokenFinished();
}
}
m_current_data = QByteArray();
}
void Parser::decodeC0(uchar character)
{
if (yat_parser_debug)
qDebug() << C0::C0(character);
switch (character) {
case C0::NUL:
case C0::SOH:
case C0::STX:
case C0::ETX:
case C0::EOT:
case C0::ENQ:
case C0::ACK:
qDebug() << "Unhandled" << C0::C0(character);
tokenFinished();
break;
case C0::BEL:
m_screen->scheduleFlash();
tokenFinished();
break;
case C0::BS:
m_screen->backspace();
tokenFinished();
break;
case C0::HT: {
int x = m_screen->cursorPosition().x();
int spaces = 8 - (x % 8);
m_screen->replaceAtCursor(QString(spaces,' '));
}
tokenFinished();
break;
case C0::LF:
m_screen->lineFeed();
tokenFinished();
break;
case C0::VT:
case C0::FF:
qDebug() << "Unhandled" << C0::C0(character);
tokenFinished();
break;
case C0::CR:
m_screen->moveCursorHome();
tokenFinished();
//next should be a linefeed;
break;
case C0::SOorLS1:
case C0::SIorLS0:
case C0::DLE:
case C0::DC1:
case C0::DC2:
case C0::DC3:
case C0::DC4:
case C0::NAK:
case C0::SYN:
case C0::ETB:
case C0::CAN:
case C0::EM:
case C0::SUB:
qDebug() << "Unhandled" << C0::C0(character);
tokenFinished();
break;
case C0::ESC:
m_decode_state = DecodeC1_7bit;
break;
case C0::IS4:
case C0::IS3:
case C0::IS2:
case C0::IS1:
default:
qDebug() << "Unhandled" << C0::C0(character);
tokenFinished();
break;
}
}
void Parser::decodeC1_7bit(uchar character)
{
if (yat_parser_debug)
qDebug() << C1_7bit::C1_7bit(character);
switch(character) {
case C1_7bit::CSI:
m_decode_state = DecodeCSI;
break;
case C1_7bit::OSC:
m_decode_state = DecodeOSC;
break;
case C1_7bit::RI:
m_screen->reverseLineFeed();
tokenFinished();
break;
case '%':
case '#':
case '(':
m_parameters.append(-character);
m_decode_state = DecodeOtherEscape;
break;
case '=':
qDebug() << "Application keypad";
tokenFinished();
break;
case '>':
qDebug() << "Normal keypad mode";
tokenFinished();
break;
default:
qDebug() << "Unhandled" << C1_7bit::C1_7bit(character);
tokenFinished();
}
}
void Parser::decodeParameters(uchar character)
{
switch (character) {
case 0x30:
case 0x31:
case 0x32:
case 0x33:
case 0x34:
case 0x35:
case 0x36:
case 0x37:
case 0x38:
case 0x39:
m_parameter_string.append(character);
break;
case 0x3a:
qDebug() << "Encountered special delimiter in parameterbyte";
break;
case 0x3b:
appendParameter();
break;
case 0x3c:
case 0x3d:
case 0x3e:
case 0x3f:
appendParameter();
m_parameters.append(-character);
break;
default:
//this is undefined for now
qDebug() << "Encountered undefined parameter byte";
break;
}
}
void Parser::decodeCSI(uchar character)
{
if (character >= 0x30 && character <= 0x3f) {
decodeParameters(character);
} else {
if (character >= 0x20 && character <= 0x2f) {
if (m_intermediate_char.unicode())
qDebug() << "Warning!: double intermediate bytes found in CSI";
m_intermediate_char = character;
} else if (character >= 0x40 && character <= 0x7d) {
if (m_intermediate_char.unicode()) {
if (yat_parser_debug)
qDebug() << FinalBytesSingleIntermediate::FinalBytesSingleIntermediate(character);
switch (character) {
case FinalBytesSingleIntermediate::SL:
case FinalBytesSingleIntermediate::SR:
case FinalBytesSingleIntermediate::GSM:
case FinalBytesSingleIntermediate::GSS:
case FinalBytesSingleIntermediate::FNT:
case FinalBytesSingleIntermediate::TSS:
case FinalBytesSingleIntermediate::JFY:
case FinalBytesSingleIntermediate::SPI:
case FinalBytesSingleIntermediate::QUAD:
case FinalBytesSingleIntermediate::SSU:
case FinalBytesSingleIntermediate::PFS:
case FinalBytesSingleIntermediate::SHS:
case FinalBytesSingleIntermediate::SVS:
case FinalBytesSingleIntermediate::IGS:
case FinalBytesSingleIntermediate::IDCS:
case FinalBytesSingleIntermediate::PPA:
case FinalBytesSingleIntermediate::PPR:
case FinalBytesSingleIntermediate::PPB:
case FinalBytesSingleIntermediate::SPD:
case FinalBytesSingleIntermediate::DTA:
case FinalBytesSingleIntermediate::SHL:
case FinalBytesSingleIntermediate::SLL:
case FinalBytesSingleIntermediate::FNK:
case FinalBytesSingleIntermediate::SPQR:
case FinalBytesSingleIntermediate::SEF:
case FinalBytesSingleIntermediate::PEC:
case FinalBytesSingleIntermediate::SSW:
case FinalBytesSingleIntermediate::SACS:
case FinalBytesSingleIntermediate::SAPV:
case FinalBytesSingleIntermediate::STAB:
case FinalBytesSingleIntermediate::GCC:
case FinalBytesSingleIntermediate::TATE:
case FinalBytesSingleIntermediate::TALE:
case FinalBytesSingleIntermediate::TAC:
case FinalBytesSingleIntermediate::TCC:
case FinalBytesSingleIntermediate::TSR:
case FinalBytesSingleIntermediate::SCO:
case FinalBytesSingleIntermediate::SRCS:
case FinalBytesSingleIntermediate::SCS:
case FinalBytesSingleIntermediate::SLS:
case FinalBytesSingleIntermediate::SCP:
default:
qDebug() << "unhandled CSI" << FinalBytesSingleIntermediate::FinalBytesSingleIntermediate(character);
tokenFinished();
break;
}
} else {
if (yat_parser_debug)
qDebug() << FinalBytesNoIntermediate::FinalBytesNoIntermediate(character);
switch (character) {
case FinalBytesNoIntermediate::ICH: {
appendParameter();
int n_chars = m_parameters.size() ? m_parameters.at(0) : 1;
qDebug() << "ICH WITH n_chars" << n_chars;
m_screen->insertEmptyCharsAtCursor(n_chars);
tokenFinished();
}
break;
case FinalBytesNoIntermediate::CUU: {
appendParameter();
Q_ASSERT(m_parameters.size() < 2);
int move_up = m_parameters.size() ? m_parameters.at(0) : 1;
m_screen->moveCursorUp(move_up);
tokenFinished();
}
break;
case FinalBytesNoIntermediate::CUD:
tokenFinished();
qDebug() << "unhandled CSI" << FinalBytesNoIntermediate::FinalBytesNoIntermediate(character);
break;
case FinalBytesNoIntermediate::CUF:{
appendParameter();
Q_ASSERT(m_parameters.size() < 2);
int move_right = m_parameters.size() ? m_parameters.at(0) : 1;
m_screen->moveCursorRight(move_right);
tokenFinished();
}
break;
case FinalBytesNoIntermediate::CUB:
case FinalBytesNoIntermediate::CNL:
case FinalBytesNoIntermediate::CPL:
qDebug() << "unhandled CSI" << FinalBytesNoIntermediate::FinalBytesNoIntermediate(character);
tokenFinished();
break;
case FinalBytesNoIntermediate::CHA: {
appendParameter();
Q_ASSERT(m_parameters.size() < 2);
int move_to_pos_on_line = m_parameters.size() ? m_parameters.at(0) : 1;
m_screen->moveCursorToCharacter(move_to_pos_on_line);
}
tokenFinished();
break;
case FinalBytesNoIntermediate::CUP:
appendParameter();
if (!m_parameters.size()) {
m_screen->moveCursorTop();
m_screen->moveCursorHome();
} else if (m_parameters.size() == 2){
m_screen->moveCursor(m_parameters.at(1), m_parameters.at(0));
} else {
qDebug() << "OHOHOHOH";
}
tokenFinished();
break;
case FinalBytesNoIntermediate::CHT:
tokenFinished();
qDebug() << "unhandled CSI" << FinalBytesNoIntermediate::FinalBytesNoIntermediate(character);
break;
case FinalBytesNoIntermediate::ED:
appendParameter();
if (!m_parameters.size()) {
m_screen->eraseFromCurrentLineToEndOfScreen();
} else {
switch (m_parameters.at(0)) {
case 1:
m_screen->eraseFromCurrentLineToBeginningOfScreen();
break;
case 2:
m_screen->eraseScreen();
break;
default:
qDebug() << "Invalid parameter value for FinalBytesNoIntermediate::ED";
}
}
tokenFinished();
break;
case FinalBytesNoIntermediate::EL:
appendParameter();
if (!m_parameters.size() || m_parameters.at(0) == 0) {
m_screen->eraseFromCursorPositionToEndOfLine();
} else if (m_parameters.at(0) == 1) {
m_screen->eraseToCursorPosition();
} else if (m_parameters.at(0) == 2) {
m_screen->eraseLine();
} else{
qDebug() << "Fault when processing FinalBytesNoIntermediate::EL";
}
tokenFinished();
break;
case FinalBytesNoIntermediate::IL: {
appendParameter();
int count = 1;
if (m_parameters.size()) {
count = m_parameters.at(0);
}
m_screen->insertLines(count);
tokenFinished();
}
break;
case FinalBytesNoIntermediate::DL: {
appendParameter();
int count = 1;
if (m_parameters.size()) {
count = m_parameters.at(0);
}
m_screen->deleteLines(count);
tokenFinished();
}
break;
case FinalBytesNoIntermediate::EF:
case FinalBytesNoIntermediate::EA:
qDebug() << "unhandled CSI" << FinalBytesNoIntermediate::FinalBytesNoIntermediate(character);
tokenFinished();
break;
case FinalBytesNoIntermediate::DCH:{
appendParameter();
Q_ASSERT(m_parameters.size() < 2);
int n_chars = m_parameters.size() ? m_parameters.at(0) : 1;
m_screen->deleteCharacters(n_chars);
}
tokenFinished();
break;
case FinalBytesNoIntermediate::SSE:
case FinalBytesNoIntermediate::CPR:
case FinalBytesNoIntermediate::SU:
case FinalBytesNoIntermediate::SD:
case FinalBytesNoIntermediate::NP:
case FinalBytesNoIntermediate::PP:
case FinalBytesNoIntermediate::CTC:
case FinalBytesNoIntermediate::ECH:
case FinalBytesNoIntermediate::CVT:
case FinalBytesNoIntermediate::CBT:
case FinalBytesNoIntermediate::SRS:
case FinalBytesNoIntermediate::PTX:
case FinalBytesNoIntermediate::SDS:
case FinalBytesNoIntermediate::SIMD:
case FinalBytesNoIntermediate::HPA:
case FinalBytesNoIntermediate::HPR:
case FinalBytesNoIntermediate::REP:
qDebug() << "unhandled CSI" << FinalBytesNoIntermediate::FinalBytesNoIntermediate(character);
tokenFinished();
break;
case FinalBytesNoIntermediate::DA:
appendParameter();
if (m_parameters.size()) {
switch (m_parameters.at(0)) {
case -'>':
m_screen->sendSecondaryDA();
break;
case -'?':
qDebug() << "WHAT!!!";
break; //ignore
case 0:
default:
m_screen->sendPrimaryDA();
}
} else {
m_screen->sendPrimaryDA();
}
tokenFinished();
break;
case FinalBytesNoIntermediate::VPA: {
appendParameter();
Q_ASSERT(m_parameters.size() < 2);
int move_to_line = m_parameters.size() ? m_parameters.at(0) : 1;
m_screen->moveCursorToLine(move_to_line);
}
tokenFinished();
break;
case FinalBytesNoIntermediate::VPR:
case FinalBytesNoIntermediate::HVP:
case FinalBytesNoIntermediate::TBC:
qDebug() << "unhandled CSI" << FinalBytesNoIntermediate::FinalBytesNoIntermediate(character);
tokenFinished();
break;
case FinalBytesNoIntermediate::SM:
appendParameter();
if (m_parameters.size() && m_parameters.at(0) == -'?') {
if (m_parameters.size() > 1) {
switch (m_parameters.at(1)) {
case 1:
m_screen->setApplicationCursorKeysMode(true);
break;
case 4:
qDebug() << "Insertion mode";
break;
case 7:
qDebug() << "MODE 7";
break;
case 12:
m_screen->setCursorBlinking(true);
break;
case 25:
m_screen->setCursorVisible(true);
break;
case 1034:
//I don't know what this sequence is
break;
case 1049:
m_screen->saveCursor();
m_screen->saveScreenData();
break;
default:
qDebug() << "unhandled CSI FinalBytesNoIntermediate::SM ? with parameter:" << m_parameters.at(1);
}
} else {
qDebug() << "unhandled CSI FinalBytesNoIntermediate::SM ?";
}
} else {
qDebug() << "unhandled CSI FinalBytesNoIntermediate::SM";
}
tokenFinished();
break;
case FinalBytesNoIntermediate::MC:
case FinalBytesNoIntermediate::HPB:
case FinalBytesNoIntermediate::VPB:
qDebug() << "unhandled CSI" << FinalBytesNoIntermediate::FinalBytesNoIntermediate(character);
tokenFinished();
break;
case FinalBytesNoIntermediate::RM:
appendParameter();
if (m_parameters.size()) {
switch(m_parameters.at(0)) {
case -'?':
if (m_parameters.size() > 1) {
switch(m_parameters.at(1)) {
case 1:
qDebug() << "Normal cursor keys";
break;
case 12:
m_screen->setCursorBlinking(false);
break;
case 25:
m_screen->setCursorVisible(false);
break;
case 1049:
m_screen->restoreCursor();
m_screen->restoreScreenData();
break;
default:
qDebug() << "unhandled CSI FinalBytesNoIntermediate::RM? with "
"parameter " << m_parameters.at(1);
}
} else {
qDebug() << "unhandled CSI FinalBytesNoIntermediate::RM";
}
break;
case 4:
m_screen->setInsertMode(Screen::Replace);
default:
qDebug() << "unhandled CSI FinalBytesNoIntermediate::RM";
break;
}
}
tokenFinished();
break;
case FinalBytesNoIntermediate::SGR: {
appendParameter();
if (!m_parameters.size())
m_parameters << 0;
for (int i = 0; i < m_parameters.size();i++) {
switch(m_parameters.at(i)) {
case 0:
// m_screen->setTextStyle(TextStyle::Normal);
m_screen->resetStyle();
break;
case 1:
m_screen->setTextStyle(TextStyle::Bold);
break;
case 5:
m_screen->setTextStyle(TextStyle::Blinking);
break;
case 7:
m_screen->setTextStyle(TextStyle::Inverse);
break;
case 8:
qDebug() << "SGR: Hidden text not supported";
break;
case 22:
m_screen->setTextStyle(TextStyle::Normal);
break;
case 24:
m_screen->setTextStyle(TextStyle::Underlined, false);
break;
case 25:
m_screen->setTextStyle(TextStyle::Blinking, false);
break;
case 27:
m_screen->setTextStyle(TextStyle::Inverse, false);
break;
case 28:
qDebug() << "SGR: Visible text is allways on";
break;
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
// case 38:
case 39:
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
// case 38:
case 49:
m_screen->setTextStyleColor(m_parameters.at(i));
break;
default:
qDebug() << "Unknown SGR" << m_parameters.at(i);
}
}
tokenFinished();
}
break;
case FinalBytesNoIntermediate::DSR:
qDebug() << "report";
case FinalBytesNoIntermediate::DAQ:
case FinalBytesNoIntermediate::Reserved0:
case FinalBytesNoIntermediate::Reserved1:
qDebug() << "Unhandeled CSI" << FinalBytesNoIntermediate::FinalBytesNoIntermediate(character);
tokenFinished();
break;
case FinalBytesNoIntermediate::Reserved2:
appendParameter();
if (m_parameters.size() == 2) {
if (m_parameters.at(0) >= 0) {
m_screen->setScrollArea(m_parameters.at(0),m_parameters.at(1));
} else {
qDebug() << "Unknown value for scrollRegion";
}
} else {
qDebug() << "Unknown parameterset for scrollRegion";
}
tokenFinished();
break;
case FinalBytesNoIntermediate::Reserved3:
case FinalBytesNoIntermediate::Reserved4:
case FinalBytesNoIntermediate::Reserved5:
case FinalBytesNoIntermediate::Reserved6:
case FinalBytesNoIntermediate::Reserved7:
case FinalBytesNoIntermediate::Reserved8:
case FinalBytesNoIntermediate::Reserved9:
case FinalBytesNoIntermediate::Reserveda:
case FinalBytesNoIntermediate::Reservedb:
case FinalBytesNoIntermediate::Reservedc:
case FinalBytesNoIntermediate::Reservedd:
case FinalBytesNoIntermediate::Reservede:
case FinalBytesNoIntermediate::Reservedf:
default:
qDebug() << "Unhandeled CSI" << FinalBytesNoIntermediate::FinalBytesNoIntermediate(character);
tokenFinished();
break;
}
}
}
}
}
void Parser::decodeOSC(uchar character)
{
if (!m_parameters.size() &&
character >= 0x30 && character <= 0x3f) {
decodeParameters(character);
} else {
if (m_decode_osc_state == None) {
appendParameter();
if (m_parameters.size() != 1) {
tokenFinished();
return;
}
switch (m_parameters.at(0)) {
case 0:
m_decode_osc_state = ChangeWindowAndIconName;
break;
case 1:
m_decode_osc_state = ChangeIconTitle;
break;
case 2:
m_decode_osc_state = ChangeWindowTitle;
break;
default:
m_decode_osc_state = Unknown;
break;
}
} else {
if (character == 0x07) {
if (m_decode_osc_state == ChangeWindowAndIconName ||
m_decode_osc_state == ChangeWindowTitle) {
QString title = QString::fromUtf8(m_current_data.mid(m_current_token_start+4,
m_currrent_position - m_current_token_start -1));
m_screen->setTitle(title);
}
tokenFinished();
}
}
}
}
void Parser::decodeOtherEscape(uchar character)
{
Q_ASSERT(m_parameters.size());
switch(m_parameters.at(0)) {
case -'(':
switch(character) {
case 0:
m_screen->setCharacterMap("DEC Special Character and Line Drawing Set");
break;
case 'A':
m_screen->setCharacterMap("UK");
break;
case 'B':
m_screen->setCharacterMap("USASCII");
break;
case '4':
m_screen->setCharacterMap("Dutch");
break;
case 'C':
case '5':
m_screen->setCharacterMap("Finnish");
break;
case 'R':
m_screen->setCharacterMap("French");
break;
case 'Q':
m_screen->setCharacterMap("FrenchCanadian");
break;
case 'K':
m_screen->setCharacterMap("German");
break;
case 'Y':
m_screen->setCharacterMap("Italian");
break;
case 'E':
case '6':
m_screen->setCharacterMap("NorDan");
break;
case 'Z':
m_screen->setCharacterMap("Spanish");
break;
case 'H':
case '7':
m_screen->setCharacterMap("Sweedish");
break;
case '=':
m_screen->setCharacterMap("Swiss");
break;
default:
qDebug() << "Not supported Character set!";
}
break;
default:
qDebug() << "Other Escape sequence not recognized";
}
tokenFinished();
}
void Parser::tokenFinished()
{
m_decode_state = PlainText;
m_decode_osc_state = None;
m_parameters.clear();
m_parameter_string.clear();
m_current_token_start = m_currrent_position + 1;
m_intermediate_char = 0;
}
void Parser::appendParameter()
{
if (m_parameter_string.size()) {
m_parameters.append(m_parameter_string.toUShort());
m_parameter_string.clear();
}
}

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

@ -0,0 +1,83 @@
/**************************************************************************************************
* 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 "text.h"
class Parser
{
public:
Parser(Screen *screen);
void addData(const QByteArray &data);
private:
enum DecodeState {
PlainText,
DecodeC0,
DecodeC1_7bit,
DecodeCSI,
DecodeOSC,
DecodeOtherEscape
};
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 decodeOtherEscape(uchar character);
void tokenFinished();
void appendParameter();
DecodeState m_decode_state;
DecodeOSCState m_decode_osc_state;
QByteArray m_current_data;
int m_current_token_start;
int m_currrent_position;
QChar m_intermediate_char;
QByteArray m_parameter_string;
QVector<int> m_parameters;
Screen *m_screen;
};
#endif // PARSER_H

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

@ -0,0 +1,958 @@
/**************************************************************************************************
* 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 "line.h"
#include "controll_chars.h"
#include <QtCore/QTimer>
#include <QtCore/QSocketNotifier>
#include <QtGui/QGuiApplication>
#include <QtQuick/QQuickItem>
#include <QtQuick/QQuickView>
#include <QtQml/QQmlComponent>
#include <QtCore/QDebug>
#include <float.h>
Screen::Screen(QObject *parent)
: QObject(parent)
, m_parser(this)
, m_timer_event_id(0)
, m_cursor_visible(true)
, m_cursor_visible_changed(false)
, m_cursor_blinking(true)
, m_cursor_blinking_changed(false)
, m_insert_mode(Replace)
, m_selection_valid(false)
, m_selection_moved(0)
, m_flash(false)
, m_cursor_changed(false)
, m_reset(false)
, m_application_cursor_key_mode(false)
{
connect(&m_pty, &YatPty::readyRead, this, &Screen::readData);
m_screen_stack.reserve(2);
m_cursor_stack << QPoint(0,0);
m_current_text_style.style = TextStyle::Normal;
m_current_text_style.forground = ColorPalette::DefaultForground;
m_current_text_style.background = ColorPalette::DefaultBackground;
connect(&m_pty, SIGNAL(hangupReceived()),qGuiApp, SLOT(quit()));
}
Screen::~Screen()
{
for (int i = 0; i < m_screen_stack.size(); i++) {
delete m_screen_stack.at(i);
}
}
QColor Screen::screenBackground()
{
return QColor(Qt::black);
}
QColor Screen::defaultForgroundColor() const
{
return m_palette.normalColor(ColorPalette::DefaultForground);
}
QColor Screen::defaultBackgroundColor() const
{
return QColor(Qt::transparent);
}
void Screen::setHeight(int height)
{
if (!m_screen_stack.size()) {
m_screen_stack << new ScreenData(this);
}
ScreenData *data = current_screen_data();
int size_difference = data->height() - height;
if (!size_difference)
return;
data->setHeight(height);
if (size_difference > 0) {
if (current_cursor_y() > 0)
current_cursor_pos().ry()--;
}
m_pty.setHeight(height, height * 10);
dispatchChanges();
}
void Screen::setWidth(int width)
{
if (!m_screen_stack.size())
m_screen_stack << new ScreenData(this);
current_screen_data()->setWidth(width);
m_pty.setWidth(width, width * 10);
}
int Screen::width() const
{
return m_pty.size().width();
}
void Screen::saveScreenData()
{
ScreenData *new_data = new ScreenData(this);
QSize pty_size = m_pty.size();
new_data->setHeight(pty_size.height());
new_data->setWidth(pty_size.width());
for (int i = 0; i < new_data->height(); i++) {
current_screen_data()->at(i)->setVisible(false);
}
m_screen_stack << new_data;
setSelectionEnabled(false);
}
void Screen::restoreScreenData()
{
ScreenData *data = current_screen_data();
m_screen_stack.remove(m_screen_stack.size()-1);
delete data;
QSize pty_size = m_pty.size();
current_screen_data()->setHeight(pty_size.height());
current_screen_data()->setWidth(pty_size.width());
for (int i = 0; i < current_screen_data()->height(); i++) {
current_screen_data()->at(i)->setVisible(true);
}
setSelectionEnabled(false);
}
int Screen::height() const
{
return current_screen_data()->height();
}
void Screen::setInsertMode(InsertMode mode)
{
m_insert_mode = mode;
}
void Screen::setTextStyle(TextStyle::Style style, bool add)
{
if (add) {
m_current_text_style.style |= style;
} else {
m_current_text_style.style &= !style;
}
}
void Screen::resetStyle()
{
m_current_text_style.background = ColorPalette::DefaultBackground;
m_current_text_style.forground = ColorPalette::DefaultForground;
m_current_text_style.style = TextStyle::Normal;
}
TextStyle Screen::currentTextStyle() const
{
return m_current_text_style;
}
TextStyle Screen::defaultTextStyle() const
{
TextStyle style;
style.style = TextStyle::Normal;
style.forground = ColorPalette::DefaultForground;
style.background = ColorPalette::DefaultBackground;
return style;
}
QPoint Screen::cursorPosition() const
{
return QPoint(current_cursor_x(),current_cursor_y());
}
void Screen::moveCursorHome()
{
current_cursor_pos().setX(0);
m_cursor_changed = true;
}
void Screen::moveCursorTop()
{
current_cursor_pos().setY(0);
m_cursor_changed = true;
}
void Screen::moveCursorUp(int n_positions)
{
if (!current_cursor_pos().y())
return;
if (n_positions <= current_cursor_pos().y()) {
current_cursor_pos().ry() -= n_positions;
} else {
current_cursor_pos().ry() = 0;
}
m_cursor_changed = true;
}
void Screen::moveCursorDown()
{
current_cursor_pos().ry() += 1;
m_cursor_changed = true;
}
void Screen::moveCursorLeft()
{
current_cursor_pos().rx() -= 1;
m_cursor_changed = true;
}
void Screen::moveCursorRight(int n_positions)
{
current_cursor_pos().rx() += n_positions;
m_cursor_changed = true;
}
void Screen::moveCursor(int x, int y)
{
if (x != 0)
x--;
if (y != 0)
y--;
current_cursor_pos().setX(x);
int height = this->height();
if (y >= height) {
current_cursor_pos().setY(height-1);
} else {
current_cursor_pos().setY(y);
}
m_cursor_changed = true;
}
void Screen::moveCursorToLine(int line)
{
current_cursor_pos().setY(line-1);
m_cursor_changed = true;
}
void Screen::moveCursorToCharacter(int character)
{
current_cursor_pos().setX(character-1);
m_cursor_changed = true;
}
void Screen::deleteCharacters(int characters)
{
switch (m_insert_mode) {
case Insert:
current_screen_data()->clearCharacters(current_cursor_y(), current_cursor_x(), current_cursor_x() + characters -1);
break;
case Replace:
current_screen_data()->deleteCharacters(current_cursor_y(), current_cursor_x(), current_cursor_x() + characters -1);
break;
default:
break;
}
}
void Screen::setCursorVisible(bool visible)
{
m_cursor_visible = visible;
m_cursor_visible_changed = true;
}
bool Screen::cursorVisible()
{
return m_cursor_visible;
}
void Screen::setCursorBlinking(bool blinking)
{
m_cursor_blinking = blinking;
m_cursor_blinking_changed = true;
}
bool Screen::cursorBlinking()
{
return m_cursor_blinking;
}
void Screen::saveCursor()
{
QPoint point = current_cursor_pos();
m_cursor_stack << point;
}
void Screen::restoreCursor()
{
if (m_cursor_stack.size() <= 1)
return;
m_cursor_stack.remove(m_screen_stack.size()-1);
}
void Screen::replaceAtCursor(const QString &text)
{
if (m_selection_valid ) {
if (current_cursor_y() >= m_selection_start.y() && current_cursor_y() <= m_selection_end.y())
//don't need to schedule as event since it will only happen once
setSelectionEnabled(false);
}
if (current_cursor_x() + text.size() <= width()) {
Line *line = current_screen_data()->at(current_cursor_y());
line->replaceAtPos(current_cursor_x(), text, m_current_text_style);
current_cursor_pos().rx() += text.size();
} else {
for (int i = 0; i < text.size();) {
if (current_cursor_x() == width()) {
current_cursor_pos().setX(0);
lineFeed();
}
QString toLine = text.mid(i,current_screen_data()->width() - current_cursor_x());
Line *line = current_screen_data()->at(current_cursor_y());
line->replaceAtPos(current_cursor_x(),toLine, m_current_text_style);
i+= toLine.size();
current_cursor_pos().rx() += toLine.size();
}
}
m_cursor_changed = true;
}
void Screen::insertEmptyCharsAtCursor(int len)
{
if (m_selection_valid) {
if (current_cursor_y() >= m_selection_start.y() && current_cursor_y() <= m_selection_end.y())
//don't need to schedule as event since it will only happen once
setSelectionEnabled(false);
}
Line *line = current_screen_data()->at(current_cursor_y());
QString empty(len, QChar(' '));
line->insertAtPos(current_cursor_x(), empty, defaultTextStyle());
}
void Screen::backspace()
{
current_cursor_pos().rx()--;
m_cursor_changed = true;
}
void Screen::eraseLine()
{
current_screen_data()->clearLine(current_cursor_y());
}
void Screen::eraseFromCursorPositionToEndOfLine()
{
current_screen_data()->clearToEndOfLine(current_cursor_y(), current_cursor_x());
}
void Screen::eraseFromCursorPosition(int n_chars)
{
current_screen_data()->clearCharacters(current_cursor_y(), current_cursor_x(), current_cursor_x() + n_chars - 1);
}
void Screen::eraseFromCurrentLineToEndOfScreen()
{
current_screen_data()->clearToEndOfScreen(current_cursor_y());
}
void Screen::eraseFromCurrentLineToBeginningOfScreen()
{
current_screen_data()->clearToBeginningOfScreen(current_cursor_y());
}
void Screen::eraseToCursorPosition()
{
qDebug() << "eraseToCursorPosition NOT IMPLEMENTED!";
}
void Screen::eraseScreen()
{
current_screen_data()->clear();
}
void Screen::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";
}
}
const ColorPalette *Screen::colorPalette() const
{
return &m_palette;
}
void Screen::lineFeed()
{
int cursor_y = current_cursor_y();
if(cursor_y == current_screen_data()->scrollAreaEnd()) {
m_selection_start.ry()--;
m_selection_end.ry()--;
m_selection_moved = true;
moveLine(current_screen_data()->scrollAreaStart(),cursor_y);
} else {
current_cursor_pos().ry()++;
m_cursor_changed = true;
}
}
void Screen::reverseLineFeed()
{
int cursor_y = current_cursor_y();
if (cursor_y == current_screen_data()->scrollAreaStart()) {
m_selection_start.ry()++;
m_selection_end.ry()++;
m_selection_moved = true;
moveLine(current_screen_data()->scrollAreaEnd(), cursor_y);
} else {
current_cursor_pos().ry()--;
m_cursor_changed = true;
}
}
void Screen::insertLines(int count)
{
for (int i = 0; i < count; i++) {
moveLine(current_screen_data()->scrollAreaEnd(),current_cursor_y());
}
}
void Screen::deleteLines(int count)
{
for (int i = 0; i < count; i++) {
moveLine(current_cursor_y(),current_screen_data()->scrollAreaEnd());
}
}
void Screen::setScrollArea(int from, int to)
{
from--;
to--;
current_screen_data()->setScrollArea(from,to);
}
QPointF Screen::selectionAreaStart() const
{
return m_selection_start;
}
void Screen::setSelectionAreaStart(const QPointF &start)
{
bool emitChanged = m_selection_start != start;
m_selection_start = start;
setSelectionValidity();
if (emitChanged)
emit selectionAreaStartChanged();
}
QPointF Screen::selectionAreaEnd() const
{
return m_selection_end;
}
void Screen::setSelectionAreaEnd(const QPointF &end)
{
bool emitChanged = m_selection_end != end;
m_selection_end = end;
setSelectionValidity();
if (emitChanged)
emit selectionAreaEndChanged();
}
bool Screen::selectionEnabled() const
{
return m_selection_valid;
}
void Screen::setSelectionEnabled(bool enabled)
{
bool emitchanged = m_selection_valid != enabled;
m_selection_valid = enabled;
if (emitchanged)
emit selectionEnabledChanged();
}
void Screen::sendSelectionToClipboard() const
{
current_screen_data()->sendSelectionToClipboard(m_selection_start, m_selection_end, QClipboard::Clipboard);
}
void Screen::sendSelectionToSelection() const
{
current_screen_data()->sendSelectionToClipboard(m_selection_start, m_selection_end, QClipboard::Selection);
}
void Screen::pasteFromSelection()
{
m_pty.write(QGuiApplication::clipboard()->text(QClipboard::Selection).toUtf8());
}
void Screen::pasteFromClipboard()
{
m_pty.write(QGuiApplication::clipboard()->text(QClipboard::Clipboard).toUtf8());
}
void Screen::doubleClicked(const QPointF &clicked)
{
int start, end;
current_screen_data()->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;
}
Line *Screen::at(int i) const
{
return current_screen_data()->at(i);
}
void Screen::printScreen() const
{
current_screen_data()->printStyleInformation();
}
void Screen::dispatchChanges()
{
if (m_reset) {
emit reset();
m_update_actions.clear();
m_reset = false;
} else {
qint16 begin_move = -1;
qint16 end_move = -1;
for (int i = 0; i < m_update_actions.size(); i++) {
UpdateAction action = m_update_actions.at(i);
switch(action.action) {
case UpdateAction::MoveLine: {
if (begin_move < 0) {
begin_move = qMin(action.to_line, action.from_line);
end_move = qMax(action.to_line, action.from_line);
} else
if (action.from_line > action.to_line) {
begin_move = qMin(action.to_line, begin_move);
end_move = qMax(action.from_line, end_move);
} else {
begin_move = qMin(action.from_line, begin_move);
end_move = qMax(action.to_line, end_move);
}
}
break;
default:
qDebug() << "unhandeled UpdatAction in TerminalScreen";
break;
}
}
if (begin_move >= 0) {
current_screen_data()->updateIndexes(begin_move, end_move);
}
current_screen_data()->dispatchLineEvents();
emit dispatchTextSegmentChanges();
}
if (m_flash) {
m_flash = false;
emit flash();
}
if (m_cursor_changed) {
m_cursor_changed = false;
emit cursorPositionChanged(current_cursor_x(), current_cursor_y());
}
if (m_cursor_visible_changed) {
m_cursor_visible_changed = false;
emit cursorVisibleChanged();
}
if (m_cursor_blinking_changed) {
m_cursor_blinking_changed = false;
emit cursorBlinkingChanged();
}
if (m_selection_valid && m_selection_moved) {
if (m_selection_start.y() < 0 ||
m_selection_end.y() >= current_screen_data()->height()) {
setSelectionEnabled(false);
} else {
emit selectionAreaStartChanged();
emit selectionAreaEndChanged();
}
}
m_update_actions.clear();
}
void Screen::sendPrimaryDA()
{
m_pty.write(QByteArrayLiteral("\033[?6c"));
}
void Screen::sendSecondaryDA()
{
m_pty.write(QByteArrayLiteral("\033[>1;95;0c"));
}
void Screen::setCharacterMap(const QString &string)
{
m_character_map = string;
}
QString Screen::characterMap() const
{
return m_character_map;
}
void Screen::setApplicationCursorKeysMode(bool enable)
{
m_application_cursor_key_mode = enable;
}
bool Screen::applicationCursorKeyMode() const
{
return m_application_cursor_key_mode;
}
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)
{
/// UGH, this functions 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;
}
Line *Screen::line_at_cursor() const
{
return current_screen_data()->at(current_cursor_y());
}
void Screen::readData(const QByteArray &data)
{
m_parser.addData(data);
if (!m_timer_event_id)
m_timer_event_id = startTimer(3);
m_time_since_parsed.restart();
}
void Screen::moveLine(qint16 from, qint16 to)
{
current_screen_data()->moveLine(from,to);
scheduleMoveSignal(from,to);
}
void Screen::scheduleMoveSignal(qint16 from, qint16 to)
{
if (m_update_actions.size() &&
m_update_actions.last().action == UpdateAction::MoveLine &&
m_update_actions.last().from_line == from &&
m_update_actions.last().to_line == to) {
m_update_actions.last().count++;
} else {
m_update_actions << UpdateAction(UpdateAction::MoveLine, from, to, 1);
}
}
void Screen::setSelectionValidity()
{
if (m_selection_end.y() > m_selection_start.y() ||
(m_selection_end.y() == m_selection_start.y() &&
m_selection_end.x() > m_selection_start.x())) {
setSelectionEnabled(true);
} else {
setSelectionEnabled(false);
}
}
void Screen::timerEvent(QTimerEvent *)
{
if (m_timer_event_id && m_time_since_parsed.elapsed() > 3) {
killTimer(m_timer_event_id);
m_timer_event_id = 0;
dispatchChanges();
}
}

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

@ -0,0 +1,243 @@
/**************************************************************************************************
* 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 "text.h"
#include "color_palette.h"
#include "parser.h"
#include "yat_pty.h"
#include "update_action.h"
#include "screen_data.h"
#include <QtCore/QPoint>
#include <QtCore/QSize>
#include <QtCore/QStack>
#include <QtCore/QElapsedTimer>
class Line;
class QQuickItem;
class QQmlEngine;
class QQmlComponent;
class Screen : public QObject
{
Q_OBJECT
Q_PROPERTY(int height READ height WRITE setHeight)
Q_PROPERTY(int width READ width WRITE setWidth)
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY screenTitleChanged)
Q_PROPERTY(bool cursorVisible READ cursorVisible NOTIFY cursorVisibleChanged)
Q_PROPERTY(bool cursorBlinking READ cursorBlinking NOTIFY cursorBlinkingChanged)
Q_PROPERTY(bool selectionEnabled READ selectionEnabled NOTIFY selectionEnabledChanged)
Q_PROPERTY(QPointF selectionAreaStart READ selectionAreaStart WRITE setSelectionAreaStart NOTIFY selectionAreaStartChanged)
Q_PROPERTY(QPointF selectionAreaEnd READ selectionAreaEnd WRITE setSelectionAreaEnd NOTIFY selectionAreaEndChanged)
public:
enum InsertMode {
Insert,
Replace
};
explicit Screen(QObject *parent = 0);
~Screen();
void setHeight(int height);
int height() const;
void setWidth(int width);
int width() const;
void saveScreenData();
void restoreScreenData();
void setInsertMode(InsertMode mode);
void setTextStyle(TextStyle::Style style, bool add = true);
void resetStyle();
TextStyle currentTextStyle() const;
TextStyle defaultTextStyle() const;
Q_INVOKABLE QColor screenBackground();
QColor defaultForgroundColor() const;
QColor defaultBackgroundColor() const;
void setTextStyleColor(ushort color);
const ColorPalette *colorPalette() const;
QPoint cursorPosition() const;
void moveCursorHome();
void moveCursorTop();
void moveCursorUp(int n_positions = 1);
void moveCursorDown();
void moveCursorLeft();
void moveCursorRight(int n_positions);
void moveCursor(int x, int y);
void moveCursorToLine(int line);
void moveCursorToCharacter(int character);
void deleteCharacters(int characters);
void setCursorVisible(bool visible);
bool cursorVisible();
void setCursorBlinking(bool blinking);
bool cursorBlinking();
void saveCursor();
void restoreCursor();
void replaceAtCursor(const QString &text);
void insertEmptyCharsAtCursor(int len);
void backspace();
void eraseLine();
void eraseFromCursorPositionToEndOfLine();
void eraseFromCursorPosition(int n_chars);
void eraseFromCurrentLineToEndOfScreen();
void eraseFromCurrentLineToBeginningOfScreen();
void eraseToCursorPosition();
void eraseScreen();
void lineFeed();
void reverseLineFeed();
void insertLines(int count);
void deleteLines(int count);
void setScrollArea(int from, int to);
QPointF selectionAreaStart() const;
void setSelectionAreaStart(const QPointF &start);
QPointF selectionAreaEnd() const;
void setSelectionAreaEnd(const QPointF &end);
bool selectionEnabled() const;
Q_INVOKABLE void setSelectionEnabled(bool enabled);
Q_INVOKABLE void sendSelectionToClipboard() const;
Q_INVOKABLE void sendSelectionToSelection() const;
Q_INVOKABLE void pasteFromSelection();
Q_INVOKABLE void pasteFromClipboard();
Q_INVOKABLE void doubleClicked(const QPointF &clicked);
void setTitle(const QString &title);
QString title() const;
void scheduleFlash();
Q_INVOKABLE Line *at(int i) const;
Q_INVOKABLE void printScreen() const;
void dispatchChanges();
void sendPrimaryDA();
void sendSecondaryDA();
void setCharacterMap(const QString &string);
QString characterMap() const;
void setApplicationCursorKeysMode(bool enable);
bool applicationCursorKeyMode() const;
Q_INVOKABLE void sendKey(const QString &text, Qt::Key key, Qt::KeyboardModifiers modifiers);
YatPty *pty();
//For tests
Line *line_at_cursor() const;
public slots:
void readData(const QByteArray &data);
signals:
void moveLines(int from_line, int to_line, int count);
void reset();
void flash();
void dispatchLineChanges();
void dispatchTextSegmentChanges();
void selectionAreaStartChanged();
void selectionAreaEndChanged();
void selectionEnabledChanged();
void screenTitleChanged();
void cursorPositionChanged(int x, int y);
void cursorVisibleChanged();
void cursorBlinkingChanged();
void lineCreated(Line *line);
protected:
void timerEvent(QTimerEvent *);
private:
void moveLine(qint16 from, qint16 to);
void scheduleMoveSignal(qint16 from, qint16 to);
ScreenData *current_screen_data() const { return m_screen_stack[m_screen_stack.size()-1]; }
QPoint &current_cursor_pos() { return m_cursor_stack[m_cursor_stack.size()-1]; }
int current_cursor_x() const { return m_cursor_stack.at(m_cursor_stack.size()-1).x(); }
int current_cursor_y() const { return m_cursor_stack.at(m_cursor_stack.size()-1).y(); }
void setSelectionValidity();
ColorPalette m_palette;
YatPty m_pty;
Parser m_parser;
QElapsedTimer m_time_since_parsed;
int m_timer_event_id;
QVector<ScreenData *> m_screen_stack;
QVector<QPoint> m_cursor_stack;
bool m_cursor_visible;
bool m_cursor_visible_changed;
bool m_cursor_blinking;
bool m_cursor_blinking_changed;
TextStyle m_current_text_style;
QString m_title;
InsertMode m_insert_mode;
bool m_selection_valid;
bool m_selection_moved;
QPointF m_selection_start;
QPointF m_selection_end;
QString m_character_map;
QList<UpdateAction> m_update_actions;
bool m_flash;
bool m_cursor_changed;
bool m_reset;
bool m_application_cursor_key_mode;
friend class ScreenData;
};
#endif // TERMINALSCREEN_H

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

@ -0,0 +1,317 @@
/**************************************************************************************************
* 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 "line.h"
#include "screen.h"
#include <stdio.h>
#include <QtGui/QGuiApplication>
#include <QtCore/QDebug>
ScreenData::ScreenData(Screen *screen)
: m_screen(screen)
, m_scroll_start(0)
, m_scroll_end(0)
, m_scroll_area_set(false)
{
}
ScreenData::~ScreenData()
{
for (int i = 0; i < m_screen_lines.size(); i++) {
delete m_screen_lines.at(i);
}
}
int ScreenData::width() const
{
return m_width;
}
void ScreenData::setWidth(int width)
{
if (width == m_width)
return;
m_width = width;
for (int i = 0; i < m_screen_lines.size(); i++) {
m_screen_lines.at(i)->setWidth(width);
}
}
int ScreenData::height() const
{
return m_screen_lines.size();
}
void ScreenData::setHeight(int height)
{
if (height == m_screen_lines.size())
return;
if (m_screen_lines.size() > height) {
int removeElements = m_screen_lines.size() - height;
for (int i = 0; i < m_screen_lines.size(); i++) {
if (i <removeElements) {
int not_broadcasted = m_new_lines.indexOf(m_screen_lines.at(i));
if (not_broadcasted >= 0)
m_new_lines.remove(not_broadcasted);
delete m_screen_lines[i];
} else {
m_screen_lines.at(i)->setIndex(i - removeElements);
}
}
m_screen_lines.remove(0, removeElements);
} else if (m_screen_lines.size() < height){
int rowsToAdd = height - m_screen_lines.size();
for (int i = 0; i < rowsToAdd; i++) {
Line *newLine = new Line(m_screen);
m_screen_lines.append(newLine);
m_new_lines.append(newLine);
newLine->setIndex(m_screen_lines.size()-1);
}
}
if (!m_scroll_area_set)
m_scroll_end = height - 1;
}
int ScreenData::scrollAreaStart() const
{
return m_scroll_start;
}
int ScreenData::scrollAreaEnd() const
{
return m_scroll_end;
}
Line *ScreenData::at(int index) const
{
return m_screen_lines.at(index);
}
void ScreenData::clearToEndOfLine(int row, int from_char)
{
m_screen_lines.at(row)->clearToEndOfLine(from_char);
}
void ScreenData::clearToEndOfScreen(int row)
{
for(int i = row; i < m_screen_lines.size(); i++) {
Line *line = m_screen_lines.at(i);
line->clear();
}
}
void ScreenData::clearToBeginningOfScreen(int row)
{
for (int i = row; i >= 0; i--) {
Line *line = m_screen_lines.at(i);
line->clear();
}
}
void ScreenData::clearLine(int index)
{
m_screen_lines.at(index)->clear();
}
void ScreenData::clear()
{
for (int i = 0; i < m_screen_lines.size(); i++) {
Line *line = m_screen_lines.at(i);
line->clear();
}
}
void ScreenData::clearCharacters(int line, int from, int to)
{
Line *line_item = m_screen_lines.at(line);
line_item->clearCharacters(from,to);
}
void ScreenData::deleteCharacters(int line, int from, int to)
{
Line *line_item = m_screen_lines.at(line);
line_item->deleteCharacters(from,to);
}
void ScreenData::setScrollArea(int from, int to)
{
m_scroll_area_set = true;
m_scroll_start = from;
m_scroll_end = to;
}
void ScreenData::moveLine(int from, int to)
{
if (from == to)
return;
if (from < to) {
int lines_to_shift = to - from;
Line *from_line = m_screen_lines.at(from);
Line **from_line_ptr = m_screen_lines.data() + from;
memmove(from_line_ptr, from_line_ptr+1, sizeof(from_line_ptr) * lines_to_shift);
from_line->clear();
m_screen_lines.replace(to,from_line);
} else {
int lines_to_shift = from - to;
Line *from_line = m_screen_lines.at(from);
Line **to_line_ptr = const_cast<Line **>(m_screen_lines.constData() + to);
memmove(to_line_ptr + 1, to_line_ptr, sizeof(to_line_ptr) * lines_to_shift);
from_line->clear();
m_screen_lines.replace(to,from_line);
}
}
void ScreenData::updateIndexes(int from, int to)
{
if (to < 0) {
to = m_screen_lines.size() -1;
}
for (int i = from; i <= to; i++) {
m_screen_lines.at(i)->setIndex(i);
}
}
void ScreenData::sendSelectionToClipboard(const QPointF &start, const QPointF &end, QClipboard::Mode clipboard)
{
QString data;
int start_line = qMax((int)start.y(), 0);
int end_line = qMin((int)end.y(), m_screen_lines.size()-1);
for (int i = start_line; i <= end_line; i++) {
int char_start = 0;
int char_end = m_width - 1;
if (i == start_line)
char_start = start.x();
else
data.append(QChar('\n'));
if (i == end_line)
char_end = end.x();
data += m_screen_lines.at(i)->textLine()->mid(char_start, char_end - char_start).trimmed();
}
QGuiApplication::clipboard()->setText(data, clipboard);
}
void ScreenData::getDoubleClickSelectionArea(const QPointF &cliked, int *start_ret, int *end_ret) const
{
static const QChar delimiter_list[] = {
' ',
'<',
'>',
')',
'(',
'{',
'}',
'[',
']'
};
static const int size_of_delimiter_list = sizeof delimiter_list / sizeof *delimiter_list;
*start_ret = -1;
*end_ret = -1;
bool find_equals = false;
QStringRef to_return(m_screen_lines.at(cliked.y())->textLine());
QChar clicked_char = to_return.at(cliked.x());
for (int i=0; i<size_of_delimiter_list; i++) {
if (clicked_char == delimiter_list[i])
find_equals = true;
}
for (int i = cliked.x() - 1; i >= 0; i--) {
if (find_equals) {
if (clicked_char != to_return.at(i)) {
*start_ret = i + 1;
break;
}
} else {
for (int delimiter_i = 0; delimiter_i < size_of_delimiter_list; delimiter_i++) {
if (to_return.at(i) == delimiter_list[delimiter_i]) {
*start_ret = i + 1;
i = -1;
break;
}
}
}
}
if (*start_ret < 0)
*start_ret = 0;
for (int i = cliked.x() + 1; i < to_return.size(); i++) {
if (find_equals) {
if (clicked_char != to_return.at(i)) {
*end_ret = i;
break;
}
} else {
for (int delimiter_i = 0; delimiter_i < size_of_delimiter_list; delimiter_i++) {
if (to_return.at(i) == delimiter_list[delimiter_i]) {
*end_ret = i;
i = to_return.size();
break;
}
}
}
}
if (*end_ret < 0)
*end_ret = to_return.size();
}
void ScreenData::dispatchLineEvents()
{
for (int i = 0; i < m_new_lines.size(); i++) {
emit m_screen->lineCreated(m_new_lines.at(i));
}
m_new_lines.clear();
for (int i = 0; i < m_screen_lines.size(); i++) {
m_screen_lines.at(i)->dispatchEvents();
}
}
void ScreenData::printScreen() const
{
for (int line = 0; line < m_screen_lines.size(); line++) {
// for (int i = 0; i < m_screen_lines.at(line)->size(); i++) {
// fprintf(stderr, "%s", qPrintable(m_screen_lines.at(line)->at(i)->text()));
// }
// fprintf(stderr, "\n");
fprintf(stderr, "%s\n", qPrintable(*m_screen_lines.at(line)->textLine()));
}
}
void ScreenData::printStyleInformation() const
{
for (int line_number = 0; line_number < m_screen_lines.size(); line_number++) {
const Line *line = m_screen_lines.at(line_number);
line->printStyleList();
}
}

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

@ -0,0 +1,81 @@
/**************************************************************************************************
* 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 <QtCore/QVector>
#include <QtCore/QPoint>
#include <QtGui/QClipboard>
class Line;
class Screen;
class ScreenData
{
public:
ScreenData(Screen *screen);
~ScreenData();
int width() const;
void setWidth(int width);
int height() const;
void setHeight(int height);
int scrollAreaStart() const;
int scrollAreaEnd() const;
Line *at(int index) const;
void clearToEndOfLine(int row, int from_char);
void clearToEndOfScreen(int row);
void clearToBeginningOfScreen(int row);
void clearLine(int index);
void clear();
void clearCharacters(int line, int from, int to);
void deleteCharacters(int line, int from, int to);
void setScrollArea(int from, int to);
void moveLine(int from, int to);
void updateIndexes(int from = 0, int to = -1);
void sendSelectionToClipboard(const QPointF &start, const QPointF &end, QClipboard::Mode clipboard);
void getDoubleClickSelectionArea(const QPointF &cliked, int *start_ret, int *end_ret) const;
void dispatchLineEvents();
void printScreen() const;
void printStyleInformation() const;
private:
Screen *m_screen;
int m_width;
QVector<Line *> m_screen_lines;
QVector<Line *> m_new_lines;
int m_scroll_start;
int m_scroll_end;
bool m_scroll_area_set;
};
#endif // SCREENDATA_H

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

@ -0,0 +1,147 @@
/**************************************************************************************************
* 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 "line.h"
#include <QtQuick/QQuickItem>
#include <QtCore/QDebug>
Text::Text(Screen *screen)
: QObject(screen)
, m_style_dirty(true)
, m_text_dirty(true)
, m_visible(true)
, m_visible_old(true)
, m_line(0)
{
}
Text::~Text()
{
emit aboutToBeDestroyed();
}
void Text::setLine(Line *line)
{
if (line == m_line)
return;
m_line = line;
if (m_line) {
m_text_line = line->textLine();
}
}
int Text::index() const
{
return m_start_index;
}
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
{
if (m_style.style & TextStyle::Inverse) {
if (m_style.background == ColorPalette::DefaultBackground)
return screen()->screenBackground();
return screen()->colorPalette()->color(m_style.background, m_style.style & TextStyle::Bold);
}
return screen()->colorPalette()->color(m_style.forground, m_style.style & TextStyle::Bold);
}
QColor Text::backgroundColor() const
{
if (m_style.style & TextStyle::Inverse)
return screen()->colorPalette()->color(m_style.forground, false);
return screen()->colorPalette()->color(m_style.background, false);
}
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;
}
Screen *Text::screen() const
{
return m_line->screen();
}
void Text::dispatchEvents()
{
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;
bool emit_text_style = m_new_style.style != m_style.style;
m_style = m_new_style;
if (emit_forground)
emit forgroundColorChanged();
if (emit_background)
emit backgroundColorChanged();
if (emit_text_style)
emit textStyleChanged();
}
if (m_old_start_index != m_start_index
|| m_text_dirty) {
m_text_dirty = false;
m_text = m_text_line->mid(m_start_index, m_end_index + 1 - m_start_index);
if (m_old_start_index != m_start_index) {
m_old_start_index = m_start_index;
emit indexChanged();
}
emit textChanged();
}
if (m_visible_old != m_visible) {
m_visible_old = m_visible;
emit visibleChanged();
}
}

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

@ -0,0 +1,96 @@
/**************************************************************************************************
* 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 Line;
class QQuickItem;
class Text : public QObject
{
Q_OBJECT
Q_PROPERTY(int index READ index NOTIFY indexChanged)
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(Screen *screen READ screen CONSTANT)
public:
Text(Screen *screen);
~Text();
void setLine(Line *line);
int index() const;
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);
Screen *screen() const;
QObject *item() const;
public slots:
void dispatchEvents();
signals:
void indexChanged();
void visibleChanged();
void textChanged();
void forgroundColorChanged();
void backgroundColorChanged();
void textStyleChanged();
void aboutToBeDestroyed();
private:
QString m_text;
QString *m_text_line;
int m_start_index;
int m_old_start_index;
int m_end_index;
TextStyle m_style;
TextStyle m_new_style;
bool m_style_dirty;
bool m_text_dirty;
bool m_visible;
bool m_visible_old;
Line *m_line;
};
#endif // TEXT_SEGMENT_H

View File

@ -0,0 +1,17 @@
#include "text_style.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;
}

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

@ -0,0 +1,37 @@
#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;
};
#endif // TEXT_STYLE_H

View File

@ -0,0 +1,21 @@
/**************************************************************************************************
* 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 "update_action.h"

View File

@ -0,0 +1,54 @@
/**************************************************************************************************
* 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 UPDATE_ACTION_H
#define UPDATE_ACTION_H
#include <QtCore/qnamespace.h>
class UpdateAction
{
public:
enum Action {
InvalidAction,
MoveLine
};
UpdateAction(Action action, qint16 from_line, qint16 to_line, qint16 count)
: action(action)
, from_line(from_line)
, to_line(to_line)
, count(count)
{ }
UpdateAction(Action action, int count)
: action(action)
, from_line(0)
, to_line(0)
, count(count)
{ }
Action action;
qint16 from_line;
qint16 to_line;
qint16 count;
};
#endif // UPDATE_ACTION_H

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",
"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[4096];
};
#endif //YAT_PTY_H

BIN
yat/docs/Ecma-048.pdf Normal file

Binary file not shown.

File diff suppressed because it is too large Load Diff

3
yat/tests/auto/auto.pro Normal file
View File

@ -0,0 +1,3 @@
TEMPLATE = subdirs
SUBDIRS = \
line

View File

@ -0,0 +1,8 @@
CONFIG += testcase
QT += testlib quick
include(../../../backend/backend.pri)
SOURCES += \
tst_line.cpp \

View File

@ -0,0 +1,724 @@
#include "../../../backend/line.h"
#include <QtTest/QtTest>
#include <QtQml/QQmlEngine>
#include "../../../backend/screen.h"
class LineHandler
{
public:
LineHandler() {
screen.setHeight(50);
screen.setWidth(100);
screen.line_at_cursor()->clear();
QCOMPARE(line()->style_list().size(), 1);
default_style = line()->style_list().at(0);
default_text_style = default_style.style;
}
Line *line() const
{
return screen.line_at_cursor();
}
TextStyle default_style;
TextStyle::Styles default_text_style;
Screen screen;
};
class tst_Line: public QObject
{
Q_OBJECT
private slots:
void replaceStart();
void replaceEdgeOfStyle();
void replaceCompatibleStyle();
void replaceIncompatibleStyle();
void replaceIncompaitibleStylesCrossesBoundary();
void replace3IncompatibleStyles();
void replaceIncomaptibleStylesCrosses2Boundaries();
void replaceSwapStyles();
void replaceEndLine();
void clearLine();
void clearToEndOfLine1Segment();
void clearToEndOfLine3Segment();
void clearToEndOfLineMiddle3Segment();
void deleteCharacters1Segment();
void deleteCharacters2Segments();
void deleteCharacters3Segments();
void deleteCharactersRemoveSegmentEnd();
void deleteCharactersRemoveSegmentBeginning();
void insertCharacters();
void insertCharacters2Segments();
void insertCharacters3Segments();
};
void tst_Line::replaceStart()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QVector<TextStyleLine> old_style_list = line->style_list();
QCOMPARE(old_style_list.size(), 1);
QString replace_text("This is a test");
TextStyle textStyle;
textStyle.style = TextStyle::Overlined;
line->replaceAtPos(0,replace_text, textStyle);
QVector<TextStyleLine> new_style_list = line->style_list();
TextStyleLine first_style = new_style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, replace_text.size() - 1);
QCOMPARE(new_style_list.size(), 2);
}
void tst_Line::replaceEdgeOfStyle()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString first_text("This is the First");
TextStyle textStyle;
textStyle.style = TextStyle::Overlined;
line->replaceAtPos(0,first_text, textStyle);
QString second_text("This is the Second");
textStyle.style = TextStyle::Bold;
line->replaceAtPos(first_text.size(), second_text, textStyle);
QVector<TextStyleLine> style_list = line->style_list();
QCOMPARE(style_list.size(), 3);
const TextStyleLine &first_style = style_list.at(0);
QCOMPARE(first_style.style, TextStyle::Overlined);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, first_text.size() - 1);
const TextStyleLine &second_style = style_list.at(1);
QCOMPARE(second_style.style, TextStyle::Bold);
QCOMPARE(second_style.start_index, first_text.size());
QCOMPARE(second_style.end_index, first_text.size()+ second_text.size() - 1);
const TextStyleLine &third_style = style_list.at(2);
QCOMPARE(third_style.style, TextStyle::Normal);
QCOMPARE(third_style.start_index, first_text.size()+ second_text.size());
}
void tst_Line::replaceCompatibleStyle()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString replace_text("replaceed Text");
line->replaceAtPos(10, replace_text, lineHandler.default_style);
QVector<TextStyleLine> after_style_list = line->style_list();
QCOMPARE(after_style_list.size(), 1);
QCOMPARE(after_style_list.at(0).style, lineHandler.default_text_style);
}
void tst_Line::replaceIncompatibleStyle()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString replace_text("replaceed Text");
TextStyle replace_style;
replace_style.style = TextStyle::Blinking;
line->replaceAtPos(10, replace_text, replace_style);
QVector<TextStyleLine> after_style_list = line->style_list();
QCOMPARE(after_style_list.size(), 3);
const TextStyleLine &first_style = after_style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, 9);
QCOMPARE(first_style.style, lineHandler.default_text_style);
const TextStyleLine &second_style = after_style_list.at(1);
QCOMPARE(second_style.start_index, 10);
QCOMPARE(second_style.end_index, 10 + replace_text.size() -1);
QCOMPARE(second_style.style, TextStyle::Blinking);
const TextStyleLine &third_style = after_style_list.at(2);
QCOMPARE(third_style.start_index, 10 + replace_text.size());
QCOMPARE(third_style.style, lineHandler.default_text_style);
}
void tst_Line::replaceIncompaitibleStylesCrossesBoundary()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString replace_text("replaceed Text");
TextStyle replace_style;
replace_style.style = TextStyle::Blinking;
line->replaceAtPos(0, replace_text, replace_style);
QString crosses_boundary("New incompatible text");
replace_style.style = TextStyle::Framed;
int replace_pos = replace_text.size()/2;
line->replaceAtPos(replace_pos, crosses_boundary, replace_style);
QVector<TextStyleLine> after_style_list = line->style_list();
QCOMPARE(after_style_list.size(), 3);
const TextStyleLine &first_style = after_style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, replace_pos -1);
QCOMPARE(first_style.style, TextStyle::Blinking);
const TextStyleLine &second_style = after_style_list.at(1);
QCOMPARE(second_style.start_index, replace_pos);
QCOMPARE(second_style.end_index, replace_pos + crosses_boundary.size() -1);
QCOMPARE(second_style.style, TextStyle::Framed);
const TextStyleLine &third_style = after_style_list.at(2);
QCOMPARE(third_style.start_index, replace_pos + crosses_boundary.size());
QCOMPARE(third_style.style, lineHandler.default_text_style);
}
void tst_Line::replace3IncompatibleStyles()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString first_text("First Text");
TextStyle replace_style;
replace_style.style = TextStyle::Blinking;
line->replaceAtPos(0, first_text, replace_style);
QString second_text("Second Text");
replace_style.style = TextStyle::Italic;
line->replaceAtPos(first_text.size(), second_text, replace_style);
QString third_text("Third Text");
replace_style.style = TextStyle::Encircled;
line->replaceAtPos(first_text.size() + second_text.size(), third_text, replace_style);
QCOMPARE(line->style_list().size(), 4);
QVector<TextStyleLine> after_style_list = line->style_list();
const TextStyleLine &first_style = after_style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, first_text.size() -1);
const TextStyleLine &second_style = after_style_list.at(1);
QCOMPARE(second_style.start_index, first_text.size());
QCOMPARE(second_style.end_index, first_text.size() + second_text.size() - 1);
QCOMPARE(second_style.style, TextStyle::Italic);
const TextStyleLine &third_style = after_style_list.at(2);
QCOMPARE(third_style.start_index, first_text.size() + second_text.size());
QCOMPARE(third_style.end_index, first_text.size() + second_text.size() + third_text.size() - 1);
QCOMPARE(third_style.style, TextStyle::Encircled);
const TextStyleLine &fourth_style = after_style_list.at(3);
QCOMPARE(fourth_style.start_index, first_text.size() + second_text.size() + third_text.size());
}
void tst_Line::replaceIncomaptibleStylesCrosses2Boundaries()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString first_text("First Text");
TextStyle replace_style;
replace_style.style = TextStyle::Blinking;
line->replaceAtPos(0, first_text, replace_style);
QString second_text("Second Text");
replace_style.style = TextStyle::Italic;
line->replaceAtPos(first_text.size(), second_text, replace_style);
QString third_text("Third Text");
replace_style.style = TextStyle::Encircled;
line->replaceAtPos(first_text.size() + second_text.size(), third_text, replace_style);
QCOMPARE(line->style_list().size(), 4);
QVector<TextStyleLine> before_style_list = line->style_list();
QString overlap_first_third;
overlap_first_third.fill(QChar('A'), second_text.size() + 4);
replace_style.style = TextStyle::DoubleUnderlined;
line->replaceAtPos(first_text.size() -2, overlap_first_third, replace_style);
QVector<TextStyleLine> after_style_list = line->style_list();
QCOMPARE(line->style_list().size(), 4);
const TextStyleLine &first_style = after_style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, first_text.size() - 3);
QCOMPARE(first_style.style, TextStyle::Blinking);
const TextStyleLine &second_style = after_style_list.at(1);
QCOMPARE(second_style.style, TextStyle::DoubleUnderlined);
QCOMPARE(second_style.start_index, first_text.size() - 2);
QCOMPARE(second_style.end_index, first_text.size() - 2 + overlap_first_third.size() -1);
const TextStyleLine &third_style = after_style_list.at(2);
QCOMPARE(third_style.style, TextStyle::Encircled);
QCOMPARE(third_style.start_index, first_text.size() - 2 + overlap_first_third.size());
QCOMPARE(third_style.end_index, first_text.size() - 2 + overlap_first_third.size() + third_text.size() - 1 - 2);
const TextStyleLine &fourth_style = after_style_list.at(3);
QCOMPARE(fourth_style.style, lineHandler.default_text_style);
QCOMPARE(fourth_style.start_index, first_text.size() - 2 + overlap_first_third.size() + third_text.size() - 2);
}
void tst_Line::replaceSwapStyles()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString first_text("First Text");
TextStyle replace_style;
replace_style.style = TextStyle::Blinking;
line->replaceAtPos(0, first_text, replace_style);
QString second_text("Second Text");
replace_style.style = TextStyle::Italic;
line->replaceAtPos(first_text.size(), second_text, replace_style);
QString third_text("Third Text");
replace_style.style = TextStyle::Encircled;
line->replaceAtPos(first_text.size() + second_text.size(), third_text, replace_style);
QString replace_second("Dnoces Text");
replace_style.style = TextStyle::Bold;
line->replaceAtPos(first_text.size(), replace_second, replace_style);
QCOMPARE(line->style_list().size(), 4);
}
void tst_Line::replaceEndLine()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString *full_line = line->textLine();
int line_size = full_line->size();
QString replace_text("at the end of the string");
TextStyle style = lineHandler.default_style;
style.style = TextStyle::Bold;
line->replaceAtPos(line_size - replace_text.size(), replace_text, style);
QCOMPARE(line->textLine()->size(), line_size);
QVector<TextStyleLine> style_list = line->style_list();
QCOMPARE(style_list.size(), 2);
const TextStyleLine &first_style = style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, line_size - replace_text.size() -1);
QCOMPARE(first_style.style, lineHandler.default_text_style);
const TextStyleLine &second_style = style_list.at(1);
QCOMPARE(second_style.start_index, line_size - replace_text.size());
QCOMPARE(second_style.end_index, line_size - 1);
QCOMPARE(second_style.style, TextStyle::Bold);
}
void tst_Line::clearLine()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QVERIFY(line->textLine()->size() > 0);
QCOMPARE(line->textLine()->trimmed().size(), 0);
}
void tst_Line::clearToEndOfLine1Segment()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString replace_text("To be replaceed");
TextStyle style = lineHandler.default_style;
style.style = TextStyle::Encircled;
line->replaceAtPos(0, replace_text, style);
int before_clear_size = line->textLine()->size();
line->clearToEndOfLine(5);
int after_clear_size = line->textLine()->size();
QCOMPARE(after_clear_size, before_clear_size);
QVector<TextStyleLine> style_list = line->style_list();
QCOMPARE(style_list.size(), 2);
const TextStyleLine &first_style = style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, 4);
const TextStyleLine &second_style = style_list.at(1);
QCOMPARE(second_style.start_index, 5);
QString cleared("To be");
QCOMPARE(line->textLine()->trimmed(), cleared);
}
void tst_Line::clearToEndOfLine3Segment()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString replace_text("To be");
TextStyle style = lineHandler.default_style;
style.style = TextStyle::Encircled;
line->replaceAtPos(0, replace_text, style);
QString replace_text2(" or not to be");
style.style = TextStyle::Bold;
line ->replaceAtPos(replace_text.size(), replace_text2, style);
line->clearToEndOfLine(replace_text.size());
QVector<TextStyleLine> style_list = line->style_list();
QCOMPARE(style_list.size(), 2);
const TextStyleLine &first_style = style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, replace_text.size() - 1);
const TextStyleLine &second_style = style_list.at(1);
QCOMPARE(second_style.start_index, replace_text.size());
QCOMPARE(second_style.style, lineHandler.default_text_style);
}
void tst_Line::clearToEndOfLineMiddle3Segment()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString replace_text("To be");
TextStyle style = lineHandler.default_style;
style.style = TextStyle::Encircled;
line->replaceAtPos(0, replace_text, style);
QString replace_text2(" or not to be");
style.style = TextStyle::Bold;
line ->replaceAtPos(replace_text.size(), replace_text2, style);
line->clearToEndOfLine(replace_text.size() + 3);
QVector<TextStyleLine> style_list = line->style_list();
QCOMPARE(style_list.size(), 3);
const TextStyleLine &first_style = style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, replace_text.size() - 1);
const TextStyleLine &second_style = style_list.at(1);
QCOMPARE(second_style.start_index, replace_text.size());
QCOMPARE(second_style.end_index, replace_text.size() + 2);
const TextStyleLine &third_style = style_list.at(2);
QCOMPARE(third_style.start_index, replace_text.size() + 3);
QCOMPARE(third_style.style, lineHandler.default_text_style);
}
void tst_Line::deleteCharacters1Segment()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString replace_text("replaceing some text");
TextStyle style = lineHandler.default_style;
style.style = TextStyle::Encircled;
line->replaceAtPos(0, replace_text, style);
QString *full_line = line->textLine();
int line_size = full_line->size();
line->deleteCharacters(10,14);
QCOMPARE(line->textLine()->size(), line_size);
QVector<TextStyleLine> style_list = line->style_list();
QCOMPARE(style_list.size(), 2);
const TextStyleLine &first_style = style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, 14);
const TextStyleLine &second_style = style_list.at(1);
QCOMPARE(second_style.start_index, 15);
QCOMPARE(second_style.style, lineHandler.default_text_style);
}
void tst_Line::deleteCharacters2Segments()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString replace_text("replaceing some text");
TextStyle style = lineHandler.default_style;
style.style = TextStyle::Encircled;
line->replaceAtPos(0, replace_text, style);
QString *full_line = line->textLine();
int line_size = full_line->size();
line->deleteCharacters(15,25);
QCOMPARE(line->textLine()->size(), line_size);
QVector<TextStyleLine> style_list = line->style_list();
QCOMPARE(style_list.size(), 2);
const TextStyleLine &first_style = style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, 14);
const TextStyleLine &second_style = style_list.at(1);
QCOMPARE(second_style.start_index, 15);
QCOMPARE(second_style.style, lineHandler.default_text_style);
}
void tst_Line::deleteCharacters3Segments()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString replace_text("replaceing some text");
TextStyle style = lineHandler.default_style;
style.style = TextStyle::Encircled;
line->replaceAtPos(0, replace_text, style);
QString replace_more_text("Some more text");
style.style = TextStyle::Bold;
line->replaceAtPos(replace_text.size(), replace_more_text, style);
QString *full_line = line->textLine();
int line_size = full_line->size();
line->deleteCharacters(10,15);
QCOMPARE(line->textLine()->size(), line_size);
QVector<TextStyleLine> style_list = line->style_list();
QCOMPARE(style_list.size(), 3);
const TextStyleLine &first_style = style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, 13);
const TextStyleLine &second_style = style_list.at(1);
QCOMPARE(second_style.start_index, 14);
QCOMPARE(second_style.end_index, 14 + replace_more_text.size() -1);
QCOMPARE(second_style.style, TextStyle::Bold);
const TextStyleLine &third_style = style_list.at(2);
QCOMPARE(third_style.start_index, 14 + replace_more_text.size());
QCOMPARE(third_style.style, lineHandler.default_text_style);
}
void tst_Line::deleteCharactersRemoveSegmentEnd()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString replace_text("replaceing some text");
TextStyle style = lineHandler.default_style;
style.style = TextStyle::Encircled;
line->replaceAtPos(0, replace_text, style);
QString replace_more_text("Some more text");
style.style = TextStyle::Bold;
line->replaceAtPos(replace_text.size(), replace_more_text, style);
QString *full_line = line->textLine();
int line_size = full_line->size();
line->deleteCharacters(16,33);
QCOMPARE(line->textLine()->size(), line_size);
QVector<TextStyleLine> style_list = line->style_list();
QCOMPARE(style_list.size(), 2);
const TextStyleLine &first_style = style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, 15);
const TextStyleLine &second_style = style_list.at(1);
QCOMPARE(second_style.start_index, 16);
QCOMPARE(second_style.style, lineHandler.default_text_style);
}
void tst_Line::deleteCharactersRemoveSegmentBeginning()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString replace_text("replaceing some text");
TextStyle style = lineHandler.default_style;
style.style = TextStyle::Encircled;
line->replaceAtPos(0, replace_text, style);
QString replace_more_text("Some more text");
style.style = TextStyle::Bold;
line->replaceAtPos(replace_text.size(), replace_more_text, style);
QString *full_line = line->textLine();
int line_size = full_line->size();
line->deleteCharacters(replace_text.size(),replace_text.size() + replace_more_text.size() + 3);
QCOMPARE(line->textLine()->size(), line_size);
QVector<TextStyleLine> style_list = line->style_list();
QCOMPARE(style_list.size(), 2);
const TextStyleLine &first_style = style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, replace_text.size() - 1);
const TextStyleLine &second_style = style_list.at(1);
QCOMPARE(second_style.start_index, replace_text.size());
QCOMPARE(second_style.style, lineHandler.default_text_style);
}
void tst_Line::insertCharacters()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString *full_line = line->textLine();
int line_size = full_line->size();
QString insert_text("inserting some text");
TextStyle style = lineHandler.default_style;
style.style = TextStyle::Encircled;
line->insertAtPos(5, insert_text, style);
QCOMPARE(line->textLine()->size(), line_size);
QVector<TextStyleLine> style_list = line->style_list();
QCOMPARE(style_list.size(), 3);
const TextStyleLine &first_style = style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, 4);
QCOMPARE(first_style.style, lineHandler.default_text_style);
const TextStyleLine &second_style = style_list.at(1);
QCOMPARE(second_style.start_index, 5);
QCOMPARE(second_style.end_index, 5 + insert_text.size() -1);
QCOMPARE(second_style.style, TextStyle::Encircled);
const TextStyleLine &third_style = style_list.at(2);
QCOMPARE(third_style.start_index, 5 + insert_text.size());
QCOMPARE(third_style.end_index, line_size - 1);
QCOMPARE(third_style.style, lineHandler.default_text_style);
}
void tst_Line::insertCharacters2Segments()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString *full_line = line->textLine();
int line_size = full_line->size();
QString replace_text("at the end of the string");
TextStyle style = lineHandler.default_style;
style.style = TextStyle::Bold;
line->replaceAtPos(line_size - replace_text.size(), replace_text, style);
QString insert_text("inserting some text");
style.style = TextStyle::Encircled;
line->insertAtPos(5, insert_text, style);
QCOMPARE(line->textLine()->size(), line_size);
QVector<TextStyleLine> style_list = line->style_list();
QCOMPARE(style_list.size(), 4);
const TextStyleLine &first_style = style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, 4);
QCOMPARE(first_style.style, lineHandler.default_text_style);
const TextStyleLine &second_style = style_list.at(1);
QCOMPARE(second_style.start_index, 5);
QCOMPARE(second_style.end_index, 5 + insert_text.size() -1);
QCOMPARE(second_style.style, TextStyle::Encircled);
const TextStyleLine &third_style = style_list.at(2);
QCOMPARE(third_style.start_index, 5 + insert_text.size());
QCOMPARE(third_style.end_index, line_size -1 - replace_text.size() + insert_text.size());
QCOMPARE(third_style.style, lineHandler.default_text_style);
const TextStyleLine &fourth_style = style_list.at(3);
QCOMPARE(fourth_style.start_index, line_size - replace_text.size() + insert_text.size());
QCOMPARE(fourth_style.end_index, line_size -1 );
QCOMPARE(fourth_style.style, TextStyle::Bold);
}
void tst_Line::insertCharacters3Segments()
{
LineHandler lineHandler;
Line *line = lineHandler.line();
QString *full_line = line->textLine();
int line_size = full_line->size();
QString replace_text("at the end of the string");
TextStyle style = lineHandler.default_style;
style.style = TextStyle::Bold;
line->replaceAtPos(line_size - replace_text.size(), replace_text, style);
QString replace_text2("somewhere in the string");
style.style = TextStyle::Encircled;
line->replaceAtPos(20,replace_text2, style);
QVector<TextStyleLine> tmp_style_list = line->style_list();
QCOMPARE(tmp_style_list.size(), 4);
QString insert_text("this text is longer than last segment");
style.style = TextStyle::Italic;
line->insertAtPos(10, insert_text, style);
QCOMPARE(line->textLine()->size(), line_size);
QVector<TextStyleLine> style_list = line->style_list();
QCOMPARE(style_list.size(), 5);
const TextStyleLine &first_style = style_list.at(0);
QCOMPARE(first_style.start_index, 0);
QCOMPARE(first_style.end_index, 9);
QCOMPARE(first_style.style, lineHandler.default_text_style);
const TextStyleLine &second_style = style_list.at(1);
QCOMPARE(second_style.start_index, 10);
QCOMPARE(second_style.end_index, 10 + insert_text.size() -1);
QCOMPARE(second_style.style, TextStyle::Italic);
const TextStyleLine &third_style = style_list.at(2);
QCOMPARE(third_style.start_index, 10 + insert_text.size());
QCOMPARE(third_style.end_index, 20 + insert_text.size() - 1);
QCOMPARE(third_style.style, lineHandler.default_text_style);
const TextStyleLine &fourth_style = style_list.at(3);
QCOMPARE(fourth_style.start_index, 20 + insert_text.size());
QCOMPARE(fourth_style.end_index, 20 + insert_text.size() + replace_text2.size() - 1);
QCOMPARE(fourth_style.style, TextStyle::Encircled);
const TextStyleLine &fith_style = style_list.at(4);
QCOMPARE(fith_style.start_index, 20 + insert_text.size() + replace_text2.size());
QCOMPARE(fith_style.end_index, line_size - 1);
QCOMPARE(fith_style.style, lineHandler.default_text_style);
}
#include <tst_line.moc>
QTEST_MAIN(tst_Line);

3
yat/tests/tests.pro Normal file
View File

@ -0,0 +1,3 @@
TEMPLATE = subdirs
SUBDIRS = \
auto

5
yat/yat.pro Normal file
View File

@ -0,0 +1,5 @@
TEMPLATE=subdirs
CONFIG += ordered
SUBDIRS= \
yat_declarative \
tests

View File

@ -0,0 +1,43 @@
/**************************************************************************************************
* 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 <QtGui/QGuiApplication>
#include <QtCore/QResource>
#include <QtCore/QThread>
#include <QtQuick/QQuickView>
#include <QtQuick/QQuickItem>
#include "register_qml_types.h"
#include "terminal_screen.h"
#include "yat_pty.h"
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
register_qml_types();
QQuickView view(QUrl("qrc:/qml/yat_declarative/main.qml"));
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.show();
return app.exec();
}

View File

@ -0,0 +1,55 @@
/*******************************************************************************
* 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 "object_destruct_item.h"
ObjectDestructItem::ObjectDestructItem(QQuickItem *parent)
: QQuickItem(parent)
, m_object(0)
{
}
QObject *ObjectDestructItem::objectHandle() const
{
return m_object;
}
void ObjectDestructItem::setObjectHandle(QObject *object)
{
bool emit_changed = m_object != object;
if (m_object) {
m_object->disconnect(this);
}
m_object = object;
connect(m_object, SIGNAL(destroyed()), this, SLOT(objectDestroyed()));
if (emit_changed)
emit objectHandleChanged();
}
void ObjectDestructItem::objectDestroyed()
{
delete this;
}

View File

@ -0,0 +1,52 @@
/*******************************************************************************
* 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 OBJECT_DESTRUCT_ITEM_H
#define OBJECT_DESTRUCT_ITEM_H
#include <QtQuick/QQuickItem>
#include <QtCore/QObject>
class ObjectDestructItem : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(QObject *objectHandle READ objectHandle WRITE setObjectHandle NOTIFY objectHandleChanged)
public:
ObjectDestructItem(QQuickItem *parent = 0);
QObject *objectHandle() const;
void setObjectHandle(QObject *line);
signals:
void objectHandleChanged();
private slots:
void objectDestroyed();
private:
QObject *m_object;
};
#endif //OBJECT_DESTRUCT_ITEM_H

View File

@ -0,0 +1,75 @@
import QtQuick 2.0
Item {
id: highlightArea
property real characterWidth: 0
property real characterHeight: 0
property int screenWidth: width / characterWidth
property point start
property point end
property color color: "grey"
width: parent.width
height: parent.height
opacity: 0.8
Rectangle {
id: begginning_rectangle
color: parent.color
opacity: parent.opacity
y:0
height: characterHeight
}
Rectangle {
id: middle_rectangle
color: parent.color
opacity: parent.opacity
width: parent.width
x: 0
anchors.top: begginning_rectangle.bottom
}
Rectangle {
id: end_rectangle
color: parent.color
opacity: parent.opacity
x: 0
height: characterHeight
anchors.top: middle_rectangle.bottom
}
onCharacterWidthChanged: calculateRectangles();
onCharacterHeightChanged: calculateRectangles();
onScreenWidthChanged: calculateRectangles();
onStartChanged: calculateRectangles();
onEndChanged: calculateRectangles();
function calculateRectangles() {
highlightArea.y = start.y * characterHeight;
begginning_rectangle.x = start.x * characterWidth;
if (start.y === end.y) {
middle_rectangle.visible = false;
end_rectangle.visible = false
begginning_rectangle.width = (end.x - start.x) * characterWidth;
} else {
begginning_rectangle.width = (screenWidth - start.x) * characterWidth;
if (start.y === end.y - 1) {
middle_rectangle.height = 0;
middle_rectangle.visible = false;
}else {
middle_rectangle.visible = true;
middle_rectangle.height = (end.y - start.y - 1) * characterHeight;
}
end_rectangle.visible = true;
end_rectangle.width = end.x * characterWidth;
}
}
}

View File

@ -0,0 +1,34 @@
import QtQuick 2.0
import org.yat 1.0
ObjectDestructItem {
id: textLine
property var textComponent : Qt.createComponent("TerminalText.qml")
property font font
property real fontHeight
property real fontWidth
height: fontHeight
width: parent.width
visible: objectHandle.visible
Connections {
target: objectHandle
onIndexChanged: {
y = objectHandle.index * fontHeight;
}
onTextCreated: {
var textSegment = textComponent.createObject(textLine,
{
"objectHandle" : text,
"font" : textLine.font,
"fontWidth" : textLine.fontWidth,
})
}
}
}

View File

@ -0,0 +1,194 @@
import QtQuick 2.0
import org.yat 1.0
TerminalScreen {
id: screenItem
property font font
property real fontWidth: fontMetricText.paintedWidth
property real fontHeight: fontMetricText.paintedHeight
property var lineComponent : Qt.createComponent("TerminalLine.qml")
font.family: "courier"
Text {
id: fontMetricText
text: "B"
font: parent.font
visible: false
textFormat: Text.PlainText
}
Rectangle {
id: background
anchors.fill: parent
color: "black"
}
Connections {
id: connections
target: terminal.screen
onFlash: {
flashAnimation.start()
}
onCursorPositionChanged: {
cursor.x = x * fontWidth;
cursor.y = y * fontHeight;
}
onReset: {
resetScreenItems();
}
onLineCreated: {
var lineVariable = lineComponent.createObject(screenItem,
{
"objectHandle" : line,
"font": screenItem.font,
"fontWidth" : screenItem.fontWidth,
"fontHeight" : screenItem.fontHeight,
})
}
}
onFontChanged: {
setTerminalHeight();
setTerminalWidth();
}
onWidthChanged: {
setTerminalWidth();
}
onHeightChanged: {
setTerminalHeight();
}
Component.onCompleted: {
setTerminalWidth();
setTerminalHeight();
}
function setTerminalWidth() {
if (fontWidth > 0) {
var pty_width = Math.floor(width / fontWidth);
screen.width = pty_width;
}
}
function setTerminalHeight() {
if (fontHeight > 0) {
var pty_height = Math.floor(height / fontHeight);
screen.height = pty_height;
}
}
Item {
id: keyHandler
focus: true
Keys.onPressed: {
terminal.screen.sendKey(event.text, event.key, event.modifiers);
if (event.text === "?") {
terminal.screen.printScreen()
}
}
}
HighlightArea {
characterHeight: fontHeight
characterWidth: fontWidth
start: screen.selectionAreaStart
end: screen.selectionAreaEnd
visible: screen.selectionEnabled
}
Rectangle {
id: cursor
width: fontWidth
height: fontHeight
x: 0
y: 0
color: "grey"
}
Rectangle {
id: flash
anchors.fill: parent
color: "grey"
opacity: 0
SequentialAnimation {
id: flashAnimation
NumberAnimation {
target: flash
property: "opacity"
to: 1
duration: 75
}
NumberAnimation {
target: flash
property: "opacity"
to: 0
duration: 75
}
}
}
MouseArea {
id:mousArea
property point drag_start
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.MiddleButton
onPressed: {
if (mouse.button == Qt.LeftButton) {
hoverEnabled = true;
var character = Math.floor((mouse.x / screen.charWidth));
var line = Math.floor(mouse.y / screen.lineHeight);
var start = Qt.point(character,line);
drag_start = start;
screen.selectionAreaStart = start;
screen.selectionAreaEnd = start;
}
}
onPositionChanged: {
var character = Math.floor(mouse.x / screen.charWidth);
var line = Math.floor(mouse.y / screen.lineHeight);
var current_pos = Qt.point(character,line);
if (line < drag_start.y || (line === drag_start.y && character < drag_start.x)) {
screen.selectionAreaStart = current_pos;
screen.selectionAreaEnd = drag_start;
}else {
screen.selectionAreaEnd = current_pos;
screen.selectionAreaStart = drag_start;
}
}
onReleased: {
if (mouse.button == Qt.LeftButton) {
hoverEnabled = false;
screen.sendSelectionToSelection();
}
}
onClicked: {
if (mouse.button == Qt.MiddleButton) {
screen.pasteFromSelection();
}
}
onDoubleClicked: {
if (mouse.button == Qt.LeftButton) {
var character = Math.floor(mouse.x / screen.charWidth);
var line = Math.floor(mouse.y / screen.lineHeight);
screen.doubleClicked(Qt.point(character,line));
}
}
}
}

View File

@ -0,0 +1,78 @@
/*******************************************************************************
* 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.
*
*******************************************************************************/
import QtQuick 2.0
import org.yat 1.0
ObjectDestructItem {
id: textItem
property font font
property real fontWidth
y: 0
x: 0
width: textElement.paintedWidth
height: textElement.paintedHeight
visible: objectHandle.visible
Rectangle {
anchors.fill: parent
color: textItem.objectHandle.backgroundColor
}
Text {
id: textElement
anchors.fill: parent
text: objectHandle.text
color: objectHandle.foregroundColor
font: textItem.font
textFormat: Text.PlainText
}
Connections {
target: objectHandle
onIndexChanged: {
textItem.x = objectHandle.index * textItem.fontWidth;
}
}
//Component.onCompleted: {
// //color = randomBg();
//}
//function randomBg()
//{
// var hex1=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
// var hex2=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
// var hex3=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
// var hex4=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
// var hex5=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
// var hex6=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
// var bg="#"+hex1[Math.floor(Math.random()*hex1.length)]+hex2[Math.floor(Math.random()*hex2.length)]+hex3[Math.floor(Math.random()*hex3.length)]+hex4[Math.floor(Math.random()*hex4.length)]+hex5[Math.floor(Math.random()*hex5.length)]+hex6[Math.floor(Math.random()*hex6.length)]
// return bg
//}
}

View File

@ -0,0 +1,7 @@
import QtQuick 2.0
TerminalScreen {
id: terminal
width: 800
height: 600
}

View File

@ -0,0 +1,9 @@
<RCC>
<qresource prefix="/">
<file>qml/yat_declarative/main.qml</file>
<file>qml/yat_declarative/TerminalLine.qml</file>
<file>qml/yat_declarative/TerminalScreen.qml</file>
<file>qml/yat_declarative/TerminalText.qml</file>
<file>qml/yat_declarative/HighlightArea.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,18 @@
#include "register_qml_types.h"
#include <QtQml>
#include "terminal_screen.h"
#include "object_destruct_item.h"
#include "screen.h"
#include "text.h"
#include "line.h"
void register_qml_types()
{
qmlRegisterType<TerminalScreen>("org.yat", 1, 0, "TerminalScreen");
qmlRegisterType<ObjectDestructItem>("org.yat", 1, 0, "ObjectDestructItem");
qmlRegisterType<Screen>();
qmlRegisterType<Text>();
qmlRegisterType<Line>();
}

View File

@ -0,0 +1,6 @@
#ifndef REGISTER_QML_TYPES_H
#define REGISTER_QML_TYPES_H
void register_qml_types();
#endif // REGISTER_QML_TYPES_H

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_screen.h"
TerminalScreen::TerminalScreen(QQuickItem *parent)
: QQuickItem(parent)
, m_screen(new Screen(this))
{
}
Screen *TerminalScreen::screen() const
{
return m_screen;
}

View File

@ -0,0 +1,46 @@
/******************************************************************************
* 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 TERMINALITEM_H
#define TERMINALITEM_H
#include <QtCore/QObject>
#include <QtQuick/QQuickItem>
#include "screen.h"
class TerminalScreen : public QQuickItem
{
Q_OBJECT
Q_PROPERTY(Screen *screen READ screen CONSTANT)
public:
TerminalScreen(QQuickItem *parent = 0);
Screen *screen() const;
private:
Screen *m_screen;
};
#endif // TERMINALITEM_H

View File

@ -0,0 +1,27 @@
QT += gui quick
TARGET = yat
include(../backend/backend.pri)
SOURCES += main.cpp \
terminal_screen.cpp \
object_destruct_item.cpp \
register_qml_types.cpp \
HEADERS += \
terminal_screen.h \
object_destruct_item.h \
register_qml_types.h \
QML_IMPORT_PATH =
OTHER_FILES += \
qml/yat_declarative/main.qml \
qml/yat_declarative/TerminalLine.qml \
qml/yat_declarative/TerminalScreen.qml \
qml/yat_declarative/TerminalText.qml \
qml/yat_declarative/HighlightArea.qml
RESOURCES += \
qml_sources.qrc