52938
|
1 |
/*
|
|
2 |
* Copyright (c) 2002-2016, the original author or authors.
|
|
3 |
*
|
|
4 |
* This software is distributable under the BSD license. See the terms of the
|
|
5 |
* BSD license in the documentation provided with this software.
|
|
6 |
*
|
58903
|
7 |
* https://opensource.org/licenses/BSD-3-Clause
|
52938
|
8 |
*/
|
|
9 |
package jdk.internal.org.jline.terminal.impl;
|
|
10 |
|
|
11 |
import jdk.internal.org.jline.terminal.Cursor;
|
|
12 |
import jdk.internal.org.jline.terminal.Terminal;
|
|
13 |
import jdk.internal.org.jline.utils.Curses;
|
|
14 |
import jdk.internal.org.jline.utils.InfoCmp;
|
|
15 |
|
|
16 |
import java.io.IOError;
|
|
17 |
import java.io.IOException;
|
|
18 |
import java.util.function.IntConsumer;
|
|
19 |
import java.util.regex.Matcher;
|
|
20 |
import java.util.regex.Pattern;
|
|
21 |
|
|
22 |
public class CursorSupport {
|
|
23 |
|
|
24 |
public static Cursor getCursorPosition(Terminal terminal, IntConsumer discarded) {
|
|
25 |
try {
|
|
26 |
String u6 = terminal.getStringCapability(InfoCmp.Capability.user6);
|
|
27 |
String u7 = terminal.getStringCapability(InfoCmp.Capability.user7);
|
|
28 |
if (u6 == null || u7 == null) {
|
|
29 |
return null;
|
|
30 |
}
|
|
31 |
// Prepare parser
|
|
32 |
boolean inc1 = false;
|
|
33 |
StringBuilder patb = new StringBuilder();
|
|
34 |
int index = 0;
|
|
35 |
while (index < u6.length()) {
|
|
36 |
char ch;
|
|
37 |
switch (ch = u6.charAt(index++)) {
|
|
38 |
case '\\':
|
|
39 |
switch (u6.charAt(index++)) {
|
|
40 |
case 'e':
|
|
41 |
case 'E':
|
|
42 |
patb.append("\\x1b");
|
|
43 |
break;
|
|
44 |
default:
|
|
45 |
throw new IllegalArgumentException();
|
|
46 |
}
|
|
47 |
break;
|
|
48 |
case '%':
|
|
49 |
ch = u6.charAt(index++);
|
|
50 |
switch (ch) {
|
|
51 |
case '%':
|
|
52 |
patb.append('%');
|
|
53 |
break;
|
|
54 |
case 'i':
|
|
55 |
inc1 = true;
|
|
56 |
break;
|
|
57 |
case 'd':
|
|
58 |
patb.append("([0-9]+)");
|
|
59 |
break;
|
|
60 |
default:
|
|
61 |
throw new IllegalArgumentException();
|
|
62 |
}
|
|
63 |
break;
|
|
64 |
default:
|
|
65 |
switch (ch) {
|
|
66 |
case '[':
|
|
67 |
patb.append('\\');
|
|
68 |
break;
|
|
69 |
}
|
|
70 |
patb.append(ch);
|
|
71 |
break;
|
|
72 |
}
|
|
73 |
}
|
|
74 |
Pattern pattern = Pattern.compile(patb.toString());
|
|
75 |
// Output cursor position request
|
|
76 |
Curses.tputs(terminal.writer(), u7);
|
|
77 |
terminal.flush();
|
|
78 |
StringBuilder sb = new StringBuilder();
|
|
79 |
int start = 0;
|
|
80 |
while (true) {
|
|
81 |
int c = terminal.reader().read();
|
|
82 |
if (c < 0) {
|
|
83 |
return null;
|
|
84 |
}
|
|
85 |
sb.append((char) c);
|
|
86 |
Matcher matcher = pattern.matcher(sb.substring(start));
|
|
87 |
if (matcher.matches()) {
|
|
88 |
int y = Integer.parseInt(matcher.group(1));
|
|
89 |
int x = Integer.parseInt(matcher.group(2));
|
|
90 |
if (inc1) {
|
|
91 |
x--;
|
|
92 |
y--;
|
|
93 |
}
|
|
94 |
if (discarded != null) {
|
|
95 |
for (int i = 0; i < start; i++) {
|
|
96 |
discarded.accept(sb.charAt(i));
|
|
97 |
}
|
|
98 |
}
|
|
99 |
return new Cursor(x, y);
|
|
100 |
} else if (!matcher.hitEnd()) {
|
|
101 |
start++;
|
|
102 |
}
|
|
103 |
}
|
|
104 |
} catch (IOException e) {
|
|
105 |
throw new IOError(e);
|
|
106 |
}
|
|
107 |
}
|
|
108 |
|
|
109 |
}
|