Vaucanson-gのタイプセット
症状
PC変えたら、vaucanson-g.sty (状態遷移図用)のタイプセットができなくなってました。って言うか、設定ファイルがごちゃごちゃだったので、うっかり整理したせいです。
環境
TeXLive2014+jsarticle+vaucanson-g+windows7+SumatraPDF+dviout+gnupack EMACS+msys64+...
ふつーにインストールして使っているだけです。
TeXコード(test.tex)
\documentclass[]{jsarticle} \usepackage{vaucanson-g} \begin{document} \begin{figure}[h] \center \begin{VCPicture}{(0,-2)(5.5,2)} \State[p]{(0,0)}{A} \State{(2.5,0)}{B} \State[r]{(5.5,0)}{C} \Initial{A} \Final{C} \EdgeL{A}{B}{a} \ArcL{B}{C}{b} \ArcL{C}{B}{b} \LoopN{A}{a} \LoopS{C}{d} \end{VCPicture} \caption{Vaucanson-gのテスト} \end{figure} \end{document}
国際化の事例
概要
wxWidgetsでgettextを使ってメッセージを国際化してみました。プラットフォームは VisualStudio Express 2012 (win7) です。
gettextはプログラムのメッセージを国際化するための仕組みです。ここで言うメッセージの国際化とは、ダイアログボタンの「Ok」や「Cancel」を、日本語実行環境で「はい」、「取り消し」などと表示することです。原理は、英語文字列をキーとした対訳辞書から日本語を取り出して表示するというものです。
国際化を考えたアプリではメッセージを英語で作成し、日本語はコード上に埋め込まないようにします(コメントは日本語でOk)。
サンプルソース(VisualStudioExpress2012) @gettext.zip
環境
抽出と対訳の編集
C++ソースコードからxgettext.exeを使ってキーリストを抽出し、messages.poを生成します。これに対訳を付加して、msgfmt.exeを使って、アプリ実行用のバイナリファイルmessages.moを作成します。
$ xgettext.exe --keyword='_' ../../MyApp.cpp ../../rcMyFrame.cpp (編集作業) $ msgfmt.exe messages.po
フォルダ構成と辞書のロード(初期化)の関係
詳細はソースコード MyApp.cpp のOnInit()を参照して下さい。
辞書引きの過程
ソースコードに埋め込まれたマクロ「_("msgid")」は、ビルド時にwxGetTranslation("msgid")関数として展開されます。関数内では、初期化時にロードされた辞書(messages.mo)から"msgid"を検索して、対訳の"msgstr"を取り出します。
サンプル開発のトピック
アプリケーション概観
サンプルはボタンが一つだけあるようなシンプルなフレームだけのアプリです。タイトルとボタンラベルが「_()」マクロでマークされています。ちなみにボタンを押しても何も起きません。
国際化をしない状態では、タイトルとボタンラベルの文字列は英語文字列になります。
GUI生成
GUIは、wxFormBuilderで作成しました。ボタンラベルの「MyButton」というのはwxFormBuilderが既定で自動で付けるラベルそのままです。
Code Generate(F8)ボタンでC++用のコードが生成されます。その際に注意すべきは、プロジェクトのプロパティで「internationalize」にチェックを入れておくことです。
これにより、生成されたコードで「_()」マクロが使用されます。自動で生成されたコード部分を見ると、ボタンラベルが「_("MyButton")」になっています(rcMyFrame.cpp)。
rcMyFrame::rcMyFrame( wxWindow* parent, wxWindowID id, const wxString& title , const wxPoint& pos, const wxSize& size, long style ) : wxFrame( parent, id, title, pos, size, style ) { this->SetSizeHints( wxDefaultSize, wxDefaultSize ); wxBoxSizer* bSizer1; bSizer1 = new wxBoxSizer( wxVERTICAL ); m_buttonMyButton = new wxButton( this,wxID_ANY , _("MyButton") // 翻訳対象としてマーク , wxDefaultPosition, wxDefaultSize, 0 ); bSizer1->Add( m_buttonMyButton, 0, wxALL, 5 ); this->SetSizer( bSizer1 ); this->Layout(); this->Centre( wxBOTH ); }
アプリ初期化(辞書のロード)
さて、国際化機能を使うためには言語環境に応じた辞書をアプリにロードしなければなりません。これは、アプリの初期化部分でおこないます(MyApp.cpp)。
bool MyApp::OnInit() { if ( !wxApp::OnInit() ) return false; wxLocale::AddCatalogLookupPathPrefix("catalogs"); //辞書のあるフォルダ名(ドメイン) wxLocale locale; locale.Init( wxLANGUAGE_JAPANESE, wxLOCALE_DONT_LOAD_DEFAULT ); // 日本語環境の指定 locale.AddCatalog("messages"); // 辞書の名前 locale.AddCatalog("wxstd"); // wxWidgets標準の辞書 // and create a top level window _MyFrame = new MyFrame( _("My Application") /*GetAppName()*/ ); // 翻訳対象としてマーク(手作業) _MyFrame->SetIcon( wxIcon("APPLICATION_ICO") ); // start process ... return _MyFrame->Show(true); }
wxLocale 関連の関数でドメイン名、辞書名、言語を指定します。ここでは、原理的な動作を明らかにする目的で、言語を陽に指定していますが、システム(OS)の既定言語を取得して設定すれば、環境に応じて自動的に言語が設定されるはずです。
タイトルバーに表示されるアプリケーション名は、通常ですとGetAppName()関数などで取得しますが、今回は「_("My Application")」で与えました。つまり、表示アプリ名も翻訳の対象にします。
辞書の作成
つぎに、ソースコードからキー「_()」を抽出します。抽出にはxgettext.exeを使います。作業はコンソール(cygwin)上で行います。
$ cd catalogs/ja $ xgettext.exe --keyword='_' ../../MyApp.cpp ../../rcMyFrame.cpp $ ls messages.po
抽出されたキーリストは messages.po というファイルに書き込まれます。「messages」というのは、xgettext.exe の既定の辞書名です。例ではドメイン名(catalogs)のフォルダと、その下に言語名(ja)のフォルダを作成し、そのフォルダで実行しました。
開発、実行環境のフォルダ構成
この段階でのフォルダ構成を見ておきます。
. ├── MyApp.h エントリーポイント定義ヘッダ ├── MyApp.cpp エントリーポイント定義コード ├── rcMyFrame.h wxFormBuilderが生成したGUI定義ヘッダ ├── rcMyFrame.cpp wxFormBuilderが生成したGUI定義コード ├── MyFrame.h GUI定義ヘッダ ├── MyFrame.cpp GUI定義コード ├── MyApp.fbp wxFormBuilderファイル ├── MyApp.rc リソースファイル ├── application.ico アプリケーションアイコンファイル ├── stdwx.h プリコンパイルヘッダ ├── stdwx.cpp プリコンパイルコード ├── catalogs ドメイン │ └── ja 言語 │ └── messages.po 翻訳テキスト形式(xgettextが生成) ├── MyApp.sln VisualStudioソリューションファイル ├── MyApp.vcxproj VisualStudioプロジェクトファイル ├── wx3.0.0ud-vs2012.props wxWidgets Unicode Debug プロパティファイル └── wx3.0.0u-vs2012.props wxWidgets Unicode Release プロパティファイル
辞書(po)の編集
messages.poを編集します。初期状態では次のようになっています。
# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2014-07-13 16:43+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: ../../MyApp.cpp:40 msgid "My Application" msgstr "" #: ../../rcMyFrame.cpp:21 msgid "MyButton" msgstr ""
辞書として最低限必要なものにするとつぎのようになります。
msgid "" msgstr "" "Content-Type: text/plain; charset=CHARSET\n" msgid "My Application" msgstr "" msgid "MyButton" msgstr ""
大分すっきりしました。msgidが辞書のキーで、msgstrがその値になります。各々の対訳をmsgstrに書きます。また、charsetはこのmessages.poのエンコードを指定します。埋め草のCHARSETを「utf-8」に書き換えます。
書き換えるとつぎのようになります。
msgid "" msgstr "" "Content-Type: text/plain; charset=utf-8\n" msgid "My Application" msgstr "アプリケーション-ja" msgid "MyButton" msgstr "押せるだけ"
VisualStudioで編集作業をした場合は、必ずエンコードを「utf-8(シグネチャなし)」に指定して保存してください。
辞書のバイナリ形式(.mo)
テキスト形式の.poをアプリで使用するためにmsgfmt.exeを使ってバイナリ化します。コンソール上で作業します。
$ msgfmt.exe messages.po $ ls messages.mo messages.po
ここで、エラーが出力された場合は.poのエンコードを確認してください。エラーがある限り、gettextは動きません。
言語の指定方法
アプリ上で言語の指定を「wxLANGUAGE_JAPANESE」で行い、フォルダ構成上では「ja」としました。日本語の場合はこれでよいのですが、英語圏では「wxLANGUAGE_ENGLISH_UK、wxLANGUAGE_ENGLISH_US、wxLANGUAGE_ENGLISH_AUSTRALIA...」などがあり、フォルダ名としては、「en_UK、en_US、en_AU...」と細かく指定できます。日本語でこれに相当するのが「ja_JP」です。これを正準形(canonical)と呼びます。日本語の場合はこれひとつです。また、エンコードを指定できます。これは、Windowsではコードページ932 になります。
日本語の場合は「ja」フォルダを使用します。「ja_JP」、「ja_JP.WINDOWS-932」のように詳細に指定した言語名のフォルダが優先的に利用されるようです。例えば、つぎのようなフォルダ構成の場合は、「ja_JP.WINDOWS-932」が使用されます。
├── catalogs ドメイン │ ├── ja 言語 │ │ ├── messages.mo 翻訳バイナリ形式 │ │ └── messages.po 翻訳テキスト形式(xgettextが生成) │ ├── ja_JP 言語(正準形) │ │ ├── messages.mo 翻訳バイナリ形式 │ │ └── messages.po 翻訳テキスト形式(xgettextが生成) │ └── ja_JP.WINDOWS-932 言語(正準形+エンコーディング) │ ├── messages.mo 翻訳バイナリ形式 │ └── messages.po 翻訳テキスト形式(xgettextが生成)
トラックボールマウス壊れた
LogicoolのM570の左クリックがチャタリング起こし始めたので、3年保証で交換してやろうとしましたが、購入記録(Amazon)、保証書などがありませんでした。電池蓋内部に記載されているP/N番号の画像で代用可能らしいのですが、暇なのでマイクロスイッチの交換をしました。
買ったマイクロスイッチは、Amazon「おまけ付き5個セット! オムロン(OMRON) D2FC-F-7N(20M) D2F-01F互換品 マイクロスイッチ SHINAX品質保証付」(送料込¥1040)です。
今回壊れたM570の修理のついでに、以前壊れたトラックマンホイール(TM250)も修理しました。両方とも使えるようになりました。
先代のTM250は左クリックがチャタリング起こしてお役御免でしたが、先々代のマイクロソフトのトラックボールオプティカルは、ボールを支持する金属が摩り減った為にお役御免にしたのであって、チャタリングは起こしていませんでした。気になったので、マイクロソフトのトラックボールも分解してみたところ、マイクロスイッチには「OMRON JAPAN」の印刷がありました。一方、Logicoolは「OMRON C**NA」でした(某国の名誉の為に伏字)。推定無罪ということもあるので、断罪はできません。
ちなみに、M570のボール(青目)をTM250に嵌めてみましたが、なんとドリフトしました。その逆は正常に使えます。
また、M570、TM250の両方をPCに認識させて、トレイのLogicoolアイコンをM570でクリックすると、M570用セットポイント画面が、TM250でクリックするとTM250用セットポイント画面が表示されます。Logicool、なかなか素晴らしい。マイクロスイッチの耐久性能以外は...。
今後、トラックボールは市場から消えるのでしょうか?それとも、サンワサプライが新規参入したように、参入するメーカーが増えるなんてことはあるのでしょうか?いずれにせよ、マイクロスイッチを交換したトラックボールが2台になったので、しばらくは悩まなくて済みそうです。
(追記:2014.7.21)
右ボタンもチャタリングし始めました。Firefoxのマウスジェスチャでコンテキストメニュが開いたり(右クリ)、「上」に行こうとすると(右クリ:左->上)、「前」に戻ったりします(右クリ:左)。チャタリングだと思います。左は酷使するから理解できますが、右も?意外です。
(追記:2015.7.31)
えーっと、勝手にダブルクリックし始めたので、再度、左ボタンのスイッチ交換しました。約1年ですか。
ここ2ヶ月ほど主PC用にはTM250を使用し、M570はセカンドPC用にして使っていたので使用頻度は低下していたのですが、2週間程前からチャタリングがひどくなったので、いらっとして交換しました。
こんどは慣れてたので30分かからなかったと思います。ちなみにスルーホールが抜けてしまいました。劣化か半田取りが不十分だったのか・・・。
抜けてしまった銅のキャップみたいな物を基盤にそーっとねじ込んで、スイッチを押し込み、半田付けしましたが大丈夫でした。
auxが不正になる
TeXLive2013+emacs+YaTeX環境ですが、他の環境(auctexなど)でも起きるようです。
症状
数式エラー「$の不釣り合い」などでタイプセットがエラーになった後、正しく修正しても、
「! File ended while scanning use of \@writefile.」
あるいは、
「! File ended while scanning use of \@newl@bel.」
というエラーが出て、その後のタイプセットが通らなくなる。.auxをみると、参照ラベルのリストアップが頓挫している。
解決策
僕の場合は、1を使ってますが、以前は3の
(setq tex-command "platex -kanji=utf8 -src-specials -interaction=nonstopmode")
としてましたが、エラーが起きても、*YaTeX-typesetting*バッファに「! Emergency stop.」としか表示されず、解りにくくなるので、今は使っていません。
蛇足
MWE(Minimum Working Example)を作ろうとしてソースの改変を行うとエラーの箇所が変化します。
最初は、「! File ended while scanning use of \@writefile.」であったのに、改変すると「! File ended while scanning use of \@newl@bel.」など、改変方法が異なれば他のメッセージに変化します。しかし、いずれも、auxの参照ラベルのリストアップが頓挫していることには変わりありません。
全くの推測ですが、エラー発生時にタイプセッタ内のバッファがフラッシュされていないのではないかと思います。ここで言うバッファというのは、emacsのバッファではなく、latex.exeやplatex.exeの内部バッファのことです。
TeX Q&Aや、海外サイトでも、この症状に関して、MWEの提出が求められていますが、内部バッファの吐き出しに関する不具合だとすれば、量とタイミングが関連するので、おそらく相当の作業と幸運に恵まれなければ、MWEに到達できないのではないかと想像します。
僕の場合は、分割タイプセットが10本になった時に症状が出て、MWE作成を試みるも、3本にまで絞った段階で挫折しました。今もMWEは作れていません。ただ、latex.exeのソースコードに知見のある人ならば何か思いつくのではないかと・・・他力本願な記事でした。
英語のフォント名
そこそこ調べたけど、結局使わなかったコードの断片を記録します。
症状
C++のプログラムで、フォント名(font face name)の英語表記を欲しかったのですが、日本語環境ではなかなか得ることができませんでした。つまり、下のような英語表記が欲しかったのです。
日本語 | 英語 |
---|---|
MS Pゴシック | MS PGothic |
メイリオ | Meiryo |
解決方法
.NETの FontFamily.GetName(1033) を使う。
経緯とサンプル
- サンプルは、VS2012Express、Win32コンソールアプリで作成しました。[空のプロジェクト]を作成して、プロジェクトのプロパティで、共通ランタイムサポート(/clr)を選択したものです。
サンプルソリューションのパック(ConsoleApplication7.zip)
- (記事の下の方にdll化してみたものも置いてます。)
- ちなみに、英語LCID(=1033)は、次のコードで得られます。
WORD langid =MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ); DWORD lcid =MAKELCID( langid, SORT_DEFAULT );
- 識別子の一覧に関しては、サンプルコード中のコメントを参照してください。
- サンプルは
- .NETのフォントピッカーを開いて、
- マネージされた英語のフォント名をC++の文字列に変換して
- コンソールに表示するものです。
#pragma once #include <SDKDDKVer.h> // windows.hのインクルードに必要で、アーキテクチャや #include <Windows.h> // プラットフォームを限定するためのものです。 #include <stdio.h> #include <tchar.h> #include <iostream> #include <vcclr.h> // pin_ptrを使用するためのものです。 /* * オブジェクトの参照が必要です。ソリューションエクスプローラのプロジェクトを右クリして、 * [プロパティ][共通プロパティ][Frameworkと参照][新しい参照の追加(N)...] * でチェックすることで、有効化できます。コンパイラの/FUオプションになります。 * あるいは、#usingディレクティブを使って、コード中に埋め込むこともできます。 */ #using <System.dll> #using <System.Windows.Forms.dll> #using <System.Drawing.dll> int main(int argc, _TCHAR* argv[]) { std::locale::global(std::locale("japanese")); System::Windows::Forms::FontDialog^ fd=gcnew System::Windows::Forms::FontDialog(); fd->ShowDialog(); System::Drawing::FontFamily^ ff=fd->Font->FontFamily; /* * MAKELANGID, MAKELCID マクロや識別子に関しては、次のような文言でWeb検索すると * マイクロソフトの開発者用リファレンスが参照できます。 * 国際化に関係した識別子一覧があります。 * * ・National Language Support Reference * ・Language Identifier Constants and Strings * ・Sort Order Identifiers * */ WORD langid =MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ); DWORD lcid =MAKELCID( langid, SORT_DEFAULT ); System::String^ strFFName_EN =ff->GetName(lcid); System::String^ strFFName_JP =ff->GetName(0); /* * pin_ptrを使って、String^をwchar_t*に変更することで、普通のC++のように記述できます。 * 次の文言でWeb検索すると、pin_ptr のサンプルが見れます。 * * ・方法: System::String を wchar_t* または char* に変換する */ pin_ptr<const wchar_t> wchFFName_EN = PtrToStringChars(strFFName_EN); pin_ptr<const wchar_t> wchFFName_JP = PtrToStringChars(strFFName_JP); std::wcout <<L"英語:" <<(const wchar_t*)wchFFName_EN <<std::endl; std::wcout <<L"日本語:" <<(const wchar_t*)wchFFName_JP <<std::endl; std::wcout <<L"Press ENTER to exit:"; std::cin.ignore(); return 0; }
- .NETを使用するために、/clrオプションを指定すること、
- #usingで適切な.dllを宣言することが必要です。
- あるいは、プロジェクトの[共通プロパティ][Frameworkと参照]にて、参照を参加させます。
- サンプル起動直後にフォントピッカーが開くので、フォントを選択します。
- コンソールにフォントの日本語と英語の表記が出力されます。
DLL化したサンプル
ふっと思いついて、.NET部分をDLLに封じ込めてみました。
DLL化したサンプル(ConsoleApplication7b.zip)
「メイリオ」を渡すと「Meiryo」を返すdll。「メイリオ」などと有効なフォント名でないと、何が起きるかわかりません。
メイン(ConsoleApplication.cpp)
#pragma once #include <stdio.h> #include <tchar.h> #include <iostream> #include "FontFamily\FontFamily.h" int main(int argc, _TCHAR* argv[]) { std::locale::global(std::locale("japanese")); const wchar_t* wchNameEn =GetName(L"メイリオ"); std::wcout <<L"英語:" <<(const wchar_t*)wchNameEn <<std::endl; std::wcout <<L"Press ENTER to exit:"; std::cin.ignore(); return 0; }
DLL(FontFamily.cpp)
#include "stdafx.h" #include "FontFamily.h" #include <vcclr.h> #using <System.Drawing.dll> FONTFAMILY_API const wchar_t* GetName( const wchar_t* nameJp ) { System::Drawing::FontFamily^ ff =gcnew System::Drawing::FontFamily( gcnew System::String(nameJp) ); WORD langid =MAKELANGID( LANG_ENGLISH, SUBLANG_ENGLISH_US ); DWORD lcid =MAKELCID( langid, SORT_DEFAULT ); System::String^ strNameEn =ff->GetName(lcid); pin_ptr<const wchar_t> wchNameEn =PtrToStringChars(strNameEn); return (const wchar_t*)wchNameEn; }
- Dllの名前がFontFamilyだったり、エクスポート関数名がGetNameだったりと非実用的なネーミングです。
- 文字列のポインタ返しとか大丈夫なのか?とか今の僕にはわかりません。
- 記事書いて、ご飯食べたら、ふっと思いついただけなので...
- フォントピッカーは出ません。「メイリオ」決め打ちです。
- vcclr.hは、PtrToStringCharsを使うためのものですね。訂正します。
- 今思うと、なぜdll化したのだろう。単に関数化でもよかったかな?
- ご飯食べてて、ふっと思いついた勢いで作ったので...
- 思い出した、本体側で/clrしなくてもよいことになるからでした。
以上です。
中華詐欺メール
多くの人が既に晒してます。スクエアエニックス社のサイトには、注意喚起ページがあります。
詐欺メール全文
お客様
株式会社营团社サービスシステムをご利用いただき、ありがとうございます。
システムはお客様のアカウントが異常にログインされたことを感知しました。
下記のログイン時間を照らし合せてご本人様によるログインであるかどうかご確認お願いします。
ログイン地点 ログインIP ログイン時間 大阪 61.204.255.255 2013-07-27 02:06
ご本人によるログインでなければ、アカウントの安全に問題があると考えられます。
以下のURLをクリックし、画面の案内にそってパスワードの再設定を行ってアカウントを保護してください。https://secure.square-enixcom/account/app/svc/Login?cont=account
(上記URLをクリックしてもページが開かないときはURLをコピーし、ご利用のウェブブラウザーのアドレス入力欄に貼り付けてお試しください)
もし、ご本人によるログインでしたら、お手数ですが本メールの破棄をお願いいたします。
ご意見やご要望
スクウェア·エニックス会社
2013年08月01日
- 营 ... 中華語のセールスの意味らしい。
- 团 ... 中華語のグループの意味らしい。
蛇足
ゲーム中毒の子供が犯人だとしたら、日本語使いが巧みだと感心したりしますが、大人だったら子供レベルの知能です。残念。
TortoiseSVN1.8 オーバーレイアイコン消失
症状
「TortoiseSVN-1.8.0.24401-x64-svn-1.8.0.msi」でアップデートしたら、オーバーレイアイコンが消えてしまいました。
- SVN1.7に上書きアップデートでアイコンが消失
- リブートしても消失したまま
- 「C:\Users\etc\AppData\Local\IconCache.db」を削除して、リブートするも消失したまま
- 「HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellIconOverlayIdentifiers」をチェックするも登録数15個なので問題なし
- SVN1.8のインストーラで修復を試みるも消失したまま(リブートしても相変わらず)
- TortoiseSVN1.8をアンインストールし、IconCahe.dbを削除、レジストリのアイコン数をチェックして、再インストールするもアイコンは消失したまま
解決策
TortoiseSVN1.8をアンインストールして、1.7をインストールしました。つまり、問題のなかったバージョンに戻したということです(根性無しなので...)。
感想
バージョンアップ時のトラブル回避に、xx.0 はインストールを見合わせるというのがありますが、ToroiseSVNのような大き目のアプリの場合は、XX.XX.0 にも注意を払う必要がありそうです。TortoiseSVNはとりあえず頻繁にアップデートをしていくという方針なので、ほんのちょっと待ってからアップデートしようと思います。