/*************************************************************************** * Copyright (C) 2005 by TAM(Teppei Tamra) * * tam-t@par.odn.ne.jp * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the * * Free Software Foundation, Inc., * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ #include "primeprediction.h" #ifdef HAVE_CONFIG_H #include <config.h> #endif #ifdef HAVE_GETTEXT #include <libintl.h> #define _(String) dgettext(GETTEXT_PACKAGE,String) #define N_(String) (String) #else #define _(String) (String) #define N_(String) (String) #define bindtextdomain(Package,Directory) #define textdomain(domain) #define bind_textdomain_codeset(domain,codeset) #endif #include <sys/types.h> #include <signal.h> #include <sys/wait.h> #include <sys/shm.h> // プライグイン化のおまじないです。 HonokaPluginRegister(PrimePrediction); HonokaPluginSetup(PrimePrediction); HonokaSetupCorePage *PrimePrediction::setup() { bindtextdomain (GETTEXT_PACKAGE, HONOKA_LOCALEDIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); vector<String> l; HonokaSetupPage *page = new HonokaSetupPage(_("PrimePrediction-plugin"),"",""); l.clear(); l.push_back(String("lookup")); l.push_back(String("lookup_all")); l.push_back(String("lookup_compact")); l.push_back(String("lookup_compact_all")); l.push_back(String("lookup_direct")); l.push_back(String("lookup_direct_all")); l.push_back(String("lookup_exact")); l.push_back(String("lookup_expansion")); l.push_back(String("lookup_hybrid")); l.push_back(String("lookup_hybrid_all")); l.push_back(String("lookup_mixed")); page->append(new HonokaSetupSelectItem( _("_Lookup method: "), HONOKA_CONFIG_PRIME_PREDICTION_LM, _("select the lookup method."), HONOKA_DEFAULT_PRIME_PREDICTION_LM, l )); HonokaSetupPage *sc = new HonokaSetupPage(_("shortcut keys: "),"",""); sc->append(new HonokaSetupKeyItem( _("Prime Prediction: "), String(HONOKA_CONFIG_KEY_PREDICTOR_PREFIX) + String("/PrimePrediction"), "", "" )); page->append(sc); return page; }; PrimePrediction::PrimePrediction(ConfigPointer cfg) : Predictor(cfg) { bindtextdomain (GETTEXT_PACKAGE, HONOKA_LOCALEDIR); bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8"); m_iconv.set_encoding ("EUC-JP"); prime_pid = -1; mid = shmget(IPC_PRIVATE,sizeof(bool),IPC_CREAT | 0666); if (mid != -1) { con = (bool *)shmat(mid,0,0); con[0] = false; // shmat失敗時のエラー処理は?。 // 同一プロセスで確実に同じIDなら失敗しようがない気もするが。 } lookup_method = cfg->read(HONOKA_CONFIG_PRIME_PREDICTION_LM,String(HONOKA_DEFAULT_PRIME_PREDICTION_LM)); if ((lookup_method != "lookup") && (lookup_method != "lookup_all") && (lookup_method != "lookup_compact") && (lookup_method != "lookup_compact_all") && (lookup_method != "lookup_direct") && (lookup_method != "lookup_direct_all") && (lookup_method != "lookup_exact") && (lookup_method != "lookup_expansion") && (lookup_method != "lookup_hybrid") && (lookup_method != "lookup_hybrid_all") && (lookup_method != "lookup_mixed")) lookup_method = String(HONOKA_DEFAULT_PRIME_PREDICTION_LM); } PrimePrediction::~PrimePrediction() { disconnect(); if (prime_pid != -1) { kill(prime_pid,SIGKILL); wait(NULL); } if (mid != -1) shmctl(mid,IPC_RMID,0); } /*! \fn PrimePrediction::parser(const String &str) */ ResultEntry PrimePrediction::parser(const String &str) { vector<String> rl; String r; for(unsigned int i = 0;i < str.length();i ++) { if ((str[i] == '\t') || (str[i] == ' ')) { if (r.length()) { rl.push_back(r); r = ""; } } else r += str[i]; } if (r.length()) rl.push_back(r); if (rl.size() < 2) return ResultEntry(); WideString w,a; for(unsigned int i = 2;i < rl.size();i ++) { if (rl[i].length() < 7) continue; if (rl[i].substr(0,6) == "usage=") m_iconv.convert(a,rl[i].substr(6)); } m_iconv.convert(w,rl[1]); if (!a.length()) a = w; else a = w + utf8_mbstowcs(String(" (")) + a + utf8_mbstowcs(String(")")); return ResultEntry(w,a); } /*! \fn PrimePrediction::getPredictionList(const WideString &str) */ ResultList PrimePrediction::getPredictionList(const WideString &str) { ResultList l; if (mid == -1) return l; if (!con[0]) return l; String s = lookup_method + "\t"; String t; m_iconv.convert(t,str); s = s + t + String("\n"); write(ifd,s.c_str(),s.length()); char b[1024]; vector<String> sl; s = ""; while(-1) { int c = read(ofd,b,1023); s += String(b,c); if (s.substr(s.length() - 2,2) == "\n\n") break; } t = ""; for(unsigned int i = 0;i < s.length();i ++) { if (s[i] == '\n') { sl.push_back(t); t = ""; } else t += s[i]; } if (t.length()) sl.push_back(t); l.Title = utf8_mbstowcs(String(_("lookup result"))); l.kType = PREDICTION; for(unsigned int i = 1;i < sl.size();i ++) { ResultEntry e = parser(sl[i]); if (e.kanji.length()) l.kouho.push_back(e); } return l; } /*! \fn PrimePrediction::disconnect() */ void PrimePrediction::disconnect() { if (mid == -1) return; if (con[0]) return; String s = "close\n"; write(ifd,s.c_str(),s.length()); close(ifd); close(ofd); con[0] = false; prime_pid = -1; } /*! \fn PrimePrediction::connect() */ bool PrimePrediction::connect() { if (mid == -1) return false; // primeチェーック! int ps; if (fork() == 0) { execlp("prime","--help",NULL); _exit(0); } wait(&ps); if (!WIFEXITED(ps)) return false; if (WEXITSTATUS(ps) != 0) return false; // primeは動いてるっぽい。以下。 int in_fd[2],out_fd[2],i; if (con[0]) return true; if (pipe(in_fd) == -1) return false; if (pipe(out_fd) == -1) return false; prime_pid = fork(); switch(prime_pid) { case -1: { close(in_fd[0]); close(in_fd[1]); close(out_fd[0]); close(out_fd[1]); con[0] = false; return false; } case 0: { close(in_fd[1]); close(out_fd[0]); dup2(in_fd[0],0); dup2(out_fd[1],1); close(in_fd[0]); close(out_fd[1]); con[0] = true; execlp("prime",NULL); con[0] = false; _exit(0); } } close(in_fd[0]); close(out_fd[1]); ifd = in_fd[1]; ofd = out_fd[0]; return true; } /*! \fn PrimePrediction::isConnected() */ bool PrimePrediction::isConnected() { if (mid == -1) return false; return con[0]; } /*! \fn PrimePrediction::getPropertyName() */ String PrimePrediction::getPropertyName() { return String(_("PrimePrediction")); } /*! \fn PrimePrediction::getName() */ String PrimePrediction::getName() { return String("PrimePrediction"); } /*! \fn PrimePrediction::update(const WideString str,const WideString yomi) */ void PrimePrediction::update(const WideString str,const WideString yomi) { }