STORY.html (8876B)
1 <html> 2 <head> 3 <title>w3mの開発について</title> 4 </head> 5 <body> 6 <h1>w3mの開発について</h1> 7 <div align=right> 8 1999/2/18<br> 9 1999/3/8改訂<br> 10 伊藤 彰則<br> 11 aito@fw.ipsj.or.jp 12 </div> 13 <h2>はじめに</h2> 14 w3mは,WWWに対応したページャ/ブラウザで,テキストベースで動く. 15 w3mに最も近いアプリケーションとして,有名なテキストベースブラウザ 16 <a href="http://www.lynx.browser.org/">Lynx</a>がある.しかし,w3mには 17 Lynxにないいくつかの特徴がある.例えば, 18 <UL> 19 <LI>tableがレンダリングできる. 20 <LI>frameがレンダリングできる(frameをtableに変換して表示するだけ). 21 <LI>標準入力を読んで表示することができる. 22 (最近のLynx では,こんな風にして標準入力から文書を読むことができる 23 そうです: 24 <pre> 25 lynx /dev/fd/0 < file 26 </pre> 27 うん,Linuxでは確かに動くようです.) 28 <LI>軽くて小さい.stripした後のw3mのバイナリサイズは,Sparcの場合で 29 260KByte弱である(version beta-990217現在). 30 ちなみにLynxのバイナリは 1.8MB以上ある. 31 </UL> 32 などだ.もちろん,Lynx は優れたブラウザで,w3mにない多くの機能を 33 持っている.Lynxにあってw3mにない機能は,例えば 34 <UL> 35 <LI>Cookie対応. 36 <LI>豊富なオプション設定. 37 <LI>多国語対応. 38 </UL> 39 などなど.Lynx には豊富なドキュメントもあり,一方w3mにはほとんどまともな 40 ドキュメントがない.ドキュメントは今後の課題だ. 41 <P> 42 というわけで,w3mは既存のブラウザ(Netscapeはもちろん,Lynxも)を代替 43 するものでは<strong>ない</strong>.それではw3mは何のためにあるのか? 44 それは,日常的に「ちょっと」 web を使うためだ.専用線で接続された環境で, 45 「ちょっとwebを見に行きたい」とき,Netscapeを立ちあげるのはイライラする. 46 Lynxも立ちあがるのにちょっと間がある. 47 その点,w3mは一瞬で立ちあがり,マシンにほとんど負担をかけない. 48 そこで情報を見て,もっと詳細に見たいときに,はじめて他のブラウザを使う 49 のだ.もっとも私の場合,ほとんどはw3mだけで十分なのだが. 50 51 <h2>w3mの誕生</h2> 52 <P> 53 w3m の前身は,fm 54 というページャ(moreやlessの親戚)だった.fmが書かれたのは1991年以前 55 (記録していなかったので正確な日付はわからない)で,当時まだWWWは 56 一般的ではなかった(存在しなかったかも).その当時「ブラウザ」といえば,lessなどの 57 ファイルを見るツールのことを指していた. 58 <P> 59 fm は,当時私が書いていた 60 研究用のプログラムをデバッグするために書いたものだ.プログラムの状態 61 をトレースするため,プログラムの内部状態を延々とファイルにダンプし, 62 それを見ながらデバッグをしていた.ある時点での内部状態を1行にプリント 63 していたため,そのファイルは1行が数百文字あった.それをmoreやlessで 64 見ると,行が折り返されるため,何が何だかわからなくなってしまうのだった. 65 そこで私は,行を折り返さないページャであるfmを書いた.物理的な1行は 66 画面の上でも1行で,画面からはみ出した部分を見るには,画面全体をずらす 67 という設計にした.当時私は80x24の画面を使っていたので,fm はデバッグ 68 にとても役立った. 69 <P> 70 そのうち,私もWWWの存在を知って使いはじめた.当時使っていたブラウザは, 71 XMosaic と Chimera だった.特に Chimera は軽いので愛用していた. 72 興味があったので HTML と HTTP の勉強をしてみたが,案外簡単なので, 73 これなら自分でもブラウザが書けるのではないかと思った.当時のHTTPは 74 GOPHERプロトコルに毛が生えた程度で,非常に簡単なものだった.また, 75 HTML は 2.0 で,行の折り返しと箇条書きがほとんど全てだった. 76 そこで,fm にちょっと手を入れて,WWWブラウザを作ってみた.これがw3mだった. 77 ちなみに,w3m は WWW-wo-Miru (日本語だ)の略で,fm (File-wo-Miru)に 78 倣った.最初に w3m を書いたのは,1995年初頭だったと思う. 79 80 <h2>w3mの没落と再生</h2> 81 <p> 82 それ以来,ずっと私は w3m を「ページャ」として使っていた.ファイルや 83 電子メール,マニュアルなどを読むときに,lessの代わりにしていたのだ. 84 w3mでwebを見ることも時々あったが,その後 w3m で正常に見られないページが 85 多くなった(その多くはtableを使っていた)こともあって,webブラウザと 86 してはほとんど使わなくなっていた.一度 table のレンダリングを検討 87 したことがあったが,難しいので放ってあった. 88 <P> 89 もう一度 w3m に手を入れる気になったのは,1998年のことだ.動機は2つあった. 90 その当時,私は客員研究員としてボストン大学に滞在しており,多少時間に余裕があった 91 ことが一つ.もう一つは,研究日誌を HTML で書いていて,結果をどうしても表に 92 したくなったためだ.それまでは表を <pre>..</pre>で書いていたのだが, 93 plain textで表を作るのがわずらわしくて仕方なかった.とうとう我慢できなくなって 94 <table>タグを使ったが,そうすると今度は Netscape を使わないと日誌が 95 見られなくなってしまった.そこで,w3m で table の 96 レンダリングができるようにしようと試みた. 97 <P> 98 私としては,それほど複雑でない表を見ることができれば十分だった.ところが, 99 半端にtableに対応した結果,画面のレイアウトにtableを使っているページの 100 表示がぐちゃぐちゃになってしまった.結局,「表が見られて」「その他のページ 101 もそこそこに見られる」ようにするためには,tableの表示が完璧に近くなければ 102 ならないのだった.茨の道だ. 103 <P> 104 結局,結構時間がかかったが,何とか 105 実用になるものができたと思う.table の実装に気をよくして,次に form を実装 106 した.これで,w3mはほぼ実用になるブラウザとして生まれ変わったのだ. 107 108 <h2>w3mでのtableのレンダリングアルゴリズム</h2> 109 110 HTMLのtableのレンダリングは結構難しい.LaTeX の tabular のように, 111 「表の各列の幅を指定するか,さもなければ必要な最大の幅を取る」 112 というのなら話は簡単なのだが,HTMLのtableは「画面に適当に収まるように」 113 列の幅を設定して,表の内容を適当に折りかえさなければならない. 114 幅の決定をいいかげんにすると,非常に表が見づらくなってしまう. 115 また,tableは入れ子にできるので,それが話を一層ややこしくしている. 116 そこで,w3mでは次のようなアルゴリズムで幅を決定している. 117 <OL> 118 <LI>まず,各列の内容の最大幅と最小幅を求める.最大幅というのは, 119 もしいくらでも広い幅が取れたとしたら,最大何桁になるかというもの 120 だ.一般的には,<BR>や<P>で区切られた段落の長さになる. 121 最小幅は,それより列の幅が狭いと内容が詰められないという限界の幅 122 である.表の内容が日本語だけの場合には最小幅は常に2であり, 123 internationalization という単語が含まれていれば最小幅は20 124 である.また,表の中に<pre>..</pre>があった場合, 125 その一行の長さの最大値が最小幅になる. 126 <LI>もし,WIDTH属性で列の幅が指定してあれば,列の幅をその値で固定 127 する.ただし,その幅が最小幅よりも小さければ,列の幅を最小幅で固定する. 128 <LI>列の最大幅(または固定幅)を合計して,画面の幅よりも広いかどうかを調べる. 129 もし合計が画面に収まるなら,その値を各列の幅として使う. 130 <LI>もし合計が画面に収まらなければ,次のようにして幅を決定する. 131 <OL> 132 <LI>画面の幅から,幅が固定された列の幅の合計を引く.これを W とする. 133 <LI>幅が固定されていない列に対して,各列の最大幅の対数に比例して W を配分する. 134 <LI>もし配分された幅が最小幅よりも小さければ,その列の幅を最小幅で固定し, 135 幅の配分をやり直す. 136 </OL> 137 </OL> 138 幅の配分を最大幅の対数に比例させているが,これでいいのかどうか検討を要する. 139 ただし,最大幅そのものに比例させると悲惨なことになる.table を画面レイアウト 140 に使っていた場合,ある列に長い文章があると,その列が画面の幅のほとんどを使って 141 しまうからだ.対数じゃなくて n 乗根でもいいかもしれない. 142 <P> 143 上記のアルゴリズムでは,画面の幅が既知であることが前提になっている.ところが, 144 これでは困る場合がある.どういう場合かというと,表が入れ子になっている場合だ. 145 外側の表の列幅がわからないと内側の表がレンダリングできないが,内側の表を 146 レンダリングしてみないと外側の表の幅が決定できないという矛盾に陥る.WIDTH属性 147 が指定してあれば問題はないのだが,そうでない場合には,結局 148 「内側の表の幅は,外側の表の幅の0.8倍」で決め打ちしてしまうことにした. 149 ほとんどの場合はこれで問題ないが,ある表の中に表を入れ子にして2つ並べると, 150 外側の表が必ず画面をはみだしてしまうようになった.もし厳密にこれを画面に収め 151 ようとすると,一旦レンダリングして全体の幅を調べたあと,幅を設定しなおして 152 もう一度レンダリングするという過程を収束するまで繰り返さなければならない. 153 Netscapeは,多分これをやっているのだろう. 154 155 <h2>利用したライブラリ</h2> 156 157 w3m は, 158 <a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/">Boehm GC</a> 159 というライブラリを利用している.これは私が書いたものではないが, 160 コンパイル時の便宜を考えて配布パッケージに含めている. 161 なお,libwww は使っていない. 162 <P> 163 Boehm GCは,Cから使えるガベージコレクタだ.table を実装したあたりにこれを 164 使いはじめたのだが,非常に快適だった.GCなしでは,w3mにtableやformを実装 165 する根性が私にあったかどうか疑わしい.Boehm GCの利用については,「 166 <a href="http://homepage2.nifty.com/aito/gc/gc.html"> 167 Boehm GCを使おう</a>」という文章を書いたので,それも見ていただけると良い 168 と思う. 169 <P> 170 beta-990304より前のバージョンでは, 171 <a href="http://home.cern.ch/~orel/libftp/libftp/libftp.html">LIBFTP</a>と 172 いうライブラリを使っていた. 173 libftp を使った理由は,FTPプロトコルが HTTP に比べて面倒だったためだ. 174 しかし,ライセンスの問題がありそうだということなので,同等の関数(のサブセット) 175 を自前で書いてしまった. 176 <P> 177 ちなみに,w3mはUNIXの正規表現ライブラリと curses ライブラリを使っていない. 178 どちらも自前の関数群だ.これらを自前で用意した理由は,fmを書いた当時, 179 日本語の通るまともでフリーな正規表現とcursesのライブラリがなかったためだ. 180 現在ではどちらも存在するし,他のライブラリを使った方が速そうなのだが, 181 面倒なので現在までこの実装を引きずっている. 182 183 <h2>今後の予定</h2> 184 185 ...ない.w3mは軽快さが売りなので,あまり機能を満載してしまうとw3m独自の 186 良さが失われるからだ.とはいっても,まだバグが多いので,それらのfixは 187 していきたいと思っている. 188 189 </body> 190 </html>