文字化けを解消するかもしれない Latin1toUtf8

Yahoo! WidgetsGoogle Calendar モジュールだと日本語が化けすぎ。
何と間違ってるんだろう、と調べてみたところ、Google Calendar から送られてくるデータはutf-8 なのに、それを Latin1であると解釈して、ユニコードに変換しているっぽい。Latin1の7ビット範囲内はUTF-8と互換なのだが、8ビット範囲の文字は変換が必要なのだ。そこで、それを元に戻す関数を作ってみた。

// Latin1 -> utf8 変換表 0 の部分があるけど大丈夫かな…
Latin1_ary = [8364,0,8218,402,8222,8230,8224,8225,710,8240,352,8249,338,0,381,0,0,8216,8217,8220,8221,8226,8211,8212,732,8482,353,8250,339,0,382,376]
latin1=String.fromCharCode.apply(String,Latin1_ary);

// 問題のあるところだけ取り出す正規表現
Latin1_reg = [];for(var i=0;i<Latin1_ary.length; i++){ if(Latin1_ary[i]!=0) Latin1_reg.push(Latin1_ary[i]) };Latin1_reg = new RegExp( "["+String.fromCharCode.apply(String,Latin1_reg)+"]", "g" );

// 変換の必要のあるところだけ変換
function unLatin1(str){
  return str.replace( Latin1_reg,function(m){
    var i=latin1.indexOf(m[0]);
    if(i!=-1)c=i+128;
    return String.fromCharCode(c);
  } );
}

// UTF-8 な文字を取り出す正規表現
Utf8_reg = /[\xc2-\xdf][\x80-\xbf]|\xe0[\xa0-\xbf][\x80-\xbf]|[\xe1-\xef][\x80-\xbf][\x80-\xbf]|\xf0[\x90-\xbf][\x80-\xbf][\x80-\xbf]|[\xf1-\xf3][\x80-\xbf][\x80-\xbf][\x80-\xbf]|\xf4[\x80-\x8f][\x80-\xbf][\x80-\xbf]/g
// UTF-8 から文字列に変換
function Utf8ToString(str){
  return str.replace( Utf8_reg, function(s){
    var c = s.charCodeAt(0);
    if((c > 191) && (c < 224)) {
      return String.fromCharCode(((c & 31) << 6) | (s.charCodeAt(1) & 63));
    } else {
      return String.fromCharCode(((c & 15) << 12) | ((s.charCodeAt(1) & 63) << 6) | (s.charCodeAt(2) & 63));
    }
  });
}

function Latin1toUtf8(str){ return Utf8ToString(unLatin1(str))}

で、Google Calendar Widget
http://widgets.yahoo.com/gallery/?search=google+calendar&x=0&y=0
ちなみに最近のYahoo! Widgets はzipではなく独自形式っぽいので、
http://widgets.yahoo.com/workshop/
WIDGET COVERTER で解凍してやる必要がある。解凍したらHTTP通信からデータを取り出している部分を変更してやる

// common.js の 400行目付近
			for(i in url){
				responses[i] = Latin1toUtf8(url[i].responseData).split('\n');
			}
			preferences.number.value = num;
			organizeData();			
		} else {
			print("splitting data");
			for(i in url){
				responses[i] = Latin1toUtf8(url[i].responseData).split('\n');
			}

ちゃんと見えたよママン!