2009年4月1日水曜日

require 'dl' してみた ... 便利だった

Win32APIをRuby/DLで呼び出してみた。
Ruby/Win32APIを使う(RubyのWin32APIとUNICODE)よりも簡単。

sample.rb
#!/usr/local/bin/ruby -Ku
# -*- encoding: utf-8 -*-

require 'dl/import'
require 'iconv'

module DSO
extend DL::Importable
dlload 'Kernel32', 'User32'
extern 'int GetTickCount()'
extern 'int MessageBoxA(int, char*, char*, int)'
extern 'int MessageBoxW(int, wchar_t*, wchar_t*, int)'
end

def s(x)
Iconv.iconv('shift_jis', 'utf-8', x + 0.chr)[0]
end

def u(x)
Iconv.iconv('utf-16le', 'utf-8', x + 0.chr)[0]
end

p DSO.getTickCount
p DSO.messageBoxA(0, s('あabc'), s('あabc'), 0)
p DSO.messageBoxW(0, u('あabc'), u('あabc'), 1)

ちなみに、ruby-1.9.1p0(に同梱されていたRuby/DL)では動かない。
  1. DL::ImportableがDL::Importerに
  2. 先頭が大文字の関数名でもそのままexternされるように
という仕様変更があったようだ。

sample_for_ruby-1_9_1.rb
#!/usr/local/bin/ruby -Ku
# -*- encoding: utf-8 -*-

require 'dl/import'
require 'iconv'

module DSO
extend DL::Importer
dlload 'Kernel32', 'User32'
extern 'int GetTickCount()'
extern 'int MessageBoxA(int, char*, char*, int)'
extern 'int MessageBoxW(int, wchar_t*, wchar_t*, int)'
end

def s(x)
Iconv.iconv('shift_jis', 'utf-8', x + 0.chr)[0]
end

def u(x)
Iconv.iconv('utf-16le', 'utf-8', x + 0.chr)[0]
end

p DSO.GetTickCount
p DSO.MessageBoxA(0, s('あabc'), s('あabc'), 0)
p DSO.MessageBoxW(0, u('あabc'), u('あabc'), 1)

2009年3月31日火曜日

JavaScriptでWYSIWYGエディタへの道

JavaScriptのWYSIWYGエディタは世の中にたくさんあるけれど、いったいどうやって実現しているんだろう?
…と気になってしまって夜も眠れなくなりそうになったのでちょっと調べてみた。

最初に見つけたのは、iframeを作ってcontentEditable = trueにする方法だった。

contentEditable.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
<head>
<title>contentEditable</title>
<script type="text/javascript">
//<![CDATA[
var o = null;
var f = null;
var d = null;
var b = null;
var la = null;
function findBody(doc){
for(var i = 0; i < doc.childNodes.length; ++i){
if(doc.childNodes[i].nodeName == 'HTML'){
for(var j = 0; j < doc.childNodes[i].childNodes.length; ++j){
if(doc.childNodes[i].childNodes[j].nodeName == 'BODY'){
return doc.childNodes[i].childNodes[j];
}
}
}
}
return null;
}
function onLoad1(){
o = document.getElementById('o');

f = document.getElementById('f');
d = f.contentDocument;
b = findBody(d);
d.charset = 'utf-8';
b.contentEditable = true;
b.innerHTML = '<div>HELLO WORLD</div>'
+ '<font style="color:red;">red string</font> '
+ '<a href="http://www.google.com/">google</a> '
+ '<font style="color:blue;">blue string</font>'
+ '<div>editable</div>';
b.focus();
}
function test1(){
var s = f.contentWindow.getSelection();
for(var i = 0; i < s.rangeCount; ++i){
var r = s.getRangeAt(i);
la = r;
var fragment = d.createDocumentFragment();
var div = d.createElement('div');
div.innerHTML = '<font style="color:green;font-size:large;font-weight:bold;">'
+ r + '</font>';
while(div.firstChild){
fragment.appendChild(div.firstChild);
}
var container = r.startContainer;
var offset = r.startOffset;
r.deleteContents();
switch(container.nodeType){
case 1:
container.insertBefore(fragment, container.clidNodes[offset]);
break;
case 3:
var node = container.splitText(offset);
node.parentNode.insertBefore(fragment, node);
break;
}
}
}
//]]>
</script>
</head>
<body onload="javascript:onLoad1()">
hello
world<br/>
<iframe name="f" id="f" src="about:blank" width="200" height="150"></iframe><br/>
<input type="button" value="test1" onclick="javascript:test1()"/><br/>
<span name="o" id="o">...</span>
</body>
</html>

※注意※IEでは動きません。

2009年3月30日月曜日

Tour de Flex

Tour de Flexも気になる~。時間つくらなくちゃ~。
もとねたはadakoda。

Flex Core ComponentsやサードパーティのComponentsや、FlickrなどのCloud APIsも収録されていて、ソースコードも閲覧できるらしい。

2009年3月24日火曜日

SubversionのWindows版 Ruby Bindings バイナリでsvn info

相変わらずドキュメント少ないなぁ。
http://svn.collab.net/viewvc/svn/trunk/subversion/bindings/swig/ruby/test/ ここを参考にして、とりあえず svn info もどきを作ってみた。
svn_info.rb
#!/usr/local/bin/ruby -Ku
# -*- encoding: utf-8 -*-

require 'svn/core'
require 'svn/client'

def make_context(user, pass)
raise 'no block given' unless block_given?

ctx = Svn::Client::Context.new

ctx.add_simple_prompt_provider(0) do |cred, realm, username, may_save|
cred.username = user
cred.password = pass
cred.may_save = false
end

yield ctx
end

def svn_info(repos_url, user, pass)
make_context(user, pass) do |ctx|
ctx.info(repos_url, 'head') do |path, info|
puts <<INFO
Path: #{path}
URL: #{info.url}
Repository Root: #{info.repos_root_url}
Repository UUID: #{info.repos_UUID}
Revision: #{info.rev}
Node Kind: #{info.kind}
Last Changed Rev: #{info.last_changed_rev}
Last Changed Date: #{info.last_changed_date}
INFO
end
end
end

if $0 == __FILE__
svn_info(*ARGV)
end

SubversionのWindows版 Ruby Bindings バイナリ

今更だけどSubversionのWindows版 Ruby Bindings バイナリが配布されているのを見つけた。

普段はTortoiseSVNで十分なので、コマンドライン版のアップデートを怠っていたのだけれど、久しぶりにアップデートを思い立ってsubversion.tigris.orgに立ち寄ってようやく気がついた。2008年10月末頃からバイナリが配布されていたようだ。

苦労しながらRuby Bindingsをビルドしていた頃が懐かしい。2007年末頃だったかな。

たまにリポジトリやワーキングコピーの操作をプログラムから行いたい時があって、svn.exeをパイプでつないでお茶を濁していたのともサヨウナラできてしまうかも。

早速、多くのマシンにインストールしたOne Click Rubyのruby 1.8.6 p111 i386-mswin32で使ってみることに。

とにかく動かしてみたいので、tigrisからsvn-win32-1.5.6.zipとsvn-win32-1.5.6_rb.zipをダウンロードしてlib/ruby/site_ruby/1.8/svnにぶち込んでirbしてみたが・・・

エラーを示すアラートダイアログボックス。

序数3866がダイナミックライブラリ LIBEAY32.dllから見つかりませんでした

C:\Temp>irb -r svn/client
c:/App/ruby-186-26/lib/ruby/site_ruby/1.8/svn/ext/core.dll: 182: このオペレーテ
ィング システムでは %1 は実行されません。 - c:/App/ruby-186-26/lib/ruby/site_r
uby/1.8/svn/ext/core.dll (LoadError)
from c:/App/ruby-186-26/lib/ruby/site_ruby/1.8/rubygems/custom_require.r
b:31:in `require'
from c:/App/ruby-186-26/lib/ruby/site_ruby/1.8/svn/error.rb:2
from c:/App/ruby-186-26/lib/ruby/site_ruby/1.8/rubygems/custom_require.r
b:31:in `gem_original_require'
from c:/App/ruby-186-26/lib/ruby/site_ruby/1.8/rubygems/custom_require.r
b:31:in `require'
from c:/App/ruby-186-26/lib/ruby/site_ruby/1.8/svn/client.rb:3
from c:/App/ruby-186-26/lib/ruby/site_ruby/1.8/rubygems/custom_require.r
b:31:in `gem_original_require'
from c:/App/ruby-186-26/lib/ruby/site_ruby/1.8/rubygems/custom_require.r
b:31:in `require'
from c:/App/ruby-186-26/lib/ruby/1.8/irb/init.rb:252:in `load_modules'
from c:/App/ruby-186-26/lib/ruby/1.8/irb/init.rb:250:in `each'
from c:/App/ruby-186-26/lib/ruby/1.8/irb/init.rb:250:in `load_modules'
from c:/App/ruby-186-26/lib/ruby/1.8/irb/init.rb:21:in `setup'
from c:/App/ruby-186-26/lib/ruby/1.8/irb.rb:54:in `start'
from c:/App/ruby-186-26/bin/irb:13

C:\Temp>

どうやらdllが古いらしい。svn-win32-1.5.6のbinにPATHを通し、ruby-186-26/binのlibeay32.dllとssleay32.dllのファイル名を適当に変えて、再挑戦・・・

D:\Temp>irb -r svn/core
irb(main):001:0>
D:\Temp>

動いた~♪

EclipseNSISを試してみる

NSISでインストーラを作ってみることを思い立ち、久しぶりにしらべてみたところ、EclipseNSISという便利そうなプラグインが開発されていることを発見。早速試してみることにする。

手元にあったEclipseはEuropa(3.3.2 M20080221-1800)で、EclipseNSISは3.4以上でないと動かないとのこと。早速eclipse.orgからeclipse-jee-ganymede-SR2-win32.zipをダウンロード&インストール&アップデート。(3.4.2 M20090211-1700)
※jeeは163Mもある。Eclipse IDE for C/C++ Developers (68 MB)こっちでも良かったかも。

そして、EclipseのSoftware Updates and Add-onsでhttp://eclipsensis.sf.net/updateからインストールする。EclipseNSIS(0.9.7.2)とEclipseNSIS InstallOptions Editor(0.9.7)の2つを選択した。

NSISを使うためには当然ながらNSISをインストールしなければいけない。NSISのウェブサイトからNSIS 2.44 Feb 21, 2009(現時点での最新版)をダウンロード&インストール。

以上で環境構築完了。

プロジェクトの作成は、EclipseのFile>New>Other...からEclipseNSIS>NSIS Scriptを選択するとWizardが起動するので必要な情報を入力していくだけ。

驚くほど簡単だ。

2009年3月23日月曜日

Bloggerにコードを載せる(2)

スタイルを変更してみた。

CSS
/* MyCode
----------------------------------------------- */
.mycodeT, .mycodeB {
font-family: consolas, "Courier New", courier, monospace;
padding: 3px 3px 3px;
}
.mycodeT {
margin: 1em 1em 0;
color: black;
background: #ffc080;
font-weight: bold;
}
.mycodeB {
margin: 0 1em 1em;
color: black;
background: papayawhip;
border-width: 1px;
border-color: #ffc080;
border-style: solid;
overflow-x: auto;
word-wrap: normal;
}