[Rainmeter-dev] TwitterのTLが文字化けする
2010.08.17 | Rainmeter-dev // Issue/互換性問題やバグ修正
21 CommentsTwitterでRainmeterについて検索してみると、TwitterのTLを表示させると文字化けするっていうつぶやきがちらほらと見受けられます。
RainmeterでTwitterのタイムラインを取得すると、「はじめまして!」のような文字列が表示されてしまいますが、これは数値文字参照と言って、文字を10進数または16進数文字列で表しています(これは「はじめまして!」を表す)。本来は表示前に元の文字へと戻してやる必要があり、ブラウザなどではその処理をしてから表示していますが、RainmeterのWebParserにはその処理が入っていません(英語圏では変換して使うような文字があまりなく、そう問題にならないので)。
この数値文字参照を元の文字に戻す処理を加えたWebParserを作ってみたので、下へ置いておきます。変なことはしてないので、1.0でも使えると思います。興味のある方は試してみてください。
Rainmeter 1.3にこの変更を取り込んだので、公開終了しました。
デフォルトでは有効化されませんので、スキン製作者側または使用者側で適宜設定を行ってください。
適用方法)
WebParserを使っているMeasureで、かつ"StringIndex="を設定してあるものに、"DecodeCharacterReference=1"を設定してください。
例)
[Feed1.mLink1]
Measure=Plugin
Plugin=Plugins\WebParser.dll
Url=[Feed1]
DecodeCharacterReference=1
StringIndex=2
設定値)
0 : なにもしない (デフォルト動作)
1 : 数値文字参照と実体参照の両方をデコードする
2 : 数値文字参照のみをデコードする
3 : 実体参照のみをデコードする
※Substituteの設定値によっては意図しない結果になることもありますので、適宜調整してください。
(例えば、結果の文字列からダブルクォーテーションを消すためにSubstitute=""":""を指定してあった場合、DecodeCharacterReferenceを定義することによって":は"に置き換えられてしまうため、消されずに残ってしまいます)
また、この件とは関係ありませんが、TwitterのBASIC認証が廃止されたために、TLが取得できなくなって困った方もおられると思います。これに関しては、GnometerがSuperTweetを介しての取得に対応していますので、そちらのコードを参考にしてみてください。
■更新履歴
2010.12.16 : 公開終了しました。
2010.08.17 : Rainmeter 1.3 beta r501 をベースに作成し直しました。処理も少しだけ変えているので、r320版と文字処理の動作が違っていたら教えてください。
続きはコード詳細。
正規表現を適用した後の文字列を結果として代入する前に、数値文字参照を元に戻す処理を挟みます。
std::wstring DecodeNCRs(std::wstring str)
{ std::wstring::size_type start = 0;
while ((start = str.find(L"&#", start)) != std::wstring::npos)
{ std::wstring::size_type end, pos;
if ((end = str.find(L';', start)) == std::wstring::npos) break;
pos = start + 2;
if (pos == end) // &#;
{ start = end + 1;
continue; }
int base; if (str[pos] == L'x' || str[pos] == L'X')
{ if (++pos == end) // &#x; or &#X;
{ start = end + 1;
continue; }
base = 16;
}
else { base = 10;
}
std::wstring num(str, pos, end - pos);
WCHAR* pch = NULL;
errno = 0;
long ch = wcstol(num.c_str(), &pch, base); if (pch == NULL || *pch != L'\0' || errno == ERANGE || ch <= 0 || ch > 0xFFFF) // invalid character
{ start = pos;
continue; }
str.replace(start, end - start + 1, 1, (WCHAR)ch);
start++;
}
return str; }
文字列中に"&#"が見つかったら、その後ろに"x"が付いていたら16進数値、付いていなければ10進数値が指定されているとして変換処理を行っています。想定外の値や文字列が続いていたら、変換処理は行いません。また、Unicode以外は考慮していません。
※ 文字列を切り出す部分とエラー処理を若干修正 (r501版)。
追記)
Rainmeter 1.3版のコードはこちら。
