ターミナルのカーソル位置を取得
(2018/3/21)
MacのTerminal.appをはじめ、現在ほぼすべてのターミナルエミュレータはVT100互換(というかANSI)なので同じシーケンスを使うことができる
エスケープシーケンスは普通はカーソルを動かすために使われるのだが、カーソル位置を知るためのシーケンスも用意されており、これを使ってターミナル上のカーソル位置を知るプログラムを書くことができる
ESC [ 6 nという問い合わせシーケンスを送るときttyからエコーが返るのは嫌なのでエコーは禁止しておくのが良いと思われる
ioctl(2)で制御できると思ったのだがどうもうまくいかない tcgetattr(3)でできるということを教えてもらってやっとうまくいった エスケープシーケンスだのioctl()だのには前世紀におおいに苦労したものだが、Web時代だとそんな情報ぐらい楽々手に入るだろうと思ったら意外に大変だった
話題が古いせいかサンプルプログラムもほとんどみつからなかった
code:cursorpos.c
struct termios state, oldstate;
void echo_off()
{
tcgetattr(0, &oldstate);
state = oldstate;
state.c_lflag &= ~(ICANON | ECHO);
tcsetattr(0, TCSANOW, &state);
}
void echo_on()
{
tcsetattr(0, TCSANOW, &oldstate);
}
int main(){
char *p = buf;
char c;
echo_off();
write(0,"\x1b[6n",4);
for (int i=0;;i++){
read(0,&c,1);
if(c >= 0x30 && c <= 0x39) *p++ = c;
if(c == ';') *p++ = ' ';
if(c == 'R') break;
}
*p = '\0';
echo_on();
printf("%s\n",buf);
}
2018/3/21 09:59