mirror of
https://github.com/Swordfish90/cool-retro-term.git
synced 2025-01-18 12:15:27 +00:00
Moved to new version of yat. Yat is no longer a submodule but is now integrated.
This commit is contained in:
parent
bd39a63a64
commit
6b4b187df5
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -1,4 +0,0 @@
|
||||
[submodule "yat"]
|
||||
path = yat
|
||||
url = https://github.com/Swordifish90/yat
|
||||
branch = stable
|
@ -1,4 +1,4 @@
|
||||
QT += widgets quick
|
||||
QT += widgets quick core-private gui-private qml-private quick quick-private
|
||||
|
||||
include(yat/yat_declarative/yat_declarative.pro)
|
||||
|
||||
|
@ -1,3 +1,26 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
|
||||
Item {
|
||||
@ -5,15 +28,19 @@ Item {
|
||||
|
||||
property real characterWidth: 0
|
||||
property real characterHeight: 0
|
||||
property int screenWidth: width / characterWidth
|
||||
property int screenWidth: 0
|
||||
|
||||
property point start
|
||||
property point end
|
||||
property int startX
|
||||
property int startY
|
||||
|
||||
property int endX
|
||||
property int endY
|
||||
|
||||
property color color: "grey"
|
||||
|
||||
y: startY * characterHeight
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
height: (endY - startY + 1) * characterHeight
|
||||
|
||||
opacity: 0.8
|
||||
|
||||
@ -48,27 +75,29 @@ Item {
|
||||
onCharacterHeightChanged: calculateRectangles();
|
||||
onScreenWidthChanged: calculateRectangles();
|
||||
|
||||
onStartChanged: calculateRectangles();
|
||||
onEndChanged: calculateRectangles();
|
||||
onStartXChanged: calculateRectangles();
|
||||
onStartYChanged: calculateRectangles();
|
||||
onEndXChanged: calculateRectangles();
|
||||
onEndYChanged: calculateRectangles();
|
||||
|
||||
function calculateRectangles() {
|
||||
highlightArea.y = start.y * characterHeight;
|
||||
begginning_rectangle.x = start.x * characterWidth;
|
||||
if (start.y === end.y) {
|
||||
highlightArea.y = startY * characterHeight;
|
||||
begginning_rectangle.x = startX * characterWidth;
|
||||
if (startY === endY) {
|
||||
middle_rectangle.visible = false;
|
||||
end_rectangle.visible = false
|
||||
begginning_rectangle.width = (end.x - start.x) * characterWidth;
|
||||
begginning_rectangle.width = (endX - startX) * characterWidth;
|
||||
} else {
|
||||
begginning_rectangle.width = (screenWidth - start.x) * characterWidth;
|
||||
if (start.y === end.y - 1) {
|
||||
begginning_rectangle.width = (screenWidth - startX) * characterWidth;
|
||||
if (startY === endY - 1) {
|
||||
middle_rectangle.height = 0;
|
||||
middle_rectangle.visible = false;
|
||||
}else {
|
||||
middle_rectangle.visible = true;
|
||||
middle_rectangle.height = (end.y - start.y - 1) * characterHeight;
|
||||
middle_rectangle.height = (endY - startY - 1) * characterHeight;
|
||||
}
|
||||
end_rectangle.visible = true;
|
||||
end_rectangle.width = end.x * characterWidth;
|
||||
end_rectangle.width = endX * characterWidth;
|
||||
}
|
||||
}
|
||||
|
||||
|
66
qml/cool-old-term/TerminalCursor.qml
Normal file
66
qml/cool-old-term/TerminalCursor.qml
Normal file
@ -0,0 +1,66 @@
|
||||
/*******************************************************************************
|
||||
* 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: cursor
|
||||
|
||||
property real fontHeight
|
||||
property real fontWidth
|
||||
|
||||
height: fontHeight
|
||||
width: fontWidth
|
||||
x: objectHandle.x * fontWidth
|
||||
y: objectHandle.y * fontHeight
|
||||
z: 1.1
|
||||
|
||||
visible: objectHandle.visible
|
||||
|
||||
ShaderEffect {
|
||||
anchors.fill: parent
|
||||
|
||||
property variant source: fragmentSource
|
||||
|
||||
fragmentShader:
|
||||
"uniform lowp float qt_Opacity;" +
|
||||
"uniform sampler2D source;" +
|
||||
"varying highp vec2 qt_TexCoord0;" +
|
||||
|
||||
"void main() {" +
|
||||
" lowp vec4 color = texture2D(source, qt_TexCoord0 ) * qt_Opacity;" +
|
||||
" gl_FragColor = vec4(1.0 - color.r, 1.0 - color.g, 1.0 - color.b, color.a);" +
|
||||
"}"
|
||||
|
||||
ShaderEffectSource {
|
||||
id: fragmentSource
|
||||
sourceItem: background
|
||||
live: true
|
||||
|
||||
sourceRect: Qt.rect(cursor.x,cursor.y,cursor.width,cursor.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,28 @@
|
||||
/*******************************************************************************
|
||||
* 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 QtQuick.Controls 1.1
|
||||
|
||||
import org.yat 1.0
|
||||
|
||||
@ -10,10 +34,35 @@ TerminalScreen {
|
||||
property real fontHeight: fontMetricText.paintedHeight
|
||||
|
||||
property var lineComponent : Qt.createComponent("TerminalLine.qml")
|
||||
property var textComponent : Qt.createComponent("TerminalText.qml")
|
||||
property var cursorComponent : Qt.createComponent("TerminalCursor.qml")
|
||||
|
||||
font.family: "Pet Me"
|
||||
font.pointSize: 14
|
||||
//font.bold: true
|
||||
font.pixelSize: 20
|
||||
focus: true
|
||||
|
||||
Action {
|
||||
id: copyAction
|
||||
shortcut: "Ctrl+Shift+C"
|
||||
onTriggered: screen.selection.sendToClipboard()
|
||||
}
|
||||
Action {
|
||||
id: paseAction
|
||||
shortcut: "Ctrl+Shift+V"
|
||||
onTriggered: screen.selection.pasteFromClipboard()
|
||||
}
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
Qt.inputMethod.show();
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.text === "?") {
|
||||
terminal.screen.printScreen()
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: fontMetricText
|
||||
@ -23,10 +72,47 @@ TerminalScreen {
|
||||
textFormat: Text.PlainText
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
color: "black"
|
||||
Flickable {
|
||||
id: flickable
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
contentWidth: width
|
||||
contentHeight: textContainer.height
|
||||
interactive: true
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
contentY: ((screen.contentHeight - screen.height) * screenItem.fontHeight)
|
||||
|
||||
Item {
|
||||
id: textContainer
|
||||
width: parent.width
|
||||
height: screen.contentHeight * screenItem.fontHeight
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
color: terminal.screen.defaultBackgroundColor
|
||||
}
|
||||
|
||||
HighlightArea {
|
||||
characterHeight: fontHeight
|
||||
characterWidth: fontWidth
|
||||
screenWidth: terminalWindow.width
|
||||
|
||||
startX: screen.selection.startX
|
||||
startY: screen.selection.startY
|
||||
|
||||
endX: screen.selection.endX
|
||||
endY: screen.selection.endY
|
||||
|
||||
visible: screen.selection.enable
|
||||
}
|
||||
}
|
||||
|
||||
onContentYChanged: {
|
||||
if (!atYEnd) {
|
||||
var top_line = Math.floor(Math.max(contentY,0) / screenItem.fontHeight);
|
||||
screen.ensureVisiblePages(top_line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
@ -38,24 +124,44 @@ TerminalScreen {
|
||||
flashAnimation.start()
|
||||
}
|
||||
|
||||
onCursorPositionChanged: {
|
||||
cursor.x = x * fontWidth;
|
||||
cursor.y = y * fontHeight;
|
||||
}
|
||||
|
||||
onReset: {
|
||||
resetScreenItems();
|
||||
}
|
||||
|
||||
onLineCreated: {
|
||||
var lineVariable = lineComponent.createObject(screenItem,
|
||||
onTextCreated: {
|
||||
var textSegment = textComponent.createObject(screenItem,
|
||||
{
|
||||
"objectHandle" : line,
|
||||
"font": screenItem.font,
|
||||
"parent" : background,
|
||||
"objectHandle" : text,
|
||||
"font" : screenItem.font,
|
||||
"fontWidth" : screenItem.fontWidth,
|
||||
"fontHeight" : screenItem.fontHeight,
|
||||
})
|
||||
}
|
||||
|
||||
onCursorCreated: {
|
||||
if (cursorComponent.status != Component.Ready) {
|
||||
console.log(cursorComponent.errorString());
|
||||
return;
|
||||
}
|
||||
var cursorVariable = cursorComponent.createObject(screenItem,
|
||||
{
|
||||
"parent" : textContainer,
|
||||
"objectHandle" : cursor,
|
||||
"fontWidth" : screenItem.fontWidth,
|
||||
"fontHeight" : screenItem.fontHeight,
|
||||
})
|
||||
}
|
||||
|
||||
onRequestHeightChange: {
|
||||
terminalWindow.height = newHeight * screenItem.fontHeight;
|
||||
terminalWindow.contentItem.height = newHeight * screenItem.fontHeight;
|
||||
}
|
||||
|
||||
onRequestWidthChange: {
|
||||
terminalWindow.width = newWidth * screenItem.fontWidth;
|
||||
terminalWindow.contentItem.width = newWidth * screenItem.fontWidth;
|
||||
}
|
||||
}
|
||||
|
||||
onFontChanged: {
|
||||
@ -77,6 +183,7 @@ TerminalScreen {
|
||||
function setTerminalWidth() {
|
||||
if (fontWidth > 0) {
|
||||
var pty_width = Math.floor(width / fontWidth);
|
||||
flickable.width = pty_width * fontWidth;
|
||||
screen.width = pty_width;
|
||||
}
|
||||
}
|
||||
@ -84,50 +191,16 @@ TerminalScreen {
|
||||
function setTerminalHeight() {
|
||||
if (fontHeight > 0) {
|
||||
var pty_height = Math.floor(height / fontHeight);
|
||||
flickable.height = pty_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: "white"
|
||||
// SequentialAnimation on opacity{
|
||||
// NumberAnimation{from: 0; to: 1; duration: 500}
|
||||
// NumberAnimation{from: 1; to: 0; duration: 500}
|
||||
// loops: Animation.Infinite
|
||||
// }
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: flash
|
||||
z: 1.2
|
||||
anchors.fill: parent
|
||||
color: "white"
|
||||
color: "grey"
|
||||
opacity: 0
|
||||
SequentialAnimation {
|
||||
id: flashAnimation
|
||||
@ -149,39 +222,49 @@ TerminalScreen {
|
||||
MouseArea {
|
||||
id:mousArea
|
||||
|
||||
property point drag_start
|
||||
property int drag_start_x
|
||||
property int drag_start_y
|
||||
|
||||
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 transformed_mouse = mapToItem(textContainer, mouse.x, mouse.y);
|
||||
var character = Math.floor((transformed_mouse.x / fontWidth));
|
||||
var line = Math.floor(transformed_mouse.y / fontHeight);
|
||||
var start = Qt.point(character,line);
|
||||
drag_start = start;
|
||||
screen.selectionAreaStart = start;
|
||||
screen.selectionAreaEnd = start;
|
||||
drag_start_x = character;
|
||||
drag_start_y = line;
|
||||
screen.selection.startX = character;
|
||||
screen.selection.startY = line;
|
||||
screen.selection.endX = character;
|
||||
screen.selection.endY = line;
|
||||
}
|
||||
}
|
||||
|
||||
onPositionChanged: {
|
||||
var character = Math.floor(mouse.x / screen.charWidth);
|
||||
var line = Math.floor(mouse.y / screen.lineHeight);
|
||||
var transformed_mouse = mapToItem(textContainer, mouse.x, mouse.y);
|
||||
var character = Math.floor(transformed_mouse.x / fontWidth);
|
||||
var line = Math.floor(transformed_mouse.y / fontHeight);
|
||||
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;
|
||||
if (line < drag_start_y || (line === drag_start_y && character < drag_start_x)) {
|
||||
screen.selection.startX = character;
|
||||
screen.selection.startY = line;
|
||||
screen.selection.endX = drag_start_x;
|
||||
screen.selection.endY = drag_start_y;
|
||||
}else {
|
||||
screen.selectionAreaEnd = current_pos;
|
||||
screen.selectionAreaStart = drag_start;
|
||||
screen.selection.startX = drag_start_x;
|
||||
screen.selection.startY = drag_start_y;
|
||||
screen.selection.endX = character;
|
||||
screen.selection.endY = line;
|
||||
}
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (mouse.button == Qt.LeftButton) {
|
||||
hoverEnabled = false;
|
||||
screen.sendSelectionToSelection();
|
||||
screen.selection.sendToSelection();
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,10 +273,12 @@ TerminalScreen {
|
||||
screen.pasteFromSelection();
|
||||
}
|
||||
}
|
||||
|
||||
onDoubleClicked: {
|
||||
if (mouse.button == Qt.LeftButton) {
|
||||
var character = Math.floor(mouse.x / screen.charWidth);
|
||||
var line = Math.floor(mouse.y / screen.lineHeight);
|
||||
var transformed_mouse = mapToItem(textContainer, mouse.x, mouse.y);
|
||||
var character = Math.floor(transformed_mouse.x / fontWidth);
|
||||
var line = Math.floor(transformed_mouse.y / fontHeight);
|
||||
screen.doubleClicked(Qt.point(character,line));
|
||||
}
|
||||
}
|
||||
|
@ -29,9 +29,10 @@ ObjectDestructItem {
|
||||
id: textItem
|
||||
property font font
|
||||
property real fontWidth
|
||||
property real fontHeight
|
||||
|
||||
y: 0
|
||||
x: 0
|
||||
y: objectHandle.line * fontHeight;
|
||||
x: objectHandle.index * fontWidth;
|
||||
|
||||
width: textElement.paintedWidth
|
||||
height: textElement.paintedHeight
|
||||
@ -40,39 +41,41 @@ ObjectDestructItem {
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: textItem.objectHandle.backgroundColor
|
||||
}
|
||||
color: "black" //objectHandle.backgroundColor
|
||||
|
||||
MonoText {
|
||||
id: textElement
|
||||
anchors.fill: parent
|
||||
text: objectHandle.text
|
||||
color: "white" //objectHandle.foregroundColor
|
||||
font.family: textItem.font.family
|
||||
font.pixelSize: textItem.font.pixelSize
|
||||
font.pointSize: textItem.font.pointSize
|
||||
font.bold: objectHandle.bold
|
||||
font.underline: objectHandle.underline
|
||||
latin: objectHandle.latin
|
||||
|
||||
Text {
|
||||
id: textElement
|
||||
anchors.fill: parent
|
||||
text: objectHandle.text
|
||||
color: "white"
|
||||
font: textItem.font
|
||||
textFormat: Text.PlainText
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: objectHandle
|
||||
|
||||
onIndexChanged: {
|
||||
textItem.x = objectHandle.index * textItem.fontWidth;
|
||||
SequentialAnimation {
|
||||
running: objectHandle.blinking
|
||||
loops: Animation.Infinite
|
||||
onRunningChanged: {
|
||||
if (running === false)
|
||||
textElement.opacity = 1
|
||||
}
|
||||
NumberAnimation {
|
||||
target: textElement
|
||||
property: "opacity"
|
||||
to: 0
|
||||
duration: 250
|
||||
}
|
||||
NumberAnimation {
|
||||
target: textElement
|
||||
property: "opacity"
|
||||
to: 1
|
||||
duration: 250
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//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
|
||||
//}
|
||||
}
|
||||
|
@ -229,13 +229,12 @@ ApplicationWindow{
|
||||
|
||||
TerminalScreen {
|
||||
id: terminal
|
||||
anchors.centerIn: parent
|
||||
width: mainwindow.width
|
||||
height: mainwindow.height
|
||||
visible: false
|
||||
anchors.fill: parent
|
||||
|
||||
//FIXME: Ugly forced clear terminal at the beginning
|
||||
Component.onCompleted: terminal.screen.sendKey("l", 76, 67108864);
|
||||
Component.onCompleted: {
|
||||
terminal.screen.sendKey("l", 76, 67108864);
|
||||
}
|
||||
}
|
||||
|
||||
RadialGradient{
|
||||
|
1
yat
1
yat
@ -1 +0,0 @@
|
||||
Subproject commit fb2266d7a1ef32e36f6c74f986fa831d1fc73588
|
8
yat/README
Normal file
8
yat/README
Normal file
@ -0,0 +1,8 @@
|
||||
forked at 8c3d6c85c3dc981bca817bd9052a693570e26e6e
|
||||
|
||||
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.
|
41
yat/backend/backend.pri
Normal file
41
yat/backend/backend.pri
Normal file
@ -0,0 +1,41 @@
|
||||
DEPENDPATH += $$PWD
|
||||
INCLUDEPATH += $$PWD
|
||||
|
||||
LIBS += -lutil
|
||||
|
||||
CONFIG += c++11
|
||||
|
||||
MOC_DIR = .moc
|
||||
OBJECTS_DIR = .obj
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/yat_pty.h \
|
||||
$$PWD/text.h \
|
||||
$$PWD/controll_chars.h \
|
||||
$$PWD/parser.h \
|
||||
$$PWD/screen.h \
|
||||
$$PWD/block.h \
|
||||
$$PWD/color_palette.h \
|
||||
$$PWD/text_style.h \
|
||||
$$PWD/screen_data.h \
|
||||
$$PWD/cursor.h \
|
||||
$$PWD/nrc_text_codec.h \
|
||||
$$PWD/scrollback.h \
|
||||
$$PWD/utf8_decoder.h \
|
||||
$$PWD/selection.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/yat_pty.cpp \
|
||||
$$PWD/text.cpp \
|
||||
$$PWD/controll_chars.cpp \
|
||||
$$PWD/parser.cpp \
|
||||
$$PWD/screen.cpp \
|
||||
$$PWD/block.cpp \
|
||||
$$PWD/color_palette.cpp \
|
||||
$$PWD/text_style.cpp \
|
||||
$$PWD/screen_data.cpp \
|
||||
$$PWD/cursor.cpp \
|
||||
$$PWD/nrc_text_codec.cpp \
|
||||
$$PWD/scrollback.cpp \
|
||||
$$PWD/selection.cpp
|
||||
|
557
yat/backend/block.cpp
Normal file
557
yat/backend/block.cpp
Normal file
@ -0,0 +1,557 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2012 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "block.h"
|
||||
|
||||
#include "text.h"
|
||||
#include "screen.h"
|
||||
|
||||
#include <QtQuick/QQuickView>
|
||||
#include <QtQuick/QQuickItem>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
Block::Block(Screen *screen)
|
||||
: m_screen(screen)
|
||||
, m_line(0)
|
||||
, m_new_line(-1)
|
||||
, m_screen_index(0)
|
||||
, m_width(m_screen->width())
|
||||
, m_visible(true)
|
||||
, m_changed(true)
|
||||
, m_only_latin(true)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
Block::~Block()
|
||||
{
|
||||
for (int i = 0; i < m_style_list.size(); i++) {
|
||||
m_style_list[i].releaseTextSegment(m_screen);
|
||||
}
|
||||
}
|
||||
|
||||
Screen *Block::screen() const
|
||||
{
|
||||
return m_screen;
|
||||
}
|
||||
|
||||
void Block::clear()
|
||||
{
|
||||
m_text_line.clear();
|
||||
|
||||
for (int i = 0; i < m_style_list.size(); i++) {
|
||||
m_style_list[i].releaseTextSegment(m_screen);
|
||||
}
|
||||
|
||||
m_style_list.clear();
|
||||
|
||||
m_only_latin = true;
|
||||
m_changed = true;
|
||||
}
|
||||
|
||||
void Block::clearToEnd(int from)
|
||||
{
|
||||
clearCharacters(from, m_text_line.size() - 1);
|
||||
}
|
||||
|
||||
void Block::clearCharacters(int from, int to)
|
||||
{
|
||||
if (from > m_text_line.size())
|
||||
return;
|
||||
|
||||
QString empty(to+1-from, QChar(' '));
|
||||
const TextStyle &defaultTextStyle = m_screen->defaultTextStyle();
|
||||
replaceAtPos(from, empty, defaultTextStyle);
|
||||
}
|
||||
|
||||
void Block::deleteCharacters(int from, int to)
|
||||
{
|
||||
m_changed = true;
|
||||
|
||||
int removed = 0;
|
||||
const int size = (to + 1) - from;
|
||||
bool found = false;
|
||||
|
||||
int last_index = -1;
|
||||
|
||||
for (int i = 0; i < m_style_list.size(); i++) {
|
||||
TextStyleLine ¤t_style = m_style_list[i];
|
||||
last_index = i;
|
||||
if (found) {
|
||||
current_style.start_index -= removed;
|
||||
current_style.end_index -= removed;
|
||||
current_style.index_dirty = true;
|
||||
if (removed != size) {
|
||||
int current_style_size = current_style.end_index + 1 - current_style.start_index;
|
||||
if (current_style_size <= size - removed) {
|
||||
removed += current_style.end_index + 1 - current_style.start_index;
|
||||
current_style.releaseTextSegment(m_screen);
|
||||
m_style_list.remove(i);
|
||||
i--;
|
||||
} else {
|
||||
current_style.end_index -= size - removed;
|
||||
removed = size;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (current_style.start_index <= from && current_style.end_index >= from) {
|
||||
found = true;
|
||||
int left_in_style = (current_style.end_index + 1) - from;
|
||||
int subtract = std::min(left_in_style, size);
|
||||
current_style.end_index -= subtract;
|
||||
current_style.text_dirty = true;
|
||||
removed = subtract;
|
||||
if (current_style.end_index < current_style.start_index) {
|
||||
current_style.releaseTextSegment(m_screen);
|
||||
m_style_list.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (last_index >= 0) {
|
||||
TextStyleLine &last_modified = m_style_list[last_index];
|
||||
TextStyle defaultStyle = m_screen->defaultTextStyle();
|
||||
if (last_modified.isCompatible(defaultStyle)) {
|
||||
last_modified.end_index += size;
|
||||
last_modified.text_dirty = true;
|
||||
} else {
|
||||
m_style_list.insert(last_index + 1, TextStyleLine(defaultStyle,
|
||||
last_modified.end_index + 1, last_modified.end_index + size));
|
||||
}
|
||||
}
|
||||
|
||||
m_text_line.remove(from, size);
|
||||
}
|
||||
|
||||
void Block::deleteToEnd(int from)
|
||||
{
|
||||
deleteCharacters(from, m_text_line.size() - 1);
|
||||
}
|
||||
|
||||
void Block::deleteLines(int from)
|
||||
{
|
||||
if (from > lineCount())
|
||||
return;
|
||||
}
|
||||
|
||||
void Block::replaceAtPos(int pos, const QString &text, const TextStyle &style, bool only_latin)
|
||||
{
|
||||
m_changed = true;
|
||||
m_only_latin = m_only_latin && only_latin;
|
||||
|
||||
if (pos >= m_text_line.size()) {
|
||||
if (pos > m_text_line.size()) {
|
||||
int old_size = m_text_line.size();
|
||||
QString filling(pos - m_text_line.size(), QChar(' '));
|
||||
m_text_line.append(filling);
|
||||
m_style_list.append(TextStyleLine(m_screen->defaultTextStyle(), old_size, old_size + filling.size() -1));
|
||||
}
|
||||
m_text_line.append(text);
|
||||
m_style_list.append(TextStyleLine(style, pos, pos + text.size()-1));
|
||||
return;
|
||||
} else if (pos + text.size() > m_text_line.size()) {
|
||||
m_style_list.append(TextStyleLine(m_screen->defaultTextStyle(), pos + text.size() - m_text_line.size(), pos + text.size() -1));
|
||||
}
|
||||
|
||||
m_text_line.replace(pos,text.size(),text);
|
||||
bool found = false;
|
||||
for (int i = 0; i < m_style_list.size(); i++) {
|
||||
TextStyleLine ¤t_style = m_style_list[i];
|
||||
if (found) {
|
||||
if (current_style.end_index <= pos + text.size() - 1) {
|
||||
current_style.releaseTextSegment(m_screen);
|
||||
m_style_list.remove(i);
|
||||
i--;
|
||||
} else if (current_style.start_index <= pos + text.size()) {
|
||||
current_style.start_index = pos + text.size();
|
||||
current_style.style_dirty = true;
|
||||
current_style.text_dirty = true;
|
||||
current_style.index_dirty = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} else if (pos >= current_style.start_index && pos <= current_style.end_index) {
|
||||
found = true;
|
||||
if (pos + text.size() -1 <= current_style.end_index) {
|
||||
if (current_style.isCompatible(style)) {
|
||||
current_style.text_dirty = true;
|
||||
} else {
|
||||
if (current_style.start_index == pos && current_style.end_index == pos + text.size() - 1) {
|
||||
current_style.setStyle(style);
|
||||
current_style.text_dirty = true;
|
||||
current_style.style_dirty = true;
|
||||
} else if (current_style.start_index == pos) {
|
||||
current_style.start_index = pos + text.size();
|
||||
current_style.text_dirty = true;
|
||||
m_style_list.insert(i, TextStyleLine(style,pos, pos+text.size() -1));
|
||||
} else if (current_style.end_index == pos + text.size() - 1) {
|
||||
current_style.end_index = pos - 1;
|
||||
current_style.text_dirty = true;
|
||||
m_style_list.insert(i+1, TextStyleLine(style,pos, pos + text.size() - 1));
|
||||
} else {
|
||||
int old_end = current_style.end_index;
|
||||
current_style.end_index = pos - 1;
|
||||
current_style.text_dirty = true;
|
||||
m_style_list.insert(i+1, TextStyleLine(style,pos, pos + text.size() - 1));
|
||||
if (pos + text.size() < m_text_line.size()) {
|
||||
m_style_list.insert(i+2, TextStyleLine(current_style,pos + text.size(), old_end));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
if (current_style.isCompatible(style)) {
|
||||
current_style.end_index = pos + text.size() - 1;
|
||||
current_style.text_dirty = true;
|
||||
} else {
|
||||
if (current_style.start_index == pos) {
|
||||
if (i > 0 && m_style_list.at(i-1).isCompatible(style)) {
|
||||
TextStyleLine &previous_style = m_style_list[i -1];
|
||||
previous_style.end_index+= text.size();
|
||||
previous_style.text_dirty = true;
|
||||
current_style.releaseTextSegment(m_screen);
|
||||
m_style_list.remove(i);
|
||||
i--;
|
||||
} else {
|
||||
current_style.end_index = pos + text.size() - 1;
|
||||
current_style.style = style.style;
|
||||
current_style.forground = style.forground;
|
||||
current_style.background = style.background;
|
||||
current_style.text_dirty = true;
|
||||
current_style.style_dirty = true;
|
||||
current_style.index_dirty = true;
|
||||
}
|
||||
} else {
|
||||
current_style.end_index = pos - 1;
|
||||
current_style.text_dirty = true;
|
||||
m_style_list.insert(i+1, TextStyleLine(style, pos, pos + text.size() -1));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Block::insertAtPos(int pos, const QString &text, const TextStyle &style, bool only_latin)
|
||||
{
|
||||
m_changed = true;
|
||||
m_only_latin = m_only_latin && only_latin;
|
||||
|
||||
m_text_line.insert(pos,text);
|
||||
bool found = false;
|
||||
|
||||
for (int i = 0; i < m_style_list.size(); i++) {
|
||||
TextStyleLine ¤t_style = m_style_list[i];
|
||||
if (found) {
|
||||
current_style.start_index += text.size();
|
||||
current_style.end_index += text.size();
|
||||
current_style.index_dirty = true;
|
||||
if (current_style.start_index >= m_text_line.size()) {
|
||||
current_style.releaseTextSegment(m_screen);
|
||||
m_style_list.remove(i);
|
||||
i--;
|
||||
} else if (current_style.end_index >= m_text_line.size()) {
|
||||
current_style.end_index = m_text_line.size()-1;
|
||||
}
|
||||
} else if (pos >= current_style.start_index && pos <= current_style.end_index) {
|
||||
found = true;
|
||||
if (current_style.start_index == pos) {
|
||||
current_style.start_index += text.size();
|
||||
current_style.end_index += text.size();
|
||||
current_style.index_dirty = true;
|
||||
m_style_list.insert(i, TextStyleLine(style, pos, pos+ text.size() - 1));
|
||||
i++;
|
||||
} else if (current_style.end_index == pos) {
|
||||
current_style.end_index--;
|
||||
current_style.text_dirty = true;
|
||||
m_style_list.insert(i+1, TextStyleLine(style, pos, pos+ text.size() - 1));
|
||||
i++;
|
||||
} else {
|
||||
int old_end = current_style.end_index;
|
||||
current_style.end_index = pos -1;
|
||||
current_style.text_dirty = true;
|
||||
m_style_list.insert(i+1, TextStyleLine(style, pos, pos + text.size() - 1));
|
||||
if (pos + text.size() < m_text_line.size()) {
|
||||
int segment_end = std::min(m_text_line.size() -1, old_end + text.size());
|
||||
m_style_list.insert(i+2, TextStyleLine(current_style, pos + text.size(), segment_end));
|
||||
i+=2;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString *Block::textLine()
|
||||
{
|
||||
return &m_text_line;
|
||||
}
|
||||
|
||||
void Block::setVisible(bool visible)
|
||||
{
|
||||
if (visible != m_visible) {
|
||||
m_changed = true;
|
||||
m_visible = visible;
|
||||
for (int i = 0; i < m_style_list.size(); i++) {
|
||||
if (m_style_list.at(i).text_segment) {
|
||||
m_style_list.at(i).text_segment->setVisible(visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool Block::visible() const
|
||||
{
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
Block *Block::split(int line)
|
||||
{
|
||||
if (line >= lineCount())
|
||||
return nullptr;
|
||||
m_changed = true;
|
||||
Block *to_return = new Block(m_screen);
|
||||
int start_index = line * m_width;
|
||||
for (int i = 0; i < m_style_list.size(); i++) {
|
||||
ensureStyleAlignWithLines(i);
|
||||
TextStyleLine ¤t_style = m_style_list[i];
|
||||
if (current_style.start_index >= start_index) {
|
||||
current_style.start_index -= start_index;
|
||||
current_style.old_index = current_style.start_index - 1;
|
||||
current_style.end_index -= start_index;
|
||||
current_style.index_dirty = true;
|
||||
current_style.text_dirty = true;
|
||||
current_style.index_dirty = true;
|
||||
to_return->m_style_list.append(TextStyleLine(current_style, current_style.start_index,
|
||||
current_style.end_index));
|
||||
m_style_list.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
to_return->m_text_line = m_text_line.mid(start_index, m_text_line.size() - start_index);
|
||||
m_text_line.remove(start_index, m_text_line.size() - start_index);
|
||||
return to_return;
|
||||
}
|
||||
|
||||
Block *Block::takeLine(int line)
|
||||
{
|
||||
if (line >= lineCount())
|
||||
return nullptr;
|
||||
m_changed = true;
|
||||
Block *to_return = new Block(m_screen);
|
||||
int start_index = line * m_width;
|
||||
int end_index = start_index + (m_width - 1);
|
||||
for (int i = 0; i < m_style_list.size(); i++) {
|
||||
ensureStyleAlignWithLines(i);
|
||||
TextStyleLine ¤t_style = m_style_list[i];
|
||||
if (current_style.start_index >= start_index && current_style.end_index <= end_index) {
|
||||
current_style.releaseTextSegment(m_screen);
|
||||
current_style.start_index -= start_index;
|
||||
current_style.end_index -= start_index;
|
||||
current_style.index_dirty = true;
|
||||
to_return->m_style_list.append(TextStyleLine(current_style, current_style.start_index,
|
||||
current_style.end_index));
|
||||
m_style_list.remove(i);
|
||||
i--;
|
||||
} else if (current_style.start_index > end_index) {
|
||||
current_style.start_index -= (end_index + 1) - start_index;
|
||||
current_style.end_index -= (end_index + 1) - start_index;
|
||||
current_style.index_dirty = true;
|
||||
current_style.text_dirty = true;
|
||||
}
|
||||
}
|
||||
to_return->m_text_line = m_text_line.mid(start_index, m_width);
|
||||
m_text_line.remove(start_index, m_width);
|
||||
return to_return;
|
||||
}
|
||||
|
||||
void Block::removeLine(int line)
|
||||
{
|
||||
if (line >= lineCount())
|
||||
return;
|
||||
|
||||
m_changed = true;
|
||||
int start_index = line * m_width;
|
||||
int end_index = start_index + (m_width - 1);
|
||||
for (int i = 0; i < m_style_list.size(); i++) {
|
||||
ensureStyleAlignWithLines(i);
|
||||
TextStyleLine ¤t_style = m_style_list[i];
|
||||
if (current_style.start_index >= start_index && current_style.end_index <= end_index) {
|
||||
current_style.releaseTextSegment(m_screen);
|
||||
m_style_list.remove(i);
|
||||
i--;
|
||||
} else if (current_style.start_index > end_index) {
|
||||
current_style.start_index -= (end_index + 1) - start_index;
|
||||
current_style.end_index -= (end_index + 1) - start_index;
|
||||
current_style.index_dirty = true;
|
||||
current_style.text_dirty = true;
|
||||
}
|
||||
}
|
||||
m_text_line.remove(start_index, m_width);
|
||||
}
|
||||
|
||||
void Block::moveLinesFromBlock(Block *block, int start_line, int count)
|
||||
{
|
||||
Q_ASSERT(block);
|
||||
Q_ASSERT(block->lineCount() >= start_line + count);
|
||||
|
||||
int start_char = block->width() * start_line;
|
||||
int end_char = (block->width() * (start_line + count)) - 1;
|
||||
|
||||
for (int i = 0; i < block->m_style_list.size(); i++) {
|
||||
TextStyleLine ¤t_style = block->m_style_list[i];
|
||||
if (current_style.start_index >= start_char && current_style.end_index <= end_char) {
|
||||
current_style.start_index += (-start_char + m_text_line.size());
|
||||
current_style.end_index += (-start_char + m_text_line.size());
|
||||
current_style.releaseTextSegment(m_screen);
|
||||
m_style_list.append(TextStyleLine(current_style, current_style.start_index,
|
||||
current_style.end_index));
|
||||
block->m_style_list.remove(i);
|
||||
i--;
|
||||
} else if (current_style.start_index > end_char) {
|
||||
current_style.start_index -= (end_char + 1) - start_char;
|
||||
current_style.end_index -= (end_char + 1) - start_char;
|
||||
current_style.index_dirty = true;
|
||||
current_style.text_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
m_text_line.append(block->m_text_line.mid(start_char, (end_char + 1) - start_char));
|
||||
block->m_text_line.remove(start_char, (end_char + 1) - start_char);
|
||||
m_changed = true;
|
||||
block->m_changed = true;
|
||||
}
|
||||
|
||||
void Block::dispatchEvents()
|
||||
{
|
||||
if (!m_changed) {
|
||||
return;
|
||||
}
|
||||
|
||||
mergeCompatibleStyles();
|
||||
|
||||
for (int i = 0; i < m_style_list.size(); i++) {
|
||||
ensureStyleAlignWithLines(i);
|
||||
TextStyleLine ¤t_style = m_style_list[i];
|
||||
if (current_style.text_segment == 0) {
|
||||
current_style.text_segment = m_screen->createTextSegment(current_style);
|
||||
current_style.text_segment->setLine(m_new_line, m_width, &m_text_line);
|
||||
} else if (m_new_line != m_line) {
|
||||
current_style.text_segment->setLine(m_new_line, m_width, &m_text_line);
|
||||
}
|
||||
|
||||
if (current_style.style_dirty) {
|
||||
current_style.text_segment->setTextStyle(current_style);
|
||||
current_style.style_dirty = false;
|
||||
}
|
||||
|
||||
if (current_style.index_dirty || current_style.text_dirty) {
|
||||
current_style.text_segment->setStringSegment(current_style.start_index, current_style.end_index, current_style.text_dirty);
|
||||
current_style.index_dirty = false;
|
||||
current_style.text_dirty = false;
|
||||
}
|
||||
|
||||
current_style.text_segment->setLatin(m_only_latin);
|
||||
current_style.text_segment->dispatchEvents();
|
||||
}
|
||||
|
||||
m_changed = false;
|
||||
m_line = m_new_line;
|
||||
|
||||
}
|
||||
|
||||
void Block::releaseTextObjects()
|
||||
{
|
||||
m_changed = true;
|
||||
for (int i = 0; i < m_style_list.size(); i++) {
|
||||
TextStyleLine ¤tStyleLine = m_style_list[i];
|
||||
currentStyleLine.releaseTextSegment(m_screen);
|
||||
currentStyleLine.text_dirty = true;
|
||||
currentStyleLine.style_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
QVector<TextStyleLine> Block::style_list()
|
||||
{
|
||||
return m_style_list;
|
||||
}
|
||||
|
||||
void Block::printStyleList() const
|
||||
{
|
||||
QDebug debug = qDebug();
|
||||
printStyleList(debug);
|
||||
}
|
||||
|
||||
void Block::printStyleList(QDebug &debug) const
|
||||
{
|
||||
QString text_line = m_text_line;
|
||||
debug << " " << m_line << lineCount() << m_text_line.size() << (void *) this << text_line << "\n"; debug << "\t";
|
||||
for (int i= 0; i < m_style_list.size(); i++) {
|
||||
debug << m_style_list.at(i);
|
||||
}
|
||||
}
|
||||
|
||||
void Block::printStyleListWidthText() const
|
||||
{
|
||||
QString text_line = m_text_line;
|
||||
for (int i= 0; i < m_style_list.size(); i++) {
|
||||
const TextStyleLine ¤tStyle = m_style_list.at(i);
|
||||
QDebug debug = qDebug();
|
||||
debug << m_text_line.mid(currentStyle.start_index, (currentStyle.end_index + 1) - currentStyle.start_index) << currentStyle;
|
||||
}
|
||||
}
|
||||
|
||||
void Block::mergeCompatibleStyles()
|
||||
{
|
||||
for (int i = 1; i < m_style_list.size(); i++) {
|
||||
TextStyleLine ¤t = m_style_list[i];
|
||||
if (m_style_list.at(i - 1).isCompatible(current) &&
|
||||
current.start_index % m_width != 0) {
|
||||
TextStyleLine &prev = m_style_list[i-1];
|
||||
prev.end_index = current.end_index;
|
||||
prev.text_dirty = true;
|
||||
current.releaseTextSegment(m_screen);
|
||||
m_style_list.remove(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Block::ensureStyleAlignWithLines(int i)
|
||||
{
|
||||
int start_line = m_style_list[i].start_index / m_width;
|
||||
int end_line = m_style_list[i].end_index / m_width;
|
||||
if (start_line != end_line) {
|
||||
int remainder_start_line = ((m_width * (start_line + 1))-1) - m_style_list[i].start_index;
|
||||
int next_line_end_index = m_style_list[i].end_index;
|
||||
m_style_list[i].end_index = m_style_list[i].start_index + remainder_start_line;
|
||||
m_style_list.insert(i + 1, TextStyleLine(m_style_list[i], m_style_list[i].end_index + 1, next_line_end_index));
|
||||
}
|
||||
}
|
109
yat/backend/block.h
Normal file
109
yat/backend/block.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2012 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef BLOCK_H
|
||||
#define BLOCK_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include "text_style.h"
|
||||
|
||||
class Text;
|
||||
class Screen;
|
||||
|
||||
class Block
|
||||
{
|
||||
public:
|
||||
Block(Screen *screen);
|
||||
~Block();
|
||||
|
||||
Q_INVOKABLE Screen *screen() const;
|
||||
|
||||
void clear();
|
||||
void clearToEnd(int from);
|
||||
void clearCharacters(int from, int to);
|
||||
void deleteCharacters(int from, int to);
|
||||
void deleteToEnd(int from);
|
||||
void deleteLines(int from);
|
||||
|
||||
void replaceAtPos(int i, const QString &text, const TextStyle &style, bool only_latin = true);
|
||||
void insertAtPos(int i, const QString &text, const TextStyle &style, bool only_latin = true);
|
||||
|
||||
void setScreenIndex(int index) { m_screen_index = index; }
|
||||
int screenIndex() const { return m_screen_index; }
|
||||
size_t line() { return m_new_line; }
|
||||
void setLine(size_t line) {
|
||||
if (line != m_new_line) {
|
||||
m_changed = true;
|
||||
m_new_line = line;
|
||||
}
|
||||
}
|
||||
|
||||
QString *textLine();
|
||||
int textSize() { return m_text_line.size(); }
|
||||
|
||||
int width() const { return m_width; }
|
||||
void setWidth(int width) { m_changed = true; m_width = width; }
|
||||
int lineCount() const { return (std::max((m_text_line.size() - 1),0) / m_width) + 1; }
|
||||
int lineCountAfterModified(int from_char, int text_size, bool replace) {
|
||||
int new_size = replace ? std::max(from_char + text_size, m_text_line.size())
|
||||
: std::max(from_char, m_text_line.size()) + text_size;
|
||||
return ((new_size - 1) / m_width) + 1;
|
||||
}
|
||||
|
||||
void setVisible(bool visible);
|
||||
bool visible() const;
|
||||
|
||||
Block *split(int line);
|
||||
Block *takeLine(int line);
|
||||
void removeLine(int line);
|
||||
|
||||
void moveLinesFromBlock(Block *block, int start_line, int count);
|
||||
|
||||
void dispatchEvents();
|
||||
void releaseTextObjects();
|
||||
|
||||
QVector<TextStyleLine> style_list();
|
||||
|
||||
void printStyleList() const;
|
||||
void printStyleList(QDebug &debug) const;
|
||||
void printStyleListWidthText() const;
|
||||
|
||||
private:
|
||||
void mergeCompatibleStyles();
|
||||
void ensureStyleAlignWithLines(int i);
|
||||
Screen *m_screen;
|
||||
QString m_text_line;
|
||||
QVector<TextStyleLine> m_style_list;
|
||||
size_t m_line;
|
||||
size_t m_new_line;
|
||||
int m_screen_index;
|
||||
|
||||
int m_width;
|
||||
|
||||
bool m_visible;
|
||||
bool m_changed;
|
||||
bool m_only_latin;
|
||||
};
|
||||
|
||||
#endif // BLOCK_H
|
265
yat/backend/character_sets.h
Normal file
265
yat/backend/character_sets.h
Normal file
@ -0,0 +1,265 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2013 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include <QtCore/QString>
|
||||
|
||||
static const QChar dec_special_graphics_char_set[] =
|
||||
{
|
||||
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x40*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x58*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0020,
|
||||
/*0x60*/ 0x25c6,0x2592,0x2409,0x240c,0x240d,0x240a,0x00b0,0x00b1,
|
||||
/*0x68*/ 0x2424,0x240b,0x2518,0x2510,0x250c,0x2514,0x253c,0x23ba,
|
||||
/*0x70*/ 0x23bb,0x2500,0x23bc,0x23bd,0x251c,0x2524,0x2534,0x252c,
|
||||
/*0x78*/ 0x2502,0x2264,0x2265,0x03c0,0x2260,0x00a3,0x00b7,0x0000,
|
||||
};
|
||||
|
||||
static const QChar nrc_british_char_set[] =
|
||||
{
|
||||
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x40*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x58*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x78*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
};
|
||||
|
||||
static const QChar nrc_norwegian_danish_char_set[] =
|
||||
{
|
||||
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x40*/ 0x00c4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x58*/ 0x0000,0x0000,0x0000,0x00c6,0x00d8,0x00c5,0x00dc,0x0000,
|
||||
/*0x60*/ 0x00e4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x78*/ 0x0000,0x0000,0x0000,0x00e6,0x00f8,0x00e5,0x00fc,0x0000,
|
||||
};
|
||||
|
||||
static const QChar nrc_dutch_char_set[] =
|
||||
{
|
||||
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x38*/ 0x0000,0x0000,0x00be,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x40*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x58*/ 0x0000,0x0000,0x0000,0x0133,0x00bd,0x007c,0x0000,0x0000,
|
||||
/*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x78*/ 0x0000,0x0000,0x0000,0x00a8,0x0066,0x00bc,0x00b4,0x0000,
|
||||
};
|
||||
|
||||
static const QChar nrc_finnish_char_set[] =
|
||||
{
|
||||
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x40*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x58*/ 0x0000,0x0000,0x0000,0x00c4,0x00d6,0x00c5,0x00dc,0x0000,
|
||||
/*0x60*/ 0x00e9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x78*/ 0x0000,0x0000,0x0000,0x00e4,0x00f6,0x00e5,0x00fc,0x0000,
|
||||
};
|
||||
|
||||
static const QChar nrc_french_char_set[] =
|
||||
{
|
||||
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x40*/ 0x00e0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x58*/ 0x0000,0x0000,0x0000,0x00b0,0x00e7,0x00a7,0x0000,0x0000,
|
||||
/*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x78*/ 0x0000,0x0000,0x0000,0x00e9,0x00f9,0x00e8,0x00a8,0x0000,
|
||||
};
|
||||
|
||||
static const QChar nrc_french_canadian_char_set[] =
|
||||
{
|
||||
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x40*/ 0x00e0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x58*/ 0x0000,0x0000,0x0000,0x00e2,0x00e7,0x00ea,0x00ee,0x0000,
|
||||
/*0x60*/ 0x00f4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x78*/ 0x0000,0x0000,0x0000,0x00e9,0x00f9,0x00e8,0x00fb,0x0000,
|
||||
};
|
||||
|
||||
static const QChar nrc_german_char_set[] =
|
||||
{
|
||||
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x40*/ 0x00a7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x58*/ 0x0000,0x0000,0x0000,0x00c4,0x00d6,0x00dc,0x0000,0x0000,
|
||||
/*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x78*/ 0x0000,0x0000,0x0000,0x00e4,0x00f6,0x00fc,0x00df,0x0000,
|
||||
};
|
||||
|
||||
static const QChar nrc_italian_char_set[] =
|
||||
{
|
||||
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x40*/ 0x00a7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x58*/ 0x0000,0x0000,0x0000,0x00b0,0x00e7,0x00e9,0x0000,0x0000,
|
||||
/*0x60*/ 0x00f9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x78*/ 0x0000,0x0000,0x0000,0x00e0,0x00f2,0x00e8,0x00ec,0x0000,
|
||||
};
|
||||
|
||||
static const QChar nrc_spanish_char_set[] =
|
||||
{
|
||||
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x20*/ 0x0000,0x0000,0x0000,0x00a3,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x40*/ 0x00a7,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x58*/ 0x0000,0x0000,0x0000,0x00a1,0x00d1,0x00bf,0x0000,0x0000,
|
||||
/*0x60*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x78*/ 0x0000,0x0000,0x0000,0x00b0,0x00f1,0x00e7,0x0000,0x0000,
|
||||
};
|
||||
|
||||
static const QChar nrc_swedish_char_set[] =
|
||||
{
|
||||
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x20*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x40*/ 0x00c9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x58*/ 0x0000,0x0000,0x0000,0x00c4,0x00d6,0x00c5,0x00dc,0x0000,
|
||||
/*0x60*/ 0x00e9,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x78*/ 0x0000,0x0000,0x0000,0x00e4,0x00f6,0x00e5,0x00fc,0x0000,
|
||||
};
|
||||
|
||||
static const QChar nrc_swiss_char_set[] =
|
||||
{
|
||||
/*0x00*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x08*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x10*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x18*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x20*/ 0x0000,0x0000,0x0000,0x00f9,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x28*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x30*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x38*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x40*/ 0x00e0,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x48*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x50*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x58*/ 0x0000,0x0000,0x0000,0x00e9,0x00e7,0x00ea,0x00ee,0x00e8,
|
||||
/*0x60*/ 0x00f4,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x68*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x70*/ 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
|
||||
/*0x78*/ 0x0000,0x0000,0x0000,0x00e4,0x00f6,0x00fc,0x00fb,0x0000,
|
||||
};
|
||||
|
66
yat/backend/color_palette.cpp
Normal file
66
yat/backend/color_palette.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
#include "color_palette.h"
|
||||
|
||||
#include <QDebug>
|
||||
ColorPalette::ColorPalette(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_normalColors(numberOfColors)
|
||||
, m_lightColors(numberOfColors)
|
||||
, m_intenseColors(numberOfColors)
|
||||
, m_inverse_default(false)
|
||||
{
|
||||
m_normalColors[0].setRgb(0,0,0);
|
||||
m_normalColors[1].setRgb(194,54,33);
|
||||
m_normalColors[2].setRgb(37,188,36);
|
||||
m_normalColors[3].setRgb(173,173,39);
|
||||
m_normalColors[4].setRgb(63,84,255);
|
||||
m_normalColors[5].setRgb(211,56,211);
|
||||
m_normalColors[6].setRgb(51,187,199);
|
||||
m_normalColors[7].setRgb(229,229,229);
|
||||
m_normalColors[8].setRgb(178,178,178);
|
||||
m_normalColors[9].setRgb(0,0,0);
|
||||
|
||||
m_lightColors[0].setRgb(129,131,131);
|
||||
m_lightColors[1].setRgb(252,57,31);
|
||||
m_lightColors[2].setRgb(49,231,34);
|
||||
m_lightColors[3].setRgb(234,236,35);
|
||||
m_lightColors[4].setRgb(88,51,255);
|
||||
m_lightColors[5].setRgb(249,53,248);
|
||||
m_lightColors[6].setRgb(20,240,240);
|
||||
m_lightColors[7].setRgb(233,233,233);
|
||||
m_lightColors[8].setRgb(220,220,220);
|
||||
m_lightColors[9].setRgb(50,50,50);
|
||||
|
||||
}
|
||||
|
||||
QColor ColorPalette::color(ColorPalette::Color color, bool bold) const
|
||||
{
|
||||
if (m_inverse_default) {
|
||||
if (color == DefaultForground)
|
||||
color = DefaultBackground;
|
||||
else if (color == DefaultBackground)
|
||||
color = DefaultForground;
|
||||
}
|
||||
if (bold)
|
||||
return m_lightColors.at(color);
|
||||
|
||||
return m_normalColors.at(color);
|
||||
}
|
||||
|
||||
QColor ColorPalette::normalColor(ColorPalette::Color color) const
|
||||
{
|
||||
return this->color(color, false);
|
||||
}
|
||||
|
||||
QColor ColorPalette::lightColor(ColorPalette::Color color) const
|
||||
{
|
||||
return this->color(color,true);
|
||||
}
|
||||
|
||||
void ColorPalette::setInverseDefaultColors(bool inverse)
|
||||
{
|
||||
bool emit_changed = inverse != m_inverse_default;
|
||||
if (emit_changed) {
|
||||
m_inverse_default = inverse;
|
||||
emit changed();
|
||||
}
|
||||
}
|
43
yat/backend/color_palette.h
Normal file
43
yat/backend/color_palette.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef COLOR_PALETTE_H
|
||||
#define COLOR_PALETTE_H
|
||||
|
||||
#include <QtCore/QVector>
|
||||
|
||||
#include <QtGui/QColor>
|
||||
|
||||
class ColorPalette : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ColorPalette(QObject *parent = 0);
|
||||
|
||||
enum Color {
|
||||
Black,
|
||||
Red,
|
||||
Green,
|
||||
Yellow,
|
||||
Blue,
|
||||
Magenta,
|
||||
Cyan,
|
||||
White,
|
||||
DefaultForground,
|
||||
DefaultBackground,
|
||||
numberOfColors
|
||||
};
|
||||
|
||||
QColor color(Color color, bool bold) const;
|
||||
QColor normalColor(Color color) const;
|
||||
QColor lightColor(Color color) const;
|
||||
|
||||
void setInverseDefaultColors(bool inverse);
|
||||
signals:
|
||||
void changed();
|
||||
private:
|
||||
QVector<QColor> m_normalColors;
|
||||
QVector<QColor> m_lightColors;
|
||||
QVector<QColor> m_intenseColors;
|
||||
|
||||
bool m_inverse_default;
|
||||
};
|
||||
|
||||
#endif // COLOR_PALETTE_H
|
798
yat/backend/controll_chars.cpp
Normal file
798
yat/backend/controll_chars.cpp
Normal file
@ -0,0 +1,798 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
#include "controll_chars.h"
|
||||
|
||||
namespace C0 {
|
||||
QDebug operator<<(QDebug debug, C0 character) {
|
||||
bool insert_space = debug.autoInsertSpaces();
|
||||
debug.setAutoInsertSpaces(false);
|
||||
debug << "C0::";
|
||||
switch (character) {
|
||||
case NUL:
|
||||
debug << "NUL";
|
||||
break;
|
||||
case SOH:
|
||||
debug << "SOH";
|
||||
break;
|
||||
case STX:
|
||||
debug << "STX";
|
||||
break;
|
||||
case ETX:
|
||||
debug << "ETX";
|
||||
break;
|
||||
case EOT:
|
||||
debug << "EOT";
|
||||
break;
|
||||
case ENQ:
|
||||
debug << "ENQ";
|
||||
break;
|
||||
case ACK:
|
||||
debug << "ACK";
|
||||
break;
|
||||
case BEL:
|
||||
debug << "BEL";
|
||||
break;
|
||||
case BS:
|
||||
debug << "BS";
|
||||
break;
|
||||
case HT:
|
||||
debug << "HT";
|
||||
break;
|
||||
case LF:
|
||||
debug << "LF";
|
||||
break;
|
||||
case VT:
|
||||
debug << "VT";
|
||||
break;
|
||||
case FF:
|
||||
debug << "FF";
|
||||
break;
|
||||
case CR:
|
||||
debug << "CR";
|
||||
break;
|
||||
case SOorLS1:
|
||||
debug << "SOorLS1";
|
||||
break;
|
||||
case SIorLS0:
|
||||
debug << "SIorLS0";
|
||||
break;
|
||||
case DLE:
|
||||
debug << "DLE";
|
||||
break;
|
||||
case DC1:
|
||||
debug << "DC1";
|
||||
break;
|
||||
case DC2:
|
||||
debug << "DC2";
|
||||
break;
|
||||
case DC3:
|
||||
debug << "DC3";
|
||||
break;
|
||||
case DC4:
|
||||
debug << "DC4";
|
||||
break;
|
||||
case NAK:
|
||||
debug << "NAK";
|
||||
break;
|
||||
case SYN:
|
||||
debug << "SYN";
|
||||
break;
|
||||
case ETB:
|
||||
debug << "ETB";
|
||||
break;
|
||||
case CAN:
|
||||
debug << "CAN";
|
||||
break;
|
||||
case EM:
|
||||
debug << "EM";
|
||||
break;
|
||||
case SUB:
|
||||
debug << "SUB";
|
||||
break;
|
||||
case ESC:
|
||||
debug << "ESC";
|
||||
break;
|
||||
case IS4:
|
||||
debug << "IS4";
|
||||
break;
|
||||
case IS3:
|
||||
debug << "IS3";
|
||||
break;
|
||||
case IS2:
|
||||
debug << "IS2";
|
||||
break;
|
||||
case IS1:
|
||||
debug << "IS1";
|
||||
break;
|
||||
case C0_END:
|
||||
debug << "C0_END";
|
||||
break;
|
||||
default:
|
||||
debug << qPrintable(QString("0x%1").arg(character,0,16));
|
||||
break;
|
||||
}
|
||||
debug.setAutoInsertSpaces(insert_space);
|
||||
return debug;
|
||||
}
|
||||
}
|
||||
|
||||
namespace C1_7bit {
|
||||
QDebug operator<<(QDebug debug, C1_7bit character) {
|
||||
bool insert_space = debug.autoInsertSpaces();
|
||||
debug.setAutoInsertSpaces(false);
|
||||
debug << "C1_7bit::";
|
||||
switch(character) {
|
||||
case ESC:
|
||||
debug << "ESC";
|
||||
break;
|
||||
case SCS_G0:
|
||||
debug << "SCS_G0";
|
||||
break;
|
||||
case SCS_G1:
|
||||
debug << "SCS_G1";
|
||||
break;
|
||||
case SCS_G2:
|
||||
debug << "SCS_G2";
|
||||
break;
|
||||
case SCS_G3:
|
||||
debug << "SCS_G3";
|
||||
break;
|
||||
case DECSC:
|
||||
debug << "DECSC";
|
||||
break;
|
||||
case DECRC:
|
||||
debug << "DECRC";
|
||||
break;
|
||||
case NOT_DEFINED:
|
||||
debug << "NOT_DEFINED";
|
||||
break;
|
||||
case NOT_DEFINED1:
|
||||
debug << "NOT_DEFINED1";
|
||||
break;
|
||||
case BPH:
|
||||
debug << "BPH";
|
||||
break;
|
||||
case NBH:
|
||||
debug << "NBH";
|
||||
break;
|
||||
case IND:
|
||||
debug << "IND";
|
||||
break;
|
||||
case NEL:
|
||||
debug << "NEL";
|
||||
break;
|
||||
case SSA:
|
||||
debug << "SSA";
|
||||
break;
|
||||
case ESA:
|
||||
debug << "ESA";
|
||||
break;
|
||||
case HTS:
|
||||
debug << "HTS";
|
||||
break;
|
||||
case HTJ:
|
||||
debug << "HTJ";
|
||||
break;
|
||||
case VTS:
|
||||
debug << "VTS";
|
||||
break;
|
||||
case PLD:
|
||||
debug << "PLD";
|
||||
break;
|
||||
case PLU:
|
||||
debug << "PLU";
|
||||
break;
|
||||
case RI :
|
||||
debug << "RI ";
|
||||
break;
|
||||
case SS2:
|
||||
debug << "SS2";
|
||||
break;
|
||||
case SS3:
|
||||
debug << "SS3";
|
||||
break;
|
||||
case DCS:
|
||||
debug << "DCS";
|
||||
break;
|
||||
case PU1:
|
||||
debug << "PU1";
|
||||
break;
|
||||
case PU2:
|
||||
debug << "PU2";
|
||||
break;
|
||||
case STS:
|
||||
debug << "STS";
|
||||
break;
|
||||
case CCH:
|
||||
debug << "CCH";
|
||||
break;
|
||||
case MW :
|
||||
debug << "MW ";
|
||||
break;
|
||||
case SPA:
|
||||
debug << "SPA";
|
||||
break;
|
||||
case EPA:
|
||||
debug << "EPA";
|
||||
break;
|
||||
case SOS:
|
||||
debug << "SOS";
|
||||
break;
|
||||
case NOT_DEFINED3:
|
||||
debug << "NOT_DEFINED3";
|
||||
break;
|
||||
case SCI:
|
||||
debug << "SCI";
|
||||
break;
|
||||
case CSI:
|
||||
debug << "CSI";
|
||||
break;
|
||||
case ST :
|
||||
debug << "ST ";
|
||||
break;
|
||||
case OSC:
|
||||
debug << "OSC";
|
||||
break;
|
||||
case PM :
|
||||
debug << "PM ";
|
||||
break;
|
||||
case APC:
|
||||
debug << "APC";
|
||||
break;
|
||||
case C1_7bit_Stop:
|
||||
debug << "C1_7bit_Stop";
|
||||
break;
|
||||
default:
|
||||
debug << qPrintable(QString("0x%1").arg(character,0,16));
|
||||
break;
|
||||
}
|
||||
debug.setAutoInsertSpaces(insert_space);
|
||||
return debug;
|
||||
}
|
||||
}
|
||||
|
||||
namespace C1_8bit {
|
||||
QDebug operator<<(QDebug debug, C1_8bit character) {
|
||||
bool insert_space = debug.autoInsertSpaces();
|
||||
debug.setAutoInsertSpaces(false);
|
||||
debug << "C1_8bit::";
|
||||
switch(character) {
|
||||
case NOT_DEFINED:
|
||||
debug << "NOT_DEFINED";
|
||||
break;
|
||||
case NOT_DEFINED1:
|
||||
debug << "NOT_DEFINED1";
|
||||
break;
|
||||
case BPH:
|
||||
debug << "BPH";
|
||||
break;
|
||||
case NBH:
|
||||
debug << "NBH";
|
||||
break;
|
||||
case NOT_DEFINED2:
|
||||
debug << "NOT_DEFINED2";
|
||||
break;
|
||||
case NEL:
|
||||
debug << "NEL";
|
||||
break;
|
||||
case SSA:
|
||||
debug << "SSA";
|
||||
break;
|
||||
case ESA:
|
||||
debug << "ESA";
|
||||
break;
|
||||
case HTS:
|
||||
debug << "HTS";
|
||||
break;
|
||||
case HTJ:
|
||||
debug << "HTJ";
|
||||
break;
|
||||
case VTS:
|
||||
debug << "VTS";
|
||||
break;
|
||||
case PLD:
|
||||
debug << "PLD";
|
||||
break;
|
||||
case PLU:
|
||||
debug << "PLU";
|
||||
break;
|
||||
case RI :
|
||||
debug << "RI ";
|
||||
break;
|
||||
case SS2:
|
||||
debug << "SS2";
|
||||
break;
|
||||
case SS3:
|
||||
debug << "SS3";
|
||||
break;
|
||||
case DCS:
|
||||
debug << "DCS";
|
||||
break;
|
||||
case PU1:
|
||||
debug << "PU1";
|
||||
break;
|
||||
case PU2C1_7bit:
|
||||
debug << "PU2C1_7bit";
|
||||
break;
|
||||
case STS:
|
||||
debug << "STS";
|
||||
break;
|
||||
case CCH:
|
||||
debug << "CCH";
|
||||
break;
|
||||
case MW :
|
||||
debug << "MW ";
|
||||
break;
|
||||
case SPA:
|
||||
debug << "SPA";
|
||||
break;
|
||||
case EPA:
|
||||
debug << "EPA";
|
||||
break;
|
||||
case SOS:
|
||||
debug << "SOS";
|
||||
break;
|
||||
case NOT_DEFINED3:
|
||||
debug << "NOT_DEFINED3";
|
||||
break;
|
||||
case SCI:
|
||||
debug << "SCI";
|
||||
break;
|
||||
case CSI:
|
||||
debug << "CSI";
|
||||
break;
|
||||
case ST :
|
||||
debug << "ST ";
|
||||
break;
|
||||
case OSC:
|
||||
debug << "OSC";
|
||||
break;
|
||||
case PM :
|
||||
debug << "PM ";
|
||||
break;
|
||||
case APC:
|
||||
debug << "APC";
|
||||
break;
|
||||
case C1_8bit_Stop:
|
||||
debug << "C1_8bit_Stop";
|
||||
break;
|
||||
default:
|
||||
debug << qPrintable(QString("0x%1").arg(character,0,16));
|
||||
break;
|
||||
}
|
||||
debug.setAutoInsertSpaces(insert_space);
|
||||
return debug;
|
||||
}
|
||||
}
|
||||
namespace FinalBytesNoIntermediate {
|
||||
QDebug operator<<(QDebug debug, FinalBytesNoIntermediate character) {
|
||||
bool insert_space = debug.autoInsertSpaces();
|
||||
debug.setAutoInsertSpaces(false);
|
||||
debug << "FinalBytesNoIntermediate::";
|
||||
switch(character) {
|
||||
case ICH:
|
||||
debug << "ICH";
|
||||
break;
|
||||
case CUU:
|
||||
debug << "CUU";
|
||||
break;
|
||||
case CUD:
|
||||
debug << "CUD";
|
||||
break;
|
||||
case CUF:
|
||||
debug << "CUF";
|
||||
break;
|
||||
case CUB:
|
||||
debug << "CUB";
|
||||
break;
|
||||
case CNL:
|
||||
debug << "CNL";
|
||||
break;
|
||||
case CPL:
|
||||
debug << "CPL";
|
||||
break;
|
||||
case CHA:
|
||||
debug << "CHA";
|
||||
break;
|
||||
case CUP:
|
||||
debug << "CUP";
|
||||
break;
|
||||
case CHT:
|
||||
debug << "CHT";
|
||||
break;
|
||||
case ED:
|
||||
debug << "ED";
|
||||
break;
|
||||
case EL:
|
||||
debug << "EL";
|
||||
break;
|
||||
case IL:
|
||||
debug << "IL";
|
||||
break;
|
||||
case DL:
|
||||
debug << "DL";
|
||||
break;
|
||||
case EF:
|
||||
debug << "EF";
|
||||
break;
|
||||
case EA:
|
||||
debug << "EA";
|
||||
break;
|
||||
case DCH:
|
||||
debug << "DCH";
|
||||
break;
|
||||
case SSE:
|
||||
debug << "SSE";
|
||||
break;
|
||||
case CPR:
|
||||
debug << "CPR";
|
||||
break;
|
||||
case SU:
|
||||
debug << "SU";
|
||||
break;
|
||||
case SD:
|
||||
debug << "SD";
|
||||
break;
|
||||
case NP:
|
||||
debug << "NP";
|
||||
break;
|
||||
case PP:
|
||||
debug << "PP";
|
||||
break;
|
||||
case CTC:
|
||||
debug << "CTC";
|
||||
break;
|
||||
case ECH:
|
||||
debug << "ECH";
|
||||
break;
|
||||
case CVT:
|
||||
debug << "CVT";
|
||||
break;
|
||||
case CBT:
|
||||
debug << "CBT";
|
||||
break;
|
||||
case SRS:
|
||||
debug << "SRS";
|
||||
break;
|
||||
case PTX:
|
||||
debug << "PTX";
|
||||
break;
|
||||
case SDS:
|
||||
debug << "SDS";
|
||||
break;
|
||||
case SIMD:
|
||||
debug << "SIMD";
|
||||
break;
|
||||
case NOT_DEFINED:
|
||||
debug << "NOT_DEFINED";
|
||||
break;
|
||||
case HPA:
|
||||
debug << "HPA";
|
||||
break;
|
||||
case HPR:
|
||||
debug << "HPR";
|
||||
break;
|
||||
case REP:
|
||||
debug << "REP";
|
||||
break;
|
||||
case DA:
|
||||
debug << "DA";
|
||||
break;
|
||||
case VPA:
|
||||
debug << "VPA";
|
||||
break;
|
||||
case VPR:
|
||||
debug << "VPR";
|
||||
break;
|
||||
case HVP:
|
||||
debug << "HVP";
|
||||
break;
|
||||
case TBC:
|
||||
debug << "TBC";
|
||||
break;
|
||||
case SM:
|
||||
debug << "SM";
|
||||
break;
|
||||
case MC:
|
||||
debug << "MC";
|
||||
break;
|
||||
case HPB:
|
||||
debug << "HPB";
|
||||
break;
|
||||
case VPB:
|
||||
debug << "VPB";
|
||||
break;
|
||||
case RM:
|
||||
debug << "RM";
|
||||
break;
|
||||
case SGR:
|
||||
debug << "SGR";
|
||||
break;
|
||||
case DSR:
|
||||
debug << "DSR";
|
||||
break;
|
||||
case DAQ:
|
||||
debug << "DAQ";
|
||||
break;
|
||||
case Reserved0:
|
||||
debug << "Reserved0";
|
||||
break;
|
||||
case Reserved1:
|
||||
debug << "Reserved1";
|
||||
break;
|
||||
case DECSTBM:
|
||||
debug << "DECSTBM";
|
||||
break;
|
||||
case Reserved3:
|
||||
debug << "Reserved3";
|
||||
break;
|
||||
case Reserved4:
|
||||
debug << "Reserved4";
|
||||
break;
|
||||
case Reserved5:
|
||||
debug << "Reserved5";
|
||||
break;
|
||||
case Reserved6:
|
||||
debug << "Reserved6";
|
||||
break;
|
||||
case Reserved7:
|
||||
debug << "Reserved7";
|
||||
break;
|
||||
case Reserved8:
|
||||
debug << "Reserved8";
|
||||
break;
|
||||
case Reserved9:
|
||||
debug << "Reserved9";
|
||||
break;
|
||||
case Reserveda:
|
||||
debug << "Reserveda";
|
||||
break;
|
||||
case Reservedb:
|
||||
debug << "Reservedb";
|
||||
break;
|
||||
case Reservedc:
|
||||
debug << "Reservedc";
|
||||
break;
|
||||
case Reservedd:
|
||||
debug << "Reservedd";
|
||||
break;
|
||||
case Reservede:
|
||||
debug << "Reservede";
|
||||
break;
|
||||
case Reservedf:
|
||||
debug << "Reservedf";
|
||||
break;
|
||||
default:
|
||||
debug << qPrintable(QString("0x%1").arg(character,0,16));
|
||||
break;
|
||||
}
|
||||
debug.setAutoInsertSpaces(insert_space);
|
||||
return debug;
|
||||
}
|
||||
}
|
||||
|
||||
namespace FinalBytesSingleIntermediate {
|
||||
QDebug operator<<(QDebug debug, FinalBytesSingleIntermediate character)
|
||||
{
|
||||
bool insert_space = debug.autoInsertSpaces();
|
||||
debug.setAutoInsertSpaces(false);
|
||||
debug << "FinalBytesSingleIntermediate::";
|
||||
switch(character) {
|
||||
case SL:
|
||||
debug << "SL";
|
||||
break;
|
||||
case SR:
|
||||
debug << "SR";
|
||||
break;
|
||||
case GSM:
|
||||
debug << "GSM";
|
||||
break;
|
||||
case GSS:
|
||||
debug << "GSS";
|
||||
break;
|
||||
case FNT:
|
||||
debug << "FNT";
|
||||
break;
|
||||
case TSS:
|
||||
debug << "TSS";
|
||||
break;
|
||||
case JFY:
|
||||
debug << "JFY";
|
||||
break;
|
||||
case SPI:
|
||||
debug << "SPI";
|
||||
break;
|
||||
case QUAD:
|
||||
debug << "QUAD";
|
||||
break;
|
||||
case SSU:
|
||||
debug << "SSU";
|
||||
break;
|
||||
case PFS:
|
||||
debug << "PFS";
|
||||
break;
|
||||
case SHS:
|
||||
debug << "SHS";
|
||||
break;
|
||||
case SVS:
|
||||
debug << "SVS";
|
||||
break;
|
||||
case IGS:
|
||||
debug << "IGS";
|
||||
break;
|
||||
case NOT_DEFINED:
|
||||
debug << "NOT_DEFINED";
|
||||
break;
|
||||
case IDCS:
|
||||
debug << "IDCS";
|
||||
break;
|
||||
case PPA:
|
||||
debug << "PPA";
|
||||
break;
|
||||
case PPR:
|
||||
debug << "PPR";
|
||||
break;
|
||||
case PPB:
|
||||
debug << "PPB";
|
||||
break;
|
||||
case SPD:
|
||||
debug << "SPD";
|
||||
break;
|
||||
case DTA:
|
||||
debug << "DTA";
|
||||
break;
|
||||
case SHL:
|
||||
debug << "SHL";
|
||||
break;
|
||||
case SLL:
|
||||
debug << "SLL";
|
||||
break;
|
||||
case FNK:
|
||||
debug << "FNK";
|
||||
break;
|
||||
case SPQR:
|
||||
debug << "SPQR";
|
||||
break;
|
||||
case SEF:
|
||||
debug << "SEF";
|
||||
break;
|
||||
case PEC:
|
||||
debug << "PEC";
|
||||
break;
|
||||
case SSW:
|
||||
debug << "SSW";
|
||||
break;
|
||||
case SACS:
|
||||
debug << "SACS";
|
||||
break;
|
||||
case SAPV:
|
||||
debug << "SAPV";
|
||||
break;
|
||||
case STAB:
|
||||
debug << "STAB";
|
||||
break;
|
||||
case GCC:
|
||||
debug << "GCC";
|
||||
break;
|
||||
case TATE:
|
||||
debug << "TATE";
|
||||
break;
|
||||
case TALE:
|
||||
debug << "TALE";
|
||||
break;
|
||||
case TAC:
|
||||
debug << "TAC";
|
||||
break;
|
||||
case TCC:
|
||||
debug << "TCC";
|
||||
break;
|
||||
case TSR:
|
||||
debug << "TSR";
|
||||
break;
|
||||
case SCO:
|
||||
debug << "SCO";
|
||||
break;
|
||||
case SRCS:
|
||||
debug << "SRCS";
|
||||
break;
|
||||
case SCS:
|
||||
debug << "SCS";
|
||||
break;
|
||||
case SLS:
|
||||
debug << "SLS";
|
||||
break;
|
||||
case NOT_DEFINED2:
|
||||
debug << "NOT_DEFINED2";
|
||||
break;
|
||||
case NOT_DEFINED3:
|
||||
debug << "NOT_DEFINED3";
|
||||
break;
|
||||
case SCP:
|
||||
debug << "SCP";
|
||||
break;
|
||||
case NOT_DEFINED4:
|
||||
debug << "NOT_DEFINED4";
|
||||
break;
|
||||
case NOT_DEFINED5:
|
||||
debug << "NOT_DEFINED5";
|
||||
break;
|
||||
case NOT_DEFINED6:
|
||||
debug << "NOT_DEFINED6";
|
||||
break;
|
||||
case NOT_DEFINED7:
|
||||
debug << "NOT_DEFINED7";
|
||||
break;
|
||||
case Reserved0:
|
||||
debug << "Reserved0";
|
||||
break;
|
||||
case Reserved1:
|
||||
debug << "Reserved1";
|
||||
break;
|
||||
case Reserved2:
|
||||
debug << "Reserved2";
|
||||
break;
|
||||
case Reserved3:
|
||||
debug << "Reserved3";
|
||||
break;
|
||||
case Reserved4:
|
||||
debug << "Reserved4";
|
||||
break;
|
||||
case Reserved5:
|
||||
debug << "Reserved5";
|
||||
break;
|
||||
case Reserved6:
|
||||
debug << "Reserved6";
|
||||
break;
|
||||
case Reserved7:
|
||||
debug << "Reserved7";
|
||||
break;
|
||||
case Reserved8:
|
||||
debug << "Reserved8";
|
||||
break;
|
||||
case Reserved9:
|
||||
debug << "Reserved9";
|
||||
break;
|
||||
case Reserveda:
|
||||
debug << "Reserveda";
|
||||
break;
|
||||
case Reservedb:
|
||||
debug << "Reservedb";
|
||||
break;
|
||||
case Reservedc:
|
||||
debug << "Reservedc";
|
||||
break;
|
||||
case Reservedd:
|
||||
debug << "Reservedd";
|
||||
break;
|
||||
case Reservedf:
|
||||
debug << "Reservedf";
|
||||
break;
|
||||
default:
|
||||
debug << qPrintable(QString("0x%1").arg(character,0,16));
|
||||
break;
|
||||
}
|
||||
debug.setAutoInsertSpaces(insert_space);
|
||||
return debug;
|
||||
}
|
||||
}
|
||||
|
299
yat/backend/controll_chars.h
Normal file
299
yat/backend/controll_chars.h
Normal file
@ -0,0 +1,299 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2012 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef CONTROLL_CHARS_H
|
||||
#define CONTROLL_CHARS_H
|
||||
|
||||
//This is taken largely from Standard ECMA-48
|
||||
//http://www.ecma-international.org/publications/standards/Ecma-048.htm
|
||||
//Also to heres a few handy references
|
||||
//http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
|
||||
//http://www.vt100.net/docs/vt100-ug/chapter3.html
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
namespace C0 {
|
||||
enum C0 {
|
||||
NUL = 0x00,
|
||||
SOH = 0x01,
|
||||
STX = 0x02,
|
||||
ETX = 0x03,
|
||||
EOT = 0x04,
|
||||
ENQ = 0x05,
|
||||
ACK = 0x06,
|
||||
BEL = 0x07,
|
||||
BS = 0x08,
|
||||
HT = 0x09,
|
||||
LF = 0x0a,
|
||||
VT = 0x0b,
|
||||
FF = 0x0c,
|
||||
CR = 0x0d,
|
||||
SOorLS1 = 0x0e,
|
||||
SIorLS0 = 0x0f,
|
||||
DLE = 0x10,
|
||||
DC1 = 0x11,
|
||||
DC2 = 0x12,
|
||||
DC3 = 0x13,
|
||||
DC4 = 0x14,
|
||||
NAK = 0x15,
|
||||
SYN = 0x16,
|
||||
ETB = 0x17,
|
||||
CAN = 0x18,
|
||||
EM = 0x19,
|
||||
SUB = 0x1a,
|
||||
ESC = 0x1b,
|
||||
IS4 = 0x1c,
|
||||
IS3 = 0x1d,
|
||||
IS2 = 0x1e,
|
||||
IS1 = 0x1f,
|
||||
C0_END = 0x20
|
||||
};
|
||||
QDebug operator<<(QDebug debug, C0 character);
|
||||
}
|
||||
|
||||
namespace C1_7bit {
|
||||
enum C1_7bit {
|
||||
C1_7bit_Start = 0x1b,
|
||||
ESC = 0x1b,
|
||||
SCS_G0 = 0x28,
|
||||
SCS_G1 = 0x29,
|
||||
SCS_G2 = 0x2a,
|
||||
SCS_G3 = 0x2b,
|
||||
DECSC = 0x37,
|
||||
DECRC = 0x38,
|
||||
NOT_DEFINED = 0x40,
|
||||
NOT_DEFINED1 = 0x41,
|
||||
BPH = 0x42,
|
||||
NBH = 0x43,
|
||||
IND = 0x44,
|
||||
NEL = 0x45,
|
||||
SSA = 0x46,
|
||||
ESA = 0x47,
|
||||
HTS = 0x48,
|
||||
HTJ = 0x49,
|
||||
VTS = 0x4a,
|
||||
PLD = 0x4b,
|
||||
PLU = 0x4c,
|
||||
RI = 0x4d,
|
||||
SS2 = 0x4e,
|
||||
SS3 = 0x4f,
|
||||
DCS = 0x50,
|
||||
PU1 = 0x51,
|
||||
PU2 = 0x52,
|
||||
STS = 0x53,
|
||||
CCH = 0x54,
|
||||
MW = 0x55,
|
||||
SPA = 0x56,
|
||||
EPA = 0x57,
|
||||
SOS = 0x58,
|
||||
NOT_DEFINED3 = 0x59,
|
||||
SCI = 0x5a,
|
||||
CSI = 0x5b,
|
||||
ST = 0x5c,
|
||||
OSC = 0x5d,
|
||||
PM = 0x5e,
|
||||
APC = 0x5f,
|
||||
C1_7bit_Stop = 0x60
|
||||
};
|
||||
QDebug operator<<(QDebug debug, C1_7bit character);
|
||||
}
|
||||
namespace C1_8bit {
|
||||
enum C1_8bit {
|
||||
C1_8bit_Start = 0x80,
|
||||
NOT_DEFINED = C1_8bit_Start,
|
||||
NOT_DEFINED1 = 0x81,
|
||||
BPH = 0x82,
|
||||
NBH = 0x83,
|
||||
NOT_DEFINED2 = 0x84,
|
||||
NEL = 0x85,
|
||||
SSA = 0x86,
|
||||
ESA = 0x87,
|
||||
HTS = 0x88,
|
||||
HTJ = 0x89,
|
||||
VTS = 0x8a,
|
||||
PLD = 0x8b,
|
||||
PLU = 0x8c,
|
||||
RI = 0x8d,
|
||||
SS2 = 0x8e,
|
||||
SS3 = 0x8f,
|
||||
DCS = 0x90,
|
||||
PU1 = 0x91,
|
||||
PU2C1_7bit = 0x92,
|
||||
STS = 0x93,
|
||||
CCH = 0x94,
|
||||
MW = 0x95,
|
||||
SPA = 0x96,
|
||||
EPA = 0x97,
|
||||
SOS = 0x98,
|
||||
NOT_DEFINED3 = 0x99,
|
||||
SCI = 0x9a,
|
||||
CSI = 0x9b,
|
||||
ST = 0x9c,
|
||||
OSC = 0x9d,
|
||||
PM = 0x9e,
|
||||
APC = 0x9f,
|
||||
C1_8bit_Stop = 0xa0
|
||||
};
|
||||
QDebug operator<<(QDebug debug, C1_8bit character);
|
||||
}
|
||||
|
||||
namespace FinalBytesNoIntermediate {
|
||||
enum FinalBytesNoIntermediate {
|
||||
ICH = 0x40,
|
||||
CUU = 0x41,
|
||||
CUD = 0x42,
|
||||
CUF = 0x43,
|
||||
CUB = 0x44,
|
||||
CNL = 0x45,
|
||||
CPL = 0x46,
|
||||
CHA = 0x47,
|
||||
CUP = 0x48,
|
||||
CHT = 0x49,
|
||||
ED = 0x4a,
|
||||
EL = 0x4b,
|
||||
IL = 0x4c,
|
||||
DL = 0x4d,
|
||||
EF = 0x4e,
|
||||
EA = 0x4f,
|
||||
DCH = 0x50,
|
||||
SSE = 0x51,
|
||||
CPR = 0x52,
|
||||
SU = 0x53,
|
||||
SD = 0x54,
|
||||
NP = 0x55,
|
||||
PP = 0x56,
|
||||
CTC = 0x57,
|
||||
ECH = 0x58,
|
||||
CVT = 0x59,
|
||||
CBT = 0x5a,
|
||||
SRS = 0x5b,
|
||||
PTX = 0x5c,
|
||||
SDS = 0x5d,
|
||||
SIMD = 0x5e,
|
||||
NOT_DEFINED = 0x5f,
|
||||
HPA = 0x60,
|
||||
HPR = 0x61,
|
||||
REP = 0x62,
|
||||
DA = 0x63,
|
||||
VPA = 0x64,
|
||||
VPR = 0x65,
|
||||
HVP = 0x66,
|
||||
TBC = 0x67,
|
||||
SM = 0x68,
|
||||
MC = 0x69,
|
||||
HPB = 0x6a,
|
||||
VPB = 0x6b,
|
||||
RM = 0x6c,
|
||||
SGR = 0x6d,
|
||||
DSR = 0x6e,
|
||||
DAQ = 0x6f,
|
||||
Reserved0 = 0x70,
|
||||
Reserved1 = 0x71,
|
||||
DECSTBM = 0x72,
|
||||
Reserved3 = 0x73,
|
||||
Reserved4 = 0x74,
|
||||
Reserved5 = 0x75,
|
||||
Reserved6 = 0x76,
|
||||
Reserved7 = 0x77,
|
||||
Reserved8 = 0x78,
|
||||
Reserved9 = 0x79,
|
||||
Reserveda = 0x7a,
|
||||
Reservedb = 0x7b,
|
||||
Reservedc = 0x7c,
|
||||
Reservedd = 0x7d,
|
||||
Reservede = 0x7e,
|
||||
Reservedf = 0x7f
|
||||
};
|
||||
QDebug operator<<(QDebug debug, FinalBytesNoIntermediate character);
|
||||
}
|
||||
|
||||
namespace FinalBytesSingleIntermediate {
|
||||
enum FinalBytesSingleIntermediate {
|
||||
SL = 0x40,
|
||||
SR = 0x41,
|
||||
GSM = 0x42,
|
||||
GSS = 0x43,
|
||||
FNT = 0x44,
|
||||
TSS = 0x45,
|
||||
JFY = 0x46,
|
||||
SPI = 0x47,
|
||||
QUAD = 0x48,
|
||||
SSU = 0x49,
|
||||
PFS = 0x4a,
|
||||
SHS = 0x4b,
|
||||
SVS = 0x4c,
|
||||
IGS = 0x4d,
|
||||
NOT_DEFINED = 0x4e,
|
||||
IDCS = 0x4f,
|
||||
PPA = 0x50,
|
||||
PPR = 0x51,
|
||||
PPB = 0x52,
|
||||
SPD = 0x53,
|
||||
DTA = 0x54,
|
||||
SHL = 0x55,
|
||||
SLL = 0x56,
|
||||
FNK = 0x57,
|
||||
SPQR = 0x58,
|
||||
SEF = 0x59,
|
||||
PEC = 0x5a,
|
||||
SSW = 0x5b,
|
||||
SACS = 0x5c,
|
||||
SAPV = 0x5d,
|
||||
STAB = 0x5e,
|
||||
GCC = 0x5f,
|
||||
TATE = 0x60,
|
||||
TALE = 0x61,
|
||||
TAC = 0x62,
|
||||
TCC = 0x63,
|
||||
TSR = 0x64,
|
||||
SCO = 0x65,
|
||||
SRCS = 0x66,
|
||||
SCS = 0x67,
|
||||
SLS = 0x68,
|
||||
NOT_DEFINED2 = 0x69,
|
||||
NOT_DEFINED3 = 0x6a,
|
||||
SCP = 0x6b,
|
||||
NOT_DEFINED4 = 0x6c,
|
||||
NOT_DEFINED5 = 0x6d,
|
||||
NOT_DEFINED6 = 0x6e,
|
||||
NOT_DEFINED7 = 0x6f,
|
||||
Reserved0 = 0x70,
|
||||
Reserved1 = 0x71,
|
||||
Reserved2 = 0x72,
|
||||
Reserved3 = 0x73,
|
||||
Reserved4 = 0x74,
|
||||
Reserved5 = 0x75,
|
||||
Reserved6 = 0x76,
|
||||
Reserved7 = 0x77,
|
||||
Reserved8 = 0x78,
|
||||
Reserved9 = 0x79,
|
||||
Reserveda = 0x7a,
|
||||
Reservedb = 0x7b,
|
||||
Reservedc = 0x7c,
|
||||
Reservedd = 0x7d,
|
||||
Reservedf = 0x7f
|
||||
};
|
||||
QDebug operator<<(QDebug debug, FinalBytesSingleIntermediate character);
|
||||
}
|
||||
|
||||
#endif // CONTROLL_CHARS_H
|
542
yat/backend/cursor.cpp
Normal file
542
yat/backend/cursor.cpp
Normal file
@ -0,0 +1,542 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2013 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "cursor.h"
|
||||
|
||||
#include "block.h"
|
||||
#include "screen_data.h"
|
||||
|
||||
#include <QTextCodec>
|
||||
|
||||
Cursor::Cursor(Screen* screen)
|
||||
: QObject(screen)
|
||||
, m_screen(screen)
|
||||
, m_current_text_style(screen->defaultTextStyle())
|
||||
, m_position(0,0)
|
||||
, m_new_position(0,0)
|
||||
, m_document_width(screen->width())
|
||||
, m_document_height(screen->height())
|
||||
, m_top_margin(0)
|
||||
, m_bottom_margin(0)
|
||||
, m_scroll_margins_set(false)
|
||||
, m_origin_at_margin(false)
|
||||
, m_notified(false)
|
||||
, m_visible(true)
|
||||
, m_new_visibillity(true)
|
||||
, m_blinking(false)
|
||||
, m_new_blinking(false)
|
||||
, m_wrap_around(true)
|
||||
, m_content_height_changed(false)
|
||||
, m_insert_mode(Replace)
|
||||
{
|
||||
connect(screen, SIGNAL(widthAboutToChange(int)), this, SLOT(setDocumentWidth(int)));
|
||||
connect(screen, SIGNAL(heightAboutToChange(int, int, int)), this, SLOT(setDocumentHeight(int, int, int)));
|
||||
connect(screen, SIGNAL(contentHeightChanged()), this, SLOT(contentHeightChanged()));
|
||||
|
||||
m_gl_text_codec = QTextCodec::codecForName("utf-8")->makeDecoder();
|
||||
m_gr_text_codec = QTextCodec::codecForName("utf-8")->makeDecoder();
|
||||
|
||||
for (int i = 0; i < m_document_width; i++) {
|
||||
if (i % 8 == 0) {
|
||||
m_tab_stops.append(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cursor::~Cursor()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Cursor::setDocumentWidth(int width)
|
||||
{
|
||||
if (width > m_document_width) {
|
||||
for (int i = m_document_width -1; i < width; i++) {
|
||||
if (i % 8 == 0) {
|
||||
m_tab_stops.append(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_document_width = width;
|
||||
if (new_x() >= width) {
|
||||
new_rx() = width - 1;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::setDocumentHeight(int height, int currentCursorBlock, int currentScrollBackHeight)
|
||||
{
|
||||
Q_UNUSED(currentCursorBlock);
|
||||
resetScrollArea();
|
||||
if (m_document_height > height) {
|
||||
const int to_remove = m_document_height - height;
|
||||
const int removeLinesBelowCursor =
|
||||
std::min(m_document_height - new_y(), to_remove);
|
||||
const int removeLinesAtTop = to_remove - removeLinesBelowCursor;
|
||||
if (!removeLinesAtTop) {
|
||||
new_ry() -= removeLinesAtTop;
|
||||
notifyChanged();
|
||||
|
||||
}
|
||||
} else {
|
||||
int height_diff = height - m_document_height;
|
||||
if (currentScrollBackHeight >= height_diff) {
|
||||
new_ry() += height_diff;
|
||||
} else if (currentScrollBackHeight > 0) {
|
||||
const int move = height_diff - currentScrollBackHeight;
|
||||
new_ry() += move;
|
||||
}
|
||||
}
|
||||
|
||||
m_document_height = height;
|
||||
|
||||
if (new_y() >= height) {
|
||||
new_ry() = height - 1;
|
||||
notifyChanged();
|
||||
}
|
||||
if (new_y() <= 0) {
|
||||
new_ry() = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool Cursor::visible() const
|
||||
{
|
||||
return m_visible;
|
||||
}
|
||||
void Cursor::setVisible(bool visible)
|
||||
{
|
||||
m_new_visibillity = visible;
|
||||
}
|
||||
|
||||
bool Cursor::blinking() const
|
||||
{
|
||||
return m_blinking;
|
||||
}
|
||||
|
||||
void Cursor::setBlinking(bool blinking)
|
||||
{
|
||||
m_new_blinking = blinking;
|
||||
}
|
||||
|
||||
void Cursor::setTextStyle(TextStyle::Style style, bool add)
|
||||
{
|
||||
if (add) {
|
||||
m_current_text_style.style |= style;
|
||||
} else {
|
||||
m_current_text_style.style &= !style;
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::resetStyle()
|
||||
{
|
||||
m_current_text_style.background = ColorPalette::DefaultBackground;
|
||||
m_current_text_style.forground = ColorPalette::DefaultForground;
|
||||
m_current_text_style.style = TextStyle::Normal;
|
||||
}
|
||||
|
||||
void Cursor::scrollUp(int lines)
|
||||
{
|
||||
if (new_y() < top() || new_y() > bottom())
|
||||
return;
|
||||
for (int i = 0; i < lines; i++) {
|
||||
screen_data()->moveLine(bottom(), top());
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::scrollDown(int lines)
|
||||
{
|
||||
if (new_y() < top() || new_y() > bottom())
|
||||
return;
|
||||
for (int i = 0; i < lines; i++) {
|
||||
screen_data()->moveLine(top(), bottom());
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::setTextCodec(QTextCodec *codec)
|
||||
{
|
||||
m_gl_text_codec = codec->makeDecoder();
|
||||
}
|
||||
|
||||
void Cursor::setInsertMode(InsertMode mode)
|
||||
{
|
||||
m_insert_mode = mode;
|
||||
}
|
||||
|
||||
TextStyle Cursor::currentTextStyle() const
|
||||
{
|
||||
return m_current_text_style;
|
||||
}
|
||||
|
||||
void Cursor::setTextStyleColor(ushort color)
|
||||
{
|
||||
Q_ASSERT(color >= 30 && color < 50);
|
||||
if (color < 38) {
|
||||
m_current_text_style.forground = ColorPalette::Color(color - 30);
|
||||
} else if (color == 39) {
|
||||
m_current_text_style.forground = ColorPalette::DefaultForground;
|
||||
} else if (color >= 40 && color < 48) {
|
||||
m_current_text_style.background = ColorPalette::Color(color - 40);
|
||||
} else if (color == 49) {
|
||||
m_current_text_style.background = ColorPalette::DefaultBackground;
|
||||
} else {
|
||||
qDebug() << "Failed to set color";
|
||||
}
|
||||
}
|
||||
|
||||
ColorPalette *Cursor::colorPalette() const
|
||||
{
|
||||
return m_screen->colorPalette();
|
||||
}
|
||||
|
||||
QPoint Cursor::position() const
|
||||
{
|
||||
return m_position;
|
||||
}
|
||||
|
||||
int Cursor::x() const
|
||||
{
|
||||
return m_position.x();
|
||||
}
|
||||
|
||||
int Cursor::y() const
|
||||
{
|
||||
return (m_screen->currentScreenData()->contentHeight() - m_screen->height()) + m_position.y();
|
||||
}
|
||||
|
||||
void Cursor::moveOrigin()
|
||||
{
|
||||
m_new_position = QPoint(0,adjusted_top());
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
void Cursor::moveBeginningOfLine()
|
||||
{
|
||||
new_rx() = 0;
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
void Cursor::moveUp(int lines)
|
||||
{
|
||||
int adjusted_new_y = this->adjusted_new_y();
|
||||
if (!adjusted_new_y || !lines)
|
||||
return;
|
||||
|
||||
if (lines < adjusted_new_y) {
|
||||
new_ry() -= lines;
|
||||
} else {
|
||||
new_ry() = adjusted_top();
|
||||
}
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
void Cursor::moveDown(int lines)
|
||||
{
|
||||
int bottom = adjusted_bottom();
|
||||
if (new_y() == bottom || !lines)
|
||||
return;
|
||||
|
||||
if (new_y() + lines <= bottom) {
|
||||
new_ry() += lines;
|
||||
} else {
|
||||
new_ry() = bottom;
|
||||
}
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
void Cursor::moveLeft(int positions)
|
||||
{
|
||||
if (!new_x() || !positions)
|
||||
return;
|
||||
if (positions < new_x()) {
|
||||
new_rx() -= positions;
|
||||
} else {
|
||||
new_rx() = 0;
|
||||
}
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
void Cursor::moveRight(int positions)
|
||||
{
|
||||
int width = m_screen->width();
|
||||
if (new_x() == width -1 || !positions)
|
||||
return;
|
||||
if (positions < width - new_x()) {
|
||||
new_rx() += positions;
|
||||
} else {
|
||||
new_rx() = width -1;
|
||||
}
|
||||
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
void Cursor::move(int new_x, int new_y)
|
||||
{
|
||||
int width = m_screen->width();
|
||||
|
||||
if (m_origin_at_margin) {
|
||||
new_y += m_top_margin;
|
||||
}
|
||||
|
||||
if (new_x < 0) {
|
||||
new_x = 0;
|
||||
} else if (new_x >= width) {
|
||||
new_x = width - 1;
|
||||
}
|
||||
|
||||
if (new_y < adjusted_top()) {
|
||||
new_y = adjusted_top();
|
||||
} else if (new_y > adjusted_bottom()) {
|
||||
new_y = adjusted_bottom();
|
||||
}
|
||||
|
||||
if (this->new_y() != new_y || this->new_x() != new_x) {
|
||||
m_new_position = QPoint(new_x, new_y);
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::moveToLine(int line)
|
||||
{
|
||||
const int height = m_screen->height();
|
||||
if (line < adjusted_top()) {
|
||||
line = 0;
|
||||
} else if (line > adjusted_bottom()) {
|
||||
line = height -1;
|
||||
}
|
||||
|
||||
if (line != new_y()) {
|
||||
new_rx() = line;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::moveToCharacter(int character)
|
||||
{
|
||||
const int width = m_screen->width();
|
||||
if (character < 0) {
|
||||
character = 1;
|
||||
} else if (character > width) {
|
||||
character = width;
|
||||
}
|
||||
if (character != new_x()) {
|
||||
new_rx() = character;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::moveToNextTab()
|
||||
{
|
||||
for (int i = 0; i < m_tab_stops.size(); i++) {
|
||||
if (new_x() < m_tab_stops.at(i)) {
|
||||
moveToCharacter(std::min(m_tab_stops.at(i), m_document_width -1));
|
||||
return;
|
||||
}
|
||||
}
|
||||
moveToCharacter(m_document_width - 1);
|
||||
}
|
||||
|
||||
void Cursor::setTabStop()
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < m_tab_stops.size(); i++) {
|
||||
if (new_x() == m_tab_stops.at(i))
|
||||
return;
|
||||
if (new_x() > m_tab_stops.at(i)) {
|
||||
continue;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_tab_stops.insert(i,new_x());
|
||||
}
|
||||
|
||||
void Cursor::removeTabStop()
|
||||
{
|
||||
for (int i = 0; i < m_tab_stops.size(); i++) {
|
||||
if (new_x() == m_tab_stops.at(i)) {
|
||||
m_tab_stops.remove(i);
|
||||
return;
|
||||
} else if (new_x() < m_tab_stops.at(i)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::clearTabStops()
|
||||
{
|
||||
m_tab_stops.clear();
|
||||
}
|
||||
|
||||
void Cursor::clearToBeginningOfLine()
|
||||
{
|
||||
screen_data()->clearToBeginningOfLine(m_new_position);
|
||||
}
|
||||
|
||||
void Cursor::clearToEndOfLine()
|
||||
{
|
||||
screen_data()->clearToEndOfLine(m_new_position);
|
||||
}
|
||||
|
||||
void Cursor::clearToBeginningOfScreen()
|
||||
{
|
||||
clearToBeginningOfLine();
|
||||
if (new_y() > 0)
|
||||
screen_data()->clearToBeginningOfScreen(m_new_position.y()-1);
|
||||
}
|
||||
|
||||
void Cursor::clearToEndOfScreen()
|
||||
{
|
||||
clearToEndOfLine();
|
||||
if (new_y() < m_screen->height() -1) {
|
||||
screen_data()->clearToEndOfScreen(m_new_position.y()+1);
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::clearLine()
|
||||
{
|
||||
screen_data()->clearLine(m_new_position);
|
||||
}
|
||||
|
||||
void Cursor::deleteCharacters(int characters)
|
||||
{
|
||||
screen_data()->deleteCharacters(m_new_position, new_x() + characters -1);
|
||||
}
|
||||
|
||||
void Cursor::setWrapAround(bool wrap)
|
||||
{
|
||||
m_wrap_around = wrap;
|
||||
}
|
||||
|
||||
void Cursor::addAtCursor(const QByteArray &data, bool only_latin)
|
||||
{
|
||||
if (m_insert_mode == Replace) {
|
||||
replaceAtCursor(data, only_latin);
|
||||
} else {
|
||||
insertAtCursor(data, only_latin);
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::replaceAtCursor(const QByteArray &data, bool only_latin)
|
||||
{
|
||||
const QString text = m_gl_text_codec->toUnicode(data);
|
||||
|
||||
if (!m_wrap_around && new_x() + text.size() > m_screen->width()) {
|
||||
const int size = m_document_width - new_x();
|
||||
QString toBlock = text.mid(0,size);
|
||||
toBlock.replace(toBlock.size() - 1, 1, text.at(text.size()-1));
|
||||
screen_data()->replace(m_new_position, toBlock, m_current_text_style, only_latin);
|
||||
new_rx() += toBlock.size();
|
||||
} else {
|
||||
auto diff = screen_data()->replace(m_new_position, text, m_current_text_style, only_latin);
|
||||
new_rx() += diff.character;
|
||||
new_ry() += diff.line;
|
||||
}
|
||||
|
||||
if (new_y() >= m_document_height)
|
||||
new_ry() = m_document_height - 1;
|
||||
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
void Cursor::insertAtCursor(const QByteArray &data, bool only_latin)
|
||||
{
|
||||
const QString text = m_gl_text_codec->toUnicode(data);
|
||||
auto diff = screen_data()->insert(m_new_position, text, m_current_text_style, only_latin);
|
||||
new_rx() += diff.character;
|
||||
new_ry() += diff.line;
|
||||
if (new_y() >= m_document_height)
|
||||
new_ry() = m_document_height - 1;
|
||||
if (new_x() >= m_document_width)
|
||||
new_rx() = m_document_width - 1;
|
||||
}
|
||||
|
||||
void Cursor::lineFeed()
|
||||
{
|
||||
if(new_y() >= bottom()) {
|
||||
screen_data()->insertLine(bottom(), top());
|
||||
} else {
|
||||
new_ry()++;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::reverseLineFeed()
|
||||
{
|
||||
if (new_y() == top()) {
|
||||
scrollUp(1);
|
||||
} else {
|
||||
new_ry()--;
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::setOriginAtMargin(bool atMargin)
|
||||
{
|
||||
m_origin_at_margin = atMargin;
|
||||
m_new_position = QPoint(0, adjusted_top());
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
void Cursor::setScrollArea(int from, int to)
|
||||
{
|
||||
m_top_margin = from;
|
||||
m_bottom_margin = std::min(to,m_document_height -1);
|
||||
m_scroll_margins_set = true;
|
||||
}
|
||||
|
||||
void Cursor::resetScrollArea()
|
||||
{
|
||||
m_top_margin = 0;
|
||||
m_bottom_margin = 0;
|
||||
m_scroll_margins_set = false;
|
||||
}
|
||||
|
||||
void Cursor::dispatchEvents()
|
||||
{
|
||||
if (m_new_position != m_position|| m_content_height_changed) {
|
||||
bool emit_x_changed = m_new_position.x() != m_position.x();
|
||||
bool emit_y_changed = m_new_position.y() != m_position.y();
|
||||
m_position = m_new_position;
|
||||
if (emit_x_changed)
|
||||
emit xChanged();
|
||||
if (emit_y_changed || m_content_height_changed)
|
||||
emit yChanged();
|
||||
}
|
||||
|
||||
if (m_new_visibillity != m_visible) {
|
||||
m_visible = m_new_visibillity;
|
||||
emit visibilityChanged();
|
||||
}
|
||||
|
||||
if (m_new_blinking != m_blinking) {
|
||||
m_blinking = m_new_blinking;
|
||||
emit blinkingChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Cursor::contentHeightChanged()
|
||||
{
|
||||
m_content_height_changed = true;
|
||||
}
|
||||
|
175
yat/backend/cursor.h
Normal file
175
yat/backend/cursor.h
Normal file
@ -0,0 +1,175 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2013 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef CURSOR_H
|
||||
#define CURSOR_H
|
||||
|
||||
#include "text_style.h"
|
||||
#include "screen.h"
|
||||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
class Cursor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibilityChanged)
|
||||
Q_PROPERTY(bool blinking READ blinking WRITE setBlinking NOTIFY blinkingChanged)
|
||||
Q_PROPERTY(int x READ x NOTIFY xChanged)
|
||||
Q_PROPERTY(int y READ y NOTIFY yChanged)
|
||||
public:
|
||||
enum InsertMode {
|
||||
Insert,
|
||||
Replace
|
||||
};
|
||||
|
||||
Cursor(Screen *screen);
|
||||
~Cursor();
|
||||
|
||||
bool visible() const;
|
||||
void setVisible(bool visible);
|
||||
|
||||
bool blinking() const;
|
||||
void setBlinking(bool blinking);
|
||||
|
||||
void setTextStyle(TextStyle::Style style, bool add = true);
|
||||
void resetStyle();
|
||||
TextStyle currentTextStyle() const;
|
||||
|
||||
void setTextStyleColor(ushort color);
|
||||
ColorPalette *colorPalette() const;
|
||||
|
||||
QPoint position() const;
|
||||
int x() const;
|
||||
int y() const;
|
||||
int new_x() const { return m_new_position.x(); }
|
||||
int new_y() const { return m_new_position.y(); }
|
||||
|
||||
void moveOrigin();
|
||||
void moveBeginningOfLine();
|
||||
void moveUp(int lines = 1);
|
||||
void moveDown(int lines = 1);
|
||||
void moveLeft(int positions = 1);
|
||||
void moveRight(int positions = 1);
|
||||
void move(int new_x, int new_y);
|
||||
void moveToLine(int line);
|
||||
void moveToCharacter(int character);
|
||||
|
||||
void moveToNextTab();
|
||||
void setTabStop();
|
||||
void removeTabStop();
|
||||
void clearTabStops();
|
||||
|
||||
void clearToBeginningOfLine();
|
||||
void clearToEndOfLine();
|
||||
void clearToBeginningOfScreen();
|
||||
void clearToEndOfScreen();
|
||||
void clearLine();
|
||||
|
||||
void deleteCharacters(int characters);
|
||||
|
||||
void setWrapAround(bool wrap);
|
||||
void addAtCursor(const QByteArray &text, bool only_latin = true);
|
||||
void insertAtCursor(const QByteArray &text, bool only_latin = true);
|
||||
void replaceAtCursor(const QByteArray &text, bool only_latin = true);
|
||||
|
||||
void lineFeed();
|
||||
void reverseLineFeed();
|
||||
|
||||
void setOriginAtMargin(bool atMargin);
|
||||
void setScrollArea(int from, int to);
|
||||
void resetScrollArea();
|
||||
|
||||
void scrollUp(int lines);
|
||||
void scrollDown(int lines);
|
||||
|
||||
void setTextCodec(QTextCodec *codec);
|
||||
|
||||
void setInsertMode(InsertMode mode);
|
||||
|
||||
inline void notifyChanged();
|
||||
void dispatchEvents();
|
||||
|
||||
public slots:
|
||||
void setDocumentWidth(int width);
|
||||
void setDocumentHeight(int height, int currentCursorBlock, int currentScrollBackHeight);
|
||||
|
||||
signals:
|
||||
void xChanged();
|
||||
void yChanged();
|
||||
void visibilityChanged();
|
||||
void blinkingChanged();
|
||||
|
||||
private slots:
|
||||
void contentHeightChanged();
|
||||
|
||||
private:
|
||||
ScreenData *screen_data() const { return m_screen->currentScreenData(); }
|
||||
int &new_rx() { return m_new_position.rx(); }
|
||||
int &new_ry() { return m_new_position.ry(); }
|
||||
int adjusted_new_x() const { return m_origin_at_margin ?
|
||||
m_new_position.x() - m_top_margin : m_new_position.x(); }
|
||||
int adjusted_new_y() const { return m_origin_at_margin ?
|
||||
m_new_position.y() - m_top_margin : m_new_position.y(); }
|
||||
int adjusted_top() const { return m_origin_at_margin ? m_top_margin : 0; }
|
||||
int adjusted_bottom() const { return m_origin_at_margin ? m_bottom_margin : m_document_height - 1; }
|
||||
int top() const { return m_scroll_margins_set ? m_top_margin : 0; }
|
||||
int bottom() const { return m_scroll_margins_set ? m_bottom_margin : m_document_height - 1; }
|
||||
Screen *m_screen;
|
||||
TextStyle m_current_text_style;
|
||||
QPoint m_position;
|
||||
QPoint m_new_position;
|
||||
|
||||
int m_document_width;
|
||||
int m_document_height;
|
||||
|
||||
int m_top_margin;
|
||||
int m_bottom_margin;
|
||||
bool m_scroll_margins_set;
|
||||
bool m_origin_at_margin;
|
||||
|
||||
QVector<int> m_tab_stops;
|
||||
|
||||
bool m_notified;
|
||||
bool m_visible;
|
||||
bool m_new_visibillity;
|
||||
bool m_blinking;
|
||||
bool m_new_blinking;
|
||||
bool m_wrap_around;
|
||||
bool m_content_height_changed;
|
||||
|
||||
QTextDecoder *m_gl_text_codec;
|
||||
QTextDecoder *m_gr_text_codec;
|
||||
|
||||
InsertMode m_insert_mode;
|
||||
};
|
||||
|
||||
void Cursor::notifyChanged()
|
||||
{
|
||||
if (!m_notified) {
|
||||
m_notified = true;
|
||||
m_screen->scheduleEventDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
#endif //CUROSOR_H
|
32
yat/backend/main.cpp
Normal file
32
yat/backend/main.cpp
Normal 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();
|
||||
}
|
124
yat/backend/nrc_text_codec.cpp
Normal file
124
yat/backend/nrc_text_codec.cpp
Normal file
@ -0,0 +1,124 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2013 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "nrc_text_codec.h"
|
||||
|
||||
static bool nrc_text_codec_init = false;
|
||||
void NrcTextCodec::initialize()
|
||||
{
|
||||
if (!nrc_text_codec_init) {
|
||||
nrc_text_codec_init = true;
|
||||
new NrcTextCodec("dec_special_graphics", 500001, dec_special_graphics_char_set);
|
||||
new NrcTextCodec("nrc_british", 500002, nrc_british_char_set);
|
||||
new NrcTextCodec("nrc_norwegian_danish", 5002, nrc_norwegian_danish_char_set);
|
||||
new NrcTextCodec("nrc_dutch", 5002, nrc_dutch_char_set);
|
||||
new NrcTextCodec("nrc_finnish", 5002, nrc_finnish_char_set);
|
||||
new NrcTextCodec("nrc_french", 5002, nrc_french_char_set);
|
||||
new NrcTextCodec("nrc_french_canadian", 5002, nrc_french_canadian_char_set);
|
||||
new NrcTextCodec("nrc_german", 5002, nrc_german_char_set);
|
||||
new NrcTextCodec("nrc_italian", 5002, nrc_italian_char_set);
|
||||
new NrcTextCodec("nrc_spanish", 5002, nrc_spanish_char_set);
|
||||
new NrcTextCodec("nrc_swedish", 5002, nrc_swedish_char_set);
|
||||
new NrcTextCodec("nrc_swiss", 5002, nrc_swiss_char_set);
|
||||
}
|
||||
}
|
||||
|
||||
NrcTextCodec::NrcTextCodec(const QByteArray &name, int mib, const QChar character_set[])
|
||||
: QTextCodec()
|
||||
, m_name(name)
|
||||
, m_mib(mib)
|
||||
, m_character_set(character_set)
|
||||
{
|
||||
}
|
||||
|
||||
QByteArray NrcTextCodec::name() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
int NrcTextCodec::mibEnum() const
|
||||
{
|
||||
return m_mib;
|
||||
}
|
||||
|
||||
QString NrcTextCodec::convertToUnicode(const char *in, int length, QTextCodec::ConverterState *state) const
|
||||
{
|
||||
QString ret_str;
|
||||
ret_str.reserve(length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
uchar in_char = *(in + i);
|
||||
if (in_char < 128) {
|
||||
QChar unicode = m_character_set[in_char];
|
||||
if (unicode.isNull())
|
||||
unicode = QChar(in_char);
|
||||
ret_str.append(unicode);
|
||||
} else {
|
||||
if (state) {
|
||||
if (state->flags & QTextCodec::ConvertInvalidToNull) {
|
||||
state->invalidChars++;
|
||||
ret_str.append(0);
|
||||
} else {
|
||||
state->invalidChars++;
|
||||
state->remainingChars = length - i;
|
||||
return ret_str;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret_str;
|
||||
}
|
||||
|
||||
QByteArray NrcTextCodec::convertFromUnicode(const QChar *in, int length, ConverterState *state) const
|
||||
{
|
||||
QByteArray ret_array;
|
||||
ret_array.reserve(length);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
QChar out_char = *(in + i);
|
||||
if (out_char.unicode() < 128) {
|
||||
uchar out = out_char.unicode();
|
||||
ret_array.append(out);
|
||||
} else {
|
||||
bool found = false;
|
||||
for (uchar n = 0; n < 128; n++) {
|
||||
if (m_character_set[n] == out_char) {
|
||||
ret_array.append(n);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found && state) {
|
||||
if (state->flags & QTextCodec::ConvertInvalidToNull) {
|
||||
state->invalidChars++;
|
||||
ret_array.append(char(0));
|
||||
} else {
|
||||
state->invalidChars++;
|
||||
state->remainingChars = length - i;
|
||||
return ret_array;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret_array;
|
||||
}
|
||||
|
45
yat/backend/nrc_text_codec.h
Normal file
45
yat/backend/nrc_text_codec.h
Normal file
@ -0,0 +1,45 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2013 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "character_sets.h"
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QTextCodec>
|
||||
|
||||
class NrcTextCodec : public QTextCodec
|
||||
{
|
||||
public:
|
||||
NrcTextCodec(const QByteArray &name, int mib, const QChar character_set[]);
|
||||
QByteArray name() const;
|
||||
int mibEnum() const;
|
||||
|
||||
static void initialize();
|
||||
protected:
|
||||
QString convertToUnicode(const char *in, int length, ConverterState *state) const;
|
||||
QByteArray convertFromUnicode(const QChar *in, int length, ConverterState *state) const;
|
||||
|
||||
private:
|
||||
const QByteArray m_name;
|
||||
const int m_mib;
|
||||
const QChar *m_character_set;
|
||||
};
|
1329
yat/backend/parser.cpp
Normal file
1329
yat/backend/parser.cpp
Normal file
File diff suppressed because it is too large
Load Diff
110
yat/backend/parser.h
Normal file
110
yat/backend/parser.h
Normal file
@ -0,0 +1,110 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2012 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QLinkedList>
|
||||
|
||||
#include "controll_chars.h"
|
||||
#include "utf8_decoder.h"
|
||||
|
||||
class Screen;
|
||||
|
||||
class Parser
|
||||
{
|
||||
public:
|
||||
Parser(Screen *screen);
|
||||
|
||||
void addData(const QByteArray &data);
|
||||
|
||||
private:
|
||||
|
||||
enum DecodeState {
|
||||
PlainText,
|
||||
DecodeC0,
|
||||
DecodeC1_7bit,
|
||||
DecodeCSI,
|
||||
DecodeOSC,
|
||||
DecodeCharacterSet,
|
||||
DecodeFontSize
|
||||
};
|
||||
|
||||
enum DecodeOSCState {
|
||||
None,
|
||||
ChangeWindowAndIconName,
|
||||
ChangeIconTitle,
|
||||
ChangeWindowTitle,
|
||||
Unknown
|
||||
};
|
||||
|
||||
void decodeC0(uchar character);
|
||||
void decodeC1_7bit(uchar character);
|
||||
void decodeParameters(uchar character);
|
||||
void decodeCSI(uchar character);
|
||||
void decodeOSC(uchar character);
|
||||
void decodeCharacterSet(uchar character);
|
||||
void decodeFontSize(uchar character);
|
||||
|
||||
void setMode(int mode);
|
||||
void setDecMode(int mode);
|
||||
void resetMode(int mode);
|
||||
void resetDecMode(int mode);
|
||||
|
||||
void handleSGR();
|
||||
|
||||
void tokenFinished();
|
||||
|
||||
void appendParameter();
|
||||
void handleDefaultParameters(int defaultValue);
|
||||
|
||||
DecodeState m_decode_state;
|
||||
DecodeOSCState m_decode_osc_state;
|
||||
|
||||
QByteArray m_current_data;
|
||||
|
||||
int m_current_token_start;
|
||||
int m_current_position;
|
||||
|
||||
QChar m_intermediate_char;
|
||||
|
||||
QByteArray m_parameter_string;
|
||||
QVector<int> m_parameters;
|
||||
bool m_parameters_expecting_more;
|
||||
bool m_dec_mode;
|
||||
bool m_gt_param;
|
||||
bool m_lnm_mode_set;
|
||||
bool m_contains_only_latin;
|
||||
|
||||
int m_decode_graphics_set;
|
||||
QTextCodec *m_graphic_codecs[4];
|
||||
Utf8Decoder m_utf8_decoder;
|
||||
|
||||
Screen *m_screen;
|
||||
friend QDebug operator<<(QDebug debug, DecodeState decodeState);
|
||||
};
|
||||
QDebug operator<<(QDebug debug, Parser::DecodeState decodeState);
|
||||
|
||||
#endif // PARSER_H
|
620
yat/backend/screen.cpp
Normal file
620
yat/backend/screen.cpp
Normal file
@ -0,0 +1,620 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2012 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
#include "screen_data.h"
|
||||
#include "block.h"
|
||||
#include "cursor.h"
|
||||
#include "text.h"
|
||||
#include "scrollback.h"
|
||||
#include "selection.h"
|
||||
|
||||
#include "controll_chars.h"
|
||||
#include "character_sets.h"
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtCore/QSocketNotifier>
|
||||
#include <QtGui/QGuiApplication>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <float.h>
|
||||
|
||||
Screen::Screen(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_palette(new ColorPalette(this))
|
||||
, m_parser(this)
|
||||
, m_timer_event_id(0)
|
||||
, m_width(1)
|
||||
, m_height(0)
|
||||
, m_primary_data(new ScreenData(500, this))
|
||||
, m_alternate_data(new ScreenData(0, this))
|
||||
, m_current_data(m_primary_data)
|
||||
, m_old_current_data(m_primary_data)
|
||||
, m_selection(new Selection(this))
|
||||
, m_flash(false)
|
||||
, m_cursor_changed(false)
|
||||
, m_application_cursor_key_mode(false)
|
||||
, m_fast_scroll(true)
|
||||
, m_default_background(m_palette->normalColor(ColorPalette::DefaultBackground))
|
||||
{
|
||||
Cursor *cursor = new Cursor(this);
|
||||
m_cursor_stack << cursor;
|
||||
m_new_cursors << cursor;
|
||||
|
||||
connect(m_primary_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
|
||||
connect(m_primary_data, &ScreenData::contentModified,
|
||||
this, &Screen::contentModified);
|
||||
connect(m_palette, SIGNAL(changed()), this, SLOT(paletteChanged()));
|
||||
|
||||
setHeight(25);
|
||||
setWidth(80);
|
||||
|
||||
connect(&m_pty, &YatPty::readyRead, this, &Screen::readData);
|
||||
connect(&m_pty, SIGNAL(hangupReceived()),qGuiApp, SLOT(quit()));
|
||||
|
||||
}
|
||||
|
||||
Screen::~Screen()
|
||||
{
|
||||
|
||||
for(int i = 0; i < m_to_delete.size(); i++) {
|
||||
delete m_to_delete.at(i);
|
||||
}
|
||||
//m_to_delete.clear();
|
||||
|
||||
delete m_primary_data;
|
||||
delete m_alternate_data;
|
||||
}
|
||||
|
||||
|
||||
QColor Screen::defaultForgroundColor() const
|
||||
{
|
||||
return m_palette->normalColor(ColorPalette::DefaultForground);
|
||||
}
|
||||
|
||||
QColor Screen::defaultBackgroundColor() const
|
||||
{
|
||||
return m_palette->normalColor(ColorPalette::DefaultBackground);
|
||||
}
|
||||
|
||||
void Screen::emitRequestHeight(int newHeight)
|
||||
{
|
||||
emit requestHeightChange(newHeight);
|
||||
}
|
||||
|
||||
void Screen::setHeight(int height)
|
||||
{
|
||||
if (height == m_height)
|
||||
return;
|
||||
|
||||
emit heightAboutToChange(height, currentCursor()->new_y(), currentScreenData()->scrollback()->height());
|
||||
|
||||
m_height = height;
|
||||
|
||||
m_pty.setHeight(height, height * 10);
|
||||
|
||||
emit heightChanged();
|
||||
}
|
||||
|
||||
int Screen::height() const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
int Screen::contentHeight() const
|
||||
{
|
||||
return currentScreenData()->contentHeight();
|
||||
}
|
||||
|
||||
void Screen::emitRequestWidth(int newWidth)
|
||||
{
|
||||
emit requestWidthChange(newWidth);
|
||||
}
|
||||
|
||||
void Screen::setWidth(int width)
|
||||
{
|
||||
if (width == m_width)
|
||||
return;
|
||||
|
||||
emit widthAboutToChange(width);
|
||||
|
||||
m_width = width;
|
||||
|
||||
m_pty.setWidth(width, width * 10);
|
||||
|
||||
emit widthChanged();
|
||||
}
|
||||
|
||||
int Screen::width() const
|
||||
{
|
||||
return m_width;
|
||||
}
|
||||
|
||||
void Screen::useAlternateScreenBuffer()
|
||||
{
|
||||
if (m_current_data == m_primary_data) {
|
||||
disconnect(m_primary_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
|
||||
disconnect(m_primary_data, &ScreenData::contentModified, this, &Screen::contentModified);
|
||||
m_current_data = m_alternate_data;
|
||||
m_current_data->clear();
|
||||
connect(m_alternate_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
|
||||
connect(m_primary_data, &ScreenData::contentModified, this, &Screen::contentModified);
|
||||
emit contentHeightChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::useNormalScreenBuffer()
|
||||
{
|
||||
if (m_current_data == m_alternate_data) {
|
||||
disconnect(m_alternate_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
|
||||
disconnect(m_alternate_data, &ScreenData::contentModified, this, &Screen::contentModified);
|
||||
m_current_data = m_primary_data;
|
||||
connect(m_primary_data, SIGNAL(contentHeightChanged()), this, SIGNAL(contentHeightChanged()));
|
||||
connect(m_alternate_data, &ScreenData::contentModified, this, &Screen::contentModified);
|
||||
emit contentHeightChanged();
|
||||
}
|
||||
}
|
||||
|
||||
TextStyle Screen::defaultTextStyle() const
|
||||
{
|
||||
TextStyle style;
|
||||
style.style = TextStyle::Normal;
|
||||
style.forground = ColorPalette::DefaultForground;
|
||||
style.background = ColorPalette::DefaultBackground;
|
||||
return style;
|
||||
}
|
||||
|
||||
void Screen::saveCursor()
|
||||
{
|
||||
Cursor *new_cursor = new Cursor(this);
|
||||
if (m_cursor_stack.size())
|
||||
m_cursor_stack.last()->setVisible(false);
|
||||
m_cursor_stack << new_cursor;
|
||||
m_new_cursors << new_cursor;
|
||||
}
|
||||
|
||||
void Screen::restoreCursor()
|
||||
{
|
||||
if (m_cursor_stack.size() <= 1)
|
||||
return;
|
||||
|
||||
m_delete_cursors.append(m_cursor_stack.takeLast());
|
||||
m_cursor_stack.last()->setVisible(true);
|
||||
}
|
||||
|
||||
void Screen::clearScreen()
|
||||
{
|
||||
currentScreenData()->clear();
|
||||
}
|
||||
|
||||
|
||||
ColorPalette *Screen::colorPalette() const
|
||||
{
|
||||
return m_palette;
|
||||
}
|
||||
|
||||
void Screen::fill(const QChar character)
|
||||
{
|
||||
currentScreenData()->fill(character);
|
||||
}
|
||||
|
||||
void Screen::clear()
|
||||
{
|
||||
fill(QChar(' '));
|
||||
}
|
||||
|
||||
void Screen::setFastScroll(bool fast)
|
||||
{
|
||||
m_fast_scroll = fast;
|
||||
}
|
||||
|
||||
bool Screen::fastScroll() const
|
||||
{
|
||||
return m_fast_scroll;
|
||||
}
|
||||
|
||||
Selection *Screen::selection() const
|
||||
{
|
||||
return m_selection;
|
||||
}
|
||||
|
||||
void Screen::doubleClicked(const QPointF &clicked)
|
||||
{
|
||||
Q_UNUSED(clicked);
|
||||
//int start, end;
|
||||
//currentScreenData()->getDoubleClickSelectionArea(clicked, &start, &end);
|
||||
//setSelectionAreaStart(QPointF(start,clicked.y()));
|
||||
//setSelectionAreaEnd(QPointF(end,clicked.y()));
|
||||
}
|
||||
|
||||
void Screen::setTitle(const QString &title)
|
||||
{
|
||||
m_title = title;
|
||||
emit screenTitleChanged();
|
||||
}
|
||||
|
||||
QString Screen::title() const
|
||||
{
|
||||
return m_title;
|
||||
}
|
||||
|
||||
void Screen::scheduleFlash()
|
||||
{
|
||||
m_flash = true;
|
||||
}
|
||||
|
||||
void Screen::printScreen() const
|
||||
{
|
||||
currentScreenData()->printStyleInformation();
|
||||
qDebug() << "Total height: " << currentScreenData()->contentHeight();
|
||||
}
|
||||
|
||||
void Screen::scheduleEventDispatch()
|
||||
{
|
||||
if (!m_timer_event_id) {
|
||||
m_timer_event_id = startTimer(1);
|
||||
m_time_since_initiated.restart();
|
||||
}
|
||||
|
||||
m_time_since_parsed.restart();
|
||||
}
|
||||
|
||||
void Screen::dispatchChanges()
|
||||
{
|
||||
if (m_old_current_data != m_current_data) {
|
||||
m_old_current_data->releaseTextObjects();
|
||||
m_old_current_data = m_current_data;
|
||||
}
|
||||
|
||||
currentScreenData()->dispatchLineEvents();
|
||||
emit dispatchTextSegmentChanges();
|
||||
|
||||
static int max_to_delete_size = 0;
|
||||
if (max_to_delete_size < m_to_delete.size()) {
|
||||
max_to_delete_size = m_to_delete.size();
|
||||
qDebug() << "TO DELETE SIZE :" << max_to_delete_size;
|
||||
}
|
||||
|
||||
if (m_flash) {
|
||||
m_flash = false;
|
||||
emit flash();
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_delete_cursors.size(); i++) {
|
||||
int new_index = m_new_cursors.indexOf(m_delete_cursors.at(i));
|
||||
if (new_index >= 0)
|
||||
m_new_cursors.remove(new_index);
|
||||
delete m_delete_cursors.at(i);
|
||||
}
|
||||
m_delete_cursors.clear();
|
||||
|
||||
for (int i = 0; i < m_new_cursors.size(); i++) {
|
||||
emit cursorCreated(m_new_cursors.at(i));
|
||||
}
|
||||
m_new_cursors.clear();
|
||||
|
||||
for (int i = 0; i < m_cursor_stack.size(); i++) {
|
||||
m_cursor_stack[i]->dispatchEvents();
|
||||
}
|
||||
|
||||
m_selection->dispatchChanges();
|
||||
}
|
||||
|
||||
void Screen::sendPrimaryDA()
|
||||
{
|
||||
m_pty.write(QByteArrayLiteral("\033[?6c"));
|
||||
|
||||
}
|
||||
|
||||
void Screen::sendSecondaryDA()
|
||||
{
|
||||
m_pty.write(QByteArrayLiteral("\033[>1;95;0c"));
|
||||
}
|
||||
|
||||
void Screen::setApplicationCursorKeysMode(bool enable)
|
||||
{
|
||||
m_application_cursor_key_mode = enable;
|
||||
}
|
||||
|
||||
bool Screen::applicationCursorKeyMode() const
|
||||
{
|
||||
return m_application_cursor_key_mode;
|
||||
}
|
||||
|
||||
void Screen::ensureVisiblePages(int top_line)
|
||||
{
|
||||
currentScreenData()->ensureVisiblePages(top_line);
|
||||
}
|
||||
|
||||
static bool hasControll(Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
return modifiers & Qt::MetaModifier;
|
||||
#else
|
||||
return modifiers & Qt::ControlModifier;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool hasMeta(Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
return modifiers & Qt::ControlModifier;
|
||||
#else
|
||||
return modifiers & Qt::MetaModifier;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Screen::sendKey(const QString &text, Qt::Key key, Qt::KeyboardModifiers modifiers)
|
||||
{
|
||||
|
||||
// if (key == Qt::Key_Control)
|
||||
// printScreen();
|
||||
/// UGH, this function should be re-written
|
||||
char escape = '\0';
|
||||
char control = '\0';
|
||||
char code = '\0';
|
||||
QVector<ushort> parameters;
|
||||
bool found = true;
|
||||
|
||||
switch(key) {
|
||||
case Qt::Key_Up:
|
||||
escape = C0::ESC;
|
||||
if (m_application_cursor_key_mode)
|
||||
control = C1_7bit::SS3;
|
||||
else
|
||||
control = C1_7bit::CSI;
|
||||
|
||||
code = 'A';
|
||||
break;
|
||||
case Qt::Key_Right:
|
||||
escape = C0::ESC;
|
||||
if (m_application_cursor_key_mode)
|
||||
control = C1_7bit::SS3;
|
||||
else
|
||||
control = C1_7bit::CSI;
|
||||
|
||||
code = 'C';
|
||||
break;
|
||||
case Qt::Key_Down:
|
||||
escape = C0::ESC;
|
||||
if (m_application_cursor_key_mode)
|
||||
control = C1_7bit::SS3;
|
||||
else
|
||||
control = C1_7bit::CSI;
|
||||
|
||||
code = 'B';
|
||||
break;
|
||||
case Qt::Key_Left:
|
||||
escape = C0::ESC;
|
||||
if (m_application_cursor_key_mode)
|
||||
control = C1_7bit::SS3;
|
||||
else
|
||||
control = C1_7bit::CSI;
|
||||
|
||||
code = 'D';
|
||||
break;
|
||||
case Qt::Key_Insert:
|
||||
escape = C0::ESC;
|
||||
control = C1_7bit::CSI;
|
||||
parameters.append(2);
|
||||
code = '~';
|
||||
break;
|
||||
case Qt::Key_Delete:
|
||||
escape = C0::ESC;
|
||||
control = C1_7bit::CSI;
|
||||
parameters.append(3);
|
||||
code = '~';
|
||||
break;
|
||||
case Qt::Key_Home:
|
||||
escape = C0::ESC;
|
||||
control = C1_7bit::CSI;
|
||||
parameters.append(1);
|
||||
code = '~';
|
||||
break;
|
||||
case Qt::Key_End:
|
||||
escape = C0::ESC;
|
||||
control = C1_7bit::CSI;
|
||||
parameters.append(4);
|
||||
code = '~';
|
||||
break;
|
||||
case Qt::Key_PageUp:
|
||||
escape = C0::ESC;
|
||||
control = C1_7bit::CSI;
|
||||
parameters.append(5);
|
||||
code = '~';
|
||||
break;
|
||||
case Qt::Key_PageDown:
|
||||
escape = C0::ESC;
|
||||
control = C1_7bit::CSI;
|
||||
parameters.append(6);
|
||||
code = '~';
|
||||
break;
|
||||
case Qt::Key_F1:
|
||||
case Qt::Key_F2:
|
||||
case Qt::Key_F3:
|
||||
case Qt::Key_F4:
|
||||
if (m_application_cursor_key_mode) {
|
||||
parameters.append((key & 0xff) - 37);
|
||||
escape = C0::ESC;
|
||||
control = C1_7bit::CSI;
|
||||
code = '~';
|
||||
}
|
||||
break;
|
||||
case Qt::Key_F5:
|
||||
case Qt::Key_F6:
|
||||
case Qt::Key_F7:
|
||||
case Qt::Key_F8:
|
||||
case Qt::Key_F9:
|
||||
case Qt::Key_F10:
|
||||
case Qt::Key_F11:
|
||||
case Qt::Key_F12:
|
||||
if (m_application_cursor_key_mode) {
|
||||
parameters.append((key & 0xff) - 36);
|
||||
escape = C0::ESC;
|
||||
control = C1_7bit::CSI;
|
||||
code = '~';
|
||||
}
|
||||
break;
|
||||
case Qt::Key_Control:
|
||||
case Qt::Key_Shift:
|
||||
case Qt::Key_Alt:
|
||||
case Qt::Key_AltGr:
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
found = false;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
int term_mods = 0;
|
||||
if (modifiers & Qt::ShiftModifier)
|
||||
term_mods |= 1;
|
||||
if (modifiers & Qt::AltModifier)
|
||||
term_mods |= 2;
|
||||
if (modifiers & Qt::ControlModifier)
|
||||
term_mods |= 4;
|
||||
|
||||
QByteArray toPty;
|
||||
|
||||
if (term_mods) {
|
||||
term_mods++;
|
||||
parameters.append(term_mods);
|
||||
}
|
||||
if (escape)
|
||||
toPty.append(escape);
|
||||
if (control)
|
||||
toPty.append(control);
|
||||
if (parameters.size()) {
|
||||
for (int i = 0; i < parameters.size(); i++) {
|
||||
if (i)
|
||||
toPty.append(';');
|
||||
toPty.append(QByteArray::number(parameters.at(i)));
|
||||
}
|
||||
}
|
||||
if (code)
|
||||
toPty.append(code);
|
||||
m_pty.write(toPty);
|
||||
|
||||
} else {
|
||||
QString verifiedText = text.simplified();
|
||||
if (verifiedText.isEmpty()) {
|
||||
switch (key) {
|
||||
case Qt::Key_Return:
|
||||
case Qt::Key_Enter:
|
||||
verifiedText = "\r";
|
||||
break;
|
||||
case Qt::Key_Backspace:
|
||||
verifiedText = "\010";
|
||||
break;
|
||||
case Qt::Key_Tab:
|
||||
verifiedText = "\t";
|
||||
break;
|
||||
case Qt::Key_Control:
|
||||
case Qt::Key_Meta:
|
||||
case Qt::Key_Alt:
|
||||
case Qt::Key_Shift:
|
||||
return;
|
||||
case Qt::Key_Space:
|
||||
verifiedText = " ";
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
QByteArray to_pty;
|
||||
QByteArray key_text;
|
||||
if (hasControll(modifiers)) {
|
||||
char key_char = verifiedText.toLocal8Bit().at(0);
|
||||
key_text.append(key_char & 0x1F);
|
||||
} else {
|
||||
key_text = verifiedText.toUtf8();
|
||||
}
|
||||
|
||||
if (modifiers & Qt::AltModifier) {
|
||||
to_pty.append(C0::ESC);
|
||||
}
|
||||
|
||||
if (hasMeta(modifiers)) {
|
||||
to_pty.append(C0::ESC);
|
||||
to_pty.append('@');
|
||||
to_pty.append(FinalBytesNoIntermediate::Reserved3);
|
||||
}
|
||||
|
||||
to_pty.append(key_text);
|
||||
m_pty.write(to_pty);
|
||||
}
|
||||
}
|
||||
|
||||
YatPty *Screen::pty()
|
||||
{
|
||||
return &m_pty;
|
||||
}
|
||||
|
||||
Text *Screen::createTextSegment(const TextStyleLine &style_line)
|
||||
{
|
||||
Q_UNUSED(style_line);
|
||||
Text *to_return;
|
||||
if (m_to_delete.size()) {
|
||||
to_return = m_to_delete.takeLast();
|
||||
to_return->setVisible(true);
|
||||
} else {
|
||||
to_return = new Text(this);
|
||||
emit textCreated(to_return);
|
||||
}
|
||||
|
||||
return to_return;
|
||||
}
|
||||
|
||||
void Screen::releaseTextSegment(Text *text)
|
||||
{
|
||||
m_to_delete.append(text);
|
||||
}
|
||||
|
||||
void Screen::readData(const QByteArray &data)
|
||||
{
|
||||
m_parser.addData(data);
|
||||
|
||||
scheduleEventDispatch();
|
||||
}
|
||||
|
||||
void Screen::paletteChanged()
|
||||
{
|
||||
QColor new_default = m_palette->normalColor(ColorPalette::DefaultBackground);
|
||||
if (new_default != m_default_background) {
|
||||
m_default_background = new_default;
|
||||
emit defaultBackgroundColorChanged();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Screen::timerEvent(QTimerEvent *)
|
||||
{
|
||||
if (m_timer_event_id && (m_time_since_parsed.elapsed() > 3 || m_time_since_initiated.elapsed() > 8)) {
|
||||
killTimer(m_timer_event_id);
|
||||
m_timer_event_id = 0;
|
||||
dispatchChanges();
|
||||
}
|
||||
}
|
188
yat/backend/screen.h
Normal file
188
yat/backend/screen.h
Normal file
@ -0,0 +1,188 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2012 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef TERMINALSCREEN_H
|
||||
#define TERMINALSCREEN_H
|
||||
|
||||
#include <QObject>
|
||||
|
||||
#include "color_palette.h"
|
||||
#include "parser.h"
|
||||
#include "yat_pty.h"
|
||||
#include "text_style.h"
|
||||
|
||||
#include <QtCore/QPoint>
|
||||
#include <QtCore/QSize>
|
||||
#include <QtCore/QStack>
|
||||
#include <QtCore/QElapsedTimer>
|
||||
|
||||
class Block;
|
||||
class Cursor;
|
||||
class Text;
|
||||
class ScreenData;
|
||||
class Selection;
|
||||
|
||||
class Screen : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged)
|
||||
Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged)
|
||||
Q_PROPERTY(int contentHeight READ contentHeight NOTIFY contentHeightChanged)
|
||||
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY screenTitleChanged)
|
||||
Q_PROPERTY(Selection *selection READ selection CONSTANT)
|
||||
Q_PROPERTY(QColor defaultBackgroundColor READ defaultBackgroundColor NOTIFY defaultBackgroundColorChanged)
|
||||
|
||||
public:
|
||||
explicit Screen(QObject *parent = 0);
|
||||
~Screen();
|
||||
|
||||
void emitRequestHeight(int newHeight);
|
||||
void setHeight(int height);
|
||||
int height() const;
|
||||
int contentHeight() const;
|
||||
|
||||
void emitRequestWidth(int newWidth);
|
||||
void setWidth(int width);
|
||||
int width() const;
|
||||
|
||||
ScreenData *currentScreenData() const { return m_current_data; }
|
||||
void useAlternateScreenBuffer();
|
||||
void useNormalScreenBuffer();
|
||||
|
||||
Cursor *currentCursor() const { return m_cursor_stack.last(); }
|
||||
void saveCursor();
|
||||
void restoreCursor();
|
||||
|
||||
TextStyle defaultTextStyle() const;
|
||||
|
||||
QColor defaultForgroundColor() const;
|
||||
QColor defaultBackgroundColor() const;
|
||||
|
||||
ColorPalette *colorPalette() const;
|
||||
|
||||
void clearScreen();
|
||||
|
||||
void fill(const QChar character);
|
||||
void clear();
|
||||
|
||||
void setFastScroll(bool fast);
|
||||
bool fastScroll() const;
|
||||
|
||||
Selection *selection() const;
|
||||
|
||||
Q_INVOKABLE void doubleClicked(const QPointF &clicked);
|
||||
|
||||
void setTitle(const QString &title);
|
||||
QString title() const;
|
||||
|
||||
void scheduleFlash();
|
||||
|
||||
Q_INVOKABLE void printScreen() const;
|
||||
|
||||
void scheduleEventDispatch();
|
||||
void dispatchChanges();
|
||||
|
||||
void sendPrimaryDA();
|
||||
void sendSecondaryDA();
|
||||
|
||||
void setApplicationCursorKeysMode(bool enable);
|
||||
bool applicationCursorKeyMode() const;
|
||||
|
||||
Q_INVOKABLE void sendKey(const QString &text, Qt::Key key, Qt::KeyboardModifiers modifiers);
|
||||
|
||||
YatPty *pty();
|
||||
|
||||
Q_INVOKABLE void ensureVisiblePages(int top_line);
|
||||
Text *createTextSegment(const TextStyleLine &style_line);
|
||||
void releaseTextSegment(Text *text);
|
||||
|
||||
public slots:
|
||||
void readData(const QByteArray &data);
|
||||
void paletteChanged();
|
||||
|
||||
signals:
|
||||
void reset();
|
||||
|
||||
void flash();
|
||||
|
||||
void dispatchLineChanges();
|
||||
void dispatchTextSegmentChanges();
|
||||
|
||||
void screenTitleChanged();
|
||||
|
||||
void textCreated(Text *text);
|
||||
void cursorCreated(Cursor *cursor);
|
||||
|
||||
void requestHeightChange(int newHeight);
|
||||
void heightAboutToChange(int height, int currentCursorLine, int currentScrollBackHeight);
|
||||
void heightChanged();
|
||||
void contentHeightChanged();
|
||||
|
||||
void requestWidthChange(int newWidth);
|
||||
void widthAboutToChange(int width);
|
||||
void widthChanged();
|
||||
|
||||
void defaultBackgroundColorChanged();
|
||||
|
||||
void contentModified(size_t lineModified, int lineDiff, int contentDiff);
|
||||
protected:
|
||||
void timerEvent(QTimerEvent *);
|
||||
|
||||
private:
|
||||
ColorPalette *m_palette;
|
||||
YatPty m_pty;
|
||||
Parser m_parser;
|
||||
QElapsedTimer m_time_since_parsed;
|
||||
QElapsedTimer m_time_since_initiated;
|
||||
|
||||
int m_timer_event_id;
|
||||
int m_width;
|
||||
int m_height;
|
||||
|
||||
ScreenData *m_primary_data;
|
||||
ScreenData *m_alternate_data;
|
||||
ScreenData *m_current_data;
|
||||
ScreenData *m_old_current_data;
|
||||
|
||||
QVector<Cursor *> m_cursor_stack;
|
||||
QVector<Cursor *> m_new_cursors;
|
||||
QVector<Cursor *> m_delete_cursors;
|
||||
|
||||
QString m_title;
|
||||
|
||||
Selection *m_selection;
|
||||
|
||||
bool m_flash;
|
||||
bool m_cursor_changed;
|
||||
bool m_application_cursor_key_mode;
|
||||
bool m_fast_scroll;
|
||||
|
||||
QVector<Text *> m_to_delete;
|
||||
|
||||
QColor m_default_background;
|
||||
|
||||
friend class ScreenData;
|
||||
};
|
||||
|
||||
#endif // TERMINALSCREEN_H
|
530
yat/backend/screen_data.cpp
Normal file
530
yat/backend/screen_data.cpp
Normal file
@ -0,0 +1,530 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2012 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "screen_data.h"
|
||||
|
||||
#include "block.h"
|
||||
#include "screen.h"
|
||||
#include "scrollback.h"
|
||||
#include "cursor.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
ScreenData::ScreenData(size_t max_scrollback, Screen *screen)
|
||||
: QObject(screen)
|
||||
, m_screen(screen)
|
||||
, m_scrollback(new Scrollback(max_scrollback, this))
|
||||
, m_screen_height(0)
|
||||
, m_height(0)
|
||||
, m_width(0)
|
||||
, m_block_count(0)
|
||||
, m_old_total_lines(0)
|
||||
{
|
||||
connect(screen, SIGNAL(heightAboutToChange(int, int, int)), this, SLOT(setHeight(int, int, int)));
|
||||
connect(screen, SIGNAL(widthAboutToChange(int)), this, SLOT(setWidth(int)));
|
||||
}
|
||||
|
||||
ScreenData::~ScreenData()
|
||||
{
|
||||
for (auto it = m_screen_blocks.begin(); it != m_screen_blocks.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
delete m_scrollback;
|
||||
}
|
||||
|
||||
|
||||
int ScreenData::contentHeight() const
|
||||
{
|
||||
return m_height + m_scrollback->height();
|
||||
}
|
||||
|
||||
void ScreenData::setHeight(int height, int currentCursorLine, int currentContentHeight)
|
||||
{
|
||||
Q_UNUSED(currentContentHeight);
|
||||
m_screen_height = height;
|
||||
if (height == m_height)
|
||||
return;
|
||||
|
||||
if (m_height > height) {
|
||||
const int to_remove = m_height - height;
|
||||
const int remove_from_end = std::min((m_height -1) - currentCursorLine, to_remove);
|
||||
const int remove_from_start = to_remove - remove_from_end;
|
||||
|
||||
if (remove_from_end) {
|
||||
remove_lines_from_end(remove_from_end);
|
||||
}
|
||||
if (remove_from_start) {
|
||||
push_at_most_to_scrollback(remove_from_start);
|
||||
}
|
||||
} else {
|
||||
ensure_at_least_height(height);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenData::setWidth(int width)
|
||||
{
|
||||
m_width = width;
|
||||
|
||||
for (Block *block : m_screen_blocks) {
|
||||
int before_count = block->lineCount();
|
||||
block->setWidth(width);
|
||||
m_height += block->lineCount() - before_count;
|
||||
}
|
||||
|
||||
if (m_height > m_screen_height) {
|
||||
push_at_most_to_scrollback(m_height - m_screen_height);
|
||||
} else {
|
||||
ensure_at_least_height(m_screen_height);
|
||||
}
|
||||
|
||||
m_scrollback->setWidth(width);
|
||||
}
|
||||
|
||||
|
||||
void ScreenData::clearToEndOfLine(const QPoint &point)
|
||||
{
|
||||
auto it = it_for_row_ensure_single_line_block(point.y());
|
||||
(*it)->clearToEnd(point.x());
|
||||
}
|
||||
|
||||
void ScreenData::clearToEndOfScreen(int y)
|
||||
{
|
||||
auto it = it_for_row_ensure_single_line_block(y);
|
||||
while(it != m_screen_blocks.end()) {
|
||||
clearBlock(it);
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenData::clearToBeginningOfLine(const QPoint &point)
|
||||
{
|
||||
auto it = it_for_row_ensure_single_line_block(point.y());
|
||||
(*it)->clearCharacters(0,point.x());
|
||||
}
|
||||
|
||||
void ScreenData::clearToBeginningOfScreen(int y)
|
||||
{
|
||||
auto it = it_for_row_ensure_single_line_block(y);
|
||||
if (it != m_screen_blocks.end())
|
||||
(*it)->clear();
|
||||
while(it != m_screen_blocks.begin()) {
|
||||
--it;
|
||||
clearBlock(it);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenData::clearLine(const QPoint &point)
|
||||
{
|
||||
(*it_for_row_ensure_single_line_block(point.y()))->clear();
|
||||
}
|
||||
|
||||
void ScreenData::clear()
|
||||
{
|
||||
for (auto it = m_screen_blocks.begin(); it != m_screen_blocks.end(); ++it) {
|
||||
clearBlock(it);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenData::releaseTextObjects()
|
||||
{
|
||||
for (auto it = m_screen_blocks.begin(); it != m_screen_blocks.end(); ++it) {
|
||||
(*it)->releaseTextObjects();
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenData::clearCharacters(const QPoint &point, int to)
|
||||
{
|
||||
auto it = it_for_row_ensure_single_line_block(point.y());
|
||||
(*it)->clearCharacters(point.x(),to);
|
||||
}
|
||||
|
||||
void ScreenData::deleteCharacters(const QPoint &point, int to)
|
||||
{
|
||||
auto it = it_for_row(point.y());
|
||||
if (it == m_screen_blocks.end())
|
||||
return;
|
||||
|
||||
int line_in_block = point.y() - (*it)->screenIndex();
|
||||
int chars_to_line = line_in_block * m_width;
|
||||
|
||||
(*it)->deleteCharacters(chars_to_line + point.x(), chars_to_line + to);
|
||||
}
|
||||
|
||||
CursorDiff ScreenData::replace(const QPoint &point, const QString &text, const TextStyle &style, bool only_latin)
|
||||
{
|
||||
return modify(point,text,style,true, only_latin);
|
||||
}
|
||||
|
||||
CursorDiff ScreenData::insert(const QPoint &point, const QString &text, const TextStyle &style, bool only_latin)
|
||||
{
|
||||
return modify(point,text,style,false, only_latin);
|
||||
}
|
||||
|
||||
|
||||
void ScreenData::moveLine(int from, int to)
|
||||
{
|
||||
if (from == to)
|
||||
return;
|
||||
|
||||
const size_t old_content_height = contentHeight();
|
||||
const int orig_to = to;
|
||||
if (to > from)
|
||||
to++;
|
||||
auto from_it = it_for_row_ensure_single_line_block(from);
|
||||
auto to_it = it_for_row_ensure_single_line_block(to);
|
||||
|
||||
(*from_it)->clear();
|
||||
m_screen_blocks.splice(to_it, m_screen_blocks, from_it);
|
||||
qDebug() << Q_FUNC_INFO << to;
|
||||
emit contentModified(m_scrollback->height() + to, 1, content_height_diff(old_content_height));
|
||||
}
|
||||
|
||||
void ScreenData::insertLine(int row, int topMargin)
|
||||
{
|
||||
auto row_it = it_for_row(row + 1);
|
||||
|
||||
const size_t old_content_height = contentHeight();
|
||||
|
||||
if (!topMargin && m_height >= m_screen_height) {
|
||||
push_at_most_to_scrollback(1);
|
||||
} else {
|
||||
auto row_top_margin = it_for_row_ensure_single_line_block(topMargin);
|
||||
if (row == topMargin) {
|
||||
(*row_top_margin)->clear();
|
||||
return;
|
||||
}
|
||||
delete (*row_top_margin);
|
||||
m_screen_blocks.erase(row_top_margin);
|
||||
m_height--;
|
||||
m_block_count--;
|
||||
}
|
||||
|
||||
Block *block_to_insert = new Block(m_screen);
|
||||
m_screen_blocks.insert(row_it,block_to_insert);
|
||||
m_height++;
|
||||
m_block_count++;
|
||||
|
||||
emit contentModified(m_scrollback->height() + row + 1, 1, content_height_diff(old_content_height));
|
||||
}
|
||||
|
||||
|
||||
void ScreenData::fill(const QChar &character)
|
||||
{
|
||||
clear();
|
||||
auto it = --m_screen_blocks.end();
|
||||
for (int i = 0; i < m_block_count; --it, i++) {
|
||||
QString fill_str(m_screen->width(), character);
|
||||
(*it)->replaceAtPos(0, fill_str, m_screen->defaultTextStyle());
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenData::dispatchLineEvents()
|
||||
{
|
||||
if (!m_block_count)
|
||||
return;
|
||||
const int scrollback_height = m_scrollback->height();
|
||||
int i = 0;
|
||||
for (auto it = m_screen_blocks.begin(); it != m_screen_blocks.end(); ++it) {
|
||||
int line = scrollback_height + i;
|
||||
(*it)->setLine(line);
|
||||
//(*it)->setScreenIndex(i);
|
||||
(*it)->dispatchEvents();
|
||||
i+= (*it)->lineCount();
|
||||
}
|
||||
|
||||
if (contentHeight() != m_old_total_lines) {
|
||||
m_old_total_lines = contentHeight();
|
||||
emit contentHeightChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenData::printRuler(QDebug &debug) const
|
||||
{
|
||||
QString ruler = QString("|----i----").repeated((m_width/10)+1).append("|");
|
||||
debug << " " << (void *) this << ruler;
|
||||
}
|
||||
|
||||
void ScreenData::printStyleInformation() const
|
||||
{
|
||||
auto it = m_screen_blocks.end();
|
||||
std::advance(it, -m_block_count);
|
||||
for (int i = 0; it != m_screen_blocks.end(); ++it, i++) {
|
||||
if (i % 5 == 0) {
|
||||
QDebug debug = qDebug();
|
||||
debug << "Ruler:";
|
||||
printRuler(debug);
|
||||
}
|
||||
QDebug debug = qDebug();
|
||||
(*it)->printStyleList(debug);
|
||||
}
|
||||
qDebug() << "On screen height" << m_height;
|
||||
}
|
||||
|
||||
Screen *ScreenData::screen() const
|
||||
{
|
||||
return m_screen;
|
||||
}
|
||||
|
||||
void ScreenData::ensureVisiblePages(int top_line)
|
||||
{
|
||||
m_scrollback->ensureVisiblePages(top_line);
|
||||
}
|
||||
|
||||
Scrollback *ScreenData::scrollback() const
|
||||
{
|
||||
return m_scrollback;
|
||||
}
|
||||
|
||||
void ScreenData::sendSelectionToClipboard(const QPoint &start, const QPoint &end, QClipboard::Mode mode)
|
||||
{
|
||||
if (start.y() < 0)
|
||||
return;
|
||||
if (end.y() >= contentHeight())
|
||||
return;
|
||||
|
||||
QString to_clip_board_buffer;
|
||||
|
||||
bool started_in_scrollback = false;
|
||||
if (size_t(start.y()) < m_scrollback->height()) {
|
||||
started_in_scrollback = true;
|
||||
QPoint end_scrollback = end;
|
||||
if (size_t(end.y()) >= m_scrollback->height()) {
|
||||
end_scrollback = QPoint(m_width, m_scrollback->height() - 1);
|
||||
}
|
||||
to_clip_board_buffer = m_scrollback->selection(start, end_scrollback);
|
||||
}
|
||||
|
||||
if (size_t(end.y()) >= m_scrollback->height()) {
|
||||
QPoint start_in_screen;
|
||||
if (started_in_scrollback) {
|
||||
start_in_screen = QPoint(0,0);
|
||||
} else {
|
||||
start_in_screen = start;
|
||||
start_in_screen.ry() -= m_scrollback->height();
|
||||
}
|
||||
QPoint end_in_screen = end;
|
||||
end_in_screen.ry() -= m_scrollback->height();
|
||||
|
||||
auto it = it_for_row(start_in_screen.y());
|
||||
size_t screen_index = (*it)->screenIndex();
|
||||
int start_pos = (start_in_screen.y() - (*it)->screenIndex()) * m_width + start.x();
|
||||
for (; it != m_screen_blocks.end(); ++it, start_pos = 0) {
|
||||
int end_pos = (*it)->textSize();
|
||||
bool should_break = false;
|
||||
if (size_t(screen_index + (*it)->lineCount()) > size_t(end_in_screen.y())) {
|
||||
end_pos = (end_in_screen.y() - screen_index) * m_width + end_in_screen.x();
|
||||
should_break = true;
|
||||
}
|
||||
if (to_clip_board_buffer.size())
|
||||
to_clip_board_buffer += '\n';
|
||||
to_clip_board_buffer += (*it)->textLine()->mid(start_pos, end_pos - start_pos);
|
||||
if (should_break)
|
||||
break;
|
||||
screen_index += (*it)->lineCount();
|
||||
}
|
||||
}
|
||||
QGuiApplication::clipboard()->setText(to_clip_board_buffer, mode);
|
||||
}
|
||||
|
||||
CursorDiff ScreenData::modify(const QPoint &point, const QString &text, const TextStyle &style, bool replace, bool only_latin)
|
||||
{
|
||||
auto it = it_for_row(point.y());
|
||||
Block *block = *it;
|
||||
const int start_char = (point.y() - block->screenIndex()) * m_width + point.x();
|
||||
const size_t lines_before = block->lineCount();
|
||||
const int lines_changed =
|
||||
block->lineCountAfterModified(start_char, text.size(), replace) - lines_before;
|
||||
const size_t old_content_height = contentHeight();
|
||||
m_height += lines_changed;
|
||||
if (lines_changed > 0) {
|
||||
int removed = 0;
|
||||
auto to_merge_inn = it;
|
||||
++to_merge_inn;
|
||||
while(removed < lines_changed && to_merge_inn != m_screen_blocks.end()) {
|
||||
Block *to_be_reduced = *to_merge_inn;
|
||||
bool remove_block = removed + to_be_reduced->lineCount() <= lines_changed;
|
||||
int lines_to_remove = remove_block ? to_be_reduced->lineCount() : to_be_reduced->lineCount() - (lines_changed - removed);
|
||||
block->moveLinesFromBlock(to_be_reduced, 0, lines_to_remove);
|
||||
removed += lines_to_remove;
|
||||
if (remove_block) {
|
||||
delete to_be_reduced;
|
||||
to_merge_inn = m_screen_blocks.erase(to_merge_inn);
|
||||
m_block_count--;
|
||||
} else {
|
||||
++to_merge_inn;
|
||||
}
|
||||
}
|
||||
|
||||
m_height -= removed;
|
||||
}
|
||||
|
||||
if (m_height > m_screen_height)
|
||||
push_at_most_to_scrollback(m_height - m_screen_height);
|
||||
|
||||
if (replace) {
|
||||
block->replaceAtPos(start_char, text, style, only_latin);
|
||||
} else {
|
||||
block->insertAtPos(start_char, text, style, only_latin);
|
||||
}
|
||||
int end_char = (start_char + text.size()) % m_width;
|
||||
if (end_char == 0)
|
||||
end_char = m_width -1;
|
||||
|
||||
emit contentModified(m_scrollback->height() + point.y(), lines_changed, content_height_diff(old_content_height));
|
||||
return { lines_changed, end_char - point.x()};
|
||||
}
|
||||
|
||||
void ScreenData::clearBlock(std::list<Block *>::iterator line)
|
||||
{
|
||||
int before_count = (*line)->lineCount();
|
||||
(*line)->clear();
|
||||
int diff_line = before_count - (*line)->lineCount();
|
||||
if (diff_line > 0) {
|
||||
++line;
|
||||
for (int i = 0; i < diff_line; i++) {
|
||||
m_screen_blocks.insert(line, new Block(m_screen));
|
||||
}
|
||||
m_block_count+=diff_line;
|
||||
}
|
||||
}
|
||||
|
||||
std::list<Block *>::iterator ScreenData::it_for_row_ensure_single_line_block(int row)
|
||||
{
|
||||
auto it = it_for_row(row);
|
||||
const int index = (*it)->screenIndex();
|
||||
const int lines = (*it)->lineCount();
|
||||
|
||||
if (index == row && lines == 1) {
|
||||
return it;
|
||||
}
|
||||
|
||||
int line_diff = row - index;
|
||||
return split_out_row_from_block(it, line_diff);
|
||||
}
|
||||
|
||||
std::list<Block *>::iterator ScreenData::split_out_row_from_block(std::list<Block *>::iterator it, int row_in_block)
|
||||
{
|
||||
int lines = (*it)->lineCount();
|
||||
|
||||
if (row_in_block == 0 && lines == 1)
|
||||
return it;
|
||||
|
||||
if (row_in_block == 0) {
|
||||
auto insert_before = (*it)->takeLine(0);
|
||||
insert_before->setScreenIndex(row_in_block);
|
||||
m_block_count++;
|
||||
return m_screen_blocks.insert(it,insert_before);
|
||||
} else if (row_in_block == lines -1) {
|
||||
auto insert_after = (*it)->takeLine(lines -1);
|
||||
insert_after->setScreenIndex(row_in_block);
|
||||
++it;
|
||||
m_block_count++;
|
||||
return m_screen_blocks.insert(it, insert_after);
|
||||
}
|
||||
|
||||
auto half = (*it)->split(row_in_block);
|
||||
++it;
|
||||
auto it_width_first = m_screen_blocks.insert(it, half);
|
||||
auto the_one = half->takeLine(0);
|
||||
m_block_count+=2;
|
||||
return m_screen_blocks.insert(it_width_first,the_one);
|
||||
}
|
||||
|
||||
void ScreenData::push_at_most_to_scrollback(int lines)
|
||||
{
|
||||
int pushed = 0;
|
||||
auto it = m_screen_blocks.begin();
|
||||
while (it != m_screen_blocks.end() && pushed + (*it)->lineCount() <= lines) {
|
||||
m_block_count--;
|
||||
const int block_height = (*it)->lineCount();
|
||||
m_height -= block_height;
|
||||
pushed += block_height;
|
||||
m_scrollback->addBlock(*it);
|
||||
it = m_screen_blocks.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenData::reclaim_at_least(int lines)
|
||||
{
|
||||
int lines_reclaimed = 0;
|
||||
while (m_scrollback->blockCount() && lines_reclaimed < lines) {
|
||||
Block *block = m_scrollback->reclaimBlock();
|
||||
m_height += block->lineCount();
|
||||
lines_reclaimed += block->lineCount();
|
||||
m_block_count++;
|
||||
m_screen_blocks.push_front(block);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenData::remove_lines_from_end(int lines)
|
||||
{
|
||||
int removed = 0;
|
||||
auto it = m_screen_blocks.end();
|
||||
while (it != m_screen_blocks.begin() && removed < lines) {
|
||||
--it;
|
||||
const int block_height = (*it)->lineCount();
|
||||
if (removed + block_height <= lines) {
|
||||
removed += block_height;
|
||||
m_height -= block_height;
|
||||
m_block_count--;
|
||||
delete (*it);
|
||||
it = m_screen_blocks.erase(it);
|
||||
} else {
|
||||
const int to_remove = lines - removed;
|
||||
removed += to_remove;
|
||||
m_height -= to_remove;
|
||||
Block *block = *it;
|
||||
for (int i = 0; i < to_remove; i++) {
|
||||
block->removeLine(block->lineCount()-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenData::ensure_at_least_height(int height)
|
||||
{
|
||||
if (m_height > height)
|
||||
return;
|
||||
|
||||
int to_grow = height - m_height;
|
||||
reclaim_at_least(to_grow);
|
||||
|
||||
if (height > m_height) {
|
||||
int to_insert = height - m_height;
|
||||
for (int i = 0; i < to_insert; i++) {
|
||||
m_screen_blocks.push_back(new Block(m_screen));
|
||||
}
|
||||
m_height += to_insert;
|
||||
m_block_count += to_insert;
|
||||
}
|
||||
}
|
||||
|
||||
int ScreenData::content_height_diff(size_t old_content_height)
|
||||
{
|
||||
const size_t content_height = contentHeight();
|
||||
return old_content_height < content_height ? content_height - old_content_height :
|
||||
- int(old_content_height - content_height);
|
||||
}
|
138
yat/backend/screen_data.h
Normal file
138
yat/backend/screen_data.h
Normal file
@ -0,0 +1,138 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2012 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef SCREENDATA_H
|
||||
#define SCREENDATA_H
|
||||
|
||||
#include "text_style.h"
|
||||
#include "block.h"
|
||||
|
||||
#include <QtCore/QVector>
|
||||
#include <QtCore/QPoint>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtGui/QClipboard>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
class Screen;
|
||||
class Scrollback;
|
||||
|
||||
class CursorDiff
|
||||
{
|
||||
public:
|
||||
int line;
|
||||
int character;
|
||||
};
|
||||
|
||||
class ScreenData : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScreenData(size_t max_scrollback, Screen *screen);
|
||||
~ScreenData();
|
||||
|
||||
int contentHeight() const;
|
||||
|
||||
void clearToEndOfLine(const QPoint &pos);
|
||||
void clearToEndOfScreen(int y);
|
||||
void clearToBeginningOfLine(const QPoint &pos);
|
||||
void clearToBeginningOfScreen(int y);
|
||||
void clearLine(const QPoint &pos);
|
||||
void clear();
|
||||
void releaseTextObjects();
|
||||
|
||||
void clearCharacters(const QPoint &pos, int to);
|
||||
void deleteCharacters(const QPoint &pos, int to);
|
||||
|
||||
CursorDiff replace(const QPoint &pos, const QString &text, const TextStyle &style, bool only_latin);
|
||||
CursorDiff insert(const QPoint &pos, const QString &text, const TextStyle &style, bool only_latin);
|
||||
|
||||
void moveLine(int from, int to);
|
||||
void insertLine(int insertAt, int topMargin);
|
||||
|
||||
void fill(const QChar &character);
|
||||
|
||||
void dispatchLineEvents();
|
||||
|
||||
void printRuler(QDebug &debug) const;
|
||||
void printStyleInformation() const;
|
||||
|
||||
Screen *screen() const;
|
||||
|
||||
void ensureVisiblePages(int top_line);
|
||||
|
||||
Scrollback *scrollback() const;
|
||||
|
||||
void sendSelectionToClipboard(const QPoint &start, const QPoint &end, QClipboard::Mode mode);
|
||||
|
||||
inline std::list<Block *>::iterator it_for_row(int row);
|
||||
public slots:
|
||||
void setHeight(int height, int currentCursorLine, int currentContentHeight);
|
||||
void setWidth(int width);
|
||||
|
||||
signals:
|
||||
void contentHeightChanged();
|
||||
void contentModified(size_t lineModified, int lineDiff, int contentDiff);
|
||||
|
||||
private:
|
||||
CursorDiff modify(const QPoint &pos, const QString &text, const TextStyle &style, bool replace, bool only_latin);
|
||||
void clearBlock(std::list<Block *>::iterator line);
|
||||
std::list<Block *>::iterator it_for_row_ensure_single_line_block(int row);
|
||||
std::list<Block *>::iterator split_out_row_from_block(std::list<Block *>::iterator block_it, int row_in_block);
|
||||
void push_at_most_to_scrollback(int lines);
|
||||
void reclaim_at_least(int lines);
|
||||
void remove_lines_from_end(int lines);
|
||||
void ensure_at_least_height(int height);
|
||||
int content_height_diff(size_t old_content_height);
|
||||
Screen *m_screen;
|
||||
Scrollback *m_scrollback;
|
||||
int m_screen_height;
|
||||
int m_height;
|
||||
int m_width;
|
||||
int m_block_count;
|
||||
int m_old_total_lines;
|
||||
|
||||
std::list<Block *> m_screen_blocks;
|
||||
};
|
||||
|
||||
std::list<Block *>::iterator ScreenData::it_for_row(int row)
|
||||
{
|
||||
if (row >= m_screen_height) {
|
||||
return m_screen_blocks.end();
|
||||
}
|
||||
auto it = m_screen_blocks.end();
|
||||
int line_for_block = m_screen_height;
|
||||
size_t abs_line = contentHeight();
|
||||
while (it != m_screen_blocks.begin()) {
|
||||
--it;
|
||||
line_for_block -= (*it)->lineCount();
|
||||
abs_line -= (*it)->lineCount();
|
||||
if (line_for_block <= row) {
|
||||
(*it)->setScreenIndex(line_for_block);
|
||||
(*it)->setLine(abs_line);
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
return m_screen_blocks.end();
|
||||
}
|
||||
#endif // SCREENDATA_H
|
215
yat/backend/scrollback.cpp
Normal file
215
yat/backend/scrollback.cpp
Normal file
@ -0,0 +1,215 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2013 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include "scrollback.h"
|
||||
|
||||
#include "screen_data.h"
|
||||
#include "screen.h"
|
||||
#include "block.h"
|
||||
|
||||
#define P_VAR(variable) \
|
||||
#variable ":" << variable
|
||||
|
||||
Scrollback::Scrollback(size_t max_size, ScreenData *screen_data)
|
||||
: m_screen_data(screen_data)
|
||||
, m_height(0)
|
||||
, m_width(0)
|
||||
, m_block_count(0)
|
||||
, m_max_size(max_size)
|
||||
, m_adjust_visible_pages(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Scrollback::addBlock(Block *block)
|
||||
{
|
||||
if (!m_max_size) {
|
||||
delete block;
|
||||
return;
|
||||
}
|
||||
|
||||
m_blocks.push_back(block);
|
||||
block->releaseTextObjects();
|
||||
m_block_count++;
|
||||
m_height += m_blocks.back()->lineCount();
|
||||
|
||||
while (m_height - m_blocks.front()->lineCount() >= m_max_size) {
|
||||
m_block_count--;
|
||||
m_height -= m_blocks.front()->lineCount();
|
||||
delete m_blocks.front();
|
||||
m_blocks.pop_front();
|
||||
m_adjust_visible_pages++;
|
||||
}
|
||||
|
||||
m_visible_pages.clear();
|
||||
}
|
||||
|
||||
Block *Scrollback::reclaimBlock()
|
||||
{
|
||||
if (m_blocks.empty())
|
||||
return nullptr;
|
||||
|
||||
Block *last = m_blocks.back();
|
||||
last->setWidth(m_width);
|
||||
m_block_count--;
|
||||
m_height -= last->lineCount();
|
||||
m_blocks.pop_back();
|
||||
|
||||
m_visible_pages.clear();
|
||||
return last;
|
||||
}
|
||||
|
||||
void Scrollback::ensureVisiblePages(int top_line)
|
||||
{
|
||||
if (top_line < 0)
|
||||
return;
|
||||
if (size_t(top_line) >= m_height)
|
||||
return;
|
||||
|
||||
uint height = std::max(m_screen_data->screen()->height(), 1);
|
||||
|
||||
int complete_pages = m_height / height;
|
||||
int remainder = m_height - (complete_pages * height);
|
||||
|
||||
int top_page = top_line / height;
|
||||
int bottom_page = top_page + 1;
|
||||
|
||||
std::set<int> pages_to_update;
|
||||
pages_to_update.insert(top_page);
|
||||
if (bottom_page * height < m_height)
|
||||
pages_to_update.insert(bottom_page);
|
||||
|
||||
for (auto it = m_visible_pages.begin(); it != m_visible_pages.end(); ++it) {
|
||||
Page &page = *it;
|
||||
if (pages_to_update.count(page.page_no) != 0) {
|
||||
if (page.page_no < complete_pages) {
|
||||
ensurePageVisible(page, height);
|
||||
} else if (page.page_no == complete_pages) {
|
||||
ensurePageVisible(page, remainder);
|
||||
}
|
||||
pages_to_update.erase(page.page_no);
|
||||
} else {
|
||||
ensurePageNotVisible(page);
|
||||
auto to_remove = it;
|
||||
--it;
|
||||
m_visible_pages.erase(to_remove);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = pages_to_update.begin(); it != pages_to_update.end(); ++it) {
|
||||
auto page_it = findIteratorForPage(*it);
|
||||
m_visible_pages.push_back( { *it, 0, page_it } );
|
||||
if (*it < complete_pages) {
|
||||
ensurePageVisible(m_visible_pages.back(), height);
|
||||
} else if (*it == complete_pages) {
|
||||
ensurePageVisible(m_visible_pages.back(), remainder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Scrollback::ensurePageVisible(Page &page, int new_height)
|
||||
{
|
||||
if (page.size == new_height || !m_block_count)
|
||||
return;
|
||||
|
||||
int line_no = page.page_no * m_screen_data->screen()->height();
|
||||
auto it = page.it;
|
||||
std::advance(it, page.size);
|
||||
for (int i = page.size; i < new_height; ++it, i++) {
|
||||
(*it)->setLine(line_no + i);
|
||||
(*it)->dispatchEvents();
|
||||
}
|
||||
page.size = new_height;
|
||||
}
|
||||
|
||||
void Scrollback::ensurePageNotVisible(Page &page)
|
||||
{
|
||||
auto it = page.it;
|
||||
for (int i = 0; i < page.size; ++it, i++) {
|
||||
(*it)->releaseTextObjects();
|
||||
}
|
||||
page.size = 0;
|
||||
}
|
||||
|
||||
std::list<Block *>::iterator Scrollback::findIteratorForPage(int page_no)
|
||||
{
|
||||
uint line = page_no * m_screen_data->screen()->height();
|
||||
Q_ASSERT(line < m_height);
|
||||
for (auto it = m_visible_pages.begin(); it != m_visible_pages.end(); ++it) {
|
||||
Page &page = *it;
|
||||
int diff = page_no - page.page_no;
|
||||
if (diff < 5 && diff > 5) {
|
||||
auto to_return = page.it;
|
||||
int advance = diff * m_screen_data->screen()->height();
|
||||
std::advance(to_return, advance);
|
||||
return to_return;
|
||||
}
|
||||
}
|
||||
|
||||
if (line > m_height / 2) {
|
||||
auto to_return = m_blocks.end();
|
||||
std::advance(to_return, line - m_height);
|
||||
return to_return;
|
||||
}
|
||||
|
||||
auto to_return = m_blocks.begin();
|
||||
std::advance(to_return, line);
|
||||
return to_return;
|
||||
}
|
||||
|
||||
void Scrollback::adjustVisiblePages()
|
||||
{
|
||||
if (!m_adjust_visible_pages)
|
||||
return;
|
||||
|
||||
for (auto it = m_visible_pages.begin(); it != m_visible_pages.end(); ++it) {
|
||||
Page &page = *it;
|
||||
const size_t line_for_page = page.page_no * m_screen_data->screen()->height();
|
||||
if (line_for_page < m_adjust_visible_pages) {
|
||||
auto to_remove = it;
|
||||
--it;
|
||||
m_visible_pages.erase(to_remove);
|
||||
} else {
|
||||
page.size = 0;
|
||||
std::advance(page.it, m_adjust_visible_pages);
|
||||
}
|
||||
}
|
||||
|
||||
m_adjust_visible_pages = 0;
|
||||
}
|
||||
|
||||
size_t Scrollback::height() const
|
||||
{
|
||||
return m_height;
|
||||
}
|
||||
|
||||
void Scrollback::setWidth(int width)
|
||||
{
|
||||
m_width = width;
|
||||
}
|
||||
|
||||
QString Scrollback::selection(const QPoint &start, const QPoint &end) const
|
||||
{
|
||||
Q_UNUSED(start);
|
||||
Q_UNUSED(end);
|
||||
return QString();
|
||||
}
|
73
yat/backend/scrollback.h
Normal file
73
yat/backend/scrollback.h
Normal file
@ -0,0 +1,73 @@
|
||||
/******************************************************************************
|
||||
* Copyright (c) 2013 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#ifndef SCROLLBACK_H
|
||||
#define SCROLLBACK_H
|
||||
|
||||
#include <set>
|
||||
#include <list>
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/QPoint>
|
||||
class ScreenData;
|
||||
class Block;
|
||||
|
||||
struct Page {
|
||||
int page_no;
|
||||
int size;
|
||||
std::list<Block *>::iterator it;
|
||||
};
|
||||
|
||||
class Scrollback
|
||||
{
|
||||
public:
|
||||
Scrollback(size_t max_size, ScreenData *screen_data);
|
||||
|
||||
void addBlock(Block *block);
|
||||
Block *reclaimBlock();
|
||||
void ensureVisiblePages(int top_line);
|
||||
|
||||
size_t height() const;
|
||||
|
||||
void setWidth(int width);
|
||||
|
||||
size_t blockCount() { return m_block_count; }
|
||||
|
||||
QString selection(const QPoint &start, const QPoint &end) const;
|
||||
private:
|
||||
void ensurePageVisible(Page &page, int new_height);
|
||||
void ensurePageNotVisible(Page &page);
|
||||
std::list<Block *>::iterator findIteratorForPage(int page_no);
|
||||
void adjustVisiblePages();
|
||||
ScreenData *m_screen_data;
|
||||
|
||||
std::list<Block *> m_blocks;
|
||||
std::list<Page> m_visible_pages;
|
||||
size_t m_height;
|
||||
size_t m_width;
|
||||
size_t m_block_count;
|
||||
size_t m_max_size;
|
||||
size_t m_adjust_visible_pages;
|
||||
};
|
||||
|
||||
#endif //SCROLLBACK_H
|
197
yat/backend/selection.cpp
Normal file
197
yat/backend/selection.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#include "selection.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "screen_data.h"
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
|
||||
Selection::Selection(Screen *screen)
|
||||
: QObject(screen)
|
||||
, m_screen(screen)
|
||||
, m_new_start_x(0)
|
||||
, m_start_x(0)
|
||||
, m_new_start_y(0)
|
||||
, m_start_y(0)
|
||||
, m_new_end_x(0)
|
||||
, m_end_x(0)
|
||||
, m_new_end_y(0)
|
||||
, m_end_y(0)
|
||||
, m_new_enable(false)
|
||||
{
|
||||
connect(screen, &Screen::contentModified, this, &Selection::screenContentModified);
|
||||
|
||||
}
|
||||
|
||||
void Selection::setStartX(int x)
|
||||
{
|
||||
if (x != m_new_start_x) {
|
||||
m_new_start_x = x;
|
||||
setValidity();
|
||||
m_screen->scheduleEventDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
int Selection::startX() const
|
||||
{
|
||||
return m_start_x;
|
||||
}
|
||||
|
||||
void Selection::setStartY(int y)
|
||||
{
|
||||
if (y != m_new_start_y) {
|
||||
m_new_start_y = y;
|
||||
setValidity();
|
||||
m_screen->scheduleEventDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
int Selection::startY() const
|
||||
{
|
||||
return m_start_y;
|
||||
}
|
||||
|
||||
void Selection::setEndX(int x)
|
||||
{
|
||||
if (m_new_end_x != x) {
|
||||
m_new_end_x = x;
|
||||
setValidity();
|
||||
m_screen->scheduleEventDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
int Selection::endX() const
|
||||
{
|
||||
return m_end_x;
|
||||
}
|
||||
|
||||
void Selection::setEndY(int y)
|
||||
{
|
||||
if (m_new_end_y != y) {
|
||||
m_new_end_y = y;
|
||||
setValidity();
|
||||
m_screen->scheduleEventDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
int Selection::endY() const
|
||||
{
|
||||
return m_end_y;
|
||||
}
|
||||
|
||||
void Selection::setEnable(bool enable)
|
||||
{
|
||||
if (m_new_enable != enable) {
|
||||
m_new_enable = enable;
|
||||
m_screen->scheduleEventDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void Selection::screenContentModified(size_t lineModified, int lineDiff, int contentDiff)
|
||||
{
|
||||
if (!m_new_enable)
|
||||
return;
|
||||
|
||||
if (lineModified >= size_t(m_new_start_y) && lineModified <= size_t(m_new_end_y)) {
|
||||
setEnable(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (size_t(m_new_end_y) < lineModified && lineModified != contentDiff) {
|
||||
m_new_end_y -= lineDiff - contentDiff;
|
||||
m_new_start_y -= lineDiff - contentDiff;
|
||||
if (m_new_end_y < 0) {
|
||||
setEnable(false);
|
||||
return;
|
||||
}
|
||||
if (m_new_start_y < 0) {
|
||||
m_new_start_y = 0;
|
||||
}
|
||||
m_screen->scheduleEventDispatch();
|
||||
}
|
||||
}
|
||||
|
||||
void Selection::setValidity()
|
||||
{
|
||||
if (m_new_end_y > m_new_start_y ||
|
||||
(m_new_end_y == m_new_start_y &&
|
||||
m_new_end_x > m_new_start_x)) {
|
||||
setEnable(true);
|
||||
} else {
|
||||
setEnable(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Selection::sendToClipboard() const
|
||||
{
|
||||
m_screen->currentScreenData()->sendSelectionToClipboard(start_new_point(), end_new_point(), QClipboard::Clipboard);
|
||||
}
|
||||
|
||||
void Selection::sendToSelection() const
|
||||
{
|
||||
m_screen->currentScreenData()->sendSelectionToClipboard(start_new_point(), end_new_point(), QClipboard::Selection);
|
||||
}
|
||||
|
||||
void Selection::pasteFromSelection()
|
||||
{
|
||||
m_screen->pty()->write(QGuiApplication::clipboard()->text(QClipboard::Selection).toUtf8());
|
||||
}
|
||||
|
||||
void Selection::pasteFromClipboard()
|
||||
{
|
||||
m_screen->pty()->write(QGuiApplication::clipboard()->text(QClipboard::Clipboard).toUtf8());
|
||||
}
|
||||
|
||||
void Selection::dispatchChanges()
|
||||
{
|
||||
if (!m_new_enable && !m_enable)
|
||||
return;
|
||||
|
||||
if (m_new_start_y != m_start_y) {
|
||||
m_start_y = m_new_start_y;
|
||||
emit startYChanged();
|
||||
}
|
||||
if (m_new_start_x != m_start_x) {
|
||||
m_start_x = m_new_start_x;
|
||||
emit startXChanged();
|
||||
}
|
||||
if (m_new_end_y != m_end_y) {
|
||||
m_end_y = m_new_end_y;
|
||||
emit endYChanged();
|
||||
}
|
||||
if (m_new_end_x != m_end_x) {
|
||||
m_end_x = m_new_end_x;
|
||||
emit endXChanged();
|
||||
}
|
||||
if (m_new_enable != m_enable) {
|
||||
m_enable = m_new_enable;
|
||||
emit enableChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool Selection::enable() const
|
||||
{
|
||||
return m_enable;
|
||||
}
|
93
yat/backend/selection.h
Normal file
93
yat/backend/selection.h
Normal file
@ -0,0 +1,93 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef SELECTION_H
|
||||
#define SELECTION_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QPoint>
|
||||
|
||||
class Screen;
|
||||
|
||||
class Selection : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(int startX READ startX WRITE setStartX NOTIFY startXChanged)
|
||||
Q_PROPERTY(int startY READ startY WRITE setStartY NOTIFY startYChanged)
|
||||
Q_PROPERTY(int endX READ endX WRITE setEndX NOTIFY endXChanged)
|
||||
Q_PROPERTY(int endY READ endY WRITE setEndY NOTIFY endYChanged)
|
||||
Q_PROPERTY(bool enable READ enable WRITE setEnable NOTIFY enableChanged)
|
||||
|
||||
public:
|
||||
explicit Selection(Screen *screen);
|
||||
|
||||
void setStartX(int x);
|
||||
int startX() const;
|
||||
|
||||
void setStartY(int y);
|
||||
int startY() const;
|
||||
|
||||
void setEndX(int x);
|
||||
int endX() const;
|
||||
|
||||
void setEndY(int y);
|
||||
int endY() const;
|
||||
|
||||
void setEnable(bool enabled);
|
||||
bool enable() const;
|
||||
|
||||
Q_INVOKABLE void sendToClipboard() const;
|
||||
Q_INVOKABLE void sendToSelection() const;
|
||||
Q_INVOKABLE void pasteFromSelection();
|
||||
Q_INVOKABLE void pasteFromClipboard();
|
||||
|
||||
void dispatchChanges();
|
||||
signals:
|
||||
void startXChanged();
|
||||
void startYChanged();
|
||||
void endXChanged();
|
||||
void endYChanged();
|
||||
void enableChanged();
|
||||
|
||||
private slots:
|
||||
void screenContentModified(size_t lineModified, int lineDiff, int contentDiff);
|
||||
|
||||
private:
|
||||
void setValidity();
|
||||
QPoint start_new_point() const { return QPoint(m_new_start_x, m_new_start_y); }
|
||||
QPoint end_new_point() const { return QPoint(m_new_end_x, m_new_end_y); }
|
||||
|
||||
Screen *m_screen;
|
||||
int m_new_start_x;
|
||||
int m_start_x;
|
||||
int m_new_start_y;
|
||||
int m_start_y;
|
||||
int m_new_end_x;
|
||||
int m_end_x;
|
||||
int m_new_end_y;
|
||||
int m_end_y;
|
||||
bool m_new_enable;
|
||||
bool m_enable;
|
||||
};
|
||||
#endif
|
255
yat/backend/text.cpp
Normal file
255
yat/backend/text.cpp
Normal file
@ -0,0 +1,255 @@
|
||||
/**************************************************************************************************
|
||||
* Copyright (c) 2012 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
* associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
* OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
***************************************************************************************************/
|
||||
|
||||
#include "text.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "block.h"
|
||||
#include <QtQuick/QQuickItem>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
Text::Text(Screen *screen)
|
||||
: QObject(screen)
|
||||
, m_screen(screen)
|
||||
, m_text_line(0)
|
||||
, m_start_index(0)
|
||||
, m_old_start_index(0)
|
||||
, m_end_index(0)
|
||||
, m_line(0)
|
||||
, m_old_line(0)
|
||||
, m_width(1)
|
||||
, m_style_dirty(true)
|
||||
, m_text_dirty(true)
|
||||
, m_visible(true)
|
||||
, m_visible_old(true)
|
||||
, m_latin(true)
|
||||
, m_latin_old(true)
|
||||
, m_forgroundColor(m_screen->defaultForgroundColor())
|
||||
, m_backgroundColor(m_screen->defaultBackgroundColor())
|
||||
{
|
||||
connect(m_screen->colorPalette(), SIGNAL(changed()), this, SLOT(paletteChanged()));
|
||||
connect(m_screen, SIGNAL(dispatchTextSegmentChanges()), this, SLOT(dispatchEvents()));
|
||||
}
|
||||
|
||||
Text::~Text()
|
||||
{
|
||||
}
|
||||
|
||||
int Text::index() const
|
||||
{
|
||||
return m_start_index % m_width;
|
||||
}
|
||||
|
||||
int Text::line() const
|
||||
{
|
||||
return m_line + (m_start_index / m_width);
|
||||
}
|
||||
|
||||
void Text::setLine(int line, int width, const QString *textLine)
|
||||
{
|
||||
m_line = line;
|
||||
m_width = width;
|
||||
m_text_dirty = true;
|
||||
m_text_line = textLine;
|
||||
}
|
||||
|
||||
bool Text::visible() const
|
||||
{
|
||||
return m_visible;
|
||||
}
|
||||
|
||||
void Text::setVisible(bool visible)
|
||||
{
|
||||
m_visible = visible;
|
||||
}
|
||||
|
||||
QString Text::text() const
|
||||
{
|
||||
return m_text;
|
||||
}
|
||||
|
||||
QColor Text::foregroundColor() const
|
||||
{
|
||||
return m_forgroundColor;
|
||||
}
|
||||
|
||||
|
||||
QColor Text::backgroundColor() const
|
||||
{
|
||||
return m_backgroundColor;
|
||||
}
|
||||
|
||||
void Text::setStringSegment(int start_index, int end_index, bool text_changed)
|
||||
{
|
||||
m_start_index = start_index;
|
||||
m_end_index = end_index;
|
||||
|
||||
m_text_dirty = text_changed;
|
||||
}
|
||||
|
||||
void Text::setTextStyle(const TextStyle &style)
|
||||
{
|
||||
m_new_style = style;
|
||||
m_style_dirty = true;
|
||||
}
|
||||
|
||||
bool Text::bold() const
|
||||
{
|
||||
return m_style.style & TextStyle::Bold;
|
||||
}
|
||||
|
||||
bool Text::blinking() const
|
||||
{
|
||||
return m_style.style & TextStyle::Blinking;
|
||||
}
|
||||
|
||||
bool Text::underline() const
|
||||
{
|
||||
return m_style.style & TextStyle::Underlined;
|
||||
}
|
||||
|
||||
void Text::setLatin(bool latin)
|
||||
{
|
||||
m_latin = latin;
|
||||
}
|
||||
|
||||
bool Text::latin() const
|
||||
{
|
||||
return m_latin_old;
|
||||
}
|
||||
|
||||
static bool differentStyle(TextStyle::Styles a, TextStyle::Styles b, TextStyle::Style style)
|
||||
{
|
||||
return (a & style) != (b & style);
|
||||
}
|
||||
|
||||
void Text::dispatchEvents()
|
||||
{
|
||||
int old_line = m_old_line + (m_old_start_index / m_width);
|
||||
int new_line = m_line + (m_start_index / m_width);
|
||||
if (old_line != new_line) {
|
||||
m_old_line = m_line;
|
||||
emit lineChanged();
|
||||
}
|
||||
|
||||
if (m_latin != m_latin_old) {
|
||||
m_latin_old = m_latin;
|
||||
emit latinChanged();
|
||||
}
|
||||
|
||||
if (m_old_start_index != m_start_index
|
||||
|| m_text_dirty) {
|
||||
m_text_dirty = false;
|
||||
QString old_text = m_text;
|
||||
m_text = m_text_line->mid(m_start_index, m_end_index - m_start_index + 1);
|
||||
if (m_old_start_index != m_start_index) {
|
||||
m_old_start_index = m_start_index;
|
||||
emit indexChanged();
|
||||
}
|
||||
emit textChanged();
|
||||
}
|
||||
|
||||
if (m_style_dirty) {
|
||||
m_style_dirty = false;
|
||||
|
||||
bool emit_forground = m_new_style.forground != m_style.forground;
|
||||
bool emit_background = m_new_style.background != m_style.background;
|
||||
TextStyle::Styles new_style = m_new_style.style;
|
||||
TextStyle::Styles old_style = m_style.style;
|
||||
|
||||
bool emit_bold = false;
|
||||
bool emit_blink = false;
|
||||
bool emit_underline = false;
|
||||
bool emit_inverse = false;
|
||||
if (new_style != old_style) {
|
||||
emit_bold = differentStyle(new_style, old_style, TextStyle::Bold);
|
||||
emit_blink = differentStyle(new_style, old_style, TextStyle::Blinking);
|
||||
emit_underline = differentStyle(new_style, old_style, TextStyle::Underlined);
|
||||
emit_inverse = differentStyle(new_style, old_style, TextStyle::Inverse);
|
||||
}
|
||||
|
||||
m_style = m_new_style;
|
||||
if (emit_inverse) {
|
||||
setForgroundColor();
|
||||
setBackgroundColor();
|
||||
} else {
|
||||
if (emit_forground || emit_bold) {
|
||||
setForgroundColor();
|
||||
}
|
||||
if (emit_background) {
|
||||
setBackgroundColor();
|
||||
}
|
||||
}
|
||||
|
||||
if (emit_bold) {
|
||||
emit boldChanged();
|
||||
}
|
||||
|
||||
if (emit_blink) {
|
||||
emit blinkingChanged();
|
||||
}
|
||||
|
||||
if (emit_underline) {
|
||||
emit underlineChanged();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (m_visible_old != m_visible) {
|
||||
m_visible_old = m_visible;
|
||||
emit visibleChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Text::paletteChanged()
|
||||
{
|
||||
setBackgroundColor();
|
||||
setForgroundColor();
|
||||
}
|
||||
|
||||
void Text::setBackgroundColor()
|
||||
{
|
||||
QColor new_background;
|
||||
if (m_style.style & TextStyle::Inverse) {
|
||||
new_background = m_screen->colorPalette()->color(m_style.forground, false);
|
||||
} else {
|
||||
new_background = m_screen->colorPalette()->color(m_style.background, false);
|
||||
}
|
||||
if (new_background != m_backgroundColor) {
|
||||
m_backgroundColor = new_background;
|
||||
emit backgroundColorChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void Text::setForgroundColor()
|
||||
{
|
||||
QColor new_forground;
|
||||
if (m_style.style & TextStyle::Inverse) {
|
||||
new_forground = m_screen->colorPalette()->color(m_style.background, false);
|
||||
} else {
|
||||
new_forground = m_screen->colorPalette()->color(m_style.forground, false);
|
||||
}
|
||||
if (new_forground != m_forgroundColor) {
|
||||
m_forgroundColor = new_forground;
|
||||
emit forgroundColorChanged();
|
||||
}
|
||||
}
|
121
yat/backend/text.h
Normal file
121
yat/backend/text.h
Normal file
@ -0,0 +1,121 @@
|
||||
/**************************************************************************************************
|
||||
* Copyright (c) 2012 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
* associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
* OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
***************************************************************************************************/
|
||||
|
||||
#ifndef TEXT_SEGMENT_H
|
||||
#define TEXT_SEGMENT_H
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtGui/QColor>
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QSize>
|
||||
|
||||
#include "text_style.h"
|
||||
|
||||
class Screen;
|
||||
class QQuickItem;
|
||||
|
||||
class Text : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(int index READ index NOTIFY indexChanged)
|
||||
Q_PROPERTY(int line READ line NOTIFY lineChanged)
|
||||
Q_PROPERTY(bool visible READ visible NOTIFY visibleChanged)
|
||||
Q_PROPERTY(QString text READ text NOTIFY textChanged)
|
||||
Q_PROPERTY(QColor foregroundColor READ foregroundColor NOTIFY forgroundColorChanged)
|
||||
Q_PROPERTY(QColor backgroundColor READ backgroundColor NOTIFY backgroundColorChanged)
|
||||
Q_PROPERTY(bool bold READ bold NOTIFY boldChanged)
|
||||
Q_PROPERTY(bool blinking READ blinking NOTIFY blinkingChanged)
|
||||
Q_PROPERTY(bool underline READ underline NOTIFY underlineChanged)
|
||||
Q_PROPERTY(bool latin READ latin NOTIFY latinChanged)
|
||||
public:
|
||||
Text(Screen *screen);
|
||||
~Text();
|
||||
|
||||
int index() const;
|
||||
|
||||
int line() const;
|
||||
void setLine(int line, int width, const QString *textLine);
|
||||
|
||||
bool visible() const;
|
||||
void setVisible(bool visible);
|
||||
|
||||
QString text() const;
|
||||
QColor foregroundColor() const;
|
||||
QColor backgroundColor() const;
|
||||
|
||||
void setStringSegment(int start_index, int end_index, bool textChanged);
|
||||
void setTextStyle(const TextStyle &style);
|
||||
|
||||
bool bold() const;
|
||||
bool blinking() const;
|
||||
bool underline() const;
|
||||
|
||||
void setLatin(bool latin);
|
||||
bool latin() const;
|
||||
|
||||
QObject *item() const;
|
||||
|
||||
public slots:
|
||||
void dispatchEvents();
|
||||
|
||||
signals:
|
||||
void indexChanged();
|
||||
void lineChanged();
|
||||
void visibleChanged();
|
||||
void textChanged();
|
||||
void forgroundColorChanged();
|
||||
void backgroundColorChanged();
|
||||
void boldChanged();
|
||||
void blinkingChanged();
|
||||
void underlineChanged();
|
||||
void latinChanged();
|
||||
|
||||
private slots:
|
||||
void paletteChanged();
|
||||
|
||||
private:
|
||||
void setBackgroundColor();
|
||||
void setForgroundColor();
|
||||
|
||||
Screen *m_screen;
|
||||
QString m_text;
|
||||
const QString *m_text_line;
|
||||
int m_start_index;
|
||||
int m_old_start_index;
|
||||
int m_end_index;
|
||||
int m_line;
|
||||
int m_old_line;
|
||||
int m_width;
|
||||
|
||||
TextStyle m_style;
|
||||
TextStyle m_new_style;
|
||||
|
||||
bool m_style_dirty;
|
||||
bool m_text_dirty;
|
||||
bool m_visible;
|
||||
bool m_visible_old;
|
||||
bool m_latin;
|
||||
bool m_latin_old;
|
||||
|
||||
QColor m_forgroundColor;
|
||||
QColor m_backgroundColor;
|
||||
};
|
||||
|
||||
#endif // TEXT_SEGMENT_H
|
36
yat/backend/text_style.cpp
Normal file
36
yat/backend/text_style.cpp
Normal file
@ -0,0 +1,36 @@
|
||||
#include "text_style.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "text.h"
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
TextStyle::TextStyle()
|
||||
: style(Normal)
|
||||
, forground(ColorPalette::DefaultForground)
|
||||
, background(ColorPalette::DefaultBackground)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool TextStyle::isCompatible(const TextStyle &other) const
|
||||
{
|
||||
return forground == other.forground
|
||||
&& background == other.background
|
||||
&& style == other.style;
|
||||
}
|
||||
|
||||
QDebug operator<<(QDebug debug, TextStyleLine line)
|
||||
{
|
||||
debug << "[" << line.start_index << "(" << line.style << ":" << line.forground << ":" << line.background << ")" << line.end_index << "]";
|
||||
return debug;
|
||||
}
|
||||
|
||||
void TextStyleLine::releaseTextSegment(Screen *screen)
|
||||
{
|
||||
if (text_segment) {
|
||||
text_segment->setVisible(false);
|
||||
screen->releaseTextSegment(text_segment);
|
||||
text_segment = 0;
|
||||
}
|
||||
}
|
85
yat/backend/text_style.h
Normal file
85
yat/backend/text_style.h
Normal file
@ -0,0 +1,85 @@
|
||||
#ifndef TEXT_STYLE_H
|
||||
#define TEXT_STYLE_H
|
||||
|
||||
#include <QtGui/QColor>
|
||||
|
||||
#include "color_palette.h"
|
||||
|
||||
class Screen;
|
||||
|
||||
class TextStyle
|
||||
{
|
||||
public:
|
||||
enum Style {
|
||||
Normal = 0x0000,
|
||||
Italic = 0x0001,
|
||||
Bold = 0x0002,
|
||||
Underlined = 0x0004,
|
||||
Blinking = 0x0008,
|
||||
FastBlinking = 0x0010,
|
||||
Gothic = 0x0020,
|
||||
DoubleUnderlined = 0x0040,
|
||||
Framed = 0x0080,
|
||||
Overlined = 0x0100,
|
||||
Encircled = 0x0200,
|
||||
Inverse = 0x0400
|
||||
};
|
||||
Q_DECLARE_FLAGS(Styles, Style)
|
||||
|
||||
TextStyle();
|
||||
|
||||
Styles style;
|
||||
ColorPalette::Color forground;
|
||||
ColorPalette::Color background;
|
||||
|
||||
bool isCompatible(const TextStyle &other) const;
|
||||
};
|
||||
|
||||
class Text;
|
||||
class TextStyleLine : public TextStyle {
|
||||
public:
|
||||
TextStyleLine(const TextStyle &style, int start_index, int end_index)
|
||||
: TextStyle(style)
|
||||
, start_index(start_index)
|
||||
, end_index(end_index)
|
||||
, old_index(-1)
|
||||
, text_segment(0)
|
||||
, style_dirty(true)
|
||||
, index_dirty(true)
|
||||
, text_dirty(true)
|
||||
{
|
||||
}
|
||||
|
||||
TextStyleLine()
|
||||
: start_index(0)
|
||||
, end_index(0)
|
||||
, old_index(-1)
|
||||
, text_segment(0)
|
||||
, style_dirty(false)
|
||||
, index_dirty(false)
|
||||
, text_dirty(false)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void releaseTextSegment(Screen *screen);
|
||||
|
||||
int start_index;
|
||||
int end_index;
|
||||
|
||||
int old_index;
|
||||
Text *text_segment;
|
||||
bool style_dirty;
|
||||
bool index_dirty;
|
||||
bool text_dirty;
|
||||
|
||||
void setStyle(const TextStyle &style) {
|
||||
forground = style.forground;
|
||||
background = style.background;
|
||||
this->style = style.style;
|
||||
}
|
||||
};
|
||||
QDebug operator<<(QDebug debug, TextStyleLine line);
|
||||
|
||||
|
||||
#endif // TEXT_STYLE_H
|
109
yat/backend/utf8_decoder.h
Normal file
109
yat/backend/utf8_decoder.h
Normal file
@ -0,0 +1,109 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2013 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef UTF8_DECODER
|
||||
#define UTF8_DECODER
|
||||
|
||||
#include "controll_chars.h"
|
||||
|
||||
class Utf8Decoder
|
||||
{
|
||||
public:
|
||||
inline Utf8Decoder();
|
||||
|
||||
inline void addChar(uchar character);
|
||||
|
||||
inline bool isLatin() const;
|
||||
inline bool isC1() const;
|
||||
|
||||
inline void clear();
|
||||
private:
|
||||
short m_expected_length;
|
||||
short m_length;
|
||||
uint32_t m_unicode;
|
||||
};
|
||||
|
||||
Utf8Decoder::Utf8Decoder()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void Utf8Decoder::addChar(uchar character)
|
||||
{
|
||||
if (m_length && m_length == m_expected_length) {
|
||||
clear();
|
||||
}
|
||||
|
||||
if (character < 0x80)
|
||||
return;
|
||||
|
||||
fprintf(stderr, "Character: 0x%x\n", character);
|
||||
if (m_expected_length == 0) {
|
||||
//this is naive. There must be a faster way.
|
||||
if ((character & 0xfc) == 0xfc) {
|
||||
m_expected_length = 5;
|
||||
m_unicode = character & 0x01;
|
||||
} else if ((character & 0xf8) == 0xf8) {
|
||||
m_expected_length = 4;
|
||||
m_unicode = character & 0x03;
|
||||
} else if ((character & 0xf0) == 0xf0) {
|
||||
m_expected_length = 3;
|
||||
m_unicode = character & 0x07;
|
||||
} else if ((character & 0xe0) == 0xe0) {
|
||||
m_expected_length = 2;
|
||||
m_unicode = character & 0x0f;
|
||||
} else if ((character & 0xc0) == 0xc0) {
|
||||
m_expected_length = 1;
|
||||
m_unicode = character & 0x1f;
|
||||
} else {
|
||||
m_expected_length = 0;
|
||||
m_unicode = 0;
|
||||
qWarning("Utf8Decoder: invalid decoder character");
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Before 0x%x adding 0x%x pure 0x%x\n", m_unicode,(character & 0x3f), character);
|
||||
m_unicode = (m_unicode << 6) | (character & 0x3f);
|
||||
fprintf(stderr, "After 0x%x\n", m_unicode);
|
||||
m_length++;
|
||||
}
|
||||
}
|
||||
|
||||
bool Utf8Decoder::isLatin() const
|
||||
{
|
||||
return m_expected_length < 2 && m_unicode < 0xff;
|
||||
}
|
||||
|
||||
bool Utf8Decoder::isC1() const
|
||||
{
|
||||
return m_expected_length == 2 && m_length == m_expected_length &&
|
||||
(m_unicode >= C1_8bit::C1_8bit_Start && m_unicode <= C1_8bit::C1_8bit_Stop);
|
||||
}
|
||||
|
||||
void Utf8Decoder::clear()
|
||||
{
|
||||
m_expected_length = 0;
|
||||
m_length = 0;
|
||||
m_unicode = 0;
|
||||
}
|
||||
|
||||
#endif
|
139
yat/backend/yat_pty.cpp
Normal file
139
yat/backend/yat_pty.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
/**************************************************************************************************
|
||||
* Copyright (c) 2012 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
* associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
* OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
***************************************************************************************************/
|
||||
|
||||
#include "yat_pty.h"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
|
||||
#ifdef LINUX
|
||||
#include <sys/epoll.h>
|
||||
#endif
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#ifdef Q_OS_MAC
|
||||
#include <util.h>
|
||||
#else
|
||||
#include <pty.h>
|
||||
#endif
|
||||
#include <utmp.h>
|
||||
|
||||
#include <QtCore/QSize>
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QSocketNotifier>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
static char env_variables[][255] = {
|
||||
"TERM=xterm-color",
|
||||
"COLORTERM=xterm",
|
||||
"COLORFGBG=15;0",
|
||||
"LINES",
|
||||
"COLUMNS",
|
||||
"TERMCAP"
|
||||
};
|
||||
static int env_variables_size = sizeof(env_variables) / sizeof(env_variables[0]);
|
||||
|
||||
YatPty::YatPty()
|
||||
: m_winsize(0)
|
||||
{
|
||||
m_terminal_pid = forkpty(&m_master_fd,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
if (m_terminal_pid == 0) {
|
||||
for (int i = 0; i < env_variables_size; i++) {
|
||||
::putenv(env_variables[i]);
|
||||
}
|
||||
::execl("/bin/bash", "/bin/bash", "--login", (const char *) 0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
QSocketNotifier *reader = new QSocketNotifier(m_master_fd,QSocketNotifier::Read,this);
|
||||
connect(reader, &QSocketNotifier::activated, this, &YatPty::readData);
|
||||
}
|
||||
|
||||
YatPty::~YatPty()
|
||||
{
|
||||
}
|
||||
|
||||
void YatPty::write(const QByteArray &data)
|
||||
{
|
||||
if (::write(m_master_fd, data.constData(), data.size()) < 0) {
|
||||
qDebug() << "Something whent wrong when writing to m_master_fd";
|
||||
}
|
||||
}
|
||||
|
||||
void YatPty::setWidth(int width, int pixelWidth)
|
||||
{
|
||||
if (!m_winsize) {
|
||||
m_winsize = new struct winsize;
|
||||
m_winsize->ws_row = 25;
|
||||
m_winsize->ws_ypixel = 0;
|
||||
}
|
||||
|
||||
m_winsize->ws_col = width;
|
||||
m_winsize->ws_xpixel = pixelWidth;
|
||||
ioctl(m_master_fd, TIOCSWINSZ, m_winsize);
|
||||
}
|
||||
|
||||
void YatPty::setHeight(int height, int pixelHeight)
|
||||
{
|
||||
if (!m_winsize) {
|
||||
m_winsize = new struct winsize;
|
||||
m_winsize->ws_col = 80;
|
||||
m_winsize->ws_xpixel = 0;
|
||||
}
|
||||
m_winsize->ws_row = height;
|
||||
m_winsize->ws_ypixel = pixelHeight;
|
||||
ioctl(m_master_fd, TIOCSWINSZ, m_winsize);
|
||||
|
||||
}
|
||||
|
||||
QSize YatPty::size() const
|
||||
{
|
||||
if (!m_winsize) {
|
||||
YatPty *that = const_cast<YatPty *>(this);
|
||||
that->m_winsize = new struct winsize;
|
||||
ioctl(m_master_fd, TIOCGWINSZ, m_winsize);
|
||||
}
|
||||
return QSize(m_winsize->ws_col, m_winsize->ws_row);
|
||||
}
|
||||
|
||||
int YatPty::masterDevice() const
|
||||
{
|
||||
return m_master_fd;
|
||||
}
|
||||
|
||||
|
||||
void YatPty::readData()
|
||||
{
|
||||
int size_of_buffer = sizeof m_data_buffer / sizeof *m_data_buffer;
|
||||
ssize_t read_size = ::read(m_master_fd,m_data_buffer,size_of_buffer);
|
||||
if (read_size > 0) {
|
||||
QByteArray to_return = QByteArray::fromRawData(m_data_buffer,read_size);
|
||||
emit readyRead(to_return);
|
||||
} else if (read_size < 0) {
|
||||
emit hangupReceived();
|
||||
} else {
|
||||
emit hangupReceived();
|
||||
}
|
||||
}
|
59
yat/backend/yat_pty.h
Normal file
59
yat/backend/yat_pty.h
Normal file
@ -0,0 +1,59 @@
|
||||
/**************************************************************************************************
|
||||
* Copyright (c) 2012 Jørgen Lind
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
* associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
* including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
* sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or
|
||||
* substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
|
||||
* OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
***************************************************************************************************/
|
||||
|
||||
#ifndef YAT_PTY_H
|
||||
#define YAT_PTY_H
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QLinkedList>
|
||||
#include <QtCore/QMutex>
|
||||
|
||||
class YatPty : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
YatPty();
|
||||
~YatPty();
|
||||
|
||||
void write(const QByteArray &data);
|
||||
|
||||
void setWidth(int width, int pixelWidth = 0);
|
||||
void setHeight(int height, int pixelHeight = 0);
|
||||
QSize size() const;
|
||||
|
||||
int masterDevice() const;
|
||||
|
||||
signals:
|
||||
void hangupReceived();
|
||||
void readyRead(const QByteArray &data);
|
||||
|
||||
private:
|
||||
void readData();
|
||||
|
||||
pid_t m_terminal_pid;
|
||||
int m_master_fd;
|
||||
char m_slave_file_name[PATH_MAX];
|
||||
struct winsize *m_winsize;
|
||||
char m_data_buffer[1024];
|
||||
};
|
||||
|
||||
#endif //YAT_PTY_H
|
BIN
yat/docs/Ecma-048.pdf
Normal file
BIN
yat/docs/Ecma-048.pdf
Normal file
Binary file not shown.
4841
yat/docs/Xterm Control Sequences.html
Normal file
4841
yat/docs/Xterm Control Sequences.html
Normal file
File diff suppressed because it is too large
Load Diff
3
yat/tests/auto/auto.pro
Normal file
3
yat/tests/auto/auto.pro
Normal file
@ -0,0 +1,3 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS = \
|
||||
block
|
8
yat/tests/auto/block/block.pro
Normal file
8
yat/tests/auto/block/block.pro
Normal file
@ -0,0 +1,8 @@
|
||||
CONFIG += testcase
|
||||
QT += testlib quick
|
||||
|
||||
include(../../../backend/backend.pri)
|
||||
|
||||
SOURCES += \
|
||||
tst_block.cpp \
|
||||
|
950
yat/tests/auto/block/tst_block.cpp
Normal file
950
yat/tests/auto/block/tst_block.cpp
Normal file
@ -0,0 +1,950 @@
|
||||
#include "../../../backend/block.h"
|
||||
#include <QtTest/QtTest>
|
||||
|
||||
#include <QtQml/QQmlEngine>
|
||||
#include "../../../backend/screen.h"
|
||||
#include "../../../backend/screen_data.h"
|
||||
|
||||
class BlockHandler
|
||||
{
|
||||
public:
|
||||
BlockHandler(bool fill) {
|
||||
screen.setHeight(5);
|
||||
int width = 100;
|
||||
screen.setWidth(width);
|
||||
(*screen.currentScreenData()->it_for_row(0))->clear();
|
||||
if (fill) {
|
||||
QString spaces(width, QChar(' '));
|
||||
block()->replaceAtPos(0, spaces, screen.defaultTextStyle());
|
||||
}
|
||||
QCOMPARE(block()->style_list().size(), 1);
|
||||
default_style = block()->style_list().at(0);
|
||||
default_text_style = default_style.style;
|
||||
}
|
||||
|
||||
Block *block() const
|
||||
{
|
||||
return *screen.currentScreenData()->it_for_row(0);
|
||||
}
|
||||
|
||||
void doneChanges()
|
||||
{
|
||||
screen.dispatchChanges();
|
||||
}
|
||||
|
||||
TextStyle default_style;
|
||||
TextStyle::Styles default_text_style;
|
||||
Screen screen;
|
||||
};
|
||||
|
||||
class tst_Block: public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private slots:
|
||||
void replaceStart();
|
||||
void replaceEdgeOfStyle();
|
||||
void replaceCompatibleStyle();
|
||||
void replaceCompatiblePreviousStyle();
|
||||
void replaceCompatiblePreviousStyleShouldRemove();
|
||||
void replaceCompatibleCurrentStyleShouldRemove();
|
||||
void replaceIncompatibleStyle();
|
||||
void replaceIncompaitibleStylesCrossesBoundary();
|
||||
void replace3IncompatibleStyles();
|
||||
void replaceIncomaptibleStylesCrosses2Boundaries();
|
||||
void replaceIncompatibleColor();
|
||||
void replaceRemoveOverlappedStyles();
|
||||
void replaceSwapStyles();
|
||||
void replaceEndBlock();
|
||||
void clearBlock();
|
||||
void clearToEndOfBlock1Segment();
|
||||
void clearToEndOfBlock3Segment();
|
||||
void clearToEndOfBlockMiddle3Segment();
|
||||
void deleteCharacters1Segment();
|
||||
void deleteCharacters2Segments();
|
||||
void deleteCharacters3Segments();
|
||||
void deleteCharactersRemoveSegmentEnd();
|
||||
void deleteCharactersRemoveSegmentBeginning();
|
||||
void deleteCharactersRemoveMiddle();
|
||||
void insertCharacters();
|
||||
void insertCharacters2Segments();
|
||||
void insertCharacters3Segments();
|
||||
};
|
||||
|
||||
void tst_Block::replaceStart()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QVector<TextStyleLine> old_style_list = block->style_list();
|
||||
QCOMPARE(old_style_list.size(), 1);
|
||||
|
||||
QString replace_text("This is a test");
|
||||
TextStyle textStyle;
|
||||
textStyle.style = TextStyle::Overlined;
|
||||
block->replaceAtPos(0,replace_text, textStyle);
|
||||
|
||||
QVector<TextStyleLine> new_style_list = block->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_Block::replaceEdgeOfStyle()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString first_text("This is the First");
|
||||
TextStyle textStyle;
|
||||
textStyle.style = TextStyle::Overlined;
|
||||
block->replaceAtPos(0,first_text, textStyle);
|
||||
|
||||
QString second_text("This is the Second");
|
||||
textStyle.style = TextStyle::Bold;
|
||||
block->replaceAtPos(first_text.size(), second_text, textStyle);
|
||||
|
||||
QVector<TextStyleLine> style_list = block->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_Block::replaceCompatibleStyle()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString replace_text("replaceed Text");
|
||||
block->replaceAtPos(10, replace_text, blockHandler.default_style);
|
||||
|
||||
QVector<TextStyleLine> after_style_list = block->style_list();
|
||||
QCOMPARE(after_style_list.size(), 1);
|
||||
QCOMPARE(after_style_list.at(0).style, blockHandler.default_text_style);
|
||||
}
|
||||
|
||||
void tst_Block::replaceCompatiblePreviousStyle()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
TextStyle first_style = blockHandler.default_style;
|
||||
first_style.style = TextStyle::Blinking;
|
||||
QString first_text("first");
|
||||
block->replaceAtPos(0,first_text, first_style);
|
||||
|
||||
TextStyle second_style = blockHandler.default_style;
|
||||
second_style.style = TextStyle::Bold;
|
||||
QString second_text("this is the second text");
|
||||
block->replaceAtPos(first_text.size(), second_text, second_style);
|
||||
|
||||
QString third_text("third");
|
||||
block->replaceAtPos(first_text.size(), third_text,first_style);
|
||||
|
||||
blockHandler.doneChanges();
|
||||
|
||||
QVector<TextStyleLine> style_list = block->style_list();
|
||||
QCOMPARE(style_list.size(), 3);
|
||||
|
||||
const TextStyleLine &first_check_style = style_list.at(0);
|
||||
QCOMPARE(first_check_style.start_index, 0);
|
||||
QCOMPARE(first_check_style.end_index, (first_text.size() -1) + third_text.size());
|
||||
|
||||
const TextStyleLine &second_check_style = style_list.at(1);
|
||||
QCOMPARE(second_check_style.start_index, first_text.size() + third_text.size());
|
||||
QCOMPARE(second_check_style.end_index, (first_text.size() -1) + second_text.size());
|
||||
|
||||
const TextStyleLine &third_check_style = style_list.at(2);
|
||||
QCOMPARE(third_check_style.start_index, first_text.size() + second_text.size());
|
||||
}
|
||||
|
||||
void tst_Block::replaceCompatiblePreviousStyleShouldRemove()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
TextStyle first_style = blockHandler.default_style;
|
||||
first_style.style = TextStyle::Blinking;
|
||||
QString first_text("first");
|
||||
block->replaceAtPos(0,first_text, first_style);
|
||||
|
||||
TextStyle second_style = blockHandler.default_style;
|
||||
second_style.style = TextStyle::Bold;
|
||||
QString second_text("second");
|
||||
block->replaceAtPos(first_text.size(), second_text, second_style);
|
||||
|
||||
QString third_text("this is the third");
|
||||
block->replaceAtPos(first_text.size(), third_text,first_style);
|
||||
|
||||
blockHandler.doneChanges();
|
||||
|
||||
QVector<TextStyleLine> style_list = block->style_list();
|
||||
QCOMPARE(style_list.size(), 2);
|
||||
|
||||
const TextStyleLine &first_check_style = style_list.at(0);
|
||||
QCOMPARE(first_check_style.start_index, 0);
|
||||
QCOMPARE(first_check_style.end_index, (first_text.size() -1) + third_text.size());
|
||||
|
||||
const TextStyleLine &second_check_style = style_list.at(1);
|
||||
QCOMPARE(second_check_style.start_index, first_text.size() + third_text.size());
|
||||
|
||||
}
|
||||
|
||||
void tst_Block::replaceCompatibleCurrentStyleShouldRemove()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
TextStyle first_style = blockHandler.default_style;
|
||||
first_style.style = TextStyle::Blinking;
|
||||
QString first_text("first");
|
||||
block->replaceAtPos(0,first_text, first_style);
|
||||
|
||||
TextStyle second_style = blockHandler.default_style;
|
||||
second_style.style = TextStyle::Bold;
|
||||
QString second_text("second");
|
||||
block->replaceAtPos(first_text.size(), second_text, second_style);
|
||||
|
||||
QString third_text("second");
|
||||
block->replaceAtPos(first_text.size(), third_text,first_style);
|
||||
|
||||
blockHandler.doneChanges();
|
||||
|
||||
QVector<TextStyleLine> style_list = block->style_list();
|
||||
QCOMPARE(style_list.size(), 2);
|
||||
|
||||
const TextStyleLine &first_check_style = style_list.at(0);
|
||||
QCOMPARE(first_check_style.start_index, 0);
|
||||
QCOMPARE(first_check_style.end_index, (first_text.size() -1) + third_text.size());
|
||||
|
||||
const TextStyleLine &second_check_style = style_list.at(1);
|
||||
QCOMPARE(second_check_style.start_index, first_text.size() + third_text.size());
|
||||
|
||||
}
|
||||
|
||||
void tst_Block::replaceIncompatibleStyle()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
|
||||
QString replace_text("replaceed Text");
|
||||
TextStyle replace_style;
|
||||
replace_style.style = TextStyle::Blinking;
|
||||
block->replaceAtPos(10, replace_text, replace_style);
|
||||
|
||||
QVector<TextStyleLine> after_style_list = block->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, blockHandler.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, blockHandler.default_text_style);
|
||||
}
|
||||
|
||||
void tst_Block::replaceIncompaitibleStylesCrossesBoundary()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString replace_text("replaceed Text");
|
||||
TextStyle replace_style;
|
||||
replace_style.style = TextStyle::Blinking;
|
||||
block->replaceAtPos(0, replace_text, replace_style);
|
||||
|
||||
QString crosses_boundary("New incompatible text");
|
||||
replace_style.style = TextStyle::Framed;
|
||||
int replace_pos = replace_text.size()/2;
|
||||
block->replaceAtPos(replace_pos, crosses_boundary, replace_style);
|
||||
|
||||
QVector<TextStyleLine> after_style_list = block->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, blockHandler.default_text_style);
|
||||
}
|
||||
|
||||
void tst_Block::replace3IncompatibleStyles()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString first_text("First Text");
|
||||
TextStyle replace_style;
|
||||
replace_style.style = TextStyle::Blinking;
|
||||
block->replaceAtPos(0, first_text, replace_style);
|
||||
|
||||
QString second_text("Second Text");
|
||||
replace_style.style = TextStyle::Italic;
|
||||
block->replaceAtPos(first_text.size(), second_text, replace_style);
|
||||
|
||||
QString third_text("Third Text");
|
||||
replace_style.style = TextStyle::Encircled;
|
||||
block->replaceAtPos(first_text.size() + second_text.size(), third_text, replace_style);
|
||||
|
||||
QCOMPARE(block->style_list().size(), 4);
|
||||
|
||||
QVector<TextStyleLine> after_style_list = block->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_Block::replaceIncomaptibleStylesCrosses2Boundaries()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString first_text("First Text");
|
||||
TextStyle replace_style;
|
||||
replace_style.style = TextStyle::Blinking;
|
||||
block->replaceAtPos(0, first_text, replace_style);
|
||||
|
||||
QString second_text("Second Text");
|
||||
replace_style.style = TextStyle::Italic;
|
||||
block->replaceAtPos(first_text.size(), second_text, replace_style);
|
||||
|
||||
QString third_text("Third Text");
|
||||
replace_style.style = TextStyle::Encircled;
|
||||
block->replaceAtPos(first_text.size() + second_text.size(), third_text, replace_style);
|
||||
|
||||
QCOMPARE(block->style_list().size(), 4);
|
||||
|
||||
QVector<TextStyleLine> before_style_list = block->style_list();
|
||||
|
||||
QString overlap_first_third;
|
||||
overlap_first_third.fill(QChar('A'), second_text.size() + 4);
|
||||
replace_style.style = TextStyle::DoubleUnderlined;
|
||||
block->replaceAtPos(first_text.size() -2, overlap_first_third, replace_style);
|
||||
|
||||
QVector<TextStyleLine> after_style_list = block->style_list();
|
||||
QCOMPARE(block->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, blockHandler.default_text_style);
|
||||
QCOMPARE(fourth_style.start_index, first_text.size() - 2 + overlap_first_third.size() + third_text.size() - 2);
|
||||
}
|
||||
|
||||
void tst_Block::replaceIncompatibleColor()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString first_text("291 ");
|
||||
TextStyleLine replace_style;
|
||||
replace_style.forground = ColorPalette::Yellow;
|
||||
block->replaceAtPos(0,first_text, replace_style);
|
||||
|
||||
QString second_text("QPointF Screen::selectionAreaStart() ");
|
||||
replace_style.forground = blockHandler.default_style.forground;
|
||||
block->replaceAtPos(first_text.size(), second_text, replace_style);
|
||||
|
||||
QString third_text("const");
|
||||
replace_style.forground = ColorPalette::Green;
|
||||
block->replaceAtPos(first_text.size() + second_text.size(), third_text, replace_style);
|
||||
|
||||
QString brackets("()");
|
||||
replace_style.forground = ColorPalette::Cyan;
|
||||
block->replaceAtPos(38, brackets, replace_style);
|
||||
|
||||
QVector<TextStyleLine> after_style_list = block->style_list();
|
||||
|
||||
const TextStyleLine &first_style = after_style_list.at(0);
|
||||
QCOMPARE(first_style.forground, ColorPalette::Yellow);
|
||||
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.forground, blockHandler.default_style.forground);
|
||||
QCOMPARE(second_style.start_index, first_text.size());
|
||||
QCOMPARE(second_style.end_index, 37);
|
||||
|
||||
const TextStyleLine &third_style = after_style_list.at(2);
|
||||
QCOMPARE(third_style.forground, ColorPalette::Cyan);
|
||||
QCOMPARE(third_style.start_index, 38);
|
||||
QCOMPARE(third_style.end_index, 38 + brackets.size() -1);
|
||||
|
||||
const TextStyleLine &fourth_style = after_style_list.at(3);
|
||||
QCOMPARE(fourth_style.forground, blockHandler.default_style.forground);
|
||||
QCOMPARE(fourth_style.start_index, 38 + brackets.size());
|
||||
QCOMPARE(fourth_style.end_index, first_text.size() + second_text.size() -1);
|
||||
|
||||
}
|
||||
|
||||
void tst_Block::replaceRemoveOverlappedStyles()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString first_text("First Text");
|
||||
TextStyle replace_style;
|
||||
replace_style.style = TextStyle::Blinking;
|
||||
block->replaceAtPos(0, first_text, replace_style);
|
||||
|
||||
QString second_text("Second Text");
|
||||
replace_style.style = TextStyle::Italic;
|
||||
block->replaceAtPos(first_text.size(), second_text, replace_style);
|
||||
|
||||
QString third_text("Third Text");
|
||||
replace_style.style = TextStyle::Encircled;
|
||||
block->replaceAtPos(first_text.size() + second_text.size(), third_text, replace_style);
|
||||
|
||||
QString fourth_text = third_text + second_text;
|
||||
fourth_text.chop(1);
|
||||
replace_style.style = TextStyle::Bold;
|
||||
block->replaceAtPos(first_text.size(), fourth_text, replace_style);
|
||||
|
||||
QCOMPARE(block->style_list().size(), 4);
|
||||
}
|
||||
void tst_Block::replaceSwapStyles()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString first_text("First Text");
|
||||
TextStyle replace_style;
|
||||
replace_style.style = TextStyle::Blinking;
|
||||
block->replaceAtPos(0, first_text, replace_style);
|
||||
|
||||
QString second_text("Second Text");
|
||||
replace_style.style = TextStyle::Italic;
|
||||
block->replaceAtPos(first_text.size(), second_text, replace_style);
|
||||
|
||||
QString third_text("Third Text");
|
||||
replace_style.style = TextStyle::Encircled;
|
||||
block->replaceAtPos(first_text.size() + second_text.size(), third_text, replace_style);
|
||||
|
||||
QString replace_second("Dnoces Text");
|
||||
replace_style.style = TextStyle::Bold;
|
||||
block->replaceAtPos(first_text.size(), replace_second, replace_style);
|
||||
|
||||
QCOMPARE(block->style_list().size(), 4);
|
||||
}
|
||||
|
||||
void tst_Block::replaceEndBlock()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString *full_block = block->textLine();
|
||||
int block_size = full_block->size();
|
||||
|
||||
QString replace_text("at the end of the string");
|
||||
TextStyle style = blockHandler.default_style;
|
||||
style.style = TextStyle::Bold;
|
||||
block->replaceAtPos(block_size - replace_text.size(), replace_text, style);
|
||||
|
||||
QCOMPARE(block->textLine()->size(), block_size);
|
||||
|
||||
QVector<TextStyleLine> style_list = block->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, block_size - replace_text.size() -1);
|
||||
QCOMPARE(first_style.style, blockHandler.default_text_style);
|
||||
|
||||
const TextStyleLine &second_style = style_list.at(1);
|
||||
QCOMPARE(second_style.start_index, block_size - replace_text.size());
|
||||
QCOMPARE(second_style.end_index, block_size - 1);
|
||||
QCOMPARE(second_style.style, TextStyle::Bold);
|
||||
}
|
||||
|
||||
void tst_Block::clearBlock()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QVERIFY(block->textLine()->size() > 0);
|
||||
QCOMPARE(block->textLine()->trimmed().size(), 0);
|
||||
}
|
||||
|
||||
void tst_Block::clearToEndOfBlock1Segment()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString replace_text("To be replaceed");
|
||||
TextStyle style = blockHandler.default_style;
|
||||
style.style = TextStyle::Encircled;
|
||||
block->replaceAtPos(0, replace_text, style);
|
||||
|
||||
int before_clear_size = block->textLine()->size();
|
||||
|
||||
block->clearCharacters(5, blockHandler.screen.width() -1);
|
||||
|
||||
blockHandler.doneChanges();
|
||||
|
||||
int after_clear_size = block->textLine()->size();
|
||||
QCOMPARE(after_clear_size, before_clear_size);
|
||||
QVector<TextStyleLine> style_list = block->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(block->textLine()->trimmed(), cleared);
|
||||
}
|
||||
|
||||
void tst_Block::clearToEndOfBlock3Segment()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString replace_text("To be");
|
||||
TextStyle style = blockHandler.default_style;
|
||||
style.style = TextStyle::Encircled;
|
||||
block->replaceAtPos(0, replace_text, style);
|
||||
|
||||
QString replace_text2(" or not to be");
|
||||
style.style = TextStyle::Bold;
|
||||
block ->replaceAtPos(replace_text.size(), replace_text2, style);
|
||||
|
||||
block->clearCharacters(replace_text.size(), blockHandler.screen.width() - 1);
|
||||
|
||||
blockHandler.doneChanges();
|
||||
|
||||
QVector<TextStyleLine> style_list = block->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, blockHandler.default_text_style);
|
||||
}
|
||||
|
||||
void tst_Block::clearToEndOfBlockMiddle3Segment()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString replace_text("To be");
|
||||
TextStyle style = blockHandler.default_style;
|
||||
style.style = TextStyle::Encircled;
|
||||
block->replaceAtPos(0, replace_text, style);
|
||||
|
||||
QString replace_text2(" or not to be");
|
||||
style.style = TextStyle::Bold;
|
||||
block ->replaceAtPos(replace_text.size(), replace_text2, style);
|
||||
|
||||
block->clearCharacters(replace_text.size() + 3, blockHandler.screen.width() - 1);
|
||||
|
||||
blockHandler.doneChanges();
|
||||
|
||||
QVector<TextStyleLine> style_list = block->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, blockHandler.default_text_style);
|
||||
}
|
||||
|
||||
void tst_Block::deleteCharacters1Segment()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString replace_text("replaceing some text");
|
||||
TextStyle style = blockHandler.default_style;
|
||||
style.style = TextStyle::Encircled;
|
||||
block->replaceAtPos(0, replace_text, style);
|
||||
|
||||
QString *full_block = block->textLine();
|
||||
int block_size = full_block->size();
|
||||
|
||||
block->deleteCharacters(10,14);
|
||||
|
||||
QCOMPARE(block->textLine()->size(), block_size - 5);
|
||||
|
||||
QVector<TextStyleLine> style_list = block->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, blockHandler.default_text_style);
|
||||
}
|
||||
|
||||
void tst_Block::deleteCharacters2Segments()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString replace_text("replaceing some text");
|
||||
TextStyle style = blockHandler.default_style;
|
||||
style.style = TextStyle::Encircled;
|
||||
block->replaceAtPos(0, replace_text, style);
|
||||
|
||||
QString *full_block = block->textLine();
|
||||
int block_size = full_block->size();
|
||||
|
||||
block->deleteCharacters(15,25);
|
||||
|
||||
QCOMPARE(block->textLine()->size(), block_size - 11);
|
||||
|
||||
QVector<TextStyleLine> style_list = block->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, blockHandler.default_text_style);
|
||||
|
||||
}
|
||||
|
||||
void tst_Block::deleteCharacters3Segments()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString replace_text("replaceing some text");
|
||||
TextStyle style = blockHandler.default_style;
|
||||
style.style = TextStyle::Encircled;
|
||||
block->replaceAtPos(0, replace_text, style);
|
||||
|
||||
QString replace_more_text("Some more text");
|
||||
style.style = TextStyle::Bold;
|
||||
block->replaceAtPos(replace_text.size(), replace_more_text, style);
|
||||
|
||||
QString *full_block = block->textLine();
|
||||
int block_size = full_block->size();
|
||||
|
||||
block->deleteCharacters(10,15);
|
||||
|
||||
QCOMPARE(block->textLine()->size(), block_size - 6);
|
||||
|
||||
QVector<TextStyleLine> style_list = block->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, blockHandler.default_text_style);
|
||||
}
|
||||
|
||||
void tst_Block::deleteCharactersRemoveSegmentEnd()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString replace_text("replaceing some text");
|
||||
TextStyle style = blockHandler.default_style;
|
||||
style.style = TextStyle::Encircled;
|
||||
block->replaceAtPos(0, replace_text, style);
|
||||
|
||||
QString replace_more_text("Some more text");
|
||||
style.style = TextStyle::Bold;
|
||||
block->replaceAtPos(replace_text.size(), replace_more_text, style);
|
||||
|
||||
QString *full_block = block->textLine();
|
||||
int block_size = full_block->size();
|
||||
|
||||
block->deleteCharacters(16,33);
|
||||
|
||||
QCOMPARE(block->textLine()->size(), block_size - ((33 - 16) + 1));
|
||||
|
||||
QVector<TextStyleLine> style_list = block->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, blockHandler.default_text_style);
|
||||
|
||||
}
|
||||
|
||||
void tst_Block::deleteCharactersRemoveSegmentBeginning()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString replace_text("replaceing some text");
|
||||
TextStyle style = blockHandler.default_style;
|
||||
style.style = TextStyle::Encircled;
|
||||
block->replaceAtPos(0, replace_text, style);
|
||||
|
||||
QString replace_more_text("Some more text");
|
||||
style.style = TextStyle::Bold;
|
||||
block->replaceAtPos(replace_text.size(), replace_more_text, style);
|
||||
|
||||
QString *full_block = block->textLine();
|
||||
int block_size = full_block->size();
|
||||
|
||||
block->deleteCharacters(replace_text.size(),replace_text.size() + replace_more_text.size() + 3);
|
||||
|
||||
int expected_size = block_size -1 - ((replace_text.size() + replace_more_text.size() + 3 ) - replace_text.size());
|
||||
QCOMPARE(block->textLine()->size(), expected_size);
|
||||
|
||||
QVector<TextStyleLine> style_list = block->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, blockHandler.default_text_style);
|
||||
}
|
||||
|
||||
void tst_Block::deleteCharactersRemoveMiddle()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString insert_text('A');
|
||||
int old_width = blockHandler.screen.width();
|
||||
QString empty(old_width - 2, ' ');
|
||||
insert_text += empty + 'B';
|
||||
block->replaceAtPos(0, insert_text, blockHandler.default_style);
|
||||
|
||||
Q_ASSERT(old_width == blockHandler.screen.width());
|
||||
Q_ASSERT(insert_text == *block->textLine());
|
||||
|
||||
block->deleteCharacters(1, old_width - 2);
|
||||
|
||||
Q_ASSERT(QString("AB") == block->textLine()->trimmed());
|
||||
}
|
||||
|
||||
void tst_Block::insertCharacters()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString *full_block = block->textLine();
|
||||
int block_size = full_block->size();
|
||||
|
||||
QString insert_text("inserting some text");
|
||||
TextStyle style = blockHandler.default_style;
|
||||
style.style = TextStyle::Encircled;
|
||||
block->insertAtPos(5, insert_text, style);
|
||||
|
||||
int expected_size = block_size + insert_text.size();
|
||||
|
||||
QCOMPARE(block->textLine()->size(), expected_size);
|
||||
|
||||
QVector<TextStyleLine> style_list = block->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, blockHandler.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, expected_size - 1);
|
||||
QCOMPARE(third_style.style, blockHandler.default_text_style);
|
||||
}
|
||||
|
||||
void tst_Block::insertCharacters2Segments()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString *full_block = block->textLine();
|
||||
int block_size = full_block->size();
|
||||
|
||||
QString replace_text("at the end of the string");
|
||||
TextStyle style = blockHandler.default_style;
|
||||
style.style = TextStyle::Bold;
|
||||
block->replaceAtPos(block_size - replace_text.size(), replace_text, style);
|
||||
|
||||
QString insert_text("inserting some text");
|
||||
style.style = TextStyle::Encircled;
|
||||
block->insertAtPos(5, insert_text, style);
|
||||
|
||||
int expected_size = block_size + insert_text.size();
|
||||
QCOMPARE(block->textLine()->size(), expected_size);
|
||||
|
||||
QVector<TextStyleLine> style_list = block->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, blockHandler.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, block_size -1 - replace_text.size() + insert_text.size());
|
||||
QCOMPARE(third_style.style, blockHandler.default_text_style);
|
||||
|
||||
const TextStyleLine &fourth_style = style_list.at(3);
|
||||
QCOMPARE(fourth_style.start_index, block_size - replace_text.size() + insert_text.size());
|
||||
QCOMPARE(fourth_style.end_index, expected_size - 1 );
|
||||
QCOMPARE(fourth_style.style, TextStyle::Bold);
|
||||
}
|
||||
|
||||
void tst_Block::insertCharacters3Segments()
|
||||
{
|
||||
BlockHandler blockHandler(true);
|
||||
Block *block = blockHandler.block();
|
||||
|
||||
QString *full_block = block->textLine();
|
||||
int block_size = full_block->size();
|
||||
|
||||
QString replace_text("at the end of the string");
|
||||
TextStyle style = blockHandler.default_style;
|
||||
style.style = TextStyle::Bold;
|
||||
block->replaceAtPos(block_size - replace_text.size(), replace_text, style);
|
||||
|
||||
QString replace_text2("somewhere in the string");
|
||||
style.style = TextStyle::Encircled;
|
||||
block->replaceAtPos(20,replace_text2, style);
|
||||
|
||||
QVector<TextStyleLine> tmp_style_list = block->style_list();
|
||||
QCOMPARE(tmp_style_list.size(), 4);
|
||||
|
||||
QString insert_text("this text is longer than last segment");
|
||||
style.style = TextStyle::Italic;
|
||||
block->insertAtPos(10, insert_text, style);
|
||||
|
||||
blockHandler.doneChanges();
|
||||
|
||||
int expected_size = block_size + insert_text.size();
|
||||
QCOMPARE(block->textLine()->size(), expected_size);
|
||||
|
||||
block->printStyleList();
|
||||
QVector<TextStyleLine> style_list = block->style_list();
|
||||
QCOMPARE(style_list.size(), 6);
|
||||
|
||||
const TextStyleLine &first_style = style_list.at(0);
|
||||
QCOMPARE(first_style.start_index, 0);
|
||||
QCOMPARE(first_style.end_index, 9);
|
||||
QCOMPARE(first_style.style, blockHandler.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, blockHandler.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, block_size - replace_text.size() + insert_text.size() - 1);
|
||||
QCOMPARE(fith_style.style, blockHandler.default_text_style);
|
||||
|
||||
const TextStyleLine &sixth_style = style_list.at(5);
|
||||
QCOMPARE(sixth_style.start_index, block_size - replace_text.size() + insert_text.size());
|
||||
QCOMPARE(sixth_style.end_index, block_size + insert_text.size() - 1);
|
||||
QCOMPARE(sixth_style.style, TextStyle::Bold);
|
||||
}
|
||||
|
||||
#include <tst_block.moc>
|
||||
QTEST_MAIN(tst_Block);
|
3
yat/tests/tests.pro
Normal file
3
yat/tests/tests.pro
Normal file
@ -0,0 +1,3 @@
|
||||
TEMPLATE = subdirs
|
||||
SUBDIRS = \
|
||||
auto
|
5
yat/yat.pro
Normal file
5
yat/yat.pro
Normal file
@ -0,0 +1,5 @@
|
||||
TEMPLATE=subdirs
|
||||
CONFIG += ordered
|
||||
SUBDIRS= \
|
||||
yat_declarative \
|
||||
tests
|
46
yat/yat_declarative/main.cpp
Normal file
46
yat/yat_declarative/main.cpp
Normal 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.
|
||||
*
|
||||
***************************************************************************************************/
|
||||
|
||||
#include <QtGui/QGuiApplication>
|
||||
#include <QtCore/QResource>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <QQmlEngine>
|
||||
|
||||
#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();
|
||||
|
||||
QQmlEngine engine;
|
||||
QQmlComponent component(&engine, QUrl("qrc:/qml/yat_declarative/main.qml"));
|
||||
auto errors = component.errors();
|
||||
for (int i = 0; i < errors.size(); i++) {
|
||||
qDebug() << errors.at(i).toString();
|
||||
}
|
||||
component.create();
|
||||
|
||||
return app.exec();
|
||||
}
|
249
yat/yat_declarative/mono_text.cpp
Normal file
249
yat/yat_declarative/mono_text.cpp
Normal file
@ -0,0 +1,249 @@
|
||||
/******************************************************************************
|
||||
* 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 "mono_text.h"
|
||||
|
||||
#include <QtQuick/private/qsgadaptationlayer_p.h>
|
||||
#include <QtQuick/private/qsgrenderer_p.h>
|
||||
#include <QtQuick/private/qquickitem_p.h>
|
||||
#include <QtQuick/private/qquicktextnode_p.h>
|
||||
#include <QtGui/QTextLayout>
|
||||
|
||||
class MonoSGNode : public QSGTransformNode
|
||||
{
|
||||
public:
|
||||
MonoSGNode(QQuickItem *owner)
|
||||
: m_owner(owner)
|
||||
{
|
||||
}
|
||||
|
||||
void deleteContent()
|
||||
{
|
||||
QSGNode *subnode = firstChild();
|
||||
while (subnode) {
|
||||
// We can't delete the node now as it might be in the preprocess list
|
||||
// It will be deleted in the next preprocess
|
||||
m_nodes_to_delete.append(subnode);
|
||||
subnode = subnode->nextSibling();
|
||||
}
|
||||
removeAllChildNodes();
|
||||
}
|
||||
|
||||
void preprocess()
|
||||
{
|
||||
while (m_nodes_to_delete.count())
|
||||
delete m_nodes_to_delete.takeLast();
|
||||
}
|
||||
|
||||
void setLatinText(const QString &text, const QFont &font, const QColor &color) {
|
||||
QRawFont raw_font = QRawFont::fromFont(font, QFontDatabase::Latin);
|
||||
|
||||
if (raw_font != m_raw_font) {
|
||||
m_raw_font = raw_font;
|
||||
m_positions.clear();
|
||||
}
|
||||
|
||||
if (m_positions.size() < text.size()) {
|
||||
qreal x_pos = 0;
|
||||
qreal max_char_width = raw_font.averageCharWidth();
|
||||
qreal ascent = raw_font.ascent();
|
||||
if (m_positions.size())
|
||||
x_pos = m_positions.last().x() + max_char_width;
|
||||
int to_add = text.size() - m_positions.size();
|
||||
for (int i = 0; i < to_add; i++) {
|
||||
m_positions << QPointF(x_pos, ascent);
|
||||
x_pos += max_char_width;
|
||||
}
|
||||
}
|
||||
|
||||
deleteContent();
|
||||
QSGRenderContext *sgr = QQuickItemPrivate::get(m_owner)->sceneGraphRenderContext();
|
||||
QSGGlyphNode *node = sgr->sceneGraphContext()->createGlyphNode(sgr);
|
||||
node->setOwnerElement(m_owner);
|
||||
node->geometry()->setIndexDataPattern(QSGGeometry::StaticPattern);
|
||||
node->geometry()->setVertexDataPattern(QSGGeometry::StaticPattern);
|
||||
node->setStyle(QQuickText::Normal);
|
||||
|
||||
node->setColor(color);
|
||||
QGlyphRun glyphrun;
|
||||
glyphrun.setRawFont(raw_font);
|
||||
glyphrun.setGlyphIndexes(raw_font.glyphIndexesForString(text));
|
||||
|
||||
glyphrun.setPositions(m_positions);
|
||||
node->setGlyphs(QPointF(0, raw_font.ascent()), glyphrun);
|
||||
node->update();
|
||||
appendChildNode(node);
|
||||
}
|
||||
|
||||
void setUnicodeText(const QString &text, const QFont &font, const QColor &color)
|
||||
{
|
||||
deleteContent();
|
||||
QRawFont raw_font = QRawFont::fromFont(font, QFontDatabase::Latin);
|
||||
qreal line_width = raw_font.averageCharWidth() * text.size();
|
||||
QSGRenderContext *sgr = QQuickItemPrivate::get(m_owner)->sceneGraphRenderContext();
|
||||
QTextLayout layout(text,font);
|
||||
layout.beginLayout();
|
||||
QTextLine line = layout.createLine();
|
||||
line.setLineWidth(line_width);
|
||||
//Q_ASSERT(!layout.createLine().isValid());
|
||||
layout.endLayout();
|
||||
QList<QGlyphRun> glyphRuns = line.glyphRuns();
|
||||
qreal xpos = 0;
|
||||
for (int i = 0; i < glyphRuns.size(); i++) {
|
||||
QSGGlyphNode *node = sgr->sceneGraphContext()->createGlyphNode(sgr);
|
||||
node->setOwnerElement(m_owner);
|
||||
node->geometry()->setIndexDataPattern(QSGGeometry::StaticPattern);
|
||||
node->geometry()->setVertexDataPattern(QSGGeometry::StaticPattern);
|
||||
node->setGlyphs(QPointF(xpos, raw_font.ascent()), glyphRuns.at(i));
|
||||
node->setStyle(QQuickText::Normal);
|
||||
node->setColor(color);
|
||||
xpos += raw_font.averageCharWidth() * glyphRuns.at(i).positions().size();
|
||||
node->update();
|
||||
appendChildNode(node);
|
||||
}
|
||||
}
|
||||
private:
|
||||
QQuickItem *m_owner;
|
||||
QVector<QPointF> m_positions;
|
||||
QLinkedList<QSGNode *> m_nodes_to_delete;
|
||||
QRawFont m_raw_font;
|
||||
};
|
||||
|
||||
MonoText::MonoText(QQuickItem *parent)
|
||||
: QQuickItem(parent)
|
||||
, m_color_changed(false)
|
||||
, m_latin(true)
|
||||
, m_old_latin(true)
|
||||
{
|
||||
setFlag(ItemHasContents, true);
|
||||
}
|
||||
|
||||
MonoText::~MonoText()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QString MonoText::text() const
|
||||
{
|
||||
return m_text;
|
||||
}
|
||||
|
||||
void MonoText::setText(const QString &text)
|
||||
{
|
||||
if (m_text != text) {
|
||||
m_text = text;
|
||||
emit textChanged();
|
||||
polish();
|
||||
}
|
||||
}
|
||||
|
||||
QFont MonoText::font() const
|
||||
{
|
||||
return m_font;
|
||||
}
|
||||
|
||||
void MonoText::setFont(const QFont &font)
|
||||
{
|
||||
if (font != m_font) {
|
||||
m_font = font;
|
||||
emit fontChanged();
|
||||
polish();
|
||||
}
|
||||
}
|
||||
|
||||
QColor MonoText::color() const
|
||||
{
|
||||
return m_color;
|
||||
}
|
||||
|
||||
void MonoText::setColor(const QColor &color)
|
||||
{
|
||||
if (m_color != color) {
|
||||
m_color = color;
|
||||
emit colorChanged();
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
qreal MonoText::paintedWidth() const
|
||||
{
|
||||
return implicitWidth();
|
||||
}
|
||||
|
||||
qreal MonoText::paintedHeight() const
|
||||
{
|
||||
return implicitHeight();
|
||||
}
|
||||
|
||||
bool MonoText::latin() const
|
||||
{
|
||||
return m_latin;
|
||||
}
|
||||
|
||||
void MonoText::setLatin(bool latin)
|
||||
{
|
||||
if (latin == m_latin)
|
||||
return;
|
||||
|
||||
m_latin = latin;
|
||||
emit latinChanged();
|
||||
}
|
||||
|
||||
QSGNode *MonoText::updatePaintNode(QSGNode *old, UpdatePaintNodeData *)
|
||||
{
|
||||
if (m_text.size() == 0 || m_text.trimmed().size() == 0) {
|
||||
delete old;
|
||||
return 0;
|
||||
}
|
||||
MonoSGNode *node = static_cast<MonoSGNode *>(old);
|
||||
if (!node) {
|
||||
node = new MonoSGNode(this);
|
||||
}
|
||||
|
||||
if (m_latin) {
|
||||
node->setLatinText(m_text, m_font, m_color);
|
||||
} else {
|
||||
node->setUnicodeText(m_text, m_font, m_color);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
void MonoText::updatePolish()
|
||||
{
|
||||
QRawFont raw_font = QRawFont::fromFont(m_font, QFontDatabase::Latin);
|
||||
|
||||
qreal height = raw_font.descent() + raw_font.ascent() + raw_font.lineThickness();
|
||||
qreal width = raw_font.averageCharWidth() * m_text.size();
|
||||
|
||||
bool emit_text_width_changed = width != implicitWidth();
|
||||
bool emit_text_height_changed = height != implicitHeight();
|
||||
setImplicitSize(width, height);
|
||||
|
||||
if (emit_text_width_changed)
|
||||
emit paintedWidthChanged();
|
||||
if (emit_text_height_changed)
|
||||
emit paintedHeightChanged();
|
||||
|
||||
update();
|
||||
}
|
81
yat/yat_declarative/mono_text.h
Normal file
81
yat/yat_declarative/mono_text.h
Normal 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 MONO_TEXT_H
|
||||
#define MONO_TEXT_H
|
||||
|
||||
#include <QtQuick/QQuickItem>
|
||||
#include <QtGui/QRawFont>
|
||||
|
||||
class MonoText : public QQuickItem
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged)
|
||||
Q_PROPERTY(QFont font READ font WRITE setFont NOTIFY fontChanged)
|
||||
Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged)
|
||||
Q_PROPERTY(qreal paintedWidth READ paintedWidth NOTIFY paintedWidthChanged)
|
||||
Q_PROPERTY(qreal paintedHeight READ paintedHeight NOTIFY paintedHeightChanged)
|
||||
Q_PROPERTY(bool latin READ latin WRITE setLatin NOTIFY latinChanged);
|
||||
public:
|
||||
MonoText(QQuickItem *parent=0);
|
||||
~MonoText();
|
||||
|
||||
QString text() const;
|
||||
void setText(const QString &text);
|
||||
|
||||
QFont font() const;
|
||||
void setFont(const QFont &font);
|
||||
|
||||
QColor color() const;
|
||||
void setColor(const QColor &color);
|
||||
|
||||
qreal paintedWidth() const;
|
||||
qreal paintedHeight() const;
|
||||
|
||||
bool latin() const;
|
||||
void setLatin(bool latin);
|
||||
|
||||
signals:
|
||||
void textChanged();
|
||||
void fontChanged();
|
||||
void colorChanged();
|
||||
void paintedWidthChanged();
|
||||
void paintedHeightChanged();
|
||||
void latinChanged();
|
||||
protected:
|
||||
QSGNode *updatePaintNode(QSGNode *old, UpdatePaintNodeData *data) Q_DECL_OVERRIDE;
|
||||
void updatePolish() Q_DECL_OVERRIDE;
|
||||
private:
|
||||
Q_DISABLE_COPY(MonoText);
|
||||
void updateSize();
|
||||
|
||||
QString m_text;
|
||||
QFont m_font;
|
||||
QColor m_color;
|
||||
bool m_color_changed;
|
||||
bool m_latin;
|
||||
bool m_old_latin;
|
||||
QSizeF m_text_size;
|
||||
};
|
||||
|
||||
#endif
|
55
yat/yat_declarative/object_destruct_item.cpp
Normal file
55
yat/yat_declarative/object_destruct_item.cpp
Normal 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;
|
||||
}
|
||||
|
52
yat/yat_declarative/object_destruct_item.h
Normal file
52
yat/yat_declarative/object_destruct_item.h
Normal 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
|
104
yat/yat_declarative/qml/yat_declarative/HighlightArea.qml
Normal file
104
yat/yat_declarative/qml/yat_declarative/HighlightArea.qml
Normal file
@ -0,0 +1,104 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
|
||||
Item {
|
||||
id: highlightArea
|
||||
|
||||
property real characterWidth: 0
|
||||
property real characterHeight: 0
|
||||
property int screenWidth: 0
|
||||
|
||||
property int startX
|
||||
property int startY
|
||||
|
||||
property int endX
|
||||
property int endY
|
||||
|
||||
property color color: "grey"
|
||||
|
||||
y: startY * characterHeight
|
||||
width: parent.width
|
||||
height: (endY - startY + 1) * characterHeight
|
||||
|
||||
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();
|
||||
|
||||
onStartXChanged: calculateRectangles();
|
||||
onStartYChanged: calculateRectangles();
|
||||
onEndXChanged: calculateRectangles();
|
||||
onEndYChanged: calculateRectangles();
|
||||
|
||||
function calculateRectangles() {
|
||||
highlightArea.y = startY * characterHeight;
|
||||
begginning_rectangle.x = startX * characterWidth;
|
||||
if (startY === endY) {
|
||||
middle_rectangle.visible = false;
|
||||
end_rectangle.visible = false
|
||||
begginning_rectangle.width = (endX - startX) * characterWidth;
|
||||
} else {
|
||||
begginning_rectangle.width = (screenWidth - startX) * characterWidth;
|
||||
if (startY === endY - 1) {
|
||||
middle_rectangle.height = 0;
|
||||
middle_rectangle.visible = false;
|
||||
}else {
|
||||
middle_rectangle.visible = true;
|
||||
middle_rectangle.height = (endY - startY - 1) * characterHeight;
|
||||
}
|
||||
end_rectangle.visible = true;
|
||||
end_rectangle.width = endX * characterWidth;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
66
yat/yat_declarative/qml/yat_declarative/TerminalCursor.qml
Normal file
66
yat/yat_declarative/qml/yat_declarative/TerminalCursor.qml
Normal file
@ -0,0 +1,66 @@
|
||||
/*******************************************************************************
|
||||
* 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: cursor
|
||||
|
||||
property real fontHeight
|
||||
property real fontWidth
|
||||
|
||||
height: fontHeight
|
||||
width: fontWidth
|
||||
x: objectHandle.x * fontWidth
|
||||
y: objectHandle.y * fontHeight
|
||||
z: 1.1
|
||||
|
||||
visible: objectHandle.visible
|
||||
|
||||
ShaderEffect {
|
||||
anchors.fill: parent
|
||||
|
||||
property variant source: fragmentSource
|
||||
|
||||
fragmentShader:
|
||||
"uniform lowp float qt_Opacity;" +
|
||||
"uniform sampler2D source;" +
|
||||
"varying highp vec2 qt_TexCoord0;" +
|
||||
|
||||
"void main() {" +
|
||||
" lowp vec4 color = texture2D(source, qt_TexCoord0 ) * qt_Opacity;" +
|
||||
" gl_FragColor = vec4(1.0 - color.r, 1.0 - color.g, 1.0 - color.b, color.a);" +
|
||||
"}"
|
||||
|
||||
ShaderEffectSource {
|
||||
id: fragmentSource
|
||||
sourceItem: background
|
||||
live: true
|
||||
|
||||
sourceRect: Qt.rect(cursor.x,cursor.y,cursor.width,cursor.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
285
yat/yat_declarative/qml/yat_declarative/TerminalScreen.qml
Normal file
285
yat/yat_declarative/qml/yat_declarative/TerminalScreen.qml
Normal file
@ -0,0 +1,285 @@
|
||||
/*******************************************************************************
|
||||
* 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 QtQuick.Controls 1.1
|
||||
|
||||
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")
|
||||
property var textComponent : Qt.createComponent("TerminalText.qml")
|
||||
property var cursorComponent : Qt.createComponent("TerminalCursor.qml")
|
||||
|
||||
font.family: "menlo"
|
||||
focus: true
|
||||
|
||||
Action {
|
||||
id: copyAction
|
||||
shortcut: "Ctrl+Shift+C"
|
||||
onTriggered: screen.selection.sendToClipboard()
|
||||
}
|
||||
Action {
|
||||
id: paseAction
|
||||
shortcut: "Ctrl+Shift+V"
|
||||
onTriggered: screen.selection.pasteFromClipboard()
|
||||
}
|
||||
|
||||
onActiveFocusChanged: {
|
||||
if (activeFocus) {
|
||||
Qt.inputMethod.show();
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onPressed: {
|
||||
if (event.text === "?") {
|
||||
terminal.screen.printScreen()
|
||||
}
|
||||
}
|
||||
|
||||
Text {
|
||||
id: fontMetricText
|
||||
text: "B"
|
||||
font: parent.font
|
||||
visible: false
|
||||
textFormat: Text.PlainText
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: flickable
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
contentWidth: width
|
||||
contentHeight: textContainer.height
|
||||
interactive: true
|
||||
flickableDirection: Flickable.VerticalFlick
|
||||
contentY: ((screen.contentHeight - screen.height) * screenItem.fontHeight)
|
||||
|
||||
Item {
|
||||
id: textContainer
|
||||
width: parent.width
|
||||
height: screen.contentHeight * screenItem.fontHeight
|
||||
Rectangle {
|
||||
id: background
|
||||
anchors.fill: parent
|
||||
color: terminal.screen.defaultBackgroundColor
|
||||
}
|
||||
|
||||
HighlightArea {
|
||||
characterHeight: fontHeight
|
||||
characterWidth: fontWidth
|
||||
screenWidth: terminalWindow.width
|
||||
|
||||
startX: screen.selection.startX
|
||||
startY: screen.selection.startY
|
||||
|
||||
endX: screen.selection.endX
|
||||
endY: screen.selection.endY
|
||||
|
||||
visible: screen.selection.enable
|
||||
}
|
||||
}
|
||||
|
||||
onContentYChanged: {
|
||||
if (!atYEnd) {
|
||||
var top_line = Math.floor(Math.max(contentY,0) / screenItem.fontHeight);
|
||||
screen.ensureVisiblePages(top_line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Connections {
|
||||
id: connections
|
||||
|
||||
target: terminal.screen
|
||||
|
||||
onFlash: {
|
||||
flashAnimation.start()
|
||||
}
|
||||
|
||||
onReset: {
|
||||
resetScreenItems();
|
||||
}
|
||||
|
||||
onTextCreated: {
|
||||
var textSegment = textComponent.createObject(screenItem,
|
||||
{
|
||||
"parent" : background,
|
||||
"objectHandle" : text,
|
||||
"font" : screenItem.font,
|
||||
"fontWidth" : screenItem.fontWidth,
|
||||
"fontHeight" : screenItem.fontHeight,
|
||||
})
|
||||
}
|
||||
|
||||
onCursorCreated: {
|
||||
if (cursorComponent.status != Component.Ready) {
|
||||
console.log(cursorComponent.errorString());
|
||||
return;
|
||||
}
|
||||
var cursorVariable = cursorComponent.createObject(screenItem,
|
||||
{
|
||||
"parent" : textContainer,
|
||||
"objectHandle" : cursor,
|
||||
"fontWidth" : screenItem.fontWidth,
|
||||
"fontHeight" : screenItem.fontHeight,
|
||||
})
|
||||
}
|
||||
|
||||
onRequestHeightChange: {
|
||||
terminalWindow.height = newHeight * screenItem.fontHeight;
|
||||
terminalWindow.contentItem.height = newHeight * screenItem.fontHeight;
|
||||
}
|
||||
|
||||
onRequestWidthChange: {
|
||||
terminalWindow.width = newWidth * screenItem.fontWidth;
|
||||
terminalWindow.contentItem.width = newWidth * screenItem.fontWidth;
|
||||
}
|
||||
}
|
||||
|
||||
onFontChanged: {
|
||||
setTerminalHeight();
|
||||
setTerminalWidth();
|
||||
}
|
||||
|
||||
onWidthChanged: {
|
||||
setTerminalWidth();
|
||||
}
|
||||
onHeightChanged: {
|
||||
setTerminalHeight();
|
||||
}
|
||||
Component.onCompleted: {
|
||||
setTerminalWidth();
|
||||
setTerminalHeight();
|
||||
}
|
||||
|
||||
function setTerminalWidth() {
|
||||
if (fontWidth > 0) {
|
||||
var pty_width = Math.floor(width / fontWidth);
|
||||
flickable.width = pty_width * fontWidth;
|
||||
screen.width = pty_width;
|
||||
}
|
||||
}
|
||||
|
||||
function setTerminalHeight() {
|
||||
if (fontHeight > 0) {
|
||||
var pty_height = Math.floor(height / fontHeight);
|
||||
flickable.height = pty_height * fontHeight;
|
||||
screen.height = pty_height;
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: flash
|
||||
z: 1.2
|
||||
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 int drag_start_x
|
||||
property int drag_start_y
|
||||
|
||||
anchors.fill: parent
|
||||
acceptedButtons: Qt.LeftButton | Qt.MiddleButton
|
||||
onPressed: {
|
||||
if (mouse.button == Qt.LeftButton) {
|
||||
hoverEnabled = true;
|
||||
var transformed_mouse = mapToItem(textContainer, mouse.x, mouse.y);
|
||||
var character = Math.floor((transformed_mouse.x / fontWidth));
|
||||
var line = Math.floor(transformed_mouse.y / fontHeight);
|
||||
var start = Qt.point(character,line);
|
||||
drag_start_x = character;
|
||||
drag_start_y = line;
|
||||
screen.selection.startX = character;
|
||||
screen.selection.startY = line;
|
||||
screen.selection.endX = character;
|
||||
screen.selection.endY = line;
|
||||
}
|
||||
}
|
||||
|
||||
onPositionChanged: {
|
||||
var transformed_mouse = mapToItem(textContainer, mouse.x, mouse.y);
|
||||
var character = Math.floor(transformed_mouse.x / fontWidth);
|
||||
var line = Math.floor(transformed_mouse.y / fontHeight);
|
||||
var current_pos = Qt.point(character,line);
|
||||
if (line < drag_start_y || (line === drag_start_y && character < drag_start_x)) {
|
||||
screen.selection.startX = character;
|
||||
screen.selection.startY = line;
|
||||
screen.selection.endX = drag_start_x;
|
||||
screen.selection.endY = drag_start_y;
|
||||
}else {
|
||||
screen.selection.startX = drag_start_x;
|
||||
screen.selection.startY = drag_start_y;
|
||||
screen.selection.endX = character;
|
||||
screen.selection.endY = line;
|
||||
}
|
||||
}
|
||||
|
||||
onReleased: {
|
||||
if (mouse.button == Qt.LeftButton) {
|
||||
hoverEnabled = false;
|
||||
screen.selection.sendToSelection();
|
||||
}
|
||||
}
|
||||
|
||||
onClicked: {
|
||||
if (mouse.button == Qt.MiddleButton) {
|
||||
screen.pasteFromSelection();
|
||||
}
|
||||
}
|
||||
|
||||
onDoubleClicked: {
|
||||
if (mouse.button == Qt.LeftButton) {
|
||||
var transformed_mouse = mapToItem(textContainer, mouse.x, mouse.y);
|
||||
var character = Math.floor(transformed_mouse.x / fontWidth);
|
||||
var line = Math.floor(transformed_mouse.y / fontHeight);
|
||||
screen.doubleClicked(Qt.point(character,line));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
81
yat/yat_declarative/qml/yat_declarative/TerminalText.qml
Normal file
81
yat/yat_declarative/qml/yat_declarative/TerminalText.qml
Normal file
@ -0,0 +1,81 @@
|
||||
/*******************************************************************************
|
||||
* 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
|
||||
property real fontHeight
|
||||
|
||||
y: objectHandle.line * fontHeight;
|
||||
x: objectHandle.index * fontWidth;
|
||||
|
||||
width: textElement.paintedWidth
|
||||
height: textElement.paintedHeight
|
||||
|
||||
visible: objectHandle.visible
|
||||
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: objectHandle.backgroundColor
|
||||
|
||||
MonoText {
|
||||
id: textElement
|
||||
anchors.fill: parent
|
||||
text: objectHandle.text
|
||||
color: objectHandle.foregroundColor
|
||||
font.family: textItem.font.family
|
||||
font.pixelSize: textItem.font.pixelSize
|
||||
font.pointSize: textItem.font.pointSize
|
||||
font.bold: objectHandle.bold
|
||||
font.underline: objectHandle.underline
|
||||
latin: objectHandle.latin
|
||||
|
||||
SequentialAnimation {
|
||||
running: objectHandle.blinking
|
||||
loops: Animation.Infinite
|
||||
onRunningChanged: {
|
||||
if (running === false)
|
||||
textElement.opacity = 1
|
||||
}
|
||||
NumberAnimation {
|
||||
target: textElement
|
||||
property: "opacity"
|
||||
to: 0
|
||||
duration: 250
|
||||
}
|
||||
NumberAnimation {
|
||||
target: textElement
|
||||
property: "opacity"
|
||||
to: 1
|
||||
duration: 250
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
37
yat/yat_declarative/qml/yat_declarative/main.qml
Normal file
37
yat/yat_declarative/qml/yat_declarative/main.qml
Normal file
@ -0,0 +1,37 @@
|
||||
/*******************************************************************************
|
||||
* 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 QtQuick.Window 2.0
|
||||
|
||||
Window {
|
||||
id: terminalWindow
|
||||
TerminalScreen {
|
||||
id: terminal
|
||||
anchors.fill: parent
|
||||
Component.onCompleted: terminalWindow.visible = true
|
||||
}
|
||||
width: 800
|
||||
height: 600
|
||||
color: terminal.screen.defaultBackgroundColor
|
||||
}
|
9
yat/yat_declarative/qml_sources.qrc
Normal file
9
yat/yat_declarative/qml_sources.qrc
Normal file
@ -0,0 +1,9 @@
|
||||
<RCC>
|
||||
<qresource prefix="/">
|
||||
<file>qml/yat_declarative/main.qml</file>
|
||||
<file>qml/yat_declarative/TerminalScreen.qml</file>
|
||||
<file>qml/yat_declarative/TerminalText.qml</file>
|
||||
<file>qml/yat_declarative/TerminalCursor.qml</file>
|
||||
<file>qml/yat_declarative/HighlightArea.qml</file>
|
||||
</qresource>
|
||||
</RCC>
|
22
yat/yat_declarative/register_qml_types.cpp
Normal file
22
yat/yat_declarative/register_qml_types.cpp
Normal file
@ -0,0 +1,22 @@
|
||||
#include "register_qml_types.h"
|
||||
|
||||
#include <QtQml>
|
||||
|
||||
#include "terminal_screen.h"
|
||||
#include "object_destruct_item.h"
|
||||
#include "screen.h"
|
||||
#include "text.h"
|
||||
#include "cursor.h"
|
||||
#include "mono_text.h"
|
||||
#include "selection.h"
|
||||
|
||||
void register_qml_types()
|
||||
{
|
||||
qmlRegisterType<TerminalScreen>("org.yat", 1, 0, "TerminalScreen");
|
||||
qmlRegisterType<ObjectDestructItem>("org.yat", 1, 0, "ObjectDestructItem");
|
||||
qmlRegisterType<MonoText>("org.yat", 1, 0, "MonoText");
|
||||
qmlRegisterType<Screen>();
|
||||
qmlRegisterType<Text>();
|
||||
qmlRegisterType<Cursor>();
|
||||
qmlRegisterType<Selection>();
|
||||
}
|
6
yat/yat_declarative/register_qml_types.h
Normal file
6
yat/yat_declarative/register_qml_types.h
Normal file
@ -0,0 +1,6 @@
|
||||
#ifndef REGISTER_QML_TYPES_H
|
||||
#define REGISTER_QML_TYPES_H
|
||||
|
||||
void register_qml_types();
|
||||
|
||||
#endif // REGISTER_QML_TYPES_H
|
65
yat/yat_declarative/terminal_screen.cpp
Normal file
65
yat/yat_declarative/terminal_screen.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
/**************************************************************************************************
|
||||
* 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))
|
||||
{
|
||||
setFlag(QQuickItem::ItemAcceptsInputMethod);
|
||||
}
|
||||
|
||||
Screen *TerminalScreen::screen() const
|
||||
{
|
||||
return m_screen;
|
||||
}
|
||||
|
||||
QVariant TerminalScreen::inputMethodQuery(Qt::InputMethodQuery query) const
|
||||
{
|
||||
switch (query) {
|
||||
case Qt::ImEnabled:
|
||||
return QVariant(true);
|
||||
case Qt::ImHints:
|
||||
return QVariant(Qt::ImhNoAutoUppercase | Qt::ImhNoPredictiveText);
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
void TerminalScreen::inputMethodEvent(QInputMethodEvent *event)
|
||||
{
|
||||
QString commitString = event->commitString();
|
||||
if (commitString.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Qt::Key key = Qt::Key_unknown;
|
||||
if (commitString == " ") {
|
||||
key = Qt::Key_Space; // screen requires
|
||||
}
|
||||
|
||||
m_screen->sendKey(commitString, key, 0);
|
||||
}
|
||||
|
||||
void TerminalScreen::keyPressEvent(QKeyEvent *event)
|
||||
{
|
||||
m_screen->sendKey(event->text(), Qt::Key(event->key()), event->modifiers());
|
||||
}
|
54
yat/yat_declarative/terminal_screen.h
Normal file
54
yat/yat_declarative/terminal_screen.h
Normal 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 TERMINALITEM_H
|
||||
#define TERMINALITEM_H
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtQuick/QQuickItem>
|
||||
#include <QInputMethodEvent>
|
||||
#include <QKeyEvent>
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
class TerminalScreen : public QQuickItem
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
Q_PROPERTY(Screen *screen READ screen CONSTANT)
|
||||
public:
|
||||
TerminalScreen(QQuickItem *parent = 0);
|
||||
|
||||
Screen *screen() const;
|
||||
|
||||
QVariant inputMethodQuery(Qt::InputMethodQuery query) const;
|
||||
|
||||
protected:
|
||||
void inputMethodEvent(QInputMethodEvent *event);
|
||||
void keyPressEvent(QKeyEvent *event);
|
||||
|
||||
private:
|
||||
Screen *m_screen;
|
||||
};
|
||||
|
||||
#endif // TERMINALITEM_H
|
18
yat/yat_declarative/yat_declarative.pro
Normal file
18
yat/yat_declarative/yat_declarative.pro
Normal file
@ -0,0 +1,18 @@
|
||||
QT += gui quick
|
||||
TARGET = yat
|
||||
|
||||
include(../backend/backend.pri)
|
||||
|
||||
INCLUDEPATH += $$PWD
|
||||
|
||||
SOURCES += $$PWD/terminal_screen.cpp \
|
||||
$$PWD/object_destruct_item.cpp \
|
||||
$$PWD/register_qml_types.cpp \
|
||||
$$PWD/mono_text.cpp \
|
||||
|
||||
HEADERS += \
|
||||
$$PWD/terminal_screen.h \
|
||||
$$PWD/object_destruct_item.h \
|
||||
$$PWD/register_qml_types.h \
|
||||
$$PWD/mono_text.h \
|
||||
|
Loading…
x
Reference in New Issue
Block a user