Ubuntu 11.10カスタマイズ関連の覚え書き

Ubuntu 11.10をインストールしたのだけど、気に入らないところがあったのでカスタマイズしてみた。

GUIシェルをgnome-shellにする。

個人的にUnityは好きになれないので、従来のgnome-shellにする。
端末を開いて以下のコマンドを実行。まず、apt-get update/upgradeで最新の状態にする。

sudo apt-get update
sudo apt-get upgrade
sudo apt-get install gnome-tweak-tool

ubuntu-tweakをインストールすれば、芋づる式にgnomeまでインストールされる。
一旦ログアウトし、ログイン画面で歯車のアイコンをクリックすると一覧に"gnome"があるので選択。ログインすればUnityに変わってgnomeがシェルになる。

デフォルトのテキストエディタvimにする。

ドットファイルをダブルクリックするとgeditが立ち上がるのが気に入らないので、これをgvimにする。
端末を開いて以下のコマンドを実行。

sudo apt-get install vim-gnome
sudo gvim /usr/share/applications/defaults.list 

vimで開いたファイルのtext/plain行の値をgvimにする。

text/plain=gvim.desktop

一旦ログアウトして、再度ログインすれば設定が反映される。
~/.local/share/applications/mimeapps.listがユーザーごとの設定ファイルみたいだけどうまくいかなかった。全体に影響がある部分を修正したくなかったけど、自分用の仮想マシンだから気にしない。

Webセミナー「アンドキュメンテッド(?) VCL 〜逆引きVCL新機能〜」自己フォロー

QAで指摘があった件を試してみました。

TListViewのグルーピングがうまくいかなかった件

本当は、こんな感じに表示されるはずでした。
テストは、64bit版のWindows 7でテーマ有効。実機はWindows 7の32bit版。この辺の差異かな…。

TDirectory.GetFilesでファイル属性を取得する

TDirectory.GetFilesはファイル名だけかと思いきや、無名メソッドを使用するバージョンで属性とか取れるという指摘があったので試してみました。
結果をフィルタリングするために使われる TFilterPredicate オプションがあって、そこで属性を取得。
Delphiのサンプルはこんな感じ。

procedure TForm1.Button1Click(Sender: TObject);
var
  Dir : String;
  Root: WideString;
  Files: TStringDynArray;
  FilterPredicate: TDirectory.TFilterPredicate;
begin
  Dir := GetMyDocumentsPath(CSIDL_PERSONAL);
  if SelectDirectory('フォルダを選択してください。', Root, Dir, [sdNewUI]) then
    Edit1.Text := Dir;

  with Memo1 do begin
    Clear;
    Lines.BeginUpdate;
    // ファイルを検索
    Files := TDirectory.GetFiles(Edit1.Text, '*.pas', TSearchOption.soAllDirectories,
        function(const Path: string; const SearchRec: TSearchRec): Boolean
        begin
            Lines.Add(Format('Path = %s Size = %d', [Path + SearchRec.Name, SearchRec.Size]));
            Result := true;
        end
    );
    Lines.EndUpdate;
  end;
end;

引数に無名メソッドを渡し、その中でファイルの属性を取得する。

C++Builderの場合は無名メソッドコンパイラがサポートしていないので、TCppInterfacedObjectを継承したクラスで判定する。(参考:http://www.gesource.jp/weblog/?p=4509

class Filter : public TCppInterfacedObject<TDirectory::TFilterPredicate>
{
public:
  bool __fastcall Invoke(const System::UnicodeString Path, const Sysutils::TSearchRec &SearchRec)
  {
    UnicodeString s = Format("Path = %s Size = %d", ARRAYOFCONST((Path + SearchRec.Name, SearchRec.Size)));
    Form1->Memo1->Lines->Append(s);
    return true;
  }
};

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  wchar_t DirPath[MAX_PATH];
  ::SecureZeroMemory(DirPath, sizeof(DirPath));
  ::SHGetFolderPath(0, CSIDL_PERSONAL, 0, 0, DirPath);
  UnicodeString Dir(DirPath);

  if (::SelectDirectory(L"フォルダを選択してください。", "//", Dir, TSelectDirExtOpts() << sdNewUI)) {
    Edit1->Text = Dir;
    Memo1->Clear();
    Memo1->Lines->BeginUpdate();
    // ファイルを検索
    Filter* filter = new Filter();
    TDirectory::GetFiles(Edit1->Text, "*.cpp", TSearchOption::soAllDirectories, filter);
    // delete filter; // deleteは不要
    Memo1->Lines->EndUpdate();
  }
}

フィルタリングを行うクラスのインスタンスはnewで初期化する必要があるが、明示的にdeleteする必要が無い。

ちなみに、C++11のラムダ式*1C++Builderに実装されたら、こんな感じになるのかな…。

    TDirectory::GetFiles(Edit1->Text, "*.cpp", TSearchOption::soAllDirectories, 
      [this](const System::UnicodeString Path, const Sysutils::TSearchRec &SearchRec)
      {
        UnicodeString s = Format("Path = %s Size = %d", ARRAYOFCONST((Path + SearchRec.Name, SearchRec.Size)));
        Memo1->Lines->Append(s);
        return true;
      });

ああ、滅茶苦茶便利。

*1:C++Builder XE3(?)でC++11のラムダ式サポートまだぁ?(AA略

第20回エンバカデロ デベロッパーキャンプで喋れなくなりました。

明日のセッションA4「アンドキュメンテッド(?) VCL 〜逆引きVCL新機能〜」は自分の諸事情により急遽講演中止となりました。
セッションを申し込まれた方、大変申し訳ありません。

明日の分は、後日Webセミナーとして実施する予定です。

RAD Studio XEとF-Secure Internet Security 2011の相性問題

メインマシンのセキュリティソフトをウイルスバスターからエフセキュア インターネット セキュリティ 2011に乗り換えたのだけど、RAD Studio XEを起動すると「使用許諾コードが不正」と判断されてRAD Studioが起動しなかった
これは、エフセキュア インターネット セキュリティのディープガードに由来するもので、以下の手順でBDS.EXEをディープガードの検索対象から外せばOK。

  1. F-Secure Internet Security 2011を開く
  2. [コンピュータ|ウイルスとスパイウェア スキャン]を選択
  3. [除外したオブジェクトを表示]をクリック
  4. [オブジェクト]タブを選択
  5. [追加]をクリックして、"C:\Program Files (x86)\Embarcadero\RAD Studio\8.0\bin\bds.exe"を選択
  6. [OK]をクリック
  7. [OK]をクリック
  8. [閉じる]をクリック

以上でRAD Studioが検索対象から外れるので、RAD Studioが問題なく実行される。

C++BuilderではOpen Tools APIを使ったアドオンをデバッグできない件についての回避方法

C++BuilderではOpen Tools APIを使ったアドオンをデバッグできない件があり、これをQC#92188として登録したのだけど、Embarcaderoから回答があって一応の解決法が見つかりました。

以下の手順でアドオンのデバッグが可能。

  1. OTAを使ったプロジェクトをC++Builderで作成する。
  2. プロジェクトをビルドして、アドオンをインストールする。
  3. 一旦IDEを終了する。
  4. もう一度、IDEを起動してOTAを使ったプロジェクトを読み込む。
  5. ブレークポイントを設定する。
  6. プロジェクトを読み込んだIDEとは別のIDEを起動する。この段階であとから起動したIDEでもアドオンは有効になっている。
  7. プロジェクトを読み込んだIDEで、[実行|プロセスにアタッチ]を選択し、あとから起動したIDEのプロセスにデバッガをアタッチする。
  8. アタッチしたIDEでアドオンを実行する。

いわゆる「運用で回避」と言えなくはないけど、Delphiと比べて少々面倒なのは事実。
C++Builderでのアドオン作成は諦めていたから、朗報と言えば朗報。

Universal Character Set Detector C LibraryをDelphi XEから使用する

C++Builderで試したMozillaエンコーディング自動判別ライブラリである「universalchardet」をDLL化したのをDelphiで動作させてみました。バイナリはhttp://a7m.sakura.ne.jp/SOURCE/universalchardet-CB.7zに用意したもので、C++Builder XE(BCC32.EXE 6.31)でコンパイル

Delphiでuniversalchardet.dllを使うためには、DLLの宣言を記述したユニットを作成しなければならない。

unit universalchardet;

interface

type
  chardet_t = Pointer;

const
  CHARDET_RESULT_OK = 0;
  CHARDET_RESULT_NOMEMORY = -1;
  CHARDET_RESULT_INVALID_DETECTOR = -2;
  CHARDET_MAX_ENCODING_NAME = 64;

  CHARDET_ENCODING_ISO_2022_JP = 'ISO-2022-JP';
  CHARDET_ENCODING_ISO_2022_CN = 'ISO-2022-CN';
  CHARDET_ENCODING_ISO_2022_KR = 'ISO-2022-KR';
  CHARDET_ENCODING_ISO_8859_5 = 'ISO-8859-5';
  CHARDET_ENCODING_ISO_8859_7 = 'ISO-8859-7';
  CHARDET_ENCODING_ISO_8859_8 = 'ISO-8859-8';
  CHARDET_ENCODING_BIG5 = 'BIG5';
  CHARDET_ENCODING_GB18030 = 'GB18030';
  CHARDET_ENCODING_EUC_JP = 'EUC-JP';
  CHARDET_ENCODING_EUC_KR = 'EUC-KR';
  CHARDET_ENCODING_EUC_TW = 'EUC-TW';
  CHARDET_ENCODING_SHIFT_JIS = 'SHIFT_JIS';
  CHARDET_ENCODING_IBM855 = 'IBM855';
  CHARDET_ENCODING_IBM866 = 'IBM866';
  CHARDET_ENCODING_KOI8_R = 'KOI8-R';
  CHARDET_ENCODING_MACCYRILLIC = 'MACCYRILLIC';
  CHARDET_ENCODING_WINDOWS_1251 = 'WINDOWS-1251';
  CHARDET_ENCODING_WINDOWS_1252 = 'WINDOWS-1252';
  CHARDET_ENCODING_WINDOWS_1253 = 'WINDOWS-1253';
  CHARDET_ENCODING_WINDOWS_1255 = 'WINDOWS-1255';
  CHARDET_ENCODING_UTF_8 = 'UTF-8';
  CHARDET_ENCODING_UTF_16BE = 'UTF-16BE';
  CHARDET_ENCODING_UTF_16LE = 'UTF-16LE';
  CHARDET_ENCODING_UTF_32BE = 'UTF-32BE';
  CHARDET_ENCODING_UTF_32LE = 'UTF-32LE';
  CHARDET_ENCODING_HZ_GB_2312 = 'HZ-GB-2312';
  CHARDET_ENCODING_X_ISO_10646_UCS_4_3412 = 'X-ISO-10646-UCS-4-3412';
  CHARDET_ENCODING_X_ISO_10646_UCS_4_2143 = 'X-ISO-10646-UCS-4-2143';

  // Unused
  CHARDET_ENCODING_ISO_8859_2 = 'ISO-8859-2';
  CHARDET_ENCODING_WINDOWS_1250 = 'WINDOWS-1250';
  CHARDET_ENCODING_TIS_620 = 'TIS-620';

function chardet_create(var pdet: chardet_t): integer; stdcall;
  external 'universalchardet.dll' name '_chardet_create';

procedure chardet_destroy(det: chardet_t); stdcall;
  external 'universalchardet.dll' name '_chardet_destroy';

function chardet_handle_data(det: chardet_t; const data: PAnsiChar;
  len: Cardinal): integer; stdcall;
  external 'universalchardet.dll' name '_chardet_handle_data';

function chardet_data_end(det: chardet_t): integer; stdcall;
  external 'universalchardet.dll' name '_chardet_data_end';

function chardet_reset(det: chardet_t): integer; stdcall;
  external 'universalchardet.dll' name '_chardet_reset';

function chardet_get_charset(det: chardet_t; namebuf: PAnsiChar;
  buflen: Cardinal): integer; stdcall;
  external 'universalchardet.dll' name '_chardet_get_charset';

implementation

end.

このファイルをuniversalchardet.pasとして保存する。
実際に使用する場合は、users節にuniversalchardetを追加する。サンプルコードは以下の通り。

procedure TForm1.Button1Click(Sender: TObject);
var
  ms: TMemoryStream;
  enc: TEncoding;
  encname: array[0..CHARDET_MAX_ENCODING_NAME] of AnsiChar;
  det: chardet_t;
  res: Integer;
begin
  ms := TMemoryStream.Create;
  // ファイルのロード
  ms.LoadFromFile(filename);
  // オフセットをストリームの先頭に
  ms.Position := 0;

  // エンコーディングの判別をする
  det := nil;
  chardet_create(det);
  res := chardet_handle_data(det, ms.Memory, ms.Size);
  chardet_data_end(det);

  // エンコーディング名の取得
  chardet_get_charset(det, encname, CHARDET_MAX_ENCODING_NAME);
  chardet_destroy(det);

  // 自動判別結果を元にエンコーディングを判別して読み込み
  enc := nil;
  try
    enc := TEncoding.GetEncoding(encname);
  except
    on EEncodingError do
      enc := TEncoding.Default;
  end;

  Memo1.Lines.LoadFromStream(ms, enc);
  ms.Free;
end;

7月21日のウェブセミナーと、第20回エンバカデロ デベロッパーキャンプで喋ります。

7/21のオンラインセミナーは、13/14回デベロッパーキャンプでやったポインタというかメモリ管理ネタの再演。
このネタの評判がいいとの話しでオファーがあったのでオンラインセミナーとして再演します。

9/6の第20回デベロッパーキャンプは「アンドキュメンテッド(?)VCL」と称して、残念ながらドキュメントが整備されていないVCLのクラスやコンポーネントについての使用法。BDS2006以降の新機能が中心。
一応、逆引き形式なので、何かリクエストがあれば、アンドキュメンテッドなもので無くても、自分が判る範囲で対応します。
リクエストはこの記事のコメントか、Twitterの#dcamp_jpのハッシュタグでつぶやいてください。

7/26 追記:

Q&Aで、おすすめの本は?と言うのがあったので、追記。
とりあえず、こんなものかな?

Debug Hacks -デバッグを極めるテクニック&ツール

Debug Hacks -デバッグを極めるテクニック&ツール

Binary Hacks ―ハッカー秘伝のテクニック100選

Binary Hacks ―ハッカー秘伝のテクニック100選

Linkers & Loaders

Linkers & Loaders

Boost C++ Librariesプログラミング第2版

Boost C++ Librariesプログラミング第2版

Boost C++をチューンアップする最先端ライブラリ

Boost C++をチューンアップする最先端ライブラリ

  • 作者: ビョルン・カールソン,村上雅章
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2008/10/07
  • メディア: 単行本(ソフトカバー)
  • 購入: 9人 クリック: 61回
  • この商品を含むブログ (22件) を見る