1 /*
2  *  SPDX-FileCopyrightText: 2012 Frederik Gladhorn <gladhorn@kde.org>
3  *
4  *  SPDX-License-Identifier: GPL-2.0-or-later
5  */
6 
7 #include "TerminalDisplayAccessible.h"
8 #include "session/SessionController.h"
9 #include <klocalizedstring.h>
10 
11 #include "terminalDisplay/TerminalFonts.h"
12 
13 using namespace Konsole;
14 
TerminalDisplayAccessible(TerminalDisplay * display)15 TerminalDisplayAccessible::TerminalDisplayAccessible(TerminalDisplay *display)
16     : QAccessibleWidget(display, QAccessible::Terminal, display->sessionController()->userTitle())
17 {
18 }
19 
text(QAccessible::Text t) const20 QString TerminalDisplayAccessible::text(QAccessible::Text t) const
21 {
22     if (t == QAccessible::Value) {
23         return visibleText();
24     }
25     return QAccessibleWidget::text(t);
26 }
27 
characterCount() const28 int TerminalDisplayAccessible::characterCount() const
29 {
30     return display()->_usedLines * display()->_usedColumns;
31 }
32 
cursorPosition() const33 int TerminalDisplayAccessible::cursorPosition() const
34 {
35     if (display()->screenWindow() == nullptr) {
36         return 0;
37     }
38 
39     int offset = display()->_usedColumns * display()->screenWindow()->screen()->getCursorY();
40     return offset + display()->screenWindow()->screen()->getCursorX();
41 }
42 
selection(int selectionIndex,int * startOffset,int * endOffset) const43 void TerminalDisplayAccessible::selection(int selectionIndex, int *startOffset, int *endOffset) const
44 {
45     *startOffset = 0;
46     *endOffset = 0;
47     if ((display()->screenWindow() == nullptr) || (selectionIndex != 0)) {
48         return;
49     }
50 
51     int startLine = 0;
52     int startColumn = 0;
53     int endLine = 0;
54     int endColumn = 0;
55     display()->screenWindow()->getSelectionStart(startColumn, startLine);
56     display()->screenWindow()->getSelectionEnd(endColumn, endLine);
57     if ((startLine == endLine) && (startColumn == endColumn)) {
58         return;
59     }
60     *startOffset = positionToOffset(startColumn, startLine);
61     *endOffset = positionToOffset(endColumn, endLine);
62 }
63 
selectionCount() const64 int TerminalDisplayAccessible::selectionCount() const
65 {
66     if (display()->screenWindow() == nullptr) {
67         return 0;
68     }
69 
70     int startLine = 0;
71     int startColumn = 0;
72     int endLine = 0;
73     int endColumn = 0;
74     display()->screenWindow()->getSelectionStart(startColumn, startLine);
75     display()->screenWindow()->getSelectionEnd(endColumn, endLine);
76     return ((startLine == endLine) && (startColumn == endColumn)) ? 0 : 1;
77 }
78 
visibleText() const79 QString TerminalDisplayAccessible::visibleText() const
80 {
81     // This function should be const to allow calling it from const interface functions.
82     TerminalDisplay *display = const_cast<TerminalDisplayAccessible *>(this)->display();
83     if (display->screenWindow() == nullptr) {
84         return QString();
85     }
86 
87     return display->screenWindow()->screen()->text(0, display->_usedColumns * display->_usedLines, Screen::PreserveLineBreaks);
88 }
89 
addSelection(int startOffset,int endOffset)90 void TerminalDisplayAccessible::addSelection(int startOffset, int endOffset)
91 {
92     if (display()->screenWindow() == nullptr) {
93         return;
94     }
95     display()->screenWindow()->setSelectionStart(columnForOffset(startOffset), lineForOffset(startOffset), false);
96     display()->screenWindow()->setSelectionEnd(columnForOffset(endOffset), lineForOffset(endOffset));
97 }
98 
attributes(int offset,int * startOffset,int * endOffset) const99 QString TerminalDisplayAccessible::attributes(int offset, int *startOffset, int *endOffset) const
100 {
101     // FIXME: this function should return css like attributes
102     // as defined in the web ARIA standard
103     Q_UNUSED(offset)
104     *startOffset = 0;
105     *endOffset = characterCount();
106     return QString();
107 }
108 
characterRect(int offset) const109 QRect TerminalDisplayAccessible::characterRect(int offset) const
110 {
111     int row = offset / display()->_usedColumns;
112     int col = offset - row * display()->_usedColumns;
113     QPoint position = QPoint(col * display()->terminalFont()->fontWidth(), row * display()->terminalFont()->fontHeight());
114     return QRect(position, QSize(display()->terminalFont()->fontWidth(), display()->terminalFont()->fontHeight()));
115 }
116 
offsetAtPoint(const QPoint & point) const117 int TerminalDisplayAccessible::offsetAtPoint(const QPoint &point) const
118 {
119     // FIXME return the offset into the text from the given point
120     Q_UNUSED(point)
121     return 0;
122 }
123 
removeSelection(int selectionIndex)124 void TerminalDisplayAccessible::removeSelection(int selectionIndex)
125 {
126     if ((display()->screenWindow() == nullptr) || (selectionIndex != 0)) {
127         return;
128     }
129     display()->screenWindow()->clearSelection();
130 }
131 
scrollToSubstring(int startIndex,int endIndex)132 void TerminalDisplayAccessible::scrollToSubstring(int startIndex, int endIndex)
133 {
134     // FIXME: make sure the string between startIndex and endIndex is visible
135     Q_UNUSED(startIndex)
136     Q_UNUSED(endIndex)
137 }
138 
setCursorPosition(int position)139 void TerminalDisplayAccessible::setCursorPosition(int position)
140 {
141     if (display()->screenWindow() == nullptr) {
142         return;
143     }
144 
145     display()->screenWindow()->screen()->setCursorYX(lineForOffset(position), columnForOffset(position));
146 }
147 
interface_cast(QAccessible::InterfaceType type)148 void *TerminalDisplayAccessible::interface_cast(QAccessible::InterfaceType type)
149 {
150     if (type == QAccessible::TextInterface) {
151         return static_cast<QAccessibleTextInterface *>(this);
152     }
153 
154     return QAccessibleWidget::interface_cast(type);
155 }
156 
setSelection(int selectionIndex,int startOffset,int endOffset)157 void TerminalDisplayAccessible::setSelection(int selectionIndex, int startOffset, int endOffset)
158 {
159     if (selectionIndex != 0) {
160         return;
161     }
162     addSelection(startOffset, endOffset);
163 }
164 
text(int startOffset,int endOffset) const165 QString TerminalDisplayAccessible::text(int startOffset, int endOffset) const
166 {
167     if (display()->screenWindow() == nullptr) {
168         return QString();
169     }
170 
171     return display()->screenWindow()->screen()->text(startOffset, endOffset, Screen::PreserveLineBreaks);
172 }
173 
display() const174 TerminalDisplay *TerminalDisplayAccessible::display() const
175 {
176     return qobject_cast<TerminalDisplay *>(widget());
177 }
178