<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>JeffHung.Blog &#187; Tip</title>
	<atom:link href="http://www.jeffhung.net/blog/categories/tip/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jeffhung.net/blog</link>
	<description>(My smile insists of having nose. :-)</description>
	<lastBuildDate>Thu, 24 Nov 2011 07:25:31 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.2-alpha</generator>
		<item>
		<title>Obtaining java env vars from javavmwrapper</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/807/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/807/#comments</comments>
		<pubDate>Mon, 12 Feb 2007 05:27:14 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Tip]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[shellscript]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/807/</guid>
		<description><![CDATA[JRE 有很多版本，也有很多廠商出，因此，FreeBSD 有提供一個 ports 叫做 java/javavmwrapper，是一組 shell script，會自動依據設定，從安裝於系統中的眾多 JRE 中，選擇最新或最適當的 JVM，設定環境變數後，執行 java 程式。java/javavmwrapper 安裝的主 script 叫 javavm，後面以此稱之。 然而，有些用 Java 寫的重量級套件，會附上完整的啟動 script，自動進行相關的設定，如 CLASSPATH 等。而這些啟動 script，其實並不懂怎麼使用 javavm，因此需要人工設定如 JAVA_HOME 等環境變數。也就是說，要用這些 script，我們就沒辦法利用 javavm 聰明的功能，來幫我們管理 JVMs。 還好，UNIX 系統的強項，就是方便的指令組合功能。如果 JAVAVM_DRYRUN 環境變數存在的話，javavm 就不會真的執行 JVM，而是將相關的環境變數印出來。透過這個機制，我們就可以重用 javavm 的聰明管理機制。如下： env `env JAVAVM_DRYRUN=yes java &#124; xargs echo` bin/startup.sh 在 FreeBSD 裡，裝了 java/javavmwrapper 以後，/usr/local/bin/java 其實會指到 javavm，自動幫我們選擇 JVM，因此上面的指令我們可以直接使用 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/Java_Runtime_Environment">JRE</a> 有很多版本，也有很多廠商出，因此，<a href="http://www.freebsd.org/">FreeBSD</a> 有提供一個 ports 叫做 <a href="http://www.freshports.org/java/javavmwrapper/">java/javavmwrapper</a>，是一組 shell script，會自動依據設定，從安裝於系統中的眾多 JRE 中，選擇最新或最適當的 JVM，設定環境變數後，執行 java 程式。java/javavmwrapper 安裝的主 script 叫 <code class="inline_code">javavm</code>，後面以此稱之。</p>
<p>然而，有些用 Java 寫的重量級套件，會附上完整的啟動 script，自動進行相關的設定，如 <code class="inline_code">CLASSPATH</code> 等。而這些啟動 script，其實並不懂怎麼使用 <code class="inline_code">javavm</code>，因此需要人工設定如 <code class="inline_code">JAVA_HOME</code> 等環境變數。也就是說，要用這些 script，我們就沒辦法利用 <code class="inline_code">javavm</code> 聰明的功能，來幫我們管理 JVMs。</p>
<p>還好，UNIX 系統的強項，就是方便的指令組合功能。如果 <code class="inline_code">JAVAVM_DRYRUN</code> 環境變數存在的話，<code class="inline_code">javavm</code> 就不會真的執行 JVM，而是將相關的環境變數印出來。透過這個機制，我們就可以重用 <code class="inline_code">javavm</code> 的聰明管理機制。如下：</p>
<pre class="code">env `env JAVAVM_DRYRUN=yes java | xargs echo` bin/startup.sh</pre>
<p>在 FreeBSD 裡，裝了 java/javavmwrapper <code class="inline_code"></code>以後，<code class="inline_code">/usr/local/bin/java</code> 其實會指到 <code class="inline_code">javavm</code>，自動幫我們選擇 JVM，因此上面的指令我們可以直接使用 <code class="inline_code">java</code> 呼叫。利用 <code class="inline_code">env</code>，我們讓 <code class="inline_code">javavm</code> 一行一行地印出 Java 相關的環境變數，如下：</p>
<pre class="code">JAVA_HOME=/usr/local/diablo-jdk1.5.0JAVAVM_CONF=/usr/local/etc/javavmsJAVAVM_OPTS_CONF=/usr/local/etc/javavm_opts.confJAVAVM_PROG=/usr/local/diablo-jdk1.5.0/bin/javaJAVAVM_OPTS=JAVAVM_COMMAND=/usr/local/diablo-jdk1.5.0/bin/java</pre>
<p>然後，pipe 給 <code class="inline_code">xargs echo</code> 將這幾行接起來，以空白隔開，然後再餵給 <code class="inline_code">env</code>，變成套件所需的 java 環境變數，以啟動 <code class="inline_code">bin/startup.sh</code>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/807/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Doxygen syntax coloring in Vim</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/447/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/447/#comments</comments>
		<pubDate>Tue, 02 May 2006 07:34:47 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Devel]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tip]]></category>
		<category><![CDATA[cpp]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[opensource]]></category>

		<guid isPermaLink="false">http://www.jeffhung.net/blog/articles/jeffhung/447/</guid>
		<description><![CDATA[Vim 的 syntax coloring 功能強大，讓人愛不釋手；而 doxygen 的出現，讓 C、C++ 甚至 Perl，也都能有像 Javadoc 那樣的 in-code documentation solution。如果能夠兩者結合，如許多 Java IDE 在 editor 裡對 Javadoc 的支援那樣，連 comment 裡的文件內容，都能夠把 syntax coloring 弄得漂漂亮亮的，那就更棒了。 剛剛在逛 doxygen 網站，被我發現這個 script：《DoxyGen Syntax : DoxyGen Highlighting on top of c/c++/java》。簡單說，就是能夠在原本 Vim 對 C/C++/Java/... 的 syntax coloring 的基礎上，再增加對註解裡 doxygen 文件內容的 syntax coloring。於是趕緊抓下來試試。 網頁上的安裝方法比較複雜，我試了幾次沒有成功。所以就研究了一下 Vim 的 online document，發現 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.vim.org/">Vim</a> 的 syntax coloring 功能強大，讓人愛不釋手；而 <a href="http://www.doxygen.org/">doxygen</a> 的出現，讓 C、C++ 甚至 Perl，也都能有像 <a href="http://en.wikipedia.org/wiki/Javadoc">Javadoc</a> 那樣的 in-code documentation solution。如果能夠兩者結合，如許多 Java IDE 在 editor 裡對 Javadoc 的支援那樣，連 comment 裡的文件內容，都能夠把 syntax coloring 弄得漂漂亮亮的，那就更棒了。</p>
<p>剛剛在逛 doxygen 網站，被我發現這個 script：《<a href="http://www.vim.org/scripts/script.php?script_id=5">DoxyGen Syntax : DoxyGen Highlighting on top of c/c++/java</a>》。簡單說，就是能夠在原本 Vim 對 C/C++/Java/... 的 syntax coloring 的基礎上，再增加對註解裡 doxygen 文件內容的 syntax coloring。於是趕緊抓下來試試。</p>
<p>網頁上的安裝方法比較複雜，我試了幾次沒有成功。所以就研究了一下 Vim 的 online document，發現 <a href="http://vimdoc.sourceforge.net/htmldoc/syntax.html#mysyntaxfile-add"><code class="inline_code">*mysyntaxfile-add*</code></a> 這一節這麼說道：</p>
<blockquote>
<p>If you are mostly satisfied with an existing syntax file, but would like to add a few items or change the highlighting, follow these steps:</p>
<ol>
<li>Create your user directory from 'runtimepath', see above.</li>
<li>Create a directory in there called &quot;after/syntax&quot;.&nbsp; For Unix:
<pre class="code">
mkdir ~/.vim/after
mkdir ~/.vim/after/syntax</pre>
</li>
<li>Write a Vim script that contains the commands you want to use.&nbsp; For example, to change the colors for the C syntax:
<pre class="code">
highlight cComment ctermfg=Green guifg=Green</pre>
</li>
<li>Write that file in the &quot;after/syntax&quot; directory.&nbsp; Use the name of the syntax, with &quot;.vim&quot; added.&nbsp; For our C syntax:
<pre class="code">
:w ~/.vim/after/syntax/c.vim</pre>
</li>
</ol>
<p>That's it.&nbsp; The next time you edit a C file the Comment color will be different.&nbsp; You don't even have to restart Vim.</p>
</blockquote>
<p>也就是說，放在 <code class="inline_code">~/.vim/after/syntax</code> 目錄下的檔案，會自動附加到對應檔名的 vim syntax coloring 檔案。如 <code class="inline_code">~/.vim/after/syntax/c.vim</code> 就會自動附加到 <code class="inline_code">/usr/locall/share/vim/syntax/c.vim</code> 裡。因此，整件事就很簡單啦：為每一個想要增加 doxygen syntax coloring 的檔案類型，複製一份 doxygen syntax 檔以檔案類型為檔名，放在該目錄下即可，正常來說，連一行 <code class="inline_code">~/.vimrc</code> 的設定都不必加。我的作法如下：</p>
<ol>
<li>建立 <code class="inline_code">~/.vim/after/syntax</code> 目錄；</li>
<li>自<a href="http://www.vim.org/scripts/script.php?script_id=5">網頁</a>上下載 <a href="http://www.vim.org/scripts/download_script.php?src_id=4884">doxygen.zip (v1.15)</a>；</li>
<li>解開後得到 <code class="inline_code">doxygen.vim</code> 與 <code class="inline_code">doxygen.txt</code> 兩個檔案，前者是 syntax 檔，後者是說明檔。都放到 <code class="inline_code">~/.vim/after/syntax</code> 目錄下；</li>
<li>對於每一個想要使用 doxygen syntax coloring 功能的檔案類型，做一個 soft link 如下：
<pre class="code">
cd ~/.vim/after/syntax;
ln -s doxygen.vim c.vim;
ln -s doxygen.vim cpp.vim;
ln -s doxygen.vim java.vim;</pre>
</li>
<li>如果是在 Windows 下，那就在第四步時改用 copy。</li>
</ol>
<p>有圖有真相：</p>
<div align="center"><a target="_blank" href="http://flickr.com/photos/jeffhung/138941096/"><img alt="Screenshot for doxygen syntax coloring in vim" src="http://static.flickr.com/45/138941096_c43d408faa.jpg" /></a></p>
<div align="left">
<p>另外，以下是看到的幾套，doxygen 整合其他 IDE 的 solutions：</p>
<ul>
<li><a href="http://home.gna.org/eclox/">Eclox</a> - <em>Eclox is a simple doxygen frontend 		plug-in for <a href="http://www.eclipse.org/">eclipse</a>.</em></li>
<li><a href="http://doxbar.sourceforge.net/">Doxbar</a> - <em>DoxBar is an add-in for using doxygen from within Developer Studio (VC6).</em></li>
<li><a href="http://doxycomment.sourceforge.net/">DoxyComment for Visual Studio 2005</a> - <em>DoxyComment is an add-in for Visual Studio 2005, which can help you insert comment blocks in C/C++ code. Comment blocks are generated based on the current context of the cursor. The add-in integrates nicely into Visual Studio, so you can bind your favourite short-cut keys to its commands.</em></li>
</ul>
</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/447/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Save current visio page as PNG and SVG files using VBA</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/463/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/463/#comments</comments>
		<pubDate>Tue, 21 Feb 2006 03:19:38 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Devel]]></category>
		<category><![CDATA[Tip]]></category>
		<category><![CDATA[visualbasic]]></category>

		<guid isPermaLink="false">http://www.jeffhung.idv.tw/blog/articles/jeffhung/463/</guid>
		<description><![CDATA[為了要在 OpenOffice.org2 裡用 Visio 畫出來的圖，我總是得先在 Visio 裡 save as 成 PNG 格式，然後再在 OpenOffice.org2 的 writer 裡插入並設定連結。由於要不斷地在 Visio 與 OpenOffice.org2 之間修改，所以每次都要另外設定存檔格式，十分麻煩。所以簡單地寫了個 VBA，簡化這個步驟： 將目前正在編輯的 Visio 檔案的目前頁面，以目前檔名去掉延伸檔名的部分，存檔成 PNG 格式的圖檔 (當然要再加上 .png 副檔名)。 理想上，透過 SVG 格式會更好。但是因為目前 OpenOffice.org2 對 SVG 的支援，只有一個半官方的 XML filter 叫 SVG Import Filter for OpenOffice 2.0 勉強可以用，所以暫時還是在 Visio 裡同時存檔成 PNG 與 SVG 檔，先用 PNG，以後有機會再用 SVG。 用 [...]]]></description>
			<content:encoded><![CDATA[<p>為了要在 <a href="http://www.openoffice.org/">OpenOffice.org2</a> 裡用 <a href="http://en.wikipedia.org/wiki/Microsoft_Visio">Visio</a> 畫出來的圖，我總是得先在 <a href="http://en.wikipedia.org/wiki/Microsoft_Visio">Visio</a> 裡 save as 成 <a href="http://en.wikipedia.org/wiki/PNG">PNG 格式</a>，然後再在 <a href="http://www.openoffice.org/">OpenOffice.org2</a> 的 writer 裡插入並設定連結。由於要不斷地在 <a href="http://en.wikipedia.org/wiki/Microsoft_Visio">Visio</a> 與 <a href="http://www.openoffice.org/">OpenOffice.org2</a> 之間修改，所以每次都要另外設定存檔格式，十分麻煩。所以簡單地寫了個 VBA，簡化這個步驟： </p>
<ul>
<li>將目前正在編輯的 Visio 檔案的目前頁面，以目前檔名去掉延伸檔名的部分，存檔成 <a href="http://en.wikipedia.org/wiki/PNG">PNG 格式</a>的圖檔 (當然要再加上 .png 副檔名)。</li>
<li>理想上，透過 <a href="http://www.w3.org/TR/SVG/">SVG</a> 格式會更好。但是因為目前 <a href="http://www.openoffice.org/">OpenOffice.org2</a> 對 <a href="http://www.w3.org/TR/SVG/">SVG</a> 的支援，只有一個半官方的 XML filter 叫 <a href="http://www.ipd.uni-karlsruhe.de/~hauma/svg-import/">SVG Import Filter for OpenOffice 2.0</a> 勉強可以用，所以暫時還是在 <a href="http://en.wikipedia.org/wiki/Microsoft_Visio">Visio</a> 裡同時存檔成 PNG 與 SVG 檔，先用 PNG，以後有機會再用 <a href="http://www.w3.org/TR/SVG/">SVG</a>。</li>
</ul>
<p> 用 macro 錄製了一下，發覺關鍵很簡單，就是這麼一行： </p>
<pre class="code">
Application.ActiveWindow.Page.Export &lt;filename&gt;
</pre>
<p>其中，<a href="http://en.wikipedia.org/wiki/Microsoft_Visio">Visio</a> 會依據 <code class="inline_code">&lt;filename&gt;</code> 的副檔名，決定要 export 成哪種格式。再加上檔名的處理就一切搞定。以下以 <a href="http://en.wikipedia.org/wiki/Microsoft_Visio">Visio</a> 2003 為準，完整 Sub routine 如下：</p>
<pre class="code">
Sub ExportPageAsPNGandSVG()
'
' Save current diagram as PNG with default transparent color and SVG files.
'
    Dim DotPos
    DotPos= InStrRev(ThisDocument.Name, &quot;.&quot;)
    If Not IsNull(DotPos) And DotPos &gt; 0 Then
        Dim NoExtName
        NoExtName = Left(ThisDocument.Name, DotPos - 1)
'        MsgBox NoExtName
        Application.ActiveWindow.Page.Export ThisDocument.Path + NoExtName + &quot;.png&quot;
        Application.ActiveWindow.Page.Export ThisDocument.Path + NoExtName + &quot;.svg&quot;
    Else
        MsgBox &quot;Cannot resolve path name to save, action cancelled.&quot;
    End If
End Sub
</pre>
<p>從 <a href="http://en.wikipedia.org/wiki/Microsoft_Visio">Visio</a> 的選單裡，Tools -&gt; Macros -&gt; Macros，在 Macro name 欄位裡填上 <code class="inline_code">ExportPageAsPNGandSVG</code>，按 Create 按鈕，會出現 VBA editor，把上面的程式碼填進去，然後從 VBA editor 的選單裡選 File -&gt; Close and Return to Visio 即可。以後就可以隨時從 <a href="http://en.wikipedia.org/wiki/Microsoft_Visio">Visio</a> 選單的 Tools -&gt; Macros 裡，選擇剛剛編輯的 <code class="inline_code">ExportPageAsPNGandSVG</code> 來用。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/463/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Enhance WordPress posting bookmarklet</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/459/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/459/#comments</comments>
		<pubDate>Thu, 16 Feb 2006 07:32:43 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Blogging]]></category>
		<category><![CDATA[Tip]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[wordpress]]></category>

		<guid isPermaLink="false">http://www.jeffhung.idv.tw/blog/articles/jeffhung/459/</guid>
		<description><![CDATA[由於內建了 WYSIWYG 的 HTML editor，Wordpress 2.0.* 的 posting bookmarklet 也可以直接以 WYSIWYG 的形式編輯文章了 (之前的 WYSIWYG 靠的是 plug-in，posting bookmarklet 沒有 plug 到)。 但是，官方的 posting bookmarklet 會取代掉目前的網頁，這樣在編輯文章時很麻煩，沒辦法回來參照原文編寫。所以只好下手改改這個 posting bookmarklet。基本上關鍵在這裡 (其中，Q 是目前被選取的文字，如果有的話)： location.href = 'http://www.jeffhung.idv.tw/blog/wp-admin/post.php?text=' + encodeURIComponent(Q) + '&#38;popupurl=' + encodeURIComponent(location.href) + '&#38;popuptitle=' + encodeURIComponent(document.title); 因為是更改 location.href 來啟動 blog 編輯，所以目前頁面會被替換掉，換成 window.open() 開新視窗，應該就可以了。所以我把這段改成這樣： window.open( 'http://www.jeffhung.idv.tw/blog/wp-admin/post.php?text=' + encodeURIComponent(Q) + '&#38;popupurl=' + [...]]]></description>
			<content:encoded><![CDATA[<p>由於內建了 WYSIWYG 的 HTML editor，Wordpress 2.0.* 的 posting bookmarklet 也可以直接以 WYSIWYG 的形式編輯文章了 (之前的 WYSIWYG 靠的是 plug-in，posting bookmarklet 沒有 plug 到)。</p>
<p>但是，官方的 posting bookmarklet 會取代掉目前的網頁，這樣在編輯文章時很麻煩，沒辦法回來參照原文編寫。所以只好下手改改這個 posting bookmarklet。基本上關鍵在這裡 (其中，<code class="inline_code">Q</code> 是目前被選取的文字，如果有的話)：</p>
<pre class="code">
location.href
	= 'http://www.jeffhung.idv.tw/blog/wp-admin/post.php?text='
	+ encodeURIComponent(Q)
	+ '&amp;popupurl='
	+ encodeURIComponent(location.href)
	+ '&amp;popuptitle='
	+ encodeURIComponent(document.title);
</pre>
<p>因為是更改 <code class="inline_code">location.href</code> 來啟動 blog 編輯，所以目前頁面會被替換掉，換成 <code class="inline_code">window.open()</code> 開新視窗，應該就可以了。所以我把這段改成這樣：</p>
<pre class="code">
window.open(
	'http://www.jeffhung.idv.tw/blog/wp-admin/post.php?text='
	+ encodeURIComponent(Q)
	+ '&amp;popupurl='
	+ encodeURIComponent(location.href)
	+ '&amp;popuptitle='
	+ encodeURIComponent(document.title)
);
</pre>
<p>卻沒想到，雖然新的 blog 編輯視窗有正確出現了，但原來的頁面卻被切換成這樣：</p>
<pre>
[object Window]</pre>
<p>研究了網路上其他的 bookmarklet 的寫法，才恍然大悟，如果 bookmarklet 的最後一個 statement 有「值」的話，browser (firefox) 就會把這個值顯示在頁面上。所以在最後加一個 <code class="inline_code">void(null);</code> 就可以了。最後的 wordpress posting bookmarklet 完整如下：</p>
<pre class="code">
javascript:
if (navigator.userAgent.indexOf('Safari') &gt;= 0) {
	Q = getSelection();
}
else {
	Q = document.selection
	  ? document.selection.createRange().text
	  : document.getSelection();
}
window.open(
	'http://www.jeffhung.idv.tw/blog/wp-admin/post.php?text='
	+ encodeURIComponent(Q)
	+ '&amp;popupurl='
	+ encodeURIComponent(location.href)
	+ '&amp;popuptitle='
	+ encodeURIComponent(document.title)
);
void(null);
</pre>
<p>縮成一行後如下 (為顯示美觀，以略做折行，請自行連接成一行)，把裡面的 blog 網址改一改，複製製成 bookmark 即可使用：</p>
<pre class="code">
javascript:if(navigator.userAgent.indexOf('Safari')&gt;=0){Q=g
etSelection();}else{Q=document.selection?document.selection
.createRange().text:document.getSelection();}window.open('h
ttp://www.jeffhung.idv.tw/blog/wp-admin/post.php?text='+enc
odeURIComponent(Q)+'&amp;popupurl='+encodeURIComponent(location
.href)+'&amp;popuptitle='+encodeURIComponent(document.title));v
oid(null);
</pre>
<p>不過，最後還是有個缺陷，似乎是 <a href="http://www.google.com/url?sa=t&amp;ct=res&amp;cd=3&amp;url=https%3A//addons.mozilla.org/extensions/moreinfo.php%3Fid%3D1122%26application%3Dfirefox&amp;ei=Syr0Q9uqIrmCYJPOsOkM&amp;sig2=bPYyiTm9C94sjj5JbI3OuQ">Tab Mix Plus</a> 的關係，跳出來的新視窗不會取得焦點 (focus)，所以得手動切換把 blog 編輯視窗找回來才行。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/459/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>__WFILE__ and generic __FILE__, __TFILE__</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/237/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/237/#comments</comments>
		<pubDate>Thu, 28 Jul 2005 08:58:38 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tip]]></category>
		<category><![CDATA[cpp]]></category>

		<guid isPermaLink="false">http://www.jeffhung.idv.tw/blog/?p=237</guid>
		<description><![CDATA[在 C/C++ 裡 debug 的時候，__FILE__ 和 __LINE__ 很好用，可以幫我們將錯誤發生的地點指出來。可是，因為 __FILE__ 對應的型別是 const char* (__LINE__ 對應的型別是 size_t)，在使用 wide character I/O 的時候，便不能用。就算像 L&#34;some string&#34; 一樣，前面加一個 L 也不行，因為這樣子就變成了 L__FILE__，是另外一個 symbol 了。空一格也不行，因為 L&#34;some string&#34; 的 L 必須與引號直接連接。 還好，使用 ## 這個 preprocessor operator 可以解決這個問題： #define WIDEN_(x) L##x #define WIDEN(x) WIDEN_(x) #define __WFILE__ WIDEN(__FILE__) 這樣子我們就可以依據 output 的環境，選擇 __FILE__ 或 __WFILE__ 來使用了： void [...]]]></description>
			<content:encoded><![CDATA[<p>在 C/C++ 裡 debug 的時候，<code class="inline_code">__FILE__</code> 和 <code class="inline_code">__LINE__</code> 很好用，可以幫我們將錯誤發生的地點指出來。可是，因為 <code class="inline_code">__FILE__</code> 對應的型別是 <code class="inline_code">const char*</code> (<code class="inline_code">__LINE__</code> 對應的型別是 <code class="inline_code">size_t</code>)，在使用 wide character I/O 的時候，便不能用。就算像 <code class="inline_code">L&quot;some string&quot;</code> 一樣，前面加一個 <code class="inline_code">L</code> 也不行，因為這樣子就變成了 <code class="inline_code">L__FILE__</code>，是另外一個 symbol 了。空一格也不行，因為 <code class="inline_code">L&quot;some string&quot;</code> 的 <code class="inline_code">L</code> 必須與引號直接連接。  還好，使用 <code class="inline_code">##</code> 這個 preprocessor operator 可以解決這個問題：</p>
<pre class="code">
#define WIDEN_(x) L##x
#define WIDEN(x)  WIDEN_(x)
#define __WFILE__ WIDEN(__FILE__)</pre>
<p>這樣子我們就可以依據 output 的環境，選擇 <code class="inline_code">__FILE__</code> 或 <code class="inline_code">__WFILE__</code> 來使用了：</p>
<pre class="code">
void fout(ostream&amp; os)
{
    os &lt;&lt; __FILE__ &lt;&lt; endl;
}

void wfout(wostream&amp; os)
{
    os &lt;&lt; __WFILE__ &lt;&lt; endl;
}

int main()
{
    fout(cout);
    wfout(wcout);
    return 0;
}</pre>
<p>可是，如果是在 template class/function 裡面呢？Character/string 的真實型別，由 template parameter 決定，我們根本無從選擇該用 <code class="inline_code">__FILE__</code> 還是 <code class="inline_code">__WFILE__ </code>怎麼辦？這時候，如果有個 generic 版本的 <code class="inline_code">__TFILE__</code>，能夠自動選擇要用 <code class="inline_code">__FILE__</code> 還是 <code class="inline_code">__WFILE__</code> 的話，那該有多好？可惜 pre-processor 不支援 template resolution，無法做到 generic。</p>
<pre class="code">
#define __TFILE__(char_type) \
        ((sizeof(char_type) == sizeof(char)) ? __FILE__ : __WFILE__)</pre>
<p>如上列程式使用 conditional operator 將 <code class="inline_code">__FILE__</code> 與 <code class="inline_code">__WFILE__</code> 的選擇，留待 compile-time 再來解決，是不可行的。原本的想法是，<code class="inline_code">(sizeof(char_type) == sizeof(char))</code><code class="inline_code">__FILE__</code> 與 <code class="inline_code">__WFILE__</code> 的型別不同 (分別為 <code class="inline_code">const char*</code> 與 <code class="inline_code">const wchar_t*</code>)，所以這樣子使用 conditional operator 是非法的。  山不轉路轉，「把 <code class="inline_code">__FILE__</code> 與 <code class="inline_code">__WFILE__</code> 的選擇，留待 compile-time 再來解決」的基本想法應該是對的，既然 conditional operator 不能用，那用 template specialization 如何？如下列程式：</p>
<p>是個 constant expression，所以 compiler 可以 optimize 選擇正確的版本。但因為 C++ standard 5.16.5 說，當 conditional operator 的第二個及第三個 operands 為 r-value 時，兩者的 type 必須匹配，除非可藉由 overload resolution 解決歧義。因為</p>
<pre class="code">
#include &lt;functional&gt;

template &lt;class CharT&gt;
struct tfile_sel
    : public ::std::binary_function&lt;const char*, const wchar_t*,
                                    const CharT*&gt;
{
    const CharT* operator () (const char* f, const wchar_t* wf)
    {
        return 0;
    }
};

template &lt;&gt;
inline
const char* tfile_sel&lt;char&gt;::operator () (const char* f,
                                          const wchar_t* wf)
{
    return f;
}

template &lt;&gt;
inline
const wchar_t* tfile_sel&lt;wchar_t&gt;::operator () (const char* f,
                                                const wchar_t* wf)
{
    return wf;
}

#define __TFILE__(char_type) tfile_sel&lt;char_type&gt;()(__FILE__, __WFILE__)</pre>
<p>利用 template specialization 選擇 <code class="inline_code">__FILE__</code> 或 <code class="inline_code">__WFILE__</code>，然後因為 template specialization 以及 inline 的關係，最後的 run-time overhead 理論上也應該要蠻小的。就算有，也不大，反正大多在 debug mode 裡用，可以省略這一點點的 overhead。如此，完成的 <code class="inline_code">__TFILE__</code> 可以這麼樣子用：</p>
<pre class="code">
using namespace ::std;

template &lt;class CharT&gt;
void tfout(basic_ostream&lt;CharT&gt;&amp; os)
{
    os &lt;&lt; __TFILE__(CharT) &lt;&lt; endl;
}

int main()
{
    tfout(cout);
    tfout(wcout);
    return 0;
}</pre>
<p>總整理上面的 code，含測試程式如下：</p>
<pre class="code">
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;functional&gt;

#define WIDEN_(x) L##x
#define WIDEN(x)  WIDEN_(x)
#define __WFILE__ WIDEN(__FILE__)

using namespace ::std;

template &lt;class CharT&gt;
struct tfile_sel
    : public ::std::binary_function&lt;const char*, const wchar_t*,
                                    const CharT*&gt;
{
    const CharT* operator () (const char* f, const wchar_t* wf)
    {
        return 0;
    }
};

template &lt;&gt;
inline
const char*
tfile_sel&lt;char&gt;::operator () (const char* f, const wchar_t* wf)
{
    return f;
}

template &lt;&gt;
inline
const wchar_t*
tfile_sel&lt;wchar_t&gt;::operator () (const char* f, const wchar_t* wf)
{
    return wf;
}

#define __TFILE__(char_type) tfile_sel&lt;char_type&gt;()(__FILE__, __WFILE__)

template &lt;class CharT&gt;
void tfout(basic_ostream&lt;CharT&gt;&amp; os)
{
    os &lt;&lt; __TFILE__(CharT) &lt;&lt; endl;
}

int main()
{
    tfout(cout);
    tfout(wcout);
    return 0;
}</pre>
<p>以上技巧有待統整的地方很多，好比 <code class="inline_code">WIDEN()</code> 可以提出來變成一個獨立的模組以便再利用 (reuse)。另外，雙底線開頭的識別字，在 C/C++ 裡是保留給 standard 與 compiler vendor 用的，所以最好另外換個名字。最後，應該也可以參考 <a href="http://www.boost.org/" target="_blank">Boost</a> 的 <a href="http://www.boost.org/libs/preprocessor/doc/" target="_blank">preprocessor library</a>，也許可以有其他不一樣的作法也說不定。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/237/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>TSDropCopy - Copying files between terminal server and client</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/169/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/169/#comments</comments>
		<pubDate>Fri, 17 Jun 2005 07:37:53 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Tip]]></category>
		<category><![CDATA[tsdropcopy]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://www.jeffhung.idv.tw/blog/articles/jeffhung/169/</guid>
		<description><![CDATA[今天同事介紹了一個很有用的軟體：TSDropCopy，這是一個可以讓您在 Windows Terminal Server 和 client 之間，方便傳檔的小軟體。只要把在兩端各自執行，TSDropCopy 就會停留在桌面的右下方，點兩下，就會跑出一個小視窗，將您要傳的檔案拉到這個小視窗裡，檔案就會自動傳到令一邊去。 由於平常工作時，網路是設定在部門獨立使用的 ADSL 這邊，必須透過 terminal service 連到 server 開 Outlook 才能看信。如果信件裡有夾檔，就很難傳回本機電腦，必須要到外面找台 server，用 command-line FTP 先傳上去，再從本機抓回來，非常麻煩。現在有了這個 TSDropCopy，收夾檔從此就不再是個問題了。]]></description>
			<content:encoded><![CDATA[<p>今天同事介紹了一個很有用的軟體：<a target="_blank" href="http://www.analogx.com/contents/download/system/tsdc.htm">TSDropCopy</a>，這是一個可以讓您在 <a target="_blank" href="http://www.microsoft.com/windows2000/technologies/terminal/default.asp">Windows Terminal Server</a> 和 client 之間，方便傳檔的小軟體。只要把在兩端各自執行，<a target="_blank" href="http://www.analogx.com/contents/download/system/tsdc.htm">TSDropCopy</a> 就會停留在桌面的右下方，點兩下，就會跑出一個小視窗，將您要傳的檔案拉到這個小視窗裡，檔案就會自動傳到令一邊去。</p>
<p>  由於平常工作時，網路是設定在部門獨立使用的 <a target="_blank" href="http://en.wikipedia.org/wiki/Asymmetric_Digital_Subscriber_Line">ADSL</a> 這邊，必須透過 <a target="_blank" href="http://www.microsoft.com/windows2000/technologies/terminal/default.asp">terminal service</a> 連到 server 開 <a href="http://en.wikipedia.org/wiki/Microsoft_Outlook" target="_blank">Outlook</a> 才能看信。如果信件裡有夾檔，就很難傳回本機電腦，必須要到外面找台 server，用 command-line FTP 先傳上去，再從本機抓回來，非常麻煩。現在有了這個 <a target="_blank" href="http://www.analogx.com/contents/download/system/tsdc.htm">TSDropCopy</a>，收夾檔從此就不再是個問題了。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/169/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>沒有寫好程式以前，不能上網</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/164/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/164/#comments</comments>
		<pubDate>Thu, 16 Jun 2005 05:11:09 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Devel]]></category>
		<category><![CDATA[Tip]]></category>

		<guid isPermaLink="false">http://www.jeffhung.idv.tw/blog/articles/jeffhung/164/</guid>
		<description><![CDATA[flyinsaucer 在這篇《寫作指南》裡，提出了三個方法，幫助我們增進寫作 (工作) 的效率： 設條件寫作法 (Contingency)：沒有做 XXX 之前 (XXX 是和寫作看書有關)，不可以做 YYY (就是喜歡做的事)； 改變環境：要把會分心的東西拿掉； 設定目標無法達成的懲罰：寫一張支票給你最討厭的機構，如果沒有照達成計畫的目標，保管那張支票的人就可以把它寄出去。 所以，，就此規定，在我沒有寫好程式以前，不能上網。 可是，寫程式需要上網找資料啊！&#62;&#60;]]></description>
			<content:encoded><![CDATA[<p>flyinsaucer 在這篇《<a target="_blank" href="http://blog.yam.com/Karma/archives/191574.html">寫作指南</a>》裡，提出了三個方法，幫助我們增進寫作 (工作) 的效率：</p>
<ol>
<li>設條件寫作法 (Contingency)：沒有做 XXX 之前 (XXX 是和寫作看書有關)，不可以做 YYY (就是喜歡做的事)；</li>
<li>改變環境：要把會分心的東西拿掉；</li>
<li>設定目標無法達成的懲罰：寫一張支票給你最討厭的機構，如果沒有照達成計畫的目標，保管那張支票的人就可以把它寄出去。 </li>
</ol>
<p>所以，，就此規定，在我沒有寫好程式以前，不能上網。  可是，<strong>寫程式需要上網找資料</strong>啊！&gt;&lt; </p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/164/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Search plug-in for FreeBSD manpage search</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/38/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/38/#comments</comments>
		<pubDate>Sat, 21 May 2005 12:00:05 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Tip]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[freebsd]]></category>

		<guid isPermaLink="false">http://www.jeffhung.idv.tw/blog/articles/jeffhung/38/</guid>
		<description><![CDATA[寫 blog 時，常會提到 UNIX/FreeBSD 指令，為方便加 link，以及自己的查詢需求，寫了下面這個 FreeBSD man-page search plug-in ，歡迎大家使用。:-) # Search Plug-in for FreeBSD man-page search &#60;search version = &#34;1.0&#34; name=&#34;FreeBSD Man&#34; description=&#34;FreeBSD Hypertext Man Pages&#34; method=&#34;GET&#34; action=&#34;http://www.freebsd.org/cgi/man.cgi&#34; &#62; &#60;input name=&#34;query&#34; user&#62; &#60;/search&#62; &#60;browser update=&#34;http://www.jeffhung.net/~jeffhung/firefox/search-plugin/freebsd-man.src&#34; updateIcon=&#34;http://www.jeffhung.net/~jeffhung/firefox/search-plugin/freebsd-man.png&#34; updateCheckDays=&#34;7&#34; &#62;]]></description>
			<content:encoded><![CDATA[<p>寫 blog 時，常會提到 UNIX/FreeBSD 指令，為方便加 link，以及自己的查詢需求，寫了下面這個 <a target="_blank" href="http://www.jeffhung.idv.tw/~jeffhung/firefox/search-plugin/freebsd-man.src">FreeBSD man-page search plug-in</a> <img area="256" src="http://www.jeffhung.net/~jeffhung/firefox/search-plugin/freebsd-man.png" alt="" />，歡迎大家使用。:-)</p>
<pre class="code">
# Search Plug-in for FreeBSD man-page search

&lt;search
  version = &quot;1.0&quot;
  name=&quot;FreeBSD Man&quot;
  description=&quot;FreeBSD Hypertext Man Pages&quot;
  method=&quot;GET&quot;
  action=&quot;http://www.freebsd.org/cgi/man.cgi&quot;
&gt;

&lt;input name=&quot;query&quot; user&gt;

&lt;/search&gt;

&lt;browser
  update=&quot;http://www.jeffhung.net/~jeffhung/firefox/search-plugin/freebsd-man.src&quot;
  updateIcon=&quot;http://www.jeffhung.net/~jeffhung/firefox/search-plugin/freebsd-man.png&quot;
  updateCheckDays=&quot;7&quot;
&gt;
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/38/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>在 unicode 文字檔裡檢查 big5 字元</title>
		<link>http://www.jeffhung.net/blog/articles/jeffhung/35/</link>
		<comments>http://www.jeffhung.net/blog/articles/jeffhung/35/#comments</comments>
		<pubDate>Fri, 20 May 2005 08:02:19 +0000</pubDate>
		<dc:creator>jeffhung</dc:creator>
				<category><![CDATA[Devel]]></category>
		<category><![CDATA[Tip]]></category>
		<category><![CDATA[chinese]]></category>
		<category><![CDATA[shellscript]]></category>
		<category><![CDATA[unicode]]></category>

		<guid isPermaLink="false">http://www.jeffhung.idv.tw/blog/articles/jeffhung/35/</guid>
		<description><![CDATA[之前碰到一個問題就是，我們有一堆 UTF-8 的 XML 檔案，但實際上這些檔案應該都只包含中文字，也就是可以用 BIG5 呈現的字。然而，因為是 UTF-8 是 Unicode 的關係，所以實際上可能存在有無法轉換成 BIG5 的字，因而違反程式的期待，造成程式的問題。為了避免這樣子的問題，我們必須要檢查這堆 UTF-8 的 XML 檔案，確認每個檔案裡用到的每個 UTF-8 字元，都可以被轉換成 BIG5。這個問題，在考慮到其實 BIG5 也有很多變種的情況下，越是複雜。 不過還好，想通了話其實就很簡單：用 iconv 試轉不就得了： SHELL&#62; find . -type f -name '*.xml' \ &#124; xargs -n 1 -t -x iconv -f UTF-8 -t CP950 \ &#62; /dev/null 2&#62; conv.log 這裡需注意的是，必須要用 sh 或 bash 跑這個指令，因為 csh/tcsh [...]]]></description>
			<content:encoded><![CDATA[<p>之前碰到一個問題就是，我們有一堆 UTF-8 的 XML 檔案，但實際上這些檔案應該都只包含中文字，也就是可以用 BIG5 呈現的字。然而，因為是 UTF-8 是 Unicode 的關係，所以實際上可能存在有無法轉換成 BIG5 的字，因而違反程式的期待，造成程式的問題。為了避免這樣子的問題，我們必須要檢查這堆 UTF-8 的 XML 檔案，確認每個檔案裡用到的每個 UTF-8 字元，都可以被轉換成 BIG5。這個問題，在考慮到其實 BIG5 也有很多<a target="_blank" href="http://wiki.debian.org.tw/index.php/Big5Variants">變種</a>的情況下，越是複雜。</p>
<p>不過還好，想通了話其實就很簡單：用 <a href="http://www.freebsd.org/cgi/man.cgi?query=iconv" target="_blank">iconv</a> 試轉不就得了：</p>
<pre class="code">
SHELL&gt; find . -type f -name '*.xml' \
       | xargs -n 1 -t -x iconv -f UTF-8 -t CP950 \
       &gt; /dev/null 2&gt; conv.log</pre>
<p>這裡需注意的是，必須要用 sh 或 bash 跑這個指令，因為 csh/tcsh 不能夠把 stdout 與 stderr 分開 redirect。又，CP950 是 Windows 中文版用的 charset，是 <a target="_blank" href="http://wiki.debian.org.tw/index.php/Big5Variants#CP950">BIG5 的其中一個變種</a>。</p>
<p>然後用 grep 把有問題的檔案過濾出來：</p>
<pre class="code">
SHELL&gt; cat conv.log | grep 'cannot convert'
iconv: ./Sogi0300.xml: cannot convert
iconv: ./Sogi0420.xml: cannot convert
iconv: ./Sogi0869.xml: cannot convert
iconv: ./Sogi1068.xml: cannot convert
iconv: ./Sogi1275.xml: cannot convert</pre>
<p>再一個一個重跑 iconv 找出問題點即可：</p>
<pre class="code">
SHELL&gt; iconv -f UTF-8 -t CP950 ./Sogi0300.xml
&lt;?xml version=&quot;1.0&quot; ?&gt;
&lt;sogi-spec id=&quot;Sogi0300&quot; name=&quot;Alcatel OT512&quot; imgsrc=&quot;Sogi0300.jpg&quot;&gt;
        &lt;category name=&quot;螢幕&quot;&gt;
                &lt;property name=&quot;螢幕背光燈&quot; value=&quot;藍白背光加強型顯示幕&quot; /&gt;
                &lt;property name=&quot;螢幕&quot; value=&quot;:可使用縮放效果, 最多6行文字, 最少4行文字&quot; /&gt;
                &lt;property name=&quot;主螢幕解析度&quot; value=&quot;96 * 65  pixels&quot; /&gt;
                &lt;property name=&quot;螢幕娛樂&quot; value=&quot;開機動畫, 關機動畫, 遊戲, 待機圖案&quot; /&gt;
        &lt;/category&gt;
        &lt;category name=&quot;機身外觀&quot;&gt;
                &lt;property name=&quot;尺寸&quot; value=&quot;97 * 42 * 20  mm&quot; /&gt;
iconv: SogiDB-v0.4-r190-20050509-163814/Sogi0300.xml: cannot convert
                &lt;property name=&quot;機身顏色&quot; value=&quot;浮世金、雅仕銀，螢幕的外框和液晶改Exit 1</pre>
<p>噹噹！錯誤發生在「改」字的後面。</p>
<p><strong>更新 2005-11-04</strong>：我這篇《<a href="http://www.jeffhung.net/blog/articles/jeffhung/322/" target="_blank">List non utf-8 encoded files</a>》講的是一樣的事情。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jeffhung.net/blog/articles/jeffhung/35/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

