メインコンテンツまでスキップ

描画の流れ

描画の流れとデータ構造

file.c から html 構築を分離

file.c => 2800
html parse & 2d layout => 4300

くらいに分かれた。 4300 の方を見る。

Buffer に 行を格納する

第一段階の処理。 URL から http request 、content を parse して 二次元レイアウトして格納する。

loadGeneralFile が起点となる。

Buffer *loadGeneralFile(char *path, Url *current, char *referer, int flag,
FormList *request);

この関数は多機能で url からのコンテンツの入手、 入手したコンテンツを html parse しての TERM 表現(Buffer)の生成 までを全部やってしまう。

前半のコンテンツの入手は http やそれ以外の分岐、 http だった場合は proxy の解決、socket の接続、 redirect の解決, cookie の解決、 login などの authentication の解決がる。 この関数内を goto でぐるぐる回る場合がある。

無事 http などが解決されて中身が手に入った場合は、content-type などから html であることを決定して html のパースが走る。 次の loadHTMLBuffer です。

parse

loadHTMLBuffer が起点となる。

Buffer *loadHTMLBuffer(URLFile *f, Buffer *newBuf);
utf-8 のマルチバイト処理必要
file.c HTMLlineproc2body html parser の文字送り
	    else if (*str != '<' && *str != '&') {
#ifdef USE_M17N
int len = get_mclen(str);
#endif
PPUSH(mode | effect | ex_efct(ex_effect), *(str++));
#ifdef USE_M17N
if (--len) {
mode = (mode & ~PC_WCHAR1) | PC_WCHAR2;
while (len--) {
PSIZE;
PPUSH(mode | effect | ex_efct(ex_effect), *(str++));
}
}
#endif

Line

行に文字列をつめこむ。 先頭から積算することで、カラム位置を計算する。

#define addnewline(a, b, c, d, e, f, g) _addnewline(a, b, c, e, f, g)
void addnewline(Buffer *buf, char *line, Lineprop *prop, Linecolor *color,
int pos, int width, int nlines);
typedef struct _Line {
char *lineBuf;
Lineprop *propBuf;
} Line;

// たとえば `あ` `か`

lineBuf => 0xe3 0x81 0x82 0xe3 0x81 0x8b // utf-8 1文字3byte
propBuf => 0 0 0 0 0 0 // utf-8 byte 毎の装飾
// (standout, underline, bold...etc)
width => 0 0 0 2 2 2 // カラム位置

3byte 進む毎に、1文字進み、2column進む!

Buffer を 描画する

第二段階の処理。 Buffer にためこんだ Line を escape sequence で装飾して TERM に出力する。

display

各行を出力する。

  • redrawLine
  • addChar, addMChar

全部終わったら、カーソル位置の Anchor をハイライトして再描画する。

  • redrawLineRegion

こっちの関数で描画ずれが起こって難航。

terms

1文字 = 1byte = 1column でなくなるため以下の関数が変化する。

  • terms:Screen
  • terms:addch & addmch
  • terms:refresh
  • terms:need_refresh

Screen は Line と違って、 column に対して index アクセスができる。 また、横方向のスクロールを解決済み。

terms: addmch

Screen に Utf8バイト列を追加する(1code point)。

  • 1code point 2カラム消費する場合がある。2カラムめに C_WCHAR2 フラグをセットすることでスキップする。忘れると半角スペースが出現したりして乱れる。
  • 既存の C_WCHAR2 上に上書きになる場合がある。遡って削除する必要あり

terms: refresh

Screen を stdout(ttyf) に出力する。

  for (line = 0; line <= LASTLINE; line++) {
// 各行
for (; col < COLS; col++) {
// 各列
}
}

いちおう utf-8 が貫通した

まだカーソルを動かすと描画がずれたりするけど、 以下は同じ処理で表示できた。

  • google search の ISO-8859-1 に unicode escape されるもの
  • content-type: utf-8

以下は表示できなかった。

  • content-type: Shift_JIS

それはそう。 google の response がどういう基準で文字コードを変えているのかわからない。 Request-Header のどれかだとは思うのだが…