XMapWindow

ウィンドウを表示するには、Xサーバに対して、ウィンドウの表示要求を送る必要がある。
ウィンドウをマップする(マッピング)と言う。

Manpage of XMapWindow

XMapWindowで指定のウィンドウをマップする。

ここでは、戻り値型がわからないのだが、

X Window System, Programming, No.1

一応、intらしい。

$ vi XMapWindow.c
$ gcc XMapWindow.c -lX11 -o XMapWindow
$ ./XMapWindow
d = 00d60260
wr = 02000001
result = 1
$

これでも、まだ、ウィンドウを表示できない。
戻り値のresultの1は、真の意味なのか、エラーコードが1という意味なのか、わからない。
まあ、戻り値を使うことは普通はないとおもう。

Sample/xlib/XMapWindow/XMapWindow/src/XMapWindow at master · bg1bgst333/Sample · GitHub

XCreateSimpleWindow

ウィンドウの生成には、XCreateSimpleWindowを使う。

Manpage of XCreateWindow

XCreateWindowもあるが、まずはよりシンプルなXCreateSimpleWindowにする。

第2引数は親ウィンドウ(の番号)を指定するのだが、自分が親ウィンドウの場合は、RootWindowマクロで、デフォルト(ここではスクリーン0)のルートウィンドウを指定。(この辺はいずれ扱う。)
戻り値wrは、Windowなんだけど、これは定数値で、XIDという定数値でもあり、結局はunsigned longである。
この値を出力してみる。

$ vi XCreateSimpleWindow.c
$ gcc XCreateSimpleWindow.c -lX11 -o XCreateSimpleWindow
$ ./XCreateSimpleWindow
d = 02333260
wr = 02000001
$

wrは、

http://refspecs.linuxfoundation.org/LSB_3.1.1/LSB-Desktop-generic/LSB-Desktop-generic/libx11-ddefs.html

ここのBad~っていうエラーコードの値とは違いそうなので、

X Window Systemプログラミングを勉強してみた〜ウィンドウを表示する〜 - Tomitomi's blog

ここでいうウィンドウを表す番号というかIDを返してるとは思うけど、このIDとエラーコードの仕様というか範囲がわからない・・・。

Sample/xlib/XCreateSimpleWindow/XCreateSimpleWindow/src/XCreateSimpleWindow at master · bg1bgst333/Sample · GitHub

XOpenDisplay

UNIX系OSで使われているウィンドウシステム「X Window System」(現在はX11とも言う)

X Window System

これを表示するには、Xlibを使う。

X11

まずは、その仕組み上、Xサーバに接続する必要がある。

Manpage of XOpenDisplay

XOpenDisplayで接続する。

まずは、Xlibのインストール。

$ sudo yum install libX11-devel
[sudo] bg1 のパスワード:
Fedora 29 - x86_64 - Updates
                                   4.2 kB/s | 6.9 kB     00:01
Fedora 29 - x86_64 - Updates
                                   1.1 MB/s |  27 MB     00:24
Fedora 29 - x86_64
                                   5.6 kB/s | 8.1 kB     00:01
メタデータの期限切れの最終確認: 0:00:01 時間前の xxxx年xx月xx日 xx時xx分xx秒 に実施しました。
パッケージ libX11-devel-1.6.6-1.fc29.x86_64 は既にインストールされています。
依存関係が解決しました。
行うべきことはありません。
完了しました!
$

既にインストールされてた。
(たぶんElectronやった時にインストールされたのかな。)
で、

Display構造体ポインタdを用意し、XOpenDisplayに引数NULLを渡して、戻り値のポインタをdに格納する。
これでXサーバに接続される。
あとは、dを取得できたことを確認するために、dを出力。

$ vi XOpenDisplay.c
$ gcc XOpenDisplay.c -lX11 -o XOpenDisplay
$ ./XOpenDisplay
d = 022df260
$ ./XOpenDisplay
d = 0133b260
$

dの値が出力されている。
毎回変わる模様。
これだけでは、当然まだウィンドウを表示できない。
表示への第一歩である。

Sample/xlib/XOpenDisplay/XOpenDisplay/src/XOpenDisplay at master · bg1bgst333/Sample · GitHub

getch

すぐendwinを呼んでしまうと、何も起こらないように見える。
getchは、本来、入力された文字を取得する関数だが、これを呼んでキーボード入力がされるまでは入力待ち状態になるので、その間どうなっているかを確認する。

getch(3): char from curses terminal keyboard - Linux man page

initsrcとendwinの間にgetchで待ち状態を作る。

実行前
実行前

実行すると、

待ち状態
待ち状態

画面クリアされ、カーソルが左上にある状態で、待ち状態となる。
vimを始めとするスクリーンエディタっぽくなった。
なんらかのキーを入力されると、

終了
終了

endwinが呼ばれて、プログラムが終了する。

ウィンドウアプリのメッセージループのようなイメージで、ある一定条件でループというか待ち状態を抜けるようにし、それまでは画面制御をしていくという形になる。

Sample/ncurses/getch/getch/src/getch at master · bg1bgst333/Sample · GitHub

endwin

ncursesを使ったプログラムを安全に終了させるには、ウィンドウモードを終了するためのendwinという関数を最後に呼ぶ。

endwin(3) - Linux man page
curs_initscr 3x 非公式日本語訳

何も起きない
何も起きない

今度は、実行後にリターンキーを押しても、入力が変な事にはならない。
逆に言うと、何も起きてないように見える。

Sample/ncurses/endwin/endwin/src/endwin at master · bg1bgst333/Sample · GitHub

initscr

前回の、エスケープシーケンスを使っての画面制御をプログラムでやるのは大変なので、以前はcurses、現在では後継のncursesを使う。

https://www.kushiro-ct.ac.jp/yanagawa/ex-2017/2-game/01.html#curses

インストールは、

$ sudo yum install ncurses-devel
[sudo] bg1 のパスワード:
メタデータの期限切れの最終確認: x:xx:xx 時間前の xxxx年xx月xx日 xx時xx分xx秒 に実施しました。
依存関係が解決しました。
================================================================================
 パッケージ            アーキテクチャー
                                   バージョン                 リポジトリ  サイズ
================================================================================
インストール:
 ncurses-devel         x86_64      6.1-8.20180923.fc29        fedora      508 k
依存関係をインストール中:
 ncurses-c++-libs      x86_64      6.1-8.20180923.fc29        fedora       32 k

トランザクションの概要
================================================================================
インストール  2 パッケージ

ダウンロードサイズの合計: 540 k
インストール済みのサイズ: 984 k
これでよろしいですか? [y/N]: y
パッケージのダウンロード中です:
(1/2): ncurses-c++-libs-6.1-8.20180923.fc29.x86  15 kB/s |  32 kB     00:02
(2/2): ncurses-devel-6.1-8.20180923.fc29.x86_64 238 kB/s | 508 kB     00:02
--------------------------------------------------------------------------------
合計                                            143 kB/s | 540 kB     00:03
トランザクションの確認を実行中
トランザクションの確認に成功しました。
トランザクションのテストを実行中
トランザクションのテストに成功しました。
トランザクションを実行中
  準備             :                                                        1/1
Installed: ncurses-c++-libs-6.1-8.20180923.fc29.x86_64
  インストール中   : ncurses-c++-libs-6.1-8.20180923.fc29.x86_64            1/2
Installed: ncurses-c++-libs-6.1-8.20180923.fc29.x86_64
Installed: ncurses-devel-6.1-8.20180923.fc29.x86_64
  インストール中   : ncurses-devel-6.1-8.20180923.fc29.x86_64               2/2
Installed: ncurses-devel-6.1-8.20180923.fc29.x86_64
  scriptletの実行中: ncurses-devel-6.1-8.20180923.fc29.x86_64               2/2
  検証             : ncurses-c++-libs-6.1-8.20180923.fc29.x86_64            1/2
  検証             : ncurses-devel-6.1-8.20180923.fc29.x86_64               2/2

インストール済み:
  ncurses-devel-6.1-8.20180923.fc29.x86_64
  ncurses-c++-libs-6.1-8.20180923.fc29.x86_64

完了しました!
$

こんな感じで。

今回は、画面の初期化initscr()"だけ"をやってみる。(正しい使い方でないのは承知の上。)

initscr(3) - Linux man page
curs_initscr 3x 非公式日本語訳

実行前
実行前

実行して、何も起きないと思って、何度もリターンキーを叩くと、

おかしい
おかしい

入力おかしくなる。
なので、endwin()を呼ぶべきかと。

Sample/ncurses/initscr/initscr/src/initscr at master · bg1bgst333/Sample · GitHub

エスケープシーケンス

プログラム中に改行やタブを挿入するときなどに使うエスケープシーケンス。

エスケープシーケンス - Wikipedia

これによると、実はエスケープシーケンスは3種類あって、

  • 改行などのエスケープコード(エスケープ文字)
  • 文字集合の指示・呼び出しのシーケンス(特殊な文字・漢字コード?)
  • 入力位置などを操作する画面制御シーケンス(画面制御コード)

となっているらしい。
で、今回は、

  • 改行などのエスケープコード
  • 入力位置などを操作する画面制御シーケンス

の2つを扱う。
(特殊文字はいまのところちょっと使わなそう・・・。)

特に、今回のキモは画面制御シーケンスである。
まず、terminalを起動して、"Ctrl + v"を押した後、"Esc"を押す。
すると、

$ ^[

と入力される。でこのあとに、"["を入力し、さらに特定の数字と文字で表されたコードを入力する。

https://www.kushiro-ct.ac.jp/yanagawa/ex-2017/2-game/01.html#escseq

コード表を参考に入力してみると、

テキストの色、背景色、リセット
テキストの色、背景色、リセット

テキストの色を変えたり、背景色を変えたり、リセットできる。

3行戻るコマンド
3行戻るコマンド

これを入れると、

戻っている
戻っている

カーソルが戻っている。(3行かは微妙・・・。)

3行前から入力
3行前から入力

戻ったところから入力出来たり・・・。

2Jで画面クリア
2Jで画面クリア

"^[[2J"で、

クリアされた
クリアされた

画面クリア出来たり・・・。

で、これはC言語でも出来るわけで、

前半はエスケープ文字の、改行、タブ、バックスペース、で簡単に制御している。
10秒後の後半は、画面制御コードでいろいろいじっている。
画面制御コードはprintf中に"\e[31m"(テキスト色を赤に変更)というように指定する。

エスケープ文字
エスケープ文字

まずは、エスケープ文字。
改行、タブはだいたいわかるとして、バックスペースを入れた場合は、直前の文字が消える。

画面制御コード
画面制御コード

10秒後に、画面制御コード。
ポイントは、"m行n列に戻る"というコードは、mもnも1から始まるという点だろうか・・・。0行0列は意味がなかった。
あと、画面をクリアしても、1行1列に戻らないので、自分で戻る必要がある。

Sample/c/escape_sequence/escape_sequence/src/escape_sequence at master · bg1bgst333/Sample · GitHub