描画の流れとデータ構造
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);:::warning utf-8 のマルチバイト処理必要
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
unknown: textDirective => {"type":"textDirective","name":"Screen","attributes":{},"children":[],"position":{"start":{"line":120,"column":8,"offset":2149},"end":{"line":120,"column":15,"offset":2156}}}terms
unknown: textDirective => {"type":"textDirective","name":"addch","attributes":{},"children":[],"position":{"start":{"line":121,"column":8,"offset":2164},"end":{"line":121,"column":14,"offset":2170}}}& addmchterms
unknown: textDirective => {"type":"textDirective","name":"refresh","attributes":{},"children":[],"position":{"start":{"line":122,"column":8,"offset":2187},"end":{"line":122,"column":16,"offset":2195}}}terms
unknown: textDirective => {"type":"textDirective","name":"need_refresh","attributes":{},"children":[],"position":{"start":{"line":123,"column":8,"offset":2203},"end":{"line":123,"column":21,"offset":2216}}}
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 のどれかだとは思うのだが…