diff options
Diffstat (limited to 'LibTerm')
-rw-r--r-- | LibTerm/Term.swift | 280 | ||||
-rw-r--r-- | LibTerm/TermIO.swift | 38 |
2 files changed, 318 insertions, 0 deletions
diff --git a/LibTerm/Term.swift b/LibTerm/Term.swift new file mode 100644 index 0000000..9ca17dc --- /dev/null +++ b/LibTerm/Term.swift @@ -0,0 +1,280 @@ +// +// Term.swift +// CmdLine +// +// Created by Jacky Jack on 25/02/2023. +// + +import Foundation +import Darwin + +class Term { + let esc = "\u{001B}" + + var ifd:Int32 + var ofd:Int32 + var orig_i:termios + var orig_o:termios + var raw_i:termios + var raw_o:termios + + init() { + + + + self.ifd = Darwin.STDIN_FILENO + self.ofd = Darwin.STDOUT_FILENO + + self.orig_i = termios() + self.orig_o = termios() + self.raw_i = termios() + self.raw_o = termios() + + //let p_i<> = UnsafeMutablePointer(self.orig_i) + if (-1 == tcgetattr(self.ifd, UnsafeMutablePointer(&self.orig_i))) { + print("tcgetattr error") + return + } + self.raw_i = self.orig_i + + if ( -1 == tcgetattr(self.ofd, UnsafeMutablePointer(&self.orig_o))) { + print("tcgetattr error") + return + } + self.raw_o = self.orig_o + + if (isatty(STDIN_FILENO) == 0) { + print("isatty failed") + return + } + + } + + func setSpeed(speed: speed_t) { + var ret:Int32=0 + let raw_out = UnsafeMutablePointer(&self.raw_o) + ret = cfsetospeed(raw_out, speed) + tcsetattr(self.ofd, TCSANOW, raw_out) + + let raw_in = UnsafeMutablePointer(&self.raw_o) + ret = cfsetispeed(raw_in, speed) + tcsetattr(self.ifd, TCSANOW, raw_in) + } + + func getMaxCol() -> Int { + let orig_c = getC() + //go to right marging and get position + if (write(ofd, "\u{001B}[999C", 6) != 6) { + return -1 + } + //get the position + let cur_c = getC() + if (cur_c == -1) { + return -1 + } + + //restore previouse position + let restore_position = "\u{001B}[\(cur_c-orig_c)D" + write(ofd, restore_position, restore_position.count) + + return cur_c + } + + func getMaxRow() -> Int { + let orig_r = getR() + //go to right marging and get position + if (write(ofd, "\u{001B}[999B", 6) != 6) { + return -1 + } + //get the position + let cur_r = getR() + if (cur_r == -1) { + return -1 + } + + //restore previouse position + let restore_position = "\u{001B}[\(cur_r-orig_r)A" + write(ofd, restore_position, restore_position.count) + + return cur_r + } + + func getR() -> Int { + var buf = [UInt8](repeating: 0, count: 32) + + if (write(ofd, "\u{001B}[6n", 4) != 4) { + print("Cant push escape codes for column") + } + var i=0; + while (i<buf.capacity-1) { + if (read(ifd, &buf[i], 1) == -1) { + break + } + //if eq R + if (buf[i] == 0x52) { + break + } + i+=1 + } + //maybe not most optimal way + while (buf.count-1 > i) { + buf.removeLast() + } + if (buf[0] != 0x1b) && (buf[1] != 0x5b) { + return -1 + } + + var bufs:String = "" + for i in 0..<buf.count { + bufs += String(Character(UnicodeScalar(buf[i]))) + } + let sindex = bufs.index(bufs.startIndex, offsetBy: 2) + let split = bufs.suffix(from:sindex).components(separatedBy: ";") + let s1 = split[0] // row + let s2 = split[1] //column + + return Int(s1)! + } + + func getC() -> Int { + var buf = [UInt8](repeating: 0, count: 32) + if (write(ofd, "\u{001B}[6n", 4) != 4) { + //print("Cant push escape codes for column") + } + var i=0; + while (i<buf.capacity-1) { + if (read(ifd, &buf[i], 1) == -1) { + break + } + //if eq R + if (buf[i] == 0x52) { + break + } + i+=1 + } + //maybe not most optimal way + var j=0 + while (buf.count > i) { + buf.removeLast() + j+=1 + } + if (buf[0] != 0x1b) && (buf[1] != 0x5b) { + return -1 + } + + var bufs:String = "" + for i in 0..<buf.count { + bufs += String(Character(UnicodeScalar(buf[i]))) + } + let sindex = bufs.index(bufs.startIndex, offsetBy: 2) + let split = bufs.suffix(from:sindex).components(separatedBy: ";") + let s1 = split[0] // row + let s2 = split[1] //column + + return Int(s2)! + } + + func setC(_ pos_c: Int) { + let cur_r = getR() + let escape_string = "\u{001B}[\(cur_r);\(pos_c)H" + write(ofd, escape_string, escape_string.count) + } + + func setR(_ pos_r: Int) { + let cur_c = getC() + let escape_string = "\u{001B}[\(pos_r);\(cur_c)H" + write(ofd, escape_string, escape_string.count) + } + + func setCR(_ pos_c:Int, _ pos_r: Int) { + let escape_string = "\u{001B}[\(pos_c);\(pos_r)H" + write(ofd, escape_string, escape_string.count) + } + + func clearScreen() { + //let escape = String(Unicode.Scalar(0x1b)!) + let s = "\u{001B}[H\u{001B}[2J" + //print(s.count) + let ret = write(self.ofd, s, 7); + //let ret = write(self.ofd, String("\u{001b}[2J"),4); + //print("\(esc)[2J".utf8) + } + + func setRawMode() { + if ( tcgetattr(self.ifd, UnsafeMutablePointer(&self.orig_i)) == -1) { + print("Cannot get terminal attribures") + return + } + + raw_i = orig_i + var c_iflag:Int32 = Int32(raw_i.c_iflag) + c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON) + raw_i.c_iflag = UInt(c_iflag) + + var c_oflag:Int32 = Int32(raw_i.c_oflag) + c_oflag &= ~(OPOST) + raw_i.c_oflag = UInt(c_oflag) + + var c_cflag:Int32 = Int32(raw_i.c_cflag) + c_cflag |= (CS8) + raw_i.c_cflag = UInt(c_cflag) + + var c_lflag:Int32 = Int32(raw_i.c_lflag) + c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG) + raw_i.c_lflag = UInt(c_lflag) + //https://stackoverflow.com/questions/31465943/using-termios-in-swift + //raw_i.c_cc[VTIME] = 1 + //raw_i.c_cc[VMIN] = 0; + /*withUnsafeMutablePointer(to: &raw_i.c_cc) { (tuplePtr) -> Void in + tuplePtr.withMemoryRebound(to: cc_t.self, capacity: MemoryLayout.size(ofValue: raw_i.c_cc)) { + $0[Int(VMIN)] = 1 + //$0[Int(VTIME)] = 0 + } + }*/ + //print("\(raw_i)") + //print("VMIN=\(VMIN)") + raw_i.c_cc.16 = 1 + //print("VTIME=\(VTIME)") + raw_i.c_cc.17 = 0 + let p:UnsafePointer<termios> = UnsafePointer(&self.raw_i) + if (tcsetattr(self.ifd, TCSAFLUSH, UnsafePointer(p)) == -1) { + print("Cannot set new terminal input attribures") + } + } + + func setConfigMode(c_iflag:Int32, c_oflag:Int32, c_cflag:Int32, c_lflag:Int32, vmin: UInt8, vtime: UInt8) { + if ( tcgetattr(self.ifd, UnsafeMutablePointer(&self.orig_i)) == -1) { + print("Cannot get terminal attribures") + return + } + + raw_i.c_iflag = UInt(c_iflag) + raw_i.c_oflag = UInt(c_oflag) + raw_i.c_cflag = UInt(c_cflag) + raw_i.c_lflag = UInt(c_lflag) + raw_i.c_cc.16 = vmin + raw_i.c_cc.17 = vtime + let p:UnsafePointer<termios> = UnsafePointer(&self.raw_i) + if (tcsetattr(self.ifd, TCSAFLUSH, UnsafePointer(p)) == -1) { + print("Cannot set new terminal input attribures") + } + } + + func modeRows() { + + } + + func modeColumns() { + + } + + func setOrigMode() { + if (tcsetattr(self.ifd, TCSAFLUSH, UnsafePointer(&self.orig_i)) == -1) { + print("Cannot set new terminal input attribures") + } + } + + func print(_ s: String) { + write(self.ofd, s, s.count) + } +} diff --git a/LibTerm/TermIO.swift b/LibTerm/TermIO.swift new file mode 100644 index 0000000..cbfb7a5 --- /dev/null +++ b/LibTerm/TermIO.swift @@ -0,0 +1,38 @@ +// +// TermIO.swift +// CmdLine +// +// Created by Jacky Jack on 07/06/2023. +// + +import Foundation + +class TermIO { + var term:Term + + init(term: Term) { + self.term = term + } + + func print(s: String) { + + } + + func getC() -> UInt8 { + var c:UInt8 = 0x0 + let fret = read(self.term.ifd, UnsafeMutableRawPointer(&c), 1); + if (fret == 1) { + return c; + } + return 0 + } + + func putC(_ c: UInt8) { + var buf = c + write(self.term.ofd, UnsafeRawPointer(&buf), 1) + } + + func readline(_ flag: Int) -> String { + return "<Empty>" + } +} |