メモ:put {*|+} の実装

レジスタ*のプットは :put * でできるので、まずは :ta ex_put を見てみる。
すぐに do_put() に飛んでいるので do_put にタグジャンプ。

#ifdef FEAT_CLIPBOARD
    /* Adjust register name for "unnamed" in 'clipboard'. */
    adjust_clip_reg(&regname);
    (void)may_get_selection(regname);
#endif

FEAT_CLIPBOARD は :h +clipboard に対応し、GUIクリップボード機能の有効・無効を意味する。
adjust_clip_reg()は以下の通り大したことはやっていない。

    void
adjust_clip_reg(rp)
    int		*rp;
{
    /* If no reg. specified, and "unnamed" is in 'clipboard', use '*' reg. */
	// レジスタが指定されておらず、オプション'clipboard'に"unnamed"が含まれているならば*を使う
    if (*rp == 0 && clip_unnamed)
	*rp = '*';
	// レジスタ*が使えないのに*が指定されたときは無名レジスタを使う
    if (!clip_star.available && *rp == '*')
	*rp = 0;
	// レジスタ+が使えないのに+が指定されたときは無名レジスタを使う
    if (!clip_plus.available && *rp == '+')
	*rp = 0;
}

may_get_selection(regname) はregname が*か+ならclip_get_selectionを呼んでセレクションの中身を取得する。
clip_get_selectionの中では現在vimがセレクションを取得しているかどうかを判定。
取得しているならカレントバッファからテキストをとってくる。
取得していないならclip_gen_request_selectionに入る。
この中でプラットフォームごとに場合分け。
ターミナルエミュレータ上で実行している場合は
clip_xterm_request_selection()→clip_x11_request_selection()ともぐっていく。
ここでいよいよXtの関数を呼ぶ。

    for (i =
#ifdef FEAT_MBYTE
	    0
#else
	    1
#endif
	    ; i < 5; i++)
    {
	switch (i)
	{
#ifdef FEAT_MBYTE
	    case 0:  type = vimenc_atom;	break;
#endif
	    case 1:  type = vim_atom;		break;
	    case 2:  type = compound_text_atom; break;
	    case 3:  type = text_atom;		break;
	    default: type = XA_STRING;
	}
	XtGetSelectionValue(myShell, cbd->sel_atom, type,
	    clip_x11_request_selection_cb, (XtPointer)&success, CurrentTime);

ループで回してswitchしているのは、それぞれのtypeで取得を試みて、成功したらreturn
しているため。
type の意味はここで決まっている:

    void
x11_setup_atoms(dpy)
    Display	*dpy;
{
    vim_atom	       = XInternAtom(dpy, VIM_ATOM_NAME,   False);		// vim の独自セレクションフォーマット
#ifdef FEAT_MBYTE
    vimenc_atom	       = XInternAtom(dpy, VIMENC_ATOM_NAME,False);		// vim の拡張セレクションフォーマット
#endif
    compound_text_atom = XInternAtom(dpy, "COMPOUND_TEXT", False);
    text_atom	       = XInternAtom(dpy, "TEXT",	   False);
    targets_atom       = XInternAtom(dpy, "TARGETS",       False);
    clip_star.sel_atom = XA_PRIMARY;
    clip_plus.sel_atom = XInternAtom(dpy, "CLIPBOARD",     False);
}

ただし gtk 使用の場合は gtk 用の値が入る。
さて、セレクション取得に成功するとコールバックclip_x11_request_selection_cbが呼ばれる。
_cb はコールバックを意味しているようだ。
セレクションのオーナーが firefox だったりした場合は当然 type は compound text であり、

	status = XmbTextPropertyToTextList(X_DISPLAY, &text_prop,
							 &text_list, &n_text);

で現在のロカールエンコーディングに変換されてレジスタのバッファにコピーしておしまい。