Display (2)
make cscope
FreeBSDの/sysにあるMakefileに面白い記述を発見。
# You need the devel/cscope port for this. cscope: cscope.out cscope.out: ${.CURDIR}/cscope.files cd ${.CURDIR}; cscope -k -buq -p4 -v
cscope用のDBを作ってくれるとな。それからglobalを入れておくとTAGSも作成してくれるよ。
root@fb:/sys # make TAGS cd /usr/src/sys; find bsm cam cddl compat conf contrib crypto ddb dev fs gdb geom gnu isa kern libkern modules net net80211 netgraph netinet netinet6 netipsec netpfil netsmb nfs nfsclient nfsserver nlm ofed opencrypto rpc security sys ufs vm xdr xen i386 x86 -name "*.[chSsly]" -a -type f > /usr/src/sys/cscope.files rm -f /usr/src/sys/TAGS cd /usr/src/sys; xargs etags -a < /usr/src/sys/cscope.files
これだけで、ソースの海をスイスイと泳ぎ回れるとな。追加分は次の通り。
[sakae@fb /sys]$ ls -lh cscope.* TAGS -rw-r--r-- 1 root wheel 48M Sep 11 07:43 TAGS -rw-r--r-- 1 root wheel 354K Sep 11 07:43 cscope.files -rw-r--r-- 1 root wheel 33M Sep 11 06:00 cscope.in.out -rw-r--r-- 1 root wheel 172M Sep 11 06:00 cscope.out -rw-r--r-- 1 root wheel 113M Sep 11 06:00 cscope.po.out
漢字ROM (bdf font)
漢字が表示出来るフォントに出会ったので、少しその方面を調べてみる。
Glyph Bitmap Distribution Format
[sakae@fb /usr/src/X11/font/adobe-100dpi]$ lv timR24.bdf STARTFONT 2.1 FONT -Adobe-Times-Medium-R-Normal--34-240-100-100-P-170-ISO10646-1 SIZE 24 100 100 FONTBOUNDINGBOX 38 48 -5 -11 : STARTCHAR three ENCODING 51 SWIDTH 500 0 DWIDTH 16 0 BBX 12 23 2 0 BITMAP 0F80 3FC0 : 7F00 ENDCHAR
ISO10646と言うのはユニコードなんだな。FreeBSDのコンソールでは、このタイプのフォントをvtfontcvtっていうアプリで、*.fntって形式に変換して使ってる。
bdf to (fnt|pcf)
FreeBSDのvtコンソールが扱かうフォント形式は特殊だ。そのためフォントのソースであるBDF形式を変換する必要がある。
[sakae@fb /usr/src/X11/font]$ cp sony-misc/8x16.bdf /tmp/ [sakae@fb /tmp]$ vtfontcvt -v 8x16.bdf aa.fnt Statistics: - width: 8 - height: 16 - glyph_total: 190 - glyph_normal: 190 - glyph_normal_right: 0 - glyph_bold: 0 - glyph_bold_right: 0 - glyph_unique: 190 - glyph_dupe: 0 - mapping_total: 190 - mapping_normal: 190 - mapping_normal_folded: 2 - mapping_normal_right: 0 - mapping_normal_right_folded: 0 - mapping_bold: 0 - mapping_bold_folded: 0 - mapping_bold_right: 0 - mapping_bold_right_folded: 0 - mapping_unique: 190 - mapping_dupe: 0
約30Kあったものが3kのサイズに変換された。それだけじゃなくて、マシンが扱い易い形式になっているんだろうね。
上記はFreeBSDに特有な事情だったけど、Xorg界では、 ports/x11-fonts/bdftopcf と言うフォントのコンパイラーが用意されてる。これを使うとフォントのソース(BDF)をXが普通に使うPortable Compiled Format (PCF) に変換出来る。 当然、逆コンパイラーも用意されてて、改変が出来る。
X11 の PCF ビットマップフォントファイルのフォーマット にあるように、バイナリーな形式のやつは、フォーマットがグチャグチャしてて、そのままでは容易に扱える代物では無い。
vt100
軽くフォントの事を調べてみたけど、以前にやったminixでは、フォントの話なんてさっぱり出てこなかったぞ。それにも拘わらず、ちゃんと表示出来てるって事は、ターミナル自身にフォントを内蔵してるはず。本当かどうかターミナルの元祖vt100に当ってみる。
G0 Sets Sequence G1 Sets Sequence Meaning ESC ( A ESC ) A United Kingdom Set ESC ( B ESC ) B ASCII Set ESC ( 0 ESC ) 0 Special Graphics ESC ( 1 ESC ) 1 Alternate Character ROM Standard Character Set ESC ( 2 ESC ) 2 Alternate Character ROM Special Graphics
やっぱりROMが内蔵されてた。そしてその切り換えは、得意のエスケープシーケンスで行うとな。英米の切り換えが可能。
console of ArchLinux
ちょっと更新をサボっていたら、500Mぐらい、新しいのがきた。そして、少しづつ肥大化してる。で、コンソール系はどうなってるか調べてみた。
Linux コンソール なかなか良い起点を示してくれている。
Arch Linuxのコンソールで日本語環境を作る 検索に引掛ったもの
Linux framebuffer 現代風なコンソールの土台
Text mode 古風なモード
Code page 437 IBM PCのセミ・グラフィック仕様
svgalib to SDL2
Welcome to SVGAlib こんな、画面に向ってのお絵描き例が出てた。
#include <stdlib.h> #include <unistd.h> #include <vga.h> int main(void) { int color = 4; int x = 10; int y = 10; unsigned int seconds = 5; /* detect the chipset and give up supervisor rights */ if (vga_init() < 0) return EXIT_FAILURE; vga_setmode(G320x200x256); vga_setcolor(color); vga_drawpixel(x, y); sleep(seconds); /* restore textmode and fall back to ordinary text console handling */ vga_setmode(TEXT); return EXIT_SUCCESS; }
コンパイルと実行は
[sakae@fb /tmp]$ cc -I/usr/local/include -L/usr/local/lib s.c -lvga [sakae@fb /tmp]$ chmod u+s a.out [sakae@fb /tmp]$ ./a.out svgalib: Cannot get I/O permissions.
何処で文句を言われるかと調べたら、 vga_init
の所だった。ポートになってるぐらいだから、動いてもよさそう。ひょっとして、FreeBSDでもLinuxのふりをする環境にしないと駄目なのかな?
Why does a programs terminate immediatelly with "svgalib: Cannot get I/O permissions."? svgalib programs need to be run as root. This means that either the user that runs them is root, or, if running by normal users is desirable, the program needs to be 'suid root', which means: the program must be owned by root (chown 0 program) and the suid bit needs to be set (chmod u+s program).
例によって、役にたたないFAQであります。ソース嫁が一番のFAQでしょう。
じゃ、Debianではどうか? パッケージになっていない。いやな予感。ソースからコンパイルしたらボロボロとエラーになって取り付く島もない。ArchLinuxは? やっぱり入っていない。過去の遺物なんだな。見きりをつけよう。
代わりは、SDL Language Bindings こんなのかな? ちょっと違う気がしないでもないな。
Hello SDL: Your First Graphics Window
[sakae@fb /tmp/01_hello_SDL]$ cc 01_hello_SDL.cpp -I/usr/local/include/SDL2 -L/usr/local/lib -lSDL2 [sakae@fb /tmp/01_hello_SDL]$ ls -l total 24 -rwxr-x--- 1 sakae wheel 1304 Mar 14 13:54 01_hello_SDL.cpp* -rwxr-xr-x 1 sakae wheel 13364 Sep 11 16:12 a.out* -rwxr-x--- 1 sakae wheel 286 Mar 14 13:54 readme.txt*
vesa or vga
/sys/dev/fb/{vga,vesa}.[ch] なんてのが有って、そこでsplashしてるみたい。つらつら見ていくと、どうやらBIOSからのサポートがあるみたいだ。そんなわけで、資料収集。
今更、こういう趣味に走る人は少ないので、余り出てこない。
putty
ひょんな事からputtyがUNIXでもサポートされてる事を知った。今迄Windows専用とばかり思っていたぞ。恥しい事だ。
putty-0.77 にソースやら実行形式が置いてある。確かにWindowsに傾いてはいるけどね。 んな訳で、ソースを紐解いてみる。
GUIなアプリなんで、使って天国、作るのは地獄。ついでに見るのも地獄ですよ。発散しないように注意。ターミナルってdirの中だけを干渉、もとえ鑑賞する。
まずはお約束で、terminal.h から。GUIな作者にみられるような、横幅がビローンとのび太コードになっていない。80桁にコードが収まるように、極力配慮されてる。こうでなくちゃね。 コメントがしっかり入ているので、余生を送るには最適と思うぞ。まあ、先に意気ますか。
terminal.c
/* * Terminal emulator. */ #define CL_ANSIMIN 0x0001 /* Codes in all ANSI like terminals. */ #define CL_VT100 0x0002 /* VT100 */ #define CL_VT100AVO 0x0004 /* VT100 +AVO; 132x24 (not 132x14) & attrs */ #define CL_VT102 0x0008 /* VT102 */ #define CL_VT220 0x0010 /* VT220 */ #define CL_VT320 0x0020 /* VT320 */ #define CL_VT420 0x0040 /* VT420 */ #define CL_VT510 0x0080 /* VT510, NB VT510 includes ANSI */ #define CL_VT340TEXT 0x0100 /* VT340 extensions that appear in the VT420 */ #define CL_SCOANSI 0x1000 /* SCOANSI not in ANSIMIN. */ #define CL_ANSI 0x2000 /* ANSI ECMA-48 not in the VT100..VT420 */ #define CL_OTHER 0x4000 /* Others, Xterm, linux, putty, dunno, etc */ #define TM_VT100 (CL_ANSIMIN|CL_VT100) #define TM_VT100AVO (TM_VT100|CL_VT100AVO) #define TM_VT102 (TM_VT100AVO|CL_VT102) :
色々な端末の真似をするやつだよってのが宣言されてる。 いかめしい定義の割りには、参照してる所が限定されてる。
/* * Remove everything currently in `inbuf' and stick it up on the * in-memory display. There's a big state machine in here to * process escape sequences... */ static void term_out(Terminal *term, bool called_from_term_data) { : /* * If we're in print-only mode, we use a much simpler * state machine designed only to recognise the ESC[4i * termination sequence. */ if (term->only_printing) { if (c == '\033') term->print_state = 1; else if (c == (unsigned char)'\233') term->print_state = 2; else if (c == '[' && term->print_state == 1) term->print_state = 2; else if (c == '4' && term->print_state == 2) term->print_state = 3; else if (c == 'i' && term->print_state == 3) term->print_state = 4; else term->print_state = 0; if (term->print_state == 4) { term_print_finish(term); } continue; }
エスケープシーケンスを解読するルーチン。これと同じ方策のものがminixの所でも使われていたな。
ソースの冒頭で宣言されてた奴は、こんな風に使われていたぞ。
switch (term->esc_args[0]) { case 61: term->compatibility_level &= ~TM_VTXXX; term->compatibility_level |= TM_VT102; break; case 62: term->compatibility_level &= ~TM_VTXXX; term->compatibility_level |= TM_VT220; break;
色々な端末の真似をエスケープシーケンス等を考慮しながら行うってのは、無駄に大変と言う事が分った。心して利用しろとな。
苦労の跡は、これだけじゃない。同じ階層にbidi.cってファイルが有るんだけど、何者?って思って眺めてみたら、
/* * Implementation of the Unicode bidirectional and Arabic shaping * algorithms for PuTTY. * :
アラビア言語もサポートするっていう遠大なもの。まるでemacsとかrubyみたいに、色々な言語大好きさんでした。
一つ上の階層から辿れる、unix/window.cは
/* * window.c: the main code that runs a PuTTY terminal emulator and * backend in a GTK window. */
GTKの奧座敷で動くエミュレータの制御なんだね。6000行近いコード。これはこれで気違いじみているな(褒め言葉です)。
at minix
すっきりさっぱりのminixにおけるエスケープシーケンスを見て億。
PRIVATE out_char(tp, c) register struct tty_struct *tp; /* pointer to tty struct */ char c; /* character to be output */ { /* Output a character on the console. Check for escape sequences, including * ESC 32+x 32+y to move cursor to (x, y) * ESC ~ 0 to clear from cursor to end of screen * ESC ~ 1 to reverse scroll the screen 1 line * ESC z x to set the attribute byte to x (z is a literal here) */ /* Check to see if we are part way through an escape sequence. */ if (tp->tty_esc_state == 1) { tp->tty_echar = c; tp->tty_esc_state = 2; return; } if (tp->tty_esc_state == 2) { escape(tp, tp->tty_echar, c); tp->tty_esc_state = 0; return; } : switch(c) { : case 033: /* ESC - start of an escape sequence */ flush(tp); /* print any chars queued for output */ tp->tty_esc_state = 1; /* mark ESC as seen */ return; :
出力ルーチンの中でシーケンスを見つけ出した場合、それを溜め込む。そして、溜った所で処理ルーチンを呼び出す。
PRIVATE escape(tp, x, y) register struct tty_struct *tp; /* pointer to tty struct */ char x; /* escape sequence is ESC x y; this is x */ char y; /* escape sequence is ESC x y; this is y */ { /* Handle an escape sequence. */ int n, ct, vx; /* Check for ESC z attribute - used to change attribute byte. */ if (x == 'z') { /* Set attribute byte */ tp->tty_attribute = y << 8; return; } /* Check for ESC ~ n - used for clear screen, reverse scroll. */ if (x == '~') { if (y == '0') { /* Clear from cursor to end of screen */ :
シーケンス長が固定なので、すっきりしてる。実務のやつは、長さもまちまちだし、機能も色々なので、こんなものでは済まない。
minix app
カーネルで定義されたエスケープシーケンスをminixのアプリが使っているはず。探してみたら、mined1.cに見付かった。minix流のemacs似のscreen editorらしい。
/* Escape sequences. */ #ifdef UNIX char *CE, *VS, *SO, *SE, *CL, *AL, *CM; #else char *enter_string = "\033 8\033~0"; /* String printed on entering mined */ char *pos_string = "\033"; /* Absolute cursor position */ char *rev_scroll = "\033~1"; /* String for reverse scrolling */ char *rev_video = "\033z\160"; /* String for starting reverse video */ char *normal_video = "\033z\007"; /* String for leaving reverse video */ #endif UNIX
mined2.cも見ておくと吉。なんなスクリーン・エディターって懐しいな。
昔、FM-11ってパソコンを使ってた。豪華にMC6809を2こも搭載したやつ。サブCPUは画面制御専用になってて、メインCPU側から、コマンドブロックってのにコマンドと引数を置いてコール。するとサブ側が動いて、スクロールとかを実行。
何でも、このコマンドブロック方式ってのが、大型コンピュータでも採用されてたらしくし、自慢の種になってた。
pty
こんな面白い記事を見付た。
Using pseudo-terminals (pty) to control interactive programs
大事な技術だな。普段は表に出て来る事はないけど。puttyでも使っているかな。
マスター/スレーブって、今は放送禁止用語になっちゃってるのか。