Peter Solarz
Show & Tell
Sweet Seals For You, Always
he wasn't even looking at me and he found me
d e v o n
One Nice Bug Per Day
taylor price

JBB: An Artblog!
RMH
almost home

oozey mess

★
dirt enthusiast
Xuebing Du

blake kathryn
Lint Roller? I Barely Know Her

JVL
noise dept.
Alisa U Zemlji Chuda
Cosimo Galluzzi

seen from Singapore
seen from Malaysia
seen from United States

seen from United States
seen from United States
seen from Malaysia
seen from Türkiye

seen from United States
seen from United States

seen from United States

seen from United States
seen from United States
seen from United States
seen from United States
seen from United States
seen from United States
seen from United States
seen from United States
seen from United States
seen from United States
@exeal-blog
Boost.Regex のドキュメント日本語訳更新した(1.58.0)
1.58.0 のリリースに合わせて更新した。このライブラリの更新は相変わらずリリースノートには載らんな
Boost.Regex(日本語訳)(PDF)
Boost.Regex(日本語訳)(ODF)
ドキュメント本体の変更は typo ぐらいであんま無いが、ICU 関連のバグが修正された
前から思っていたが OpenDocument 形式だとバイナリファイル扱いになって、あんまよくないな。実は一回 Sphinx 使おうとしたけど、面倒になってあきらめたのだった。Bitbucket の Wiki でもいいけどな
年末年始
去年の年末はけっこう忙しくて、今やっと休みが取れたのでちょこっとだけ振り返ってみる。
12 月は 26 日がいちおう仕事納めで、数日は休みがあった。が、急に保険に入ることにしてしまって、プライベートはバタバタしてしまった。年内に契約しないと損という話で、書類を書きまくったりして、29 日に全部終わった。あんまり休んだ気がしなかった。
今回は仕事で大型の案件があって、31 日から会社に出ていた。けっこう前から決まってたことなので、覚悟はしていたが。途中トラブルもあって 6 日まで連続で出勤したが、大体めどがついたので 7 日に 1 日だけ休みを取った。
7 日の休みは実家の近く(でもないか)の温泉に日帰りで出かけた。先に帰省していた弟が予約してくれてて、実家の両親と食事をした。海沿いの温泉宿で露天風呂だった。朝、家を出たのが 8 時過ぎでぜんぜん休んだ気がしなかったが。
食事しながら、母の栄養学の講釈を聴く(恒例)。そのあと父が定年退職後に何かやる気があると見せかけて無いとか、母が入れ歯になったとか、割とどうでもいい話で寝そうになった。私がしたかった金の話を少しして、近くの神社で初詣になった。 何となく既視感があったので母に聞いてみると、小さい時に 1 回来ていたらしい。昔飼っていた犬と遊んだような気がする。もう 20 年ぐらい前だな。
正月休みの後半に入ってダラダラしていると、ようやく私にも 2015 年が訪れた気になった。今年もよろしくお願いします。
Boost.Regex 1.57 の変更点
リリースノートにもドキュメントにも書かれていないが、実は 1 箇所だけバグ修正がある
#include <boost/regex.hpp> int main(int argc, char** argv) { const boost::regex pattern("}"); // Perl の構文を使用 return 0; }
1.56 だと正規式に開き括弧がねーぞと怒られるが、1.57 だと OK。これは 1.57 が正しい。Perl の構文では、繰り返し以外の文脈では波括弧は即値扱いになるからだ
というのがこっそり修正されていた。ドキュメントも追記があって、どうも最初から分かってたぜみたいな書き方だが
日本語訳も更新した。Python と Xpressive は 1.57 では変更なし
Boost.Regex(日本語訳)(PDF)
Boost.Regex(日本語訳)(ODF)
exeal / boostjp — Bitbucket
そうそう、Bitbucket への移行始めました
gtkmm を MSVC10 でビルドする
忘れないためにメモ。Windows だったら公式のバイナリがあるんじゃね?って話だが、3.x 系は無いのだった。3.6 であれば、有志(?)が作成したものがある
はじめに
環境は Windows Vista + Visual Studio 10 Express SP1。MingW と Python も必要(後述)
ターゲットのバージョンは gtkmm が 3.12.0 、GTK+ が 3.12.2 とした。Windows で自力でビルドすると苦労するのが各ライブラリのバージョンで、最初は全部最新版でやってみたら失敗した。よく分からんので、変な方法だが OS X マシンに入れてある MacPorts と同じバージョンにしてみた。ただし gettext のとこにも書いてあるのだが、libiconv は入れなくても動いたのでそのままにした。他にも jpeg 系のライブラリや FreeType も入れてない。とりあえず、付属のデモが動作するのまで確認した
何はともあれ、まずはドキュメントをひととおり読んでおく:
Building gtkmm on Windows
Compiling the GTK+ (and Clutter) stack using Visual C++ 2008 and later
共通項目として、
Gnome 系のソースコードパッケージは、http://ftp.gnome.org/pub/gnome/sources/
Cairo 、pixman のソースコードパッケージは、http://cairographics.org/releases/
Visual Studio のソリューションファイルがあるパッケージは極力利用する。変に意地を張るとハマる
パッケージは例えば D:/gnome/ みたいなディレクトリを作って、そこに全部放り込む。いくつかのソリューションは D:/gnome/vs10/ にライブラリとヘッダをインストールするので、素直にこれを利用する
非 Gnome 系と mm 系は特にインストールとかしてくれないので、パスの通ったディレクトリにコピーするか、上のフォルダと一緒にしてしまう
日本語環境だと C4819 が大量に出る。公式アナウンスのとおりシステムロカールを英語に変えてから作業する(マジで)。よく分からんというか、著名なライブラリとしてどうかと思うが。まぁ実際のところは BOM 無し UTF-8 のファイルが読めない cl がクソなんだが。このとおりやると、どこかで文字化けするかもしれないが、まだ確認していない
他にも警告がいっぱい出る。たぶんほとんどテストしてないな、これ
まず GLib からやっつけるのだが、そのためには libffi と zlib が必要。先は長い。
libffi(3.1)
https://sourceware.org/libffi/ からソースコード(libffi-3.1.tar.gz)を取ってくる。configure 使うので MinGW 必須(じゃないかもしれないが、もう諦めた)。適当なところに展開して、
$ ./configure CC=~/libffi-3.1/msvcc.sh CXX=~/libffi-3.1/msvcc.sh CPP="cl -nologo -EP" CXXCPP="cl -nologo -EP" LD=link make && make install
途中で「../install-sh なんかねーぞ」と怒られたので、シンボリックリンクを張ったらうまくいった。他にも色々トラブった気がするが。まだの場合は libffi.lib と libffi-6.dll の場所にパスを通しておく
zlib(1.2.8)
http://www.zlib.net/ からソースコードを取ってくる。で、中身を見ると http://www.winimage.com/zLibDll/ にバイナリがあるよ、とか書いてあるのだが、バージョンが古い(1.2.5)ので、やっぱり自分でビルドする。
ご丁寧に VS のソリューションファイル(contrib/vstudio/vc10/zlibvc.sln)があるので、これを使う。そのままビルドしてもダメっぽくて、プリプロセッサの定義から ZLIB_WINAPI を外しておく。ビルドすると、
ZlibDllDebug -- zlibwapid 、zlibwapid.lib
ZlibDllRelease -- zlibwapi 、zlibwapi.lib
ZlibDllReleaseWithoutAsm -- zlibwapi 、zlibwapi.lib
ZlibStatDebug -- zlibstat.lib
ZlibStatRelease -- zlibstat.lib
ZlibStatReleaseWithoutAsm -- zlibstat.lib
名前がいまいちだな。GLib は zlib1d.lib とかでリンクしてくるので、適当に名前を変えてパスの通ったところにコピーしとく
gettext(0.18.1.1)
これは 0.19.2 を自分でビルドしたかったんだが、なぜか configure が途中で止まってしまうのであきらめた。配布されているバイナリを取って来る。以下の 2 ファイル:
gettext-runtime_0.18.1.1-2_win32.zip -- intl.dll
gettext-runtime-dev_0.18.1.1-2_win32.zip -- intl.lib 、libintl.h
本当はビルドする場合に libiconv が必要なのだが、上記のバイナリを使うと最後まで(とりあえずは)必要ないようだ
GLib(2.40.0)
これも build/win32/vs10/glib.sln をそのままビルド。これで gio-2.0.lib 、gio-2-vs10.dll 、glib-2.0.lib 、glib-2-vs10.dll が生成される
glibmm(2.40.0)
やはり MSVC_Net2010/glibmm.sln でビルドする
giomm/Win32/Debug -- giomm-vc100-d-2_4.dll 、giomm-vc100-d-2_4.lib
giomm/Win32/Release -- giomm-vc100-2_4.dll 、giomm-vc100-2_4.lib
glibmm/Win32/Debug -- glibmm-vc100-d-2_4.dll 、glibmm-vc100-d-2_4.lib
glibmm/Win32/Release -- glibmm-vc100-2_4.dll 、glibmm-vc100-2_4.lib
libpng(1.6.12)
Cairo をビルドするのに必要。ホームページからソースコードを取ってきて開けてみると、CMakeLists.txt と vstudio.sln があるな。まぁ、大人しく Visual Studio 使っとくか。同じディレクトリにある zlib.props を開いてパスを設定してから、普通にビルドする。
Release -- libpng16.dll 、libpng16.dll 、zlib.lib
Release Library -- libpng.lib 、zlib.lib
一緒に出てくる zlib.lib は何?
Pixman(0.32.6)
ここからは Cairo だな。MSYS から make するしかない
$ cd pixman-0.32.6/pixman $ make -f Makefile.win32
何か test でファイルが無いと失敗するが...。これで pixman/release/pixman-1.lib が作成される。ヘッダファイルとライブラリを gnome/vs10/Win32/ 以下にコピーしておこう
Cairo(1.12.16)
MSYS で make してもよさそうだが、cairo-gobject のビルドがよく分からんな。というわけで GTK+ のページにあるソリューションファイルを使ってみる。Cairo のトップディレクトリに展開して msvc/vs10/cairo.sln をビルドすると __cairo_path_fixed_stroke_to_traps の定義が無いと怒られた。見ると src/cairo-path-stroke-traps.c がプロジェクトに入ってないので追加する。あとリンカの入力(cairoprops)が libpng15.lib になっているので、勝手に libpng16.lib に変えた
ソリューションをビルドしても cairo-object と install が走らないので手動でビルドして、ファイルをコピーさせる
cairomm(1.10.0)
これも MSVC_Net2010/cairomm.sln を使うのだが、プロジェクト cairomm-1.0 に region.* が入ってないので足しておく(無いと gtkmm で失敗する)。あと device.* も足りないので追加(こっちは少なくとも 1.11.2 では修正されている)
(1.11.2 でビルドしてみると FreeType 系の機能にリンクできないとかで失敗した。何じゃこりゃと思って cairo-features.h を見ると、
... #define CAIRO_HAS_FC_FONT 1 #define CAIRO_HAS_FT_FONT 1 ...
FreeType 入れてないのに有効になってるな。編集するなと書いてあるが、とりあえず FreeType は使わんし、調べるのが面倒だったのでコメントアウトしてしまった)
cairomm/Win32/Debug -- cairomm-vc100-d-1_0.dll 、cairomm-vc100-d-1_0.lib
cairomm/Win32/Release -- cairomm-vc100-1_0.dll 、cairomm-vc100-1_0.lib
Pango(1.36.5)
よく分からんが、Cairo と違ってソリューションファイルがある。build/win32/vs10/pango.sln をビルドすると break.c と pango-language-sample-table.h で文字コード(UTF-8)の判定に失敗するので BOM を付けておく(ここは日本語設定でやってしまった。英語設定だと問題ないかも)
Debug/Win32/bin -- pango-1.0.lib 、pango-1-vs10.dll 、pangocairo-1.0.lib 、pangocairo-1-vs10.dll 、pangowin32-1.0.lib 、pangowin32-1-vs10.dll
Release/Win32/bin -- pango-1.0.lib 、pango-1-vs10.dll 、pangocairo-1.0.lib 、pangocairo-1-vs10.dll 、pangowin32-1.0.lib 、pangowin32-1-vs10.dll
pangomm(2.34.0)
MSVC_Net2010/pangomm.sln を使うだけ
pangomm/Win32/Debug -- pangomm-vc100-d-1_4.dll 、pangomm-vc100-d-1_4.lib
pangomm/Win32/Release -- pangomm-vc100-1_4.dll 、pangomm-vc100-1_4.lib
ATK(2.12.0)
build/win32/vs10/atk.sln を使う。README.txt を見ると GLib 、libintl 、zlib のヘッダとライブラリファイルを指定箇所にコピーしておけと書いてある。ビルドの先頭で glib-genmarshal.exe が失敗したら、たぶんコピー先が間違ってる。うまくいくと atk-1-vs10.dll 、atk-1.0.lib が生成される
atkmm(2.22.7)
MSVC_Net2010/atkmm.sln からビルドするだけで OK。問題なし
atkmm/Win32/Debug -- atkmm-vc100-d-1_6.dll 、atkmm-vc100-d-1_6.lib
atkmm/Win32/Release -- atkmm-vc100-1_6.dll 、atkmm-vc100-1_6.lib
gdk-pixbuf(2.30.8)
GTK+ をビルドするのに必要。build/win32/vs10/gdk-pixbuf.sln を使えば OK。gdk_pixbuf-2-vs10.dll と gdk_pixbuf-2.0.lib が生成される
GTK+(3.12.2)
たぶん Python 2.7 が必要。build/win32/vs10/gtk+.sln がどうやって Python のパスを決めているのか不明だが、普通にインストールしていれば OK っぽい
gdk/win32/gdkselection-win32.c で構文エラーが出るので修正する(後のバージョンでは修正されているが)
修正前
... if (target == _image_bmp) { g_return_val_if_fail (GlobalSize (hdata) >= sizeof (BITMAPFILEHEADER), NULL); /* No conversion is needed, just strip the BITMAPFILEHEADER */ HGLOBAL hdatanew; SIZE_T size = GlobalSize (hdata) - sizeof (BITMAPFILEHEADER); guchar *ptr = GlobalLock (hdata); ...
修正後
... if (target == _image_bmp) { HGLOBAL hdatanew; SIZE_T size; guchar *ptr; g_return_val_if_fail ((GlobalSize (hdata) >= sizeof (BITMAPFILEHEADER)), NULL); /* No conversion is needed, just strip the BITMAPFILEHEADER */ size = GlobalSize (hdata) - sizeof (BITMAPFILEHEADER); ptr = GlobalLock (hdata); ...
死すべきはマクロだな
glib-compile-schemas.exe が失敗する場合は同じディレクトリに intl.dll をコピーする
これで gailutil-3*、gdk-3* 、gtk-3* とかが生成される
gtkmm(3.12.2)
gtkmm.sln を使う。リンクエラーが出まくるので、プロジェクト gtkmm-3.0 に actionbar.cc と actionbar.h を追加する。さらにプロジェクト demos_gtk-demo に example_flowbox.cc と example_headerbar.cc を足して、リンカの入力にも giomm-vc100-d-2_4.lib を足しておく(デモプログラムなので無視してもいいが)
疲れた
途中で何度も失敗した。最初は特にバージョンがワケワカで、そのたびに glibmm とか gtkmm をビルドしなおすんだが、1 回で 30 分ぐらいかかるだな、これが。アホらしいんで、大体そのまま寝てたけど
あとは Windows だと逆に大変ってのが、通しての感想だな
Boost.Regex-1.56.0 における破壊的変更
Boost 1.56 がリリースされた。Regex で 2 件、破壊的変更があったので内容を確認した。いずれもかなり重症のバグ
まず basic_regex.mark_count() で、こいつはパターン内の部分式の数を返すのだが、今まで 1 つ大きな値を返していた。実は 2007 年頃から挙動がおかしいと指摘されてたんだが、放置されていたようだ
もう 1 つは似たようなところで basic_regex.subexpression() が 1 つずれた位置の部分式を返していた。こっちは標準の std.regex には無い機能だから、使ってる人はあまりいないかもしれんが
文章で書いてもワケワカなので、コードを動かしてみよう
#include <iostream> #include <boost/regex.hpp> int main(int argc, char** argv) { boost::regex pattern("((a)(?:b)(c))", boost::regex::save_subexpression_location); std::cout << pattern.mark_count() << std::endl; for(std::size_t i = 0; ; ++i) { std::cout << "[" << i << "] : "; try { const auto sub(pattern.subexpression(i)); std::cout << "[" << (sub.first - pattern.begin()) << "," << (sub.second - pattern.begin()) << ") => " << std::string(sub.first, sub.second) << std::endl; } catch(const std::out_of_range& e) { std::cout << e.what() << std::endl; if(i != 0) break; } } return 0; }
1.55 で実行すると、
4 [0] : 0 is not a valid subexpression index. [1] : [0,12) => ((a)(?:b)(c) [2] : [1,3) => (a [3] : [9,11) => (c [4] : invalid vector subscript
1.56 だと、
3 [0] : [0,12) => ((a)(?:b)(c) [1] : [1,3) => (a [2] : [9,11) => (c [3] : invalid vector subscript
というわけで、かなりひどい。実際のコードを見ると設計段階のミスっぽくて、どこでどう間違えたかは何となく分かる気がする
変更は他にもいくつかあった。ドキュメントの翻訳版を更新した(PDF 版、ODF 版)
Glib.ustring と Python 3 str の変換
Glib.ustring を使う場合、変換器を書かなきゃならんと思っていてぜんぜんやってなかった。
Boost.Python で既存の C++ 型を使おうとすると、変換器が必要になる。特に別々の世界にある関数を呼び出すときに、引数と戻り値を適当に変換する必要がある(いろんな人が記事を書いてそうなんで細かい説明は省略)。何回書いても即効忘れるのでメモ。といっても組み込みの変換器のコードをほぼコピペしただけだが:
#include <boost/python.hpp> #include <glibmm/ustring.h> namespace me { // Glib.ustring から str への変換 struct ustring_to_python { static PyObject* convert(const Glib::ustring& cc) { return ::PyUnicode_FromStringAndSize(cc.data(), boost::implicit_cast<boost::python::ssize_t>(cc.length())); } static const PyTypeObject* get_pytype() { return &PyUnicode_Type; } }; // str から Glib.ustring への変換 struct ustring_from_python { ustring_from_python() { boost::python::converter::registry::push_back(&convertible, &construct, boost::python::type_id<Glib::ustring>(), &ustring_to_python::get_pytype); } private: static void* convertible(PyObject* p) { if(PyUnicode_Check(p)) return &::PyUnicode_AsUTF8String; if(PyBytes_Check(p)) return &identity; return nullptr; } static void construct(PyObject* p, boost::python::converter::rvalue_from_python_stage1_data* data) { typedef PyObject* (*convertible_function)(PyObject*); convertible_function creator = *static_cast<convertible_function>(data->convertible); boost::python::handle<> intermediate(creator(p)); void* const storage = reinterpret_cast<boost::python::converter::rvalue_from_python_storage<Glib::ustring>*>(data)->storage.bytes; new(storage) Glib::ustring(::PyBytes_AsString(intermediate.get()), ::PyBytes_Size(intermediate.get())); data->convertible = storage; } static PyObject* identity(PyObject* p) { boost::python::incref(p); return p; } }; }
こんな感じで変換器を書いておいて、使う前に登録する。
int main(int argc, char*[]) { ::Py_Initialize(); boost::python::to_python_converter<Glib::ustring, me::ustring_to_python, true>(); me::ustring_from_python(); // なんたら }
これで Glib.ustring と Python の str 型が自動的に相互変換されるようになる。
つまらんな。
で、今回一番気になったのは str だな。Python 2.x → 3.x で大きく変わったにもかかわらず、Boost.Python のドキュメントにはほとんど何も書いてないしな。これも気が向いたらまとめてみよう。
Gtk.Scrollable の使用
Win32 で GUI 書くのがアホらしくなって(無くなったわけではない)、1 か月前から gtkmm を使い始めたのだった。早く OS X でも動かしたいし。
gtkmm はよくできたライブラリで、かなりストレスは減った。ただドキュメントというか情報が少ないのが気にはなっていたのだが。
で、エディタのコードを書くときになって Gtk.TextView を見てみると Gtk.Scrollable ってのを使ってて、自分でスクロール機能を提供するウィジェットは同じようにしなきゃならんなという感じだった。
何となく Gtk.TextView の真似をしていればいけるだろと思っていたのだが、こいつは GtkTextView のラッパであって既に C の世界で GtkScrollable インターフェイスを実装しているのだった。要は gtkmm の中で GtkScrollable を実装しているわけではなかった。
Ascension は最初から C++ なのでやり方が違う、というところまでは理解したのだが、ドキュメントもサンプルもないので方法が分からず途方に暮れていたのだった。これで 2 週間ぐらい潰したな。
それでも色々調べまくって何となく動くコードが書けたので、メモしておこう。といっても、よく分からんところもあるのだが。
自分のウィジェットクラスを Gtk.Scrollable から(公開?)派生させる
コンストラクタで Glib.ObjectBase のコンストラクタを引数付きで呼び出す。引数は const char* か const std.type_info& のやつ
オーバーライドする 4 つのプロパティを Glib.Property 型のメンバ変数として持たせる。コンストラクタでこいつらを初期化する
Gtk.Adjustment 型のプロパティの signal_changed に接続して、シグナルハンドラの中で Gtk.Adjustment を設定する
Gtk.Scrollable.add_interface は自分で呼び出さなくてよい
ただし Gtk.Scrollable のコンストラクタが呼び出される前に Glib.Property を初期化しないとコンソールにゴチャゴチャ表示される(が、別に問題なく動作する。よく分からんな)。
すぐ忘れるので、動いたコードを載せておこう。
#include <cairomm/cairomm.h> #include <gtkmm.h> #include <gtkmm/main.h> #include <iostream> #include <memory> namespace me { class my_widget; class my_widget_base : public Gtk::Widget { protected: my_widget_base() : hadjustment_(*this, "hadjustment"), vadjustment_(*this, "vadjustment"), hscroll_policy_(*this, "hscroll-policy", Gtk::SCROLL_NATURAL), vscroll_policy_(*this, "vscroll-policy", Gtk::SCROLL_NATURAL) {} protected: Glib::Property<Glib::RefPtr<Gtk::Adjustment>> hadjustment_, vadjustment_; Glib::Property<Gtk::ScrollablePolicy> hscroll_policy_, vscroll_policy_; }; class my_widget : public my_widget_base, public Gtk::Scrollable { public: my_widget() : Glib::ObjectBase("me.my_widget"/*typeid(my_widget)*/) { property_hadjustment().signal_changed().connect(sigc::mem_fun(*this, &my_widget::adjustment_changed<false>)); property_vadjustment().signal_changed().connect(sigc::mem_fun(*this, &my_widget::adjustment_changed<true>)); set_has_window(true); } private: void configure_adjustment(bool vertical) { if(const auto v = (vertical ? property_vadjustment() : property_hadjustment()).get_value()) { v->freeze_notify(); v->set_upper(1000); v->set_step_increment(10); v->set_page_size(100); v->thaw_notify(); } } template<bool vertical> void adjustment_changed() { if(const auto v = (vertical ? property_vadjustment() : property_hadjustment()).get_value()) { sigc::connection& connection = vertical ? vadjustment_connection_ : hadjustment_connection_; connection.disconnect(); connection = v->signal_value_changed().connect(sigc::mem_fun(*this, &my_widget::adjustment_value_changed)); configure_adjustment(vertical); } } void adjustment_value_changed() { queue_draw(); } sigc::connection hadjustment_connection_, vadjustment_connection_; private: void get_preferred_width_vfunc(int& minimum_width, int& natural_width) const { minimum_width = 500; natural_width = 1000; } void get_preferred_height_for_width_vfunc(int width, int& minimum_height, int& natural_height) const { return get_preferred_height_vfunc(minimum_height, natural_height); } void get_preferred_height_vfunc(int& minimum_height, int& natural_height) const { minimum_height = 300; natural_height = 1000; } void get_preferred_width_for_height_vfunc(int height, int& minimum_width, int& natural_width) const { return get_preferred_width_vfunc(minimum_width, natural_width); } bool on_draw(const Cairo::RefPtr<Cairo::Context>& context) { static const int box_size = 15; if(window_) { const int w = get_allocated_width(), h = get_allocated_height(); context->save(); context->set_source_rgb(0, 0, 0); const int pattern_size = box_size * 2; const int hoffset = -(static_cast<int>(property_hadjustment().get_value()->get_value()) % pattern_size); const int voffset = -(static_cast<int>(property_vadjustment().get_value()->get_value()) % pattern_size); for(int x = hoffset; x < w; x += pattern_size) { for(int y = voffset; y < h; y += pattern_size) context->rectangle(x, y, box_size, box_size); } context->fill(); context->restore(); } return true; } void on_realize() { set_realized(); if(!window_) { GdkWindowAttr attributes; std::memset(&attributes, 0, sizeof(decltype(attributes))); const Gtk::Allocation allocation(get_allocation()); attributes.x = allocation.get_x(); attributes.y = allocation.get_y(); attributes.width = allocation.get_width(); attributes.height = allocation.get_height(); attributes.event_mask = get_events() | Gdk::EXPOSURE_MASK; attributes.window_type = GDK_WINDOW_CHILD; attributes.wclass = GDK_INPUT_OUTPUT; window_ = Gdk::Window::create(get_parent_window(), &attributes, Gdk::WA_X | Gdk::WA_Y); set_window(window_); override_background_color(Gdk::RGBA("red")); override_color(Gdk::RGBA("blue")); window_->set_user_data(Gtk::Widget::gobj()); } } void on_size_allocate(Gtk::Allocation& allocation) { set_allocation(allocation); if(window_) window_->move_resize(allocation.get_x(), allocation.get_y(), allocation.get_width(), allocation.get_height()); } void on_unrealize() { window_.reset(); Gtk::Widget::on_unrealize(); } private: Glib::RefPtr<Gdk::Window> window_; }; class my_window : public Gtk::Window { public: my_window() { set_title("My gtkmm application"); set_default_size(400, 300); set_border_width(0); add(scroller_); scroller_.add(child_); scroller_.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS); scroller_.set_shadow_type(Gtk::SHADOW_ETCHED_OUT); show_all_children(); } private: my_widget child_; Gtk::ScrolledWindow scroller_; }; } int main(int argc, char* argv[]) { Gtk::Main kit(argc, argv); me::my_window w; Gtk::Main::run(w); return 0; }
Boost.Xpressive ドキュメントの翻訳を更新した(1.55)
昨日更新した。
PDF 版
OpenDocument 版
今回のバージョンアップは大きな変更はなかったが、修正された #8843 は致命的なバグ。
今まで知らなかったのだが BOOST_FALLTHROUGH ってのがあって、自分も使ってみようと思う。
Boost 1.54 ドキュメント改訂した
先日 1.54 がリリースされたので、正規表現ペアのドキュメント翻訳を改訂した。
Boost.Regex ドキュメント日本語訳(PDF)
Boost.Xpressive ドキュメント日本語訳(PDF)
Boost.Python の翻訳はまだ終わっていない。