Category Archives: 未分類

txfonts のインテグラルのフォントを変える

Wednesday, July 17, 2013

txfonts の積分記号や総和記号は,他のフォントに変えることができる.

txfonts そのまま:
txfonts-normal
\int と \sum のフォントを変更:
txfonts-cm

例えば,\int, \oint, \sum, \prod のフォントを Computer Modern に戻すなら,プリアンブルに次のように書く.

\usepackage{txfonts}

\DeclareSymbolFont{cmlargesymbols}{OMX}{cmex}{m}{n}
\DeclareMathSymbol{\intop}{\mathop}{cmlargesymbols}{"5A}
  \def\int{\intop\nolimits}
\DeclareMathSymbol{\ointop}{\mathop}{cmlargesymbols}{"49}
  \def\oint{\ointop\nolimits}
\DeclareMathSymbol{\sumop}{\mathop}{cmlargesymbols}{"58}
  \let\sum\sumop
\DeclareMathSymbol{\prodop}{\mathop}{cmlargesymbols}{"59}
  \let\prod\prodop

{cmex} の代わりに {ztmcm} と書けば,mathptmx のフォントを借りてくることもできる.

文字コード表は,次のように tex testfont を実行すると得られる (cmex9 の文字コード表).

% tex testfont
Name of the font to test = cmex9
* \table
* \end

この文字コード表にない \iint などのフォントを変えるには,txfonts.sty を直接編集する.次の 2 行をコメントアウトすれば,\iint がデフォルトのフォントで出力される.

\re@DeclareMathSymbol{\iintop}{\mathop}{largesymbolsA}{33}
   \def\iint{\iintop\nolimits}

ちなみに,txfonts の改良版である newtx パッケージというのもあるが,使ってみた感じではまだバグが目立つ気がする.

参考文献

pxfonts (txfonts) の記号の一部を変える
http://perikanfan.web.fc2.com/tex.html
Mathptmx – TeX Wiki
http://oku.edu.mie-u.ac.jp/~okumura/texwiki/?Mathptmx

[C#] nkf を用いた文字コードの判別

Monday, October 15, 2012

オープンソースである nkf を借用して,テキストファイルの文字コードを簡単に判別できます。バージョン 2.0.9 以降の nkf のライセンスは zlib/libpng License です (極めて良心的なライセンスです)。対応文字コードは次の通りです。

  • Shift_JIS
  • EUC-JP
  • ISO-2022-JP
  • UTF-8
  • UTF-16LE
  • UTF-16BE

nkf32.dll を用意し,実行ファイルと同じディレクトリに置く必要があります。nkf32.dll は Vector からダウンロードできます。元々の nkf とは異なるライセンスですので,配布条件を確認してください (とは言っても緩い条件です)。

nkf.exe nkf32.dll Windows 用
http://www.vector.co.jp/soft/win95/util/se295331.html

文字コードの判別を行うには,私が作った EncodingUtilities クラスを利用してください。まずは使い方の見本から。

using System;
using System.Text;

class Program
{
    static void Main()
    {
        string path = @"c:\works\hoge.txt";

        // 文字コードを判別
        Encoding enc = EncodingUtilities.DetectEncoding(path);

        // テキストエディタを作るならこうしとくといい
        if (enc == null || enc == Encoding.ASCII)
        {
            enc = Encoding.Default;
        }

        // 処理...
    }
}

次のリンクからダウンロードできます。断りなく自由に使っていただいて結構です。

ソースコード: EncodingUtilities.cs

// EncodingUtilities.cs

using System;
using System.IO;
using System.Text;

/// <summary>
/// エンコーディングを取り扱うユーティリティを提供します。
/// </summary>
public static class EncodingUtilities
{
    /// <summary>
    /// テキストファイルで使われている文字コードを判別し,対応する Encoding オブジェクトを返します。
    /// </summary>
    /// <param name="path">テキストファイルへのパス。</param>
    /// <returns>Shift_JIS, EUC-JP, ISO-2022-JP, UTF-8, UTF-16, UTF-16BE, US-ASCII, null のいずれかが返ります。</returns>
    public static Encoding DetectEncoding(string path)
    {
        // -g: 自動判別の結果を出力する。
        // -t: 何もしない。
        SetNkfOption("-gt");

        byte[] bytes;
        
        using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
        {
            bytes = new byte[fs.Length];
            fs.Read(bytes, 0, bytes.Length);
        }

        unsafe
        {
            fixed (byte* pbs = bytes)
            {
                StringBuilder strBldr = new StringBuilder(1);
                NkfConvert(strBldr, (char*) pbs);
            }
        }

        int nEnc = NkfGetKanjiCode();

        // US-ASCII も ISO-2022-JP と判別されるので,更に篩にかける。
        if (nEnc == nJIS)
        {
            nEnc = nASCII;  // US-ASCII と仮定する
            for (int i = 0; i < bytes.Length; i++)
            {
                if (bytes[i] == 0x1b) // ISO-2022-JP であれば ESC (0x1B) が含まれる
                {
                    nEnc = nJIS;
                    break;
                }
            }
        }

        switch (nEnc)
        {
            case nSJIS:
                return Encoding.GetEncoding("shift_jis");
            case nEUC:
                return Encoding.GetEncoding("euc-jp");
            case nJIS:
                return Encoding.GetEncoding("iso-2022-jp");
            case nUTF8:
                return Encoding.GetEncoding("utf-8");
            case nUTF16LE:
                return Encoding.GetEncoding("utf-16");
            case nUTF16BE:
                return Encoding.GetEncoding("utf-16BE");
            case nASCII:
                return Encoding.ASCII;
            default:
                return null;
        }
    }

    #region nkf functions

    [System.Runtime.InteropServices.DllImport("nkf32.dll")]
    static extern int SetNkfOption(string optStr);

    [System.Runtime.InteropServices.DllImport("nkf32.dll")]
    unsafe static extern void NkfConvert(StringBuilder outStr, char* inStr);

    [System.Runtime.InteropServices.DllImport("nkf32.dll")]
    static extern int NkfGetKanjiCode();

    #endregion

    #region Fields

    // nSJIS, nEUC, nJIS, nUTF8, nUTF16LE, nUTF16BE の値は NkfGetKanjiCode() の戻り値に対応
    const int nSJIS = 0;
    const int nEUC = 1;
    const int nJIS = 2;
    const int nUTF8 = 3;
    const int nUTF16LE = 4;
    const int nUTF16BE = 5;

    const int nASCII = 1001;

    #endregion
}

「null 以外を返した」という結果は「文字コードを完全に特定できた」という意味を持つ訳ではありません。その点だけ注意してください。これは nkf の仕様に因ります。

[C#] char は全ての Unicode 文字を表せる訳ではない

Monday, October 8, 2012

System.Char のドキュメント (*1) を参照して「Unicode 文字を表します。」と書いてあるのを鵜呑みにし,第 4 水準の「&#140062」(廴+囘,U+2231E) という字を char に入れようとして失敗した。

public class Program
{
    public static void Main()
    {
        string s = char.ConvertFromUtf32(0x2231e);
        char c = s[0];

        MessageBox.Show(s.ToString(), "s"); // 表示される
        MessageBox.Show(c.ToString(), "c"); // 文字化けする
    }
}

U_2231E_MsgBox.png

Microsoft の言う「Unicode」とは Unicode ではなく UTF-16LE のことである。ConvertFromUtf32() の返り値が string 型なのを怪しく思いながら,なかなかその理由に気付けなかったことが敗因だった。


(*1) 古いバージョンを見たのがいけなかった。その後「文字をUTF-16 コード単位で表します。」と訂正されている。

[C#] SubItems[0] がなぜか埋まってる

Thursday, October 4, 2012

2012100401.png

ListViewItemSubItemsAdd でサブ項目を追加しようとすると,なぜか SubItems[0] に入れられない。

// 失敗例

ListViewItem item = new ListViewItem();
item.SubItems.Add("hoge");
item.SubItems.Add("piyo");

Console.WriteLine(item.SubItems[0].Text);  // 
Console.WriteLine(item.SubItems[1].Text);  // hoge

最初は Visual C# のバグかと思ったが,MSDN を読んだらそれらしいことが書いてあった。解決法もわかった。サブ項目をコンストラクタに渡せばいい。

// 成功例

ListViewItem item = new ListViewItem(new[] { "hoge", "piyo" });

Console.WriteLine(item.SubItems[0].Text);  // hoge
Console.WriteLine(item.SubItems[1].Text);  // piyo

ListView.Columns は普通に 0 から Add できるのに,ListViewItem.SubItems はできない。結果ずれる。こういう仕様ってどうなんだろ。

IME

Saturday, September 22, 2012

IME の変換結果を勝手に書き換えてしまうようなアプリケーションを作ろうとして頓挫した途中結果。ImmSetCompositionString がどうしても動かない。

EXPORT LRESULT CALLBACK ImeHookProc(
    int nCode, WPARAM wParam, LPARAM lParam)
{
    /* 前略 */

    // 
    if (pmsg->lParam & GCS_RESULTSTR && wParam == 1)
    {
        HWND hWndActive = GetForegroundWindow();
        HWND hIMEWnd = ImmGetDefaultIMEWnd(hWndActive);
        HIMC hImc = ImmGetContext(hIMEWnd);

        char szBuf[1024];
        memset(szBuf, '\0', sizeof szBuf);

        // これは動く
        ImmGetCompositionString(
            hImc, GCS_RESULTSTR, szBuf, sizeof szBuf);

        /* 中略 (置換処理) */

        // 動かない!
        ImmSetCompositionString(
            hImc, SCS_SETSTR, szBuf, sizeof szBuf, NULL, 0);

        ImmReleaseContext(hIMEWnd, hImc);
    }

    return CallNextHookEx(NULL, code, wParam, lParam);
}

フックプロシージャの部分はこちらを参考にさせていただいた:
http://win32.fc2web.com/win32tips/ime_kakutei.html