gnuplotでギリシャ文字などをUTF8で利用する為にした遠回りについて


## 動機と環境
gnuplotでギリシャをUTF-8で利用する際に大分遠回りをしたの記録を残す。
Åなどの文字や惑星記号、日本語などを使いたいときにも参考になるだろう。

環境は、WSL2内ubuntu をwindows termnialで利用。
gnuplot のバージョンは5.2.8。ファイル編集は、主にvimでやっている。

## gnuplotでUTF-8を使う方法（正当な方法）
個人サイト[^1]や公式資料のFAQ[^2]を参考にすれば、ギリシャ文字などを直打ちすればよいとのことである。
公式資料にも、UTF-8の環境下であれば特別なことは十中八九しなくてよい、と明記してある。 
>If you are working in a UTF-8 computing environment, you probably do not have to do anything special in gnuplot to use

ところが、x軸ラベルをλに仕様と次の様な記述をしても、公式のデモ[^3]をコピーしてきても、正しくギリシャ文字は出力されなかった。況んや日本語をや。
```
set encoding utf8
set minussign
set  xlabel "λ"
```

この原因はgnuplotにはなく、vimでファイルを保存する際に文字コードがうまく指定できていなかったことであった。
したがって、vimの方から
```
:set fenc=utf8
```
と保存時の文字コードを指定した後にファイルを保存すれば、正しくλが表示される。

つまり、ファイルの保存時に、UTF-8であることを明示すれば解決した。これに気づいた後は快適にUTF8でギリシャ文字などが扱えている。

## gnuplotでUTF-8を使う方法（遠回り編）
さて、上述の問題に気づかず行った遠回りは、公式FAQの言うところの
> Or you can use octal escape sequences to type them in byte-by-byte

を実践したことに始まる。文字コードをエスケープしてバイト毎に8進数で書けばいいのである。
16進数で書かれたutf8のコード表は割と簡単に見つかる[^4]。8進数は見つけられない。そこで、16進数からエスケープ付き8進数への変換プログラムを作った。たかだか100行も行かぬコードで十分だ。まず、コード表[^4]を睨んで、コードを見つける。λであれば、`CEBB`が16進数でのコードである。これをお手製プログラムで変換すると`\316\273`が得られる。そのため、

```
set encoding utf8
set minussign
set  xlabel "\316\273"
```
と書けば良い。文字コード表を睨むのはしんどいし、スクリプトの可読性は最悪だ。
この運用をしばらく続けていたが、上述の保存時のエンコーディングの問題に気がついた次第である。

## まとめ
gnuplotで非アスキー文字がうまく出力されないときは、一度保存のエンコーディングを調べてみよう。utf8にある記号などを利用する際に参考頂ければ幸いである。


## 変換のプログラム

```C++
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>

constexpr int MAXLINE=100000;

constexpr int DIMDATA=12;

char upper(char c){
    if('a' <= c && c <= 'z'){
        c = c - ('a' - 'A');
    }
    return c;
}

int  conv2digit(char hex[0]){
  int res = 0 ;
  switch (std::toupper(hex[0])){
    case '0': res += 0*16; break;
    case '1': res += 1*16; break;
    case '2': res += 2*16; break;
    case '3': res += 3*16; break;
    case '4': res += 4*16; break;
    case '5': res += 5*16; break;
    case '6': res += 6*16; break;
    case '7': res += 7*16; break;
    case '8': res += 8*16; break;
    case '9': res += 9*16; break;
    case 'A': res +=10*16; break;
    case 'B': res +=11*16; break;
    case 'C': res +=12*16; break;
    case 'D': res +=13*16; break;
    case 'E': res +=14*16; break;
    case 'F': res +=15*16; break;
    default:
      std::cerr << "something wrong with " << hex[1] << std::endl;
      exit (-1);
  }
  switch (std::toupper(hex[1])){
    case '0': res += 0*1; break;
    case '1': res += 1*1; break;
    case '2': res += 2*1; break;
    case '3': res += 3*1; break;
    case '4': res += 4*1; break;
    case '5': res += 5*1; break;
    case '6': res += 6*1; break;
    case '7': res += 7*1; break;
    case '8': res += 8*1; break;
    case '9': res += 9*1; break;
    case 'A': res +=10*1; break;
    case 'B': res +=11*1; break;
    case 'C': res +=12*1; break;
    case 'D': res +=13*1; break;
    case 'E': res +=14*1; break;
    case 'F': res +=15*1; break;
    default:
      std::cerr << "something wrong with " << hex[1] << std::endl;
      exit (-1);
  }
  return res;
}

int main(int argc, char ** argv){

                if(argc != 2){
                        std::cerr <<" Error: useage is : this_command.exe hex"  <<std::endl;
                        exit(1);
                }

    std::string hex(argv[1]);

    //std::cout << hex << std::endl;
    //std::stransform(hex.begin(), hex.end(), hex.begin(), [](unsigned char c){return std::toupper(c);});

    for(int i=0; i< hex.size(); i+=2){
      std::string substr = hex.substr(i,2);
      //std::cout << substr << std::endl;
      char tmp[2];
      tmp[0]=hex.substr(i,1).c_str()[0];
      tmp[1]=hex.substr(i+1,1).c_str()[0];
      int digit = conv2digit(tmp);
      std::cout <<"\\" <<  std::oct << digit ;
    }
    std::cout << std::endl;


    return 0;
}
```



[^1]: <https://mumeiyamibito.blogspot.com/2015/09/gnuplot.html>
[^2]: <http://www.gnuplot.info/faq/faq.pdf>の6.3
[^3]: <http://gnuplot.sourceforge.net/demo/enhanced_utf8.html>
[^4]: <https://orange-factory.com/dnf/utf-8.html>