Migemo Bridge

XUL/Migemoが長らく更新されてないわけですが,しかしVimperatorと組み合わせて使ってる人もいるわけでして.んで,C/MigemoでXUL/Migemoが提供しているAPI部分を代替できるんじゃないのと思って,js-ctypesとAdd-on SDKの練習がてらさらさらっと書いてみた.必要でしたら持って行ってください.パッケージング化する気力はないので必要としている人がやってくれ.

注意事項:

  • query関数しかテストしてないです.
  • migemo.dllと辞書へのPathは適宜書き換えてください.設定UIつける気力ないです.
  • Windowsじゃない人はctypes.winapi_abiをctypes.default_abiに置換しないといけないはずです.
  • *Functional系関数はよく分からないので実装してません.
//migemo.js
const {Cc,Ci,Cm,Cr,Cu} = require("chrome");
Cu.import("resource://gre/modules/ctypes.jsm", this);

/* for migemo_load() */
var MIGEMO_DICTID_INVALID = 0;
var MIGEMO_DICTID_MIGEMO = 1;
var MIGEMO_DICTID_ROMA2HIRA = 2;
var MIGEMO_DICTID_HIRA2KATA = 3;
var MIGEMO_DICTID_HAN2ZEN = 4;
var MIGEMO_DICTID_ZEN2HAN = 5;

/* for migemo_set_operator()/migemo_get_operator().  see: rxgen.h */
var MIGEMO_OPINDEX_OR = 0;
var MIGEMO_OPINDEX_NEST_IN = 1;
var MIGEMO_OPINDEX_NEST_OUT = 2;
var MIGEMO_OPINDEX_SELECT_IN = 3;
var MIGEMO_OPINDEX_SELECT_OUT = 4;
var MIGEMO_OPINDEX_NEWLINE = 5;

const migemo = new ctypes.StructType(
    'migemo',
    [
        {'enable': ctypes.int32_t},
        {'mtree': ctypes.voidptr_t},
        {'charset': ctypes.int32_t},
        {'roma2hira': ctypes.voidptr_t},
        {'hira2kata': ctypes.voidptr_t},
        {'han2zen': ctypes.voidptr_t},
        {'zen2han': ctypes.voidptr_t},
        {'rx': ctypes.voidptr_t},
        {'addword': ctypes.voidptr_t},
        {'char2int': ctypes.voidptr_t}
    ]);

var migemo_open;
var migemo_close;
var migemo_query;
var migemo_release;
var migemo_set_operator;
var migemo_get_operator;
var migemo_setproc_char2int;
var migemo_setproc_int2char;
var migemo_load;
var migemo_is_enable;

var m;
var lib;

function ensureLoaded(){
  var path = "C:\\path\\to\\migemo.dll";
  var dict = "C:\\path\\to\\dict\\utf-8\\migemo-dict";
  if(!lib){
    return load(path, dict);
  }else{
    return m;
  }
  return null;
}

function load(path, dict){
  if(!lib){
    lib = ctypes.open(path);
    if(!lib) throw "can't load migemo dll";
  }else{
    unload();
  }

  migemo_open = lib.declare("migemo_open",
			      ctypes.winapi_abi,
			      migemo.ptr,
			      ctypes.char.ptr); //path to dict

  migemo_close = lib.declare("migemo_close",
			       ctypes.winapi_abi,
			       ctypes.void_t,
			       migemo.ptr); //migemo object

  migemo_query = lib.declare("migemo_query",
			       ctypes.winapi_abi,
			       ctypes.unsigned_char.ptr,
			       migemo.ptr, //migemo object
			       ctypes.unsigned_char.ptr); //query

  migemo_release = lib.declare("migemo_release",
			       ctypes.winapi_abi,
			       ctypes.void_t,
			       migemo.ptr, //migemo object
			       ctypes.unsigned_char.ptr); //query

/* TODO:
int MIGEMO_CALLTYPE	migemo_set_operator(migemo* object, int index,
	const unsigned char* op);
const unsigned char* MIGEMO_CALLTYPE migemo_get_operator(migemo* object,
	int index);
void MIGEMO_CALLTYPE	migemo_setproc_char2int(migemo* object,
	MIGEMO_PROC_CHAR2INT proc);
void MIGEMO_CALLTYPE	migemo_setproc_int2char(migemo* object,
	MIGEMO_PROC_INT2CHAR proc);
*/

  migemo_load = lib.declare("migemo_load",
			      ctypes.winapi_abi,
			      ctypes.int32_t,
			      migemo.ptr, //migemo object
			      ctypes.int32_t, //dict_id
			      ctypes.char.ptr); //path to dict file

  migemo_is_enable = lib.declare("migemo_is_enable",
				   ctypes.winapi_abi,
				   ctypes.int32_t,
				   migemo.ptr); //migemo object

  if(!m){
    m = migemo_open(null);
  }

  if(!m.address()) throw "creation of migemo object failed";

  var rv = migemo_load(m, MIGEMO_DICTID_MIGEMO, dict);
  if(rv == 0){
    throw "failed to load migemo dict:" + dict;
  }

  return m;
}

function unload(){
  migemo_close(m);
  lib.close();
  m = null;
  lib = null;
}

function provider(){
  return "C/Migemo bridge 0.0.1"
}

function version(){
  return "0.0.1";
}

function lang(){
  return "ja"; //temporary
}

function query(aInput){
  ensureLoaded();
  var p;
  p = migemo_query(m, aInput);
  var rawstr = p.readString();
  console.log(rawstr);
  migemo_release(m, p);
  return rawstr;
}

function queries(aInput){
  var arr = aInput.split(" ");
  arr = arr.filter(function(e) {
                     return e != "";
                   });
  return arr.map(function(e){ return query(e); });
}

function queryFunctional(aInput){
  if(!ensureLoaded()) return "";
  throw "not implemented";
}

function queriesFunctional(aInput){
  if(!ensureLoaded()) return "";
  throw "not implemented";
}

function getRegExp(aInput, aFlags){
  return new RegExp(query(aInput), aFlags);
}

function getRegExps(aInput, aFlags){
  var rxs = queries(aInput);
  return rxs.map(function(e){ return new RegExp(e, aFlags); });
}

function getRegExpFunctional(aInput, aFlags){
  if(!ensureLoaded()) return null;
  throw "not implemented";
}

function getRegExpsFunctional(aInput, aFlags){
  if(!ensureLoaded()) return null;
  throw "not implemented";
}

exports.query = query;
exports.queries = queries;
exports.getRegExp = getRegExp;
exports.getRegExps = getRegExps;
//main.js
//こんな感じで使えるはず,たぶんXUL/Migemo互換.
var migemo = require("migemo");
var notifications = require("notifications");

var rawstr = migemo.query("$");
notifications.notify({ title: "Migemo", text: rawstr });

C/Migemoのソース見たらXPCOM化するためのソースも入ってたんですね,でもjs-ctypesのお陰でこの労力も要らなくなるわけだ.