VimのソースコードをVimで解析しよう(Part1-2)

(Part1-1)からの続きです。
(お知らせ) コマンドラインモードのエンターキー押下の表記を省略せずに [Enter] で表すようにします。

カーソル描画処理を探す

NO PLANっす。とりあえず cursor でgrepしてみましょう。

" 「cursor」をgrep
:grep cursor .[Enter]
" (grepが終わってから)
" カレントウィンドウを次ウィンドウ(==Quickfixウィンドウ)に移動。
<C-W><C-W>
" Quickfixウィンドウの高さを可能な限り最大化
<C-W>_
" ウィンドウを1ページ前方(↓)スクロール
<C-F>
" 〜しばしgrep結果と戯れる(時おり <C-F> 押しながら)〜

戯れて感じたこと

  • CUIのカーソル処理の話なのでおそらく gui*.c とか関係ないはず。
  • カーソル下の文字によってカーソル幅とか変わるからマルチバイト(mbyte.c)は関係するよなぁ。
  • ml_get_cursor()はカーソル位置の文字取得する関数かぁ。
  • curwin->w_cursor.lnum とか wp->w_cursor.lnum がカーソル行番号か?
    (curwinは多分カレントウィンドウの情報だろう)
  • setcursor()ってもろそれっぽい関数がある!

まずは curwin と w_cursor の定義を見てみましょう。

" QuickFixウィンドウを閉じる
:ccl[Enter]
" 「curwin」でタグジャンプ。(タグが複数あった時だけリスト表示)
:tj curwin[Enter]


タグが複数あったのでリスト表示になりました。
1つ目はkindがv(外部変数)だしファイル名がそれっぽい!
2つ目はkindがm(構造体等のメンバ変数)ですし、ファイル名がTclインターフェイス関連っぽいのでどう考えても1つ目が正解です。
ちなみにkindの文字の意味はタグファイルからの情報なので、ctagsで確認できます。

" リスト表示をキャンセル
[Enter]
" 外部プログラムを実行(ctagsでC言語のタグ種別を一覧表示)
:!ctags --list-kinds=c[Enter]

以下のように表示されます。(exuberant ctags 5.8 / 5.8J2の場合)

c  classes
d  macro definitions
e  enumerators (values inside an enumeration)
f  function definitions
g  enumeration names
l  local variables [off]
m  class, struct, and union members
n  namespaces
p  function prototypes [off]
s  structure names
t  typedefs
u  union names
v  variable definitions
x  external and forward variable declarations [off]

続けるにはENTERを押すかコマンドを入力してください

本題に戻ってリスト表示で 1 を選択しましょう。

" 2つ前のコマンドライン履歴(:tj curwin)を呼び出して実行。
:<C-P><C-P>[Enter]
" リスト表示で1つ目を選択
1[Enter]


ダイブ!!

" 前方(→)にword移動
w
" カーソル下のキーワード(win_T)でタグジャンプ。(Part1-1の下準備参照)
<C-]>
" 前方(→)に2word移動
ww
" カーソル下のキーワード(window_S)でタグジャンプ。
<C-]>
" ウィンドウを1ページ前方(↓)スクロール
<C-F>
" カーソルを2パラグラフ前方(↓)移動
}}
" カーソルを1行下の最初の非空白文字に移動
<CR>
" カーソル下のキーワード(pos_T)でタグジャンプ。
<C-]>


ん?コメントに position in file or buffer 。。ファイルかバッファ内の位置??
(カレントウィンドウにアサインされている)バッファ内の位置ということは、バッファ内のどこに注目しているかという情報であって画面上の「カーソル」を描画する位置ではないですね。
でも画面描画する時はこの情報を使うはず!深追いは止めて次いきましょう。
次は setcursor() をチェック!

" 「setcursor」でタグジャンプ。(Tabキーを押して補完)
:tj setcu<Tab>[Enter]
" カーソルを4行下へ移動
jjjj
" カーソル下(右側)のキーワード(validate_cursor)でタグジャンプ。
<C-]>
" カーソルを2行下の最初の非空白文字に移動
<CR><CR>
" カーソル下(右側)のキーワード(check_cursor_moved)でタグジャンプ。
<C-]>


引数はcurwinが渡されていますから wp は curwin です。ということはさきほどの curwin->w_cursor を参照してますね。
比較相手の w_valid_cursor の定義を見にいくと cached values とコメントに書いてます。w_cursor が キャッシュ値(w_valid_cursor) と異なる場合は、w_valid の各種フラグを落として、キャッシュ値(w_valid_cursor)を更新しています。

" タグジャンプを1つ遡る。(validate_cursorの関数定義部分へ)
<C-T>

w_valid の VALID_WCOL か VALID_WROW のフラグが落ちている場合は curs_columns() でもろもろ更新しています。

" タグジャンプを1つ遡る。(setcursorの関数定義部分へ)
<C-T>
" ウィンドウのバッファを下へ6行スクロールする。
6<C-E>


windgoto()は定義部分のコメントを見る限り、画面上の「カーソル」を描画する関数です。それも踏まえて考えると curwin->w_wrow と curwin->w_wcol は、カレントウィンドウ上のカーソル位置(行、列)でしょう。
あと気になるのはカーソル描画処理の実行/非実行を redrawing() で制御しているというところでしょうか。

調査結果まとめ

カーソル位置による相対行番号の描画データ設定処理は win_line() [screen.c : 3482]
カーソル描画処理は setcursor() [screen.c : 8644]


今回はここまで。
次回はデバッガで追いかけてみましょう。よろしくどうぞ。
(Part1-3)へ