mirror of
				https://github.com/Swordfish90/cool-retro-term.git
				synced 2025-10-31 15:12:28 +00:00 
			
		
		
		
	Moved to new version of yat. Yat is no longer a submodule but is now integrated.
This commit is contained in:
		
							
								
								
									
										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 | ||||
|     } | ||||
|  | ||||
|     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: "black" | ||||
|                 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, | ||||
|                     "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 | ||||
|  | ||||
|  | ||||
|     Text { | ||||
|         MonoText { | ||||
|             id: textElement | ||||
|             anchors.fill: parent | ||||
|             text: objectHandle.text | ||||
|         color: "white" | ||||
|         font: textItem.font | ||||
|         textFormat: Text.PlainText | ||||
|             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 | ||||
|  | ||||
|             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 | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|     Connections { | ||||
|         target: objectHandle | ||||
|  | ||||
|         onIndexChanged: { | ||||
|             textItem.x = objectHandle.index *  textItem.fontWidth; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     //Component.onCompleted: { | ||||
|     //    //color = randomBg(); | ||||
|     //} | ||||
|     //function randomBg() | ||||
|     //{ | ||||
|     //    var hex1=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F") | ||||
|     //        var hex2=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F") | ||||
|     //        var hex3=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F") | ||||
|     //        var hex4=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F") | ||||
|     //        var hex5=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F") | ||||
|     //        var hex6=new Array("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F") | ||||
|     //        var bg="#"+hex1[Math.floor(Math.random()*hex1.length)]+hex2[Math.floor(Math.random()*hex2.length)]+hex3[Math.floor(Math.random()*hex3.length)]+hex4[Math.floor(Math.random()*hex4.length)]+hex5[Math.floor(Math.random()*hex5.length)]+hex6[Math.floor(Math.random()*hex6.length)] | ||||
|     //        return bg | ||||
|     //} | ||||
| } | ||||
|   | ||||
| @@ -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
									
									
									
									
									
								
							 Submodule yat deleted from fb2266d7a1
									
								
							
							
								
								
									
										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 \ | ||||
|  | ||||
		Reference in New Issue
	
	Block a user