◀Unicode版開発トップへ
  • 2377 クリップボード関数の謎引数
    • 2378 Re:クリップボード関数の謎引数
    • 2379 Re:クリップボード関数の謎引数
      • 2380 Re2:クリップボード関数の謎引数
      • 2381 Re2:クリップボード関数の謎引数
  • [2377] クリップボード関数の謎引数 ばぼ 2016年08月26日 17:31

    愚痴です。
    v2.1で実装されたマクロ専用関数の引数定義が
    「なんかおかしくね?」というネタなので、
    大多数のユーザーには関係のない話かと思います。

    CClipboard::GetClipboradByFormat
    CClipboard::SetClipboradByFormat

    nMode -2:通常のサクラの処理, -1:バイナリモード, それ以外:文字コード
    nEndMode -1:文字コードに依存 0:GlobalSize 1:strlen 2:wcslen 4:wchar32_tの文字列

    nMode==-2は良いのです。
    通常のサクラ=unicode、ですから。
    nMode==-1が存在する理由と、文字コードの意味が分からんとです。

    windowsはCF_UNICODETEXT形式が存在する場合、
    CF_TEXT形式を要求したUNICODE非対応アプリに対して、
    ACPによる自動変換を提供します。
    つまり、自前で変換する必要はありません。
    自前で変換してCF_TEXTを突っ込むと副作用もありますし。

    サクラはwindowsロケールが対応しないコードページの、
    いくつかに対応しています。(JisとかEucとかUnicodeとか)

    SetClipboradByFormat("美乳", "CF_TEXT", 2, -1)
    ※"美乳"はEUCにしか存在しないコード値を持つ。

    とした場合、windowsはCF_TEXTにEUCの"美乳"を突っ込みます。
    この状態でCF_UNICODETEXTを要求した場合、
    windowsによる自動変換は"ja-JP.932"で行われます。
    当然、化けますよね。。。
    アプリの作りとしては、windowsロケールが対応しないコードページを使っている場合には、引数指定をガン無視してUNICODEで突っ込む対応が必要になるような気がするのです。

    でも、そうすると引数の存在意義が…
    「意味わからん」というのはそういうことです。

    nEndModeについては存在意義が不明です。
    CF_TEXTとCF_UNICODETEXTを指定した場合のデータサイズは、
    それぞれcharとwchar_tのNUL終端までと決まっています。
    これはWindowsAPIの仕様なので勝手に処理してはいかんです。
    windowsロケールはunicodeファミリを扱えないので、
    UTF32を扱うにはUTF16BEに変換し、unicodeとして突っ込むべきです。


    ググってみた感じだと
    nMode=0(SJIS)、
    nEndMode=-1(文字コード依存)
    で使われているみたいです。
    ※このマクロ関数が実装されてるのはv2系なので
     常に無駄な変換(U→A)が発生するが、
     windowsが勝手に登録するCF_LOCALEは矛盾しないので問題ない。

    取得、設定するデータに「文字列以外」を扱えるなら
    別な突っ込みになるんですけど、
    定義を見る限り、第一引数はVT_BSTR想定だし。。。

    第一引数がVT_ARRAYを受け付ける前提で、
    nMode==-1(バイナリ)、かつ
    nEndMode==0(サイズをGlobalSizeで取得)な場合だけ
    意味があるnEndModeの存在意義。

    かと言って、VT_ARRAYにして
    CF_DIBとか使えるようにしたとして、
    そういうマクロを書く人がいるのかどうかとか、
    すっごく微妙。。。


    • [2378] Re:クリップボード関数の謎引数 もか 2016年08月26日 20:06

      > nMode -1:バイナリモード
      このモードは、ビットマップとかCF_LOCALE、他のエディタのクリップボード形式などを読み書きする時に使います。
      これらの関数は、CF_TEXT/CF_UNICODETEXTでも読み書きが可能なように実装されていますが、主戦場は特殊用途です。
      普通のテキストは、Get(Set)Clipboard関数を使ってください、という方針です。
      サクラでは、一番使うのは矩形データの確認、登録です。

      CygwinのときにCF_TEXTがUTF-8だったりします(最近は不明)。
      Visual StudioのCF_TEXTもUTF-8になっているらしいです。
      そういう場合には、コード指定が必要です。
      参考:https://github.com/xyzzy-022/xyzzy/issues/73

      また日本語環境でNEC/IBM拡張漢字を区別して扱う場合に必須です。
      どういうことかというと、
      1. テキストファイルにはNEC/IBM拡張漢字がある
      2. サクラv2で読み込むとたぶんNECはUnicodeに変換されIBMは特殊なサロゲート断片になる
      3. それをそのまま普通にコピーすると、相手のソフトでIBMがゴミとして貼り付く
      4. SetClipboardByFormat(data, "CF_TEXT", 0, -1)で貼り付けると、クリップボードがIBMが元の符号位置に戻ったSJISデータになる
      6. 相手に貼り付けると、無事IBM/NECが区別されるか、WindowsのCF_UNICODETEXTの自動変換で統合されて貼り付けられる
      という風になっていて、データが変更されると困る用途に適しています。
    • [2379] Re:クリップボード関数の謎引数 もか 2016年08月26日 20:08

      (続き)
      >SetClipboradByFormat("美乳", "CF_TEXT", 2, -1)
      >当然、化けますよね。。。
      EUC-jpをCF_TEXTに突っ込むのは想定外ですが、そういうアプリが存在していてもおかしくないのです。
      例えば、存在するかしりませんがEUC-JPに設定されたCygwinとか。
      var s = GetClipboradByFormat("CF_TEXT", 2, -1)
      InsText(s);
      で「美乳」が貼り付けられるので、そういう変なアプリと通信したい場合には、これでいいと思います。
      もちろんCF_UNICODETEXTで読み書きするとおかしいですが、それは想定内です。
      CF_UNICODETEXTでも同時に読み書きができるようにしたければ、自分でCF_UNICODETEXTを設定すれば問題ないです。
      マイクロソフトが何といってるか知りませんが、ロケールって言ってるけど、UTF-8というロケールは存在しないので「言語」で「エンコード」を縛ることはできません。

      汎用的なnModeの使い方としては、
      SetClipboardByFormat(data, "HTML Format", 4, -1);
      が代表例です。HTML FormatはUTF-8と決まっています。

      >nEndMode
      他のエディタを見れば分かりますが
      「クリップボードを最後まで読み込む」関数と
      「クリップボードをNUL文字まで読み込む」関数
      が用意されていることがあります。それに対応するための処置です。
      WindowsのCF_(UNICODE)TEXTではNUL文字までと決まっていますが、実情はそうとは限りません。
      あとは独自フォーマットでは、NUL終端の後に違うデータが続いていることもあります。
      例えば、サクラが設定したCF_(UNICODE)TEXT形式では途中にNUL文字が含まれることがあります。
      UTF-32についてはおまけですが、独自形式のフォーマットがUTF-32形式互換である場合を想定していて、
      決してCF_(UNICODE)TEXTで使うためではありません。

      SetClipboradByFormatでCF_TEXTを登録するとき、サクラがCF_LOCALEを正しく登録しないのは、
      うまく動くか分かりませんが、"CF_LOCALE"も使えるようになっているので、自分で設定すればいいんだと思います。

      とりあえず、引数に意味不明な組み合わせがあることは確かです。
      そのへんは、汎用性のために犠牲になったと思ってください。
      • [2380] Re2:クリップボード関数の謎引数 ばぼ 2016年08月27日 13:49

        あるべき姿について、了解しました。

        ▼ もかさん
        > 主戦場は特殊用途です。

        結局、第一引数(Getのout引数)は「配列」ってことですね。


        > CygwinのときにCF_TEXTがUTF-8だったりします

        ぶっちゃけ、それはCygwinのバグですね。
        Cygwinとの互換性は、意識的に意識しないようにしております。

        元々Windows95にPOSIXレイヤを構築するプロジェクトです。
        POSIX依存のプログラムをWindows95で利用するためのもので、
        Windows向けに書かれたプログラムのためのものじゃないです。

        もちろん、win7向けのCygwinというのも存在しますが、
        「POSIXプログラムのための環境」がCygwinの本質です。
        Windows向けプログラムをビルドしようとするのは誤りです。
        WindowsでGCCを使うためのMinGWとは目的が違います。
        目的外利用で発生した問題は、ユーザの責任じゃないっす。


        > また日本語環境でNEC/IBM拡張漢字を区別して扱う場合に必須です。

        この問題の対処法を「独自ロジック廃止」で考えてるから
        話があわないんだろうな…と感じました(マテ


        > マイクロソフトが何といってるか知りませんが、ロケールって言ってるけど、UTF-8というロケールは存在しないので「言語」で「エンコード」を縛ることはできません。

        MS> ロケール関数にunicodeを指定すると失敗します。(サポートしません。)

        windowsロケールはansiのmultibyteをunicodeのwidecharに変換するためのものなので、unicodeファミリ内の変換は自分でやってね、ということらしいです。その割にはAPIがCP_UTF8に対応しとるんですが。


        続く...
      • [2381] Re2:クリップボード関数の謎引数 ばぼ 2016年08月27日 13:50

        そういえば、visual studioでコピーすると、
        Rich Text Formatなデータも追加されるんですが、
        サクラはこれには対応しないんでしょうか?

        (続き)

        > 汎用的なnModeの使い方としては、
        > SetClipboardByFormat(data, "HTML Format", 4, -1);
        > が代表例です。HTML FormatはUTF-8と決まっています。

        CF_HTMLはテキストじゃないので自動変換されないです。
        ビットマップとかと同じバイナリデータ。

        たしかにjavascript内でutf8作るとかありえませんし、便利ですね。
        ただ、4=UTF-8を覚えるには熟練を要しそうです。
        文字列リテラルによる指定を可能にする改善提案…(何を受け付けるかでモメそうですが)

        > >nEndMode
        > 他のエディタを見れば分かりますが

        「他のエディタが対応してるから」は
        機能が適切かどうかの指標にならんとです。
        たぶんそういう場合、本来のネイティブデータが
        別形式で登録されているはずなので、
        そちらに対応するのが正しいあり方な気がします。
        というか、エディタ側にはその機能ありませんよね(ご愛敬)

        > "CF_LOCALE"も使えるようになっているので、
        > 自分で設定すればいいんだと思います。

        サイズとエンディアンの問題があるので
        スクリプトから突っ込もうとすると微妙な感じになります。

        uint32_t lcid = 0x411; //日本語
        char pLcid1[] = { 0x11, 0x04, 0, 0 }; //普通のCPU
        char pLcid2[] = { 0, 0, 0x04, 0x11 }; //古いmacとかサーバー機
        SetClipboardByFormat(data, "CF_LOCALE", -1, 0);

        powerpc搭載型の旧式macは無視してよいので、
        pLcid1の値をdataに埋め込んでやれば一応動く...


        > とりあえず、引数に意味不明な組み合わせがあることは確かです。
        > そのへんは、汎用性のために犠牲になったと思ってください。

        というわけで、思いついたときに「見直し」をかけて
        パラメタチェックを追加してみたりするのもいいんではないかと。。。(鬼