lynx /dev/fd/0 < fileうん,Linuxでは確かに動くようです.)
というわけで,w3mは既存のブラウザ(Netscapeはもちろん,Lynxも)を代替 するものではない.それではw3mは何のためにあるのか? それは,日常的に「ちょっと」 web を使うためだ.専用線で接続された環境で, 「ちょっとwebを見に行きたい」とき,Netscapeを立ちあげるのはイライラする. Lynxも立ちあがるのにちょっと間がある. その点,w3mは一瞬で立ちあがり,マシンにほとんど負担をかけない. そこで情報を見て,もっと詳細に見たいときに,はじめて他のブラウザを使う のだ.もっとも私の場合,ほとんどはw3mだけで十分なのだが.
w3m の前身は,fm というページャ(moreやlessの親戚)だった.fmが書かれたのは1991年以前 (記録していなかったので正確な日付はわからない)で,当時まだWWWは 一般的ではなかった(存在しなかったかも).その当時「ブラウザ」といえば,lessなどの ファイルを見るツールのことを指していた.
fm は,当時私が書いていた 研究用のプログラムをデバッグするために書いたものだ.プログラムの状態 をトレースするため,プログラムの内部状態を延々とファイルにダンプし, それを見ながらデバッグをしていた.ある時点での内部状態を1行にプリント していたため,そのファイルは1行が数百文字あった.それをmoreやlessで 見ると,行が折り返されるため,何が何だかわからなくなってしまうのだった. そこで私は,行を折り返さないページャであるfmを書いた.物理的な1行は 画面の上でも1行で,画面からはみ出した部分を見るには,画面全体をずらす という設計にした.当時私は80x24の画面を使っていたので,fm はデバッグ にとても役立った.
そのうち,私もWWWの存在を知って使いはじめた.当時使っていたブラウザは, XMosaic と Chimera だった.特に Chimera は軽いので愛用していた. 興味があったので HTML と HTTP の勉強をしてみたが,案外簡単なので, これなら自分でもブラウザが書けるのではないかと思った.当時のHTTPは GOPHERプロトコルに毛が生えた程度で,非常に簡単なものだった.また, HTML は 2.0 で,行の折り返しと箇条書きがほとんど全てだった. そこで,fm にちょっと手を入れて,WWWブラウザを作ってみた.これがw3mだった. ちなみに,w3m は WWW-wo-Miru (日本語だ)の略で,fm (File-wo-Miru)に 倣った.最初に w3m を書いたのは,1995年初頭だったと思う.
それ以来,ずっと私は w3m を「ページャ」として使っていた.ファイルや 電子メール,マニュアルなどを読むときに,lessの代わりにしていたのだ. w3mでwebを見ることも時々あったが,その後 w3m で正常に見られないページが 多くなった(その多くはtableを使っていた)こともあって,webブラウザと してはほとんど使わなくなっていた.一度 table のレンダリングを検討 したことがあったが,難しいので放ってあった.
もう一度 w3m に手を入れる気になったのは,1998年のことだ.動機は2つあった. その当時,私は客員研究員としてボストン大学に滞在しており,多少時間に余裕があった ことが一つ.もう一つは,研究日誌を HTML で書いていて,結果をどうしても表に したくなったためだ.それまでは表を <pre>..</pre>で書いていたのだが, plain textで表を作るのがわずらわしくて仕方なかった.とうとう我慢できなくなって <table>タグを使ったが,そうすると今度は Netscape を使わないと日誌が 見られなくなってしまった.そこで,w3m で table の レンダリングができるようにしようと試みた.
私としては,それほど複雑でない表を見ることができれば十分だった.ところが, 半端にtableに対応した結果,画面のレイアウトにtableを使っているページの 表示がぐちゃぐちゃになってしまった.結局,「表が見られて」「その他のページ もそこそこに見られる」ようにするためには,tableの表示が完璧に近くなければ ならないのだった.茨の道だ.
結局,結構時間がかかったが,何とか 実用になるものができたと思う.table の実装に気をよくして,次に form を実装 した.これで,w3mはほぼ実用になるブラウザとして生まれ変わったのだ.
上記のアルゴリズムでは,画面の幅が既知であることが前提になっている.ところが, これでは困る場合がある.どういう場合かというと,表が入れ子になっている場合だ. 外側の表の列幅がわからないと内側の表がレンダリングできないが,内側の表を レンダリングしてみないと外側の表の幅が決定できないという矛盾に陥る.WIDTH属性 が指定してあれば問題はないのだが,そうでない場合には,結局 「内側の表の幅は,外側の表の幅の0.8倍」で決め打ちしてしまうことにした. ほとんどの場合はこれで問題ないが,ある表の中に表を入れ子にして2つ並べると, 外側の表が必ず画面をはみだしてしまうようになった.もし厳密にこれを画面に収め ようとすると,一旦レンダリングして全体の幅を調べたあと,幅を設定しなおして もう一度レンダリングするという過程を収束するまで繰り返さなければならない. Netscapeは,多分これをやっているのだろう.
Boehm GCは,Cから使えるガベージコレクタだ.table を実装したあたりにこれを 使いはじめたのだが,非常に快適だった.GCなしでは,w3mにtableやformを実装 する根性が私にあったかどうか疑わしい.Boehm GCの利用については,「 Boehm GCを使おう」という文章を書いたので,それも見ていただけると良い と思う.
beta-990304より前のバージョンでは, LIBFTPと いうライブラリを使っていた. libftp を使った理由は,FTPプロトコルが HTTP に比べて面倒だったためだ. しかし,ライセンスの問題がありそうだということなので,同等の関数(のサブセット) を自前で書いてしまった.
ちなみに,w3mはUNIXの正規表現ライブラリと curses ライブラリを使っていない. どちらも自前の関数群だ.これらを自前で用意した理由は,fmを書いた当時, 日本語の通るまともでフリーな正規表現とcursesのライブラリがなかったためだ. 現在ではどちらも存在するし,他のライブラリを使った方が速そうなのだが, 面倒なので現在までこの実装を引きずっている.