1 /**
2  * Consoleur: a package for interaction with character-oriented terminal emulators
3  *
4  * Copyright: Maxim Freck, 2017.
5  * Authors:   Maxim Freck <maxim@freck.pp.ru>
6  * License:   $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
7  */
8 module consoleur.cursor.posix;
9 version(Posix) {
10 
11 import consoleur.core;
12 import std.stdio: write;
13 
14 /*******
15  * Moves cursor to desired position
16  *
17  * Params:
18  *  dest = Coordinates
19  */
20 void moveCursorTo(Point dest) @safe
21 {
22 	import std.conv: to;
23 	write("\x1b["~to!string(dest.row)~';'~to!string(dest.col)~'f');
24 }
25 
26 /*******
27  * Moves cursor up by n rows
28  *
29  * Params:
30  *  n = Number of rows to move
31  */
32 void moveCursorUp(int n = 1)
33 {
34 	import std.conv: to;
35 	write("\x1b["~to!string(n)~"A");
36 }
37 
38 /*******
39  * Moves cursor down by n rows
40  *
41  * Params:
42  *  n = Number of rows to move
43  */
44 void moveCursorDown(int n = 1)
45 {
46 	import std.conv: to;
47 	write("\x1b["~to!string(n)~"B");
48 }
49 
50 /*******
51  * Moves cursor right by n columns
52  *
53  * Params:
54  *  n = Number of columns to move
55  */
56 void moveCursorRight(int n = 1)
57 {
58 	import std.conv: to;
59 	write("\x1b["~to!string(n)~"C");
60 }
61 
62 /*******
63  * Moves cursor left by n columns
64  *
65  * Params:
66  *  n = Number of columns to move
67  */
68 void moveCursorLeft(int n = 1)
69 {
70 	import std.conv: to;
71 	write("\x1b["~to!string(n)~"D");
72 }
73 
74 
75 /*******
76  * Saves current cursor position
77  *
78  */
79 public bool saveCursorPosition()
80 {
81 	import consoleur.commands: invokeCommand, TermCommand;
82 	return invokeCommand(TermCommand.saveCursorPosition);
83 }
84 
85 /*******
86  * Restores previously saved cursor positon
87  *
88  */
89 public bool restoreCursorPosition()
90 {
91 	import consoleur.commands: invokeCommand, TermCommand;
92 	return invokeCommand(TermCommand.restoreCursorPosition);
93 }
94 
95 /*******
96  * Returns: current cursor positon
97  *
98  */
99 public Point getCursorPosition() @trusted
100 {
101 	import consoleur.core.termparam: setTermparam, Term;
102 	import std.array: split;
103 	import std.conv: to;
104 
105 	immutable tparam = setTermparam(Term.quiet|Term.raw);
106 
107 	rawStdout("\x1b[6n");
108 
109 	auto csi = readEscapeSequence();
110 	if (csi.length <3 ) return Point(-1, -1);
111 
112 	auto pos = csi[0..$-1].split(";");
113 	if (pos.length != 2 || pos[0].length == 0 || pos[1].length == 0) return Point(-1, -1);
114 
115 	return Point(to!int(pos[0]), to!int(pos[1]));
116 }
117 
118 private bool cursorHidden = false;
119 
120 /*******
121  * Hides cursor
122  * Returns: false if cursor is already hidden, otherwise true
123  */
124 bool hideCursor() @safe
125 {
126 	import consoleur.commands: invokeCommand, TermCommand;
127 	if (cursorHidden) return false;
128 
129 	invokeCommand(TermCommand.cursorHide);
130 
131 	cursorHidden = true;
132 	return true;
133 }
134 
135 /*******
136  * Shows cursor
137  * Returns: false if cursor is already visible, otherwise true
138  */
139 bool showCursor() @safe
140 {
141 	import consoleur.commands: invokeCommand, TermCommand;
142 	if (!cursorHidden) return false;
143 
144 	invokeCommand(TermCommand.cursorShow);
145 
146 	cursorHidden = false;
147 	return true;
148 }
149 
150 }