デザインいじり

以前さくらさんとこでも緑と葉っぱというイメージでデザインしていたので、とりあえずhatena-leafをテーマに選んだわけだけども。こいつ幅狭いしpre要素で幅を超過するとサイドバーの流し込みが失敗するしでちょっと扱いにくかったので、ちょこちょことcssいじって俺好みの表示に。

幅を変えるのにけっこう苦戦したんだけども、実際に生成されるソースとhatena-leafテーマで使用されてるcssファイルを直読み・解析してカスケード的に記述(ぉ。bodyから続くページ上部のtableだとかh1だとかの幅がpx決め打ちだったから簡単に変えられなかったようで。

後は未訪問リンクを山吹色に変えたり、em・strong要素の表示を設定したり、ブロックや文字要素を相対指定にしたり、サイドバーとメイン部分の位置を逆にしたり。cssいじってるとやっぱ楽しいね。デザインのセンスとか皆無なのに色々凝っちゃったりしてね。表示確かめるためにわざわざFirefoxいれたりして(普段はSleipnir)。

そして寝られないからといってcssいじりを2時間もやってるのはどうかと思ったorz

boost::filesystemとワイド文字

boost::filesystemでまたも引っかかる点が。端的に言ってしまえばboost::filesystemではワイド文字を扱えない、ってことなんだけどその説明がFAQに以下のように載っていたので引用。

Wide-character names would provide an illusion of portability where portability does not in fact exist. Behavior would be completely different on operating systems (Windows, for example) that support wide-character names, than on systems which don't (POSIX). Providing functionality that appears to provide portability but in fact delivers only implementation-defined behavior is highly undesirable. Programs would not even be portable between library implementations on the same operating system, let alone portable to different operating systems.

Boost Filesystem FAQ

要はワイド文字の扱いは処理系依存、しかも同じ処理系でも実装によって扱われ方がまた異なる。だから怖くて使えない、ってことらしいんだけど。illusion of portabilityねぇ…。漢字圏の人たちからすればかなり切実な問題なんだけど。そういえばid3libも便利そうだと思って調べてみたらUnicode関係が腐っててダメだった思い出が(今どうなんだろう?)。

で、とりあえず直面したのは0x5c問題だけなんだけど、どうすっかなー。考えられる対応としては

  1. ワイド文字/ダメ文字を使わないようにする。
  2. boost::filesystemが日本語に対応するまで使わない。
  3. Windows系のみで使うと決め打ちしてこれを試す
  4. 自前でパッチ当てる

くらいか?パッチ以外はどうやっても縛りが出てくるなぁ…。パッチも非処理系依存のコードを一人で書くのは無理だろうしなぁ。

つーわけでまた放置。

boost::filesystemとワイド文字 その2

以前boost::filesystemがどんな挙動をするか試すために、ディレクトリを再帰的に探査していってディレクトリ・ファイル名を表示するというプログラムを書いたんだが、それが0x5c問題をスルーしていることに気付いた。ソースは以下。

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <iostream>

namespace fs = boost::filesystem;

// 再帰的にディレクトリを表示する
// nest_countは表示上、スペースを打つ回数にしか使ってない
bool print_directory_recursive
  (const fs::path & path_name, unsigned nest_count = 0)
{
  // 存在しないパス渡されたら失敗
  if(fs::exists(path_name) != true) return false;

  // 渡されたパスがディレクトリだった場合
  if(fs::is_directory(path_name) == true)
  {
    fs::directory_iterator end;
    for(fs::directory_iterator ite(path_name) ; ite!=end ; ++ite)
    {
      // ディレクトリであった場合再帰的に関数適用
      if(fs::is_directory(*ite) == true)
      {
        std::cout << "d";
        for(int i=0 ; i<nest_count+1 ; ++i) std::cout << "  ";
        std::cout << ite->leaf() << std::endl;
        print_directory_recursive(*ite, nest_count+1);
      }
      // ファイルなら表示
      else
      {
        std::cout << "f";
        for(int i=0 ; i<nest_count+1 ; ++i) std::cout << "  ";
        std::cout << ite->leaf() << std::endl;
      }
    }
  }
  // ファイルだった場合表示する
  else
  {
    std::cout << "f";
    for(int i=0 ; i<nest_count+1 ; ++i) std::cout << "  ";
    std::cout << path_name.leaf() << std::endl;
  }

  return true;
}

int main(int argc, char *argv[])
{
  // カレントディレクトリ取得
  fs::path current_path(fs::initial_path());

  // 何も指定されなかったらカレントディレクトリ以下を表示する
  if(argc < 2) print_directory_recursive(current_path);
  else print_directory_recursive(fs::path(argv[1], fs::native));

  return 0;
}

コンパイルしてファイル名にダメ文字を使ったディレクトリを指定して実行すると何故かきちんと表示される(Windows2000 with VC++6.0)。いったんboost::filesystem::pathオブジェクトにパス名が格納されてるはずなので(さらに言えば表示するときにleaf()メンバ関数を使っているのでダメ文字を使った場合その部分でファイル名がちょん切られるハズ)、ダメだと思うんだけど…。

directory_iterator経由だと大丈夫だとかなんかそういうのがあるんだろうか?