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 }