自動リンク

面倒なので、実際に使っているソースを載せます。解説はそのうち書きます。

このソースで、http, telnet, ftp はもちろん、 info, man, wais, ldap, ... いろんなスキームに対応です。足りなきゃ (chromeとかを追加したければ) scheme_types[] に追加して、scheme_types_count の値をインクリメントしておくように。

ちなみに、こっちのページで説明している isuric() 関数が必要です。

static const char* scheme_types[] = {
    "http", "https", "ftp", "mailto", "news", "shttp", "telnet",
    "file", "gopher", "man", "info", "wais", "ldap", "ntds", "whatis"    // and more...
};

// obsoleted code.
// #define scheme_types_count 15

bool scheme_check(const char* src, const char* cmp, int len)
{
    for (register int i=0; i<len; i++)
        if (src[i] != cmp[i])
            return false;
    return true;
}

unsigned int find_scheme(const std::string& source, unsigned int begin_pos)
{
    const char* src = source.c_str();
    unsigned int slen = source.length();

    for (unsigned int xpos = begin_pos; xpos < slen; xpos++) {
        if (src[xpos] == ':'
            && isuric(src[xpos + 1])
        ) {
            for (unsigned int i=3; i<=6; i++) {
                if (xpos < i)
                    continue;
                for (int j=0; j<sizeof(scheme_types)/sizeof(static const char *); j++) {
                    if (scheme_check(&src[xpos-i], scheme_types[j], i))
                        return xpos - i;
                }
            }
        }
    }
    return -1;
}

std::string html_anchor(const std::string& source)
{
    std::string result = source;
    unsigned int begin_pos = 0;

    while ((begin_pos = find_scheme(result, begin_pos)) != -1) {
        unsigned int end_pos = begin_pos;
        while (end_pos < result.length() && isuric(result[end_pos]))
            end_pos++;
        std::string url = result.substr(begin_pos, end_pos - begin_pos);
        result.erase(begin_pos, url.length());
        url = "<a href=\"" + url + "\" target=\"_top\">" + url + "</a>";
        result.insert(begin_pos, url);
        begin_pos += url.length();
    }
    return result;
}

簡単に説明すると、すべての URI に共通な文字 ':' を探し、その前がスキームのリストにあり、かつその直後の文字が uri 文字 であるか、を確認し、isuric() が成立する範囲を URI として認識し、そこにアンカー ( <a href=...> タグ) を追加している。