OSDN Git Service

moved core sources of JTalk and braille translator from nvdajp repository to nvdajp... jpbeta131029
authorTakuya Nishimoto <nishimotz@gmail.com>
Tue, 29 Oct 2013 09:46:39 +0000 (18:46 +0900)
committerTakuya Nishimoto <nishimotz@gmail.com>
Tue, 29 Oct 2013 09:46:39 +0000 (18:46 +0900)
17 files changed:
jptools/harness.py [new file with mode: 0644]
jptools/jpBrailleRunner.py [new file with mode: 0644]
jptools/jtalkPredicTest.py [new file with mode: 0644]
jptools/jtalkRunner.py [new file with mode: 0644]
jptools/make_html.cmd [new file with mode: 0644]
source/synthDrivers/jtalk/__init__.py [new file with mode: 0644]
source/synthDrivers/jtalk/_bgthread.py [new file with mode: 0644]
source/synthDrivers/jtalk/_jtalk_core.py [new file with mode: 0644]
source/synthDrivers/jtalk/_nvdajp_espeak.py [new file with mode: 0644]
source/synthDrivers/jtalk/_nvdajp_jtalk.py [new file with mode: 0644]
source/synthDrivers/jtalk/_nvdajp_predic.py [new file with mode: 0644]
source/synthDrivers/jtalk/_nvdajp_spellchar.py [new file with mode: 0644]
source/synthDrivers/jtalk/_nvdajp_unicode.py [new file with mode: 0644]
source/synthDrivers/jtalk/mecab.py [new file with mode: 0644]
source/synthDrivers/jtalk/translator1.py [new file with mode: 0644]
source/synthDrivers/jtalk/translator2.py [new file with mode: 0644]
source/synthDrivers/nvdajp_jtalk.py [new file with mode: 0644]

diff --git a/jptools/harness.py b/jptools/harness.py
new file mode 100644 (file)
index 0000000..25a0c65
--- /dev/null
@@ -0,0 +1,4309 @@
+# -*- coding: utf-8 -*-\r
+#jptools/harness.py\r
+#A part of NonVisual Desktop Access (NVDA)\r
+#This file is covered by the GNU General Public License.\r
+#See the file COPYING for more details.\r
+#Copyright (C) 2013 Masataka.Shinke, Takuya Nishimoto, NVDA Japanese Team\r
+# \r
+# For output field, blank should be 0x20 (not 0x2800).\r
+# output の空白は 0x2800 ではなく 0x20 を使います\r
+\r
+from __future__ import unicode_literals\r
+\r
+tests = [\r
+       { 'note': '+ 基本テスト +' },\r
+       {\r
+               'input': 'アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨン',\r
+               'output': '⠁⠃⠉⠋⠊⠡⠣⠩⠫⠪⠱⠳⠹⠻⠺⠕⠗⠝⠟⠞⠅⠇⠍⠏⠎⠥⠧⠭⠯⠮⠵⠷⠽⠿⠾⠌⠬⠜⠴',\r
+               'inpos1': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38],\r
+               'cursorPos': 0,\r
+               'brlCursorPos': 0,\r
+               'mode': '',\r
+               'comment': '',\r
+               },\r
+       {\r
+               'input': 'ガギグゲゴザジズゼゾダジズデドパピプペポキャキュキョチャチュチョヒャヒュヒョジャジュジョピャピュピョ',\r
+               'output': '⠐⠡⠐⠣⠐⠩⠐⠫⠐⠪⠐⠱⠐⠳⠐⠹⠐⠻⠐⠺⠐⠕⠐⠳⠐⠹⠐⠟⠐⠞⠠⠥⠠⠧⠠⠭⠠⠯⠠⠮⠈⠡⠈⠩⠈⠪⠈⠕⠈⠝⠈⠞⠈⠥⠈⠭⠈⠮⠘⠱⠘⠹⠘⠺⠨⠥⠨⠭⠨⠮',\r
+               },\r
+       {\r
+               'text': '1234567890',\r
+               'input': '1234567890',\r
+               'output': '⠼⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚',\r
+               'inpos2': [0,1,2,3,4,5,6,7,8,9],\r
+               'inpos1': [0,0,1,2,3,4,5,6,7,8,9],\r
+               'inpos':  [0,0,1,2,3,4,5,6,7,8,9],\r
+               },\r
+       {\r
+               'text': '1234567890',\r
+               'input': '1234567890',\r
+               'output': '⠼⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚',\r
+               'inpos2': [0,1,2,3,4,5,6,7,8,9],\r
+               'inpos1': [0,0,1,2,3,4,5,6,7,8,9],\r
+               'inpos':  [0,0,1,2,3,4,5,6,7,8,9],\r
+               },\r
+       {\r
+               'text': 'abcdefghijklmnopqrstuvwxyz',\r
+               'input': 'abcdefghijklmnopqrstuvwxyz',\r
+               'output': '⠰⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚⠅⠇⠍⠝⠕⠏⠟⠗⠎⠞⠥⠧⠺⠭⠽⠵',\r
+               'inpos2': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],\r
+               'inpos1': [0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],\r
+               'inpos':  [0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],\r
+               },\r
+       {\r
+               'text': 'abcdefghijklmnopqrstuvwxyz',\r
+               'input': 'abcdefghijklmnopqrstuvwxyz',\r
+               'output': '⠰⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚⠅⠇⠍⠝⠕⠏⠟⠗⠎⠞⠥⠧⠺⠭⠽⠵',\r
+               'inpos2': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],\r
+               'inpos1': [0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],\r
+               'inpos':  [0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],\r
+               },\r
+       {\r
+               'text': 'abc defghijklmnopqrstuvwxyz',\r
+               'input': 'abc defghijklmnopqrstuvwxyz',\r
+               'output': '⠰⠁⠃⠉ ⠰⠙⠑⠋⠛⠓⠊⠚⠅⠇⠍⠝⠕⠏⠟⠗⠎⠞⠥⠧⠺⠭⠽⠵',\r
+               'inpos2': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],\r
+               'inpos1': [0,0,1,2,3,4,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],\r
+               'inpos':  [0,0,1,2,3,4,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26],\r
+               },\r
+       {\r
+               'text': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',\r
+               'input': 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',\r
+               'output': '⠰⠠⠠⠁⠃⠉⠙⠑⠋⠛⠓⠊⠚⠅⠇⠍⠝⠕⠏⠟⠗⠎⠞⠥⠧⠺⠭⠽⠵',\r
+               'inpos2': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],\r
+               'inpos1': [0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],\r
+               'inpos':  [0,0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25],\r
+               },\r
+       {\r
+               'text': 'ABC abc 123 ABC abc 123',\r
+               'input': 'ABC abc 123 ABC abc 123',\r
+               'output': '⠰⠠⠠⠁⠃⠉ ⠰⠁⠃⠉ ⠼⠁⠃⠉ ⠰⠠⠠⠁⠃⠉ ⠰⠁⠃⠉ ⠼⠁⠃⠉',\r
+               'inpos2': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22],\r
+               'inpos1': [0,0,0,0,1,2,3,4,4,5,6,7,8,8,9,10,11,12,12,12,12,13,14,15,16,16,17,18,19,20,20,21,22],\r
+               'inpos':  [0,0,0,0,1,2,3,4,4,5,6,7,8,8,9,10,11,12,12,12,12,13,14,15,16,16,17,18,19,20,20,21,22],\r
+               },\r
+       {\r
+               'text': 'ab 123 あab 123 あ',\r
+               'input': 'ab 123 ア ab 123 ア',\r
+               'output': '⠰⠁⠃ ⠼⠁⠃⠉ ⠁ ⠰⠁⠃ ⠼⠁⠃⠉ ⠁',\r
+               'inpos2': [0,1,2,3,4,5,6,7,7,8,9,10,11,12,13,14,15],\r
+               'inpos1': [0,0,1,2,3,3,4,5,6,7,8,9,9,10,11,12,12,13,14,15,16],\r
+               'inpos':  [0,0,1,2,3,3,4,5,6,7,7,8,8,9,10,11,11,12,13,14,15],\r
+               },\r
+       {\r
+               'text': 'ヒロイノ カン  カンスージノ ニ',\r
+               'input': 'ヒロイノ カン  カンスージノ ニ',\r
+               'output': '⠧⠚⠃⠎ ⠡⠴  ⠡⠴⠹⠒⠐⠳⠎ ⠇',\r
+               'inpos2': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16],\r
+               'inpos1': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,13,14,15,16],\r
+               'inpos':  [0,1,2,3,4,5,6,7,8,9,10,11,12,13,13,14,15,16],\r
+               },\r
+       {\r
+               'text': 'トーヨーカンジノ カン  モジノ ジ 候補2',\r
+               'input': 'トーヨーカンジノ カン  モジノ ジ コーホ2',\r
+               'inpos2': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,19,20,21],\r
+               'inpos1': [0,1,2,3,4,5,6,6,7,8,9,10,11,12,13,14,14,15,16,17,17,18,19,20,21,22,22],\r
+               'inpos':  [0,1,2,3,4,5,6,6,7,8,9,10,11,12,13,14,14,15,16,17,17,18,19,19,20,21,21],\r
+               'output': '⠞⠒⠜⠒⠡⠴⠐⠳⠎ ⠡⠴  ⠾⠐⠳⠎ ⠐⠳ ⠪⠒⠮⠼⠃',\r
+               },\r
+       {\r
+               'text': 'カンジルノ カン  ヒラガナ じ 候補3',\r
+               'input': 'カンジルノ カン  ヒラガナ ジ コーホ3',\r
+               'inpos1': [0,1,2,2,3,4,5,6,7,8,9,10,11,12,12,13,14,15,15,16,17,18,19,20,20],\r
+               'output': '⠡⠴⠐⠳⠙⠎ ⠡⠴  ⠧⠑⠐⠡⠅ ⠐⠳ ⠪⠒⠮⠼⠉',\r
+               },\r
+       {\r
+               'text': 'カンムリノ カン  シカイシャノ シ 候補4',\r
+               'input': 'カンムリノ カン  シカイシャノ シ コーホ4',\r
+               'inpos1': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,13,15,16,17,18,19,20,21,22,22],\r
+               'output': '⠡⠴⠽⠓⠎ ⠡⠴  ⠳⠡⠃⠈⠱⠎ ⠳ ⠪⠒⠮⠼⠙',\r
+               },\r
+       {\r
+               'text': 'ミキノ カン  コト ジケンノ ジ 候補5',\r
+               'input': 'ミキノ カン  コト ジケンノ ジ コーホ5',\r
+               'inpos1': [0,1,2,3,4,5,6,7,8,9,10,11,11,12,13,14,15,16,16,17,18,19,20,21,21],\r
+               'output': '⠷⠣⠎ ⠡⠴  ⠪⠞ ⠐⠳⠫⠴⠎ ⠐⠳ ⠪⠒⠮⠼⠑',\r
+               },\r
+       {\r
+               'text': 'ヒラガナ かんじ 候補6',\r
+               'input': 'ヒラガナ カンジ コーホ6',\r
+               'inpos1': [0,1,2,2,3,4,5,6,7,7,8,9,10,11,12,12],\r
+               'output': '⠧⠑⠐⠡⠅ ⠡⠴⠐⠳ ⠪⠒⠮⠼⠋',\r
+               },\r
+       {\r
+               'text': 'ヒロイノ カン  オサメルノ ジ 候補7',\r
+               'input': 'ヒロイノ カン  オサメルノ ジ コーホ7',\r
+               'inpos1': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,15,16,17,18,19,20,20],\r
+               'output': '⠧⠚⠃⠎ ⠡⠴  ⠊⠱⠿⠙⠎ ⠐⠳ ⠪⠒⠮⠼⠛',\r
+               },\r
+       {\r
+               'text': 'クサカンムリニ カンノ カン  カンジノ ジ 候補8',\r
+               'input': 'クサカンムリニ カンノ カン  カンジノ ジ コーホ8',\r
+               'inpos1': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,18,19,20,21,21,22,23,24,25,26,26],\r
+               'output': '⠩⠱⠡⠴⠽⠓⠇ ⠡⠴⠎ ⠡⠴  ⠡⠴⠐⠳⠎ ⠐⠳ ⠪⠒⠮⠼⠓',\r
+               },\r
+       {\r
+               'text': '(U)',\r
+               'input': '(U)',\r
+               'output': '⠶⠰⠠⠥⠶',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,1,1,1,2],\r
+               'inpos':  [0,1,1,1,2],\r
+               'comment': 'nvdajp ticket 28226 (comment 2012-05-16)',\r
+               },\r
+       {\r
+               'text': '(U)',\r
+               'input': '(U)',\r
+               'output': '⠶⠰⠠⠥⠶',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,1,1,1,2],\r
+               'inpos':  [0,1,1,1,2],\r
+               'comment': '記号はUnicode正規化',\r
+               },\r
+       {\r
+               'text': '[ア]',\r
+               'input': '[ア]',\r
+               'output': '⠐⠶⠁⠶⠂',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,2,2],\r
+               'inpos':  [0,0,1,2,2],\r
+               'comment': '',\r
+               },\r
+       {\r
+               'text': '[ア]',\r
+               'input': '[ア]',\r
+               'output': '⠐⠶⠁⠶⠂',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,2,2],\r
+               'inpos':  [0,0,1,2,2],\r
+               'comment': '記号はUnicode正規化',\r
+               },\r
+       {\r
+               'text': '“ア”',\r
+               'input': '“ア”',\r
+               'output': '⠐⠶⠁⠶⠂',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,2,2],\r
+               'inpos':  [0,0,1,2,2],\r
+               'comment': '',\r
+               },\r
+       {\r
+               'text': '{ア}',\r
+               'input': '{ア}',\r
+               'output': '⠐⠶⠁⠶⠂',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,2,2],\r
+               'inpos':  [0,0,1,2,2],\r
+               'comment': '',\r
+               },\r
+       {\r
+               'text': '‘ア’',\r
+               'input': '‘ア’',\r
+               'output': '⠐⠶⠁⠶⠂',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,2,2],\r
+               'inpos':  [0,0,1,2,2],\r
+               'comment': '',\r
+               },\r
+       {\r
+               'text': '〔ア〕',\r
+               'input': '〔ア〕',\r
+               'output': '⠐⠶⠁⠶⠂',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,2,2],\r
+               'inpos':  [0,0,1,2,2],\r
+               'comment': '',\r
+               },\r
+       {\r
+               'text': '{ア}',\r
+               'input': '{ア}',\r
+               'output': '⠐⠶⠁⠶⠂',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,2,2],\r
+               'inpos':  [0,0,1,2,2],\r
+               'comment': '記号はUnicode正規化',\r
+               },\r
+       {\r
+               'text': '〈ア〉',\r
+               'input': '〈ア〉',\r
+               'output': '⠐⠶⠁⠶⠂',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,2,2],\r
+               'inpos':  [0,0,1,2,2],\r
+               'comment': '',\r
+               },\r
+       {\r
+               'text': '《ア》',\r
+               'input': '《ア》',\r
+               'output': '⠐⠶⠁⠶⠂',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,2,2],\r
+               'inpos':  [0,0,1,2,2],\r
+               'comment': '',\r
+               },\r
+       {\r
+               'text': '【ア】',\r
+               'input': '【ア】',\r
+               'output': '⠐⠶⠁⠶⠂',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,2,2],\r
+               'inpos':  [0,0,1,2,2],\r
+               'comment': '',\r
+               },\r
+       {\r
+               'text': '〝ア〟',\r
+               'input': '〝ア〟',\r
+               'output': '⠐⠶⠁⠶⠂',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,2,2],\r
+               'inpos':  [0,0,1,2,2],\r
+               'comment': '',\r
+               },\r
+       {\r
+               'text': '「ア」',\r
+               'input': '「ア」',\r
+               'output': '⠤⠁⠤',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,1,2],\r
+               'inpos':  [0,1,2],\r
+               'comment': '',\r
+               },\r
+       {\r
+               'text': '『ア』',\r
+               'input': '『ア』',\r
+               'output': '⠰⠤⠁⠤⠆',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,2,2],\r
+               'inpos':  [0,0,1,2,2],\r
+               'comment': '',\r
+               },\r
+       {\r
+               'text': '「ア」',\r
+               'input': '「ア」',\r
+               'output': '⠤⠁⠤',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,1,2],\r
+               'inpos':  [0,1,2],\r
+               'comment': '記号はUnicode正規化',\r
+               },\r
+       {\r
+               'text': 'Ctrl-Z',\r
+               'input': 'Ctrl-Z',\r
+               'output': '⠰⠠⠉⠞⠗⠇⠤⠰⠠⠵',\r
+               'inpos2': [0,1,2,3,4,5],\r
+               'inpos1': [0,0,0,1,2,3,4,5,5,5],\r
+               'inpos':  [0,0,0,1,2,3,4,5,5,5],\r
+               'comment': 'Latinの 0x002D HYPHEN-MINUS は 0x2212 MUNUS SIGN に正規化しない',\r
+               },\r
+       {\r
+               'input': 'Aア',\r
+               'output': '⠰⠠⠁⠤⠁',\r
+               'inpos1': [0,0,0,0,1],\r
+               },\r
+       {\r
+               'input': 'aアットb',\r
+               'output': '⠰⠁⠤⠁⠂⠞⠰⠃',\r
+               'inpos1': [0,0,0,1,2,3,4,4],\r
+               },\r
+       {\r
+               'text': 'a@b',\r
+               'input': '⠠⠦a@b⠠⠴',\r
+               'output': '⠠⠦⠁⠪⠃⠠⠴',\r
+               'inpos2': [0,0,0,1,2,2,2],\r
+               'inpos1': [0,1,2,3,4,5,6],\r
+               'comment': '情報処理点字を使う。@は246で。',\r
+               },\r
+       {\r
+               'text': '<a@b>',\r
+               'input': '⠠⠦<a@b>⠠⠴',\r
+               'output': '⠠⠦⠔⠔⠁⠪⠃⠢⠢⠠⠴',\r
+               'inpos2': [0,0,0,1,2,3,4,4,4],\r
+               'inpos1': [0,1,2,2,3,4,5,6,6,7,8],\r
+               'inpos':  [0,0,0,0,1,2,3,4,4,4,4],\r
+               'comment': 'メールアドレス前後の山かっこ',\r
+               },\r
+       {\r
+               'input': 'Cプラスプラス',\r
+               'output': '⠰⠠⠉⠤⠠⠭⠑⠹⠠⠭⠑⠹',\r
+               'inpos1': [0,0,0,0,1,1,2,3,4,4,5,6],\r
+               },\r
+       {\r
+               'text': 'notepad++',\r
+               'input': 'notepad++',\r
+               'output': '⠰⠝⠕⠞⠑⠏⠁⠙⠢⠢',\r
+               'inpos2': [0,1,2,3,4,5,6,7,8],\r
+               'inpos1': [0,0,1,2,3,4,5,6,7,8],\r
+               'comment': 'プラスは情報処理点字 356 だが 26 のまま。',\r
+               },\r
+       {\r
+               'text': '+@/#$%&*;',\r
+               'input': '⠠⠦+@/#$%&*;⠠⠴',\r
+               'output': '⠠⠦⠬⠪⠌⠩⠹⠻⠯⠡⠆⠠⠴',\r
+               'inpos2': [0,0,0,1,2,3,4,5,6,7,8,8,8],\r
+               'inpos1': [0,1,2,3,4,5,6,7,8,9,10,11,12],\r
+               'inpos':  [0,0,0,1,2,3,4,5,6,7,8,8,8],\r
+               'comment': '情報処理点字',\r
+               },\r
+       {\r
+               'text': ',.:;!?@#\\$%&*|+-/=<>^_~',\r
+               'input': '⠠⠦,.:;!?@#\\$%&*|+-/=<>^_~⠠⠴',\r
+               'output': '⠠⠦⠂⠲⠐⠂⠆⠖⠐⠦⠪⠩⠫⠹⠻⠯⠡⠳⠬⠤⠌⠒⠒⠔⠔⠢⠢⠘⠐⠤⠐⠉⠠⠴',\r
+               'inpos2': [0,0,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,22,22],\r
+               'inpos1': [0,1,2,3,4,4,5,6,7,7,8,9,10,11,12,13,14,15,16,17,18,19,19,20,20,21,21,22,23,23,24,24,25,26],\r
+               'inpos':  [0,0,0,1,2,2,3,4,5,5,6,7,8,9,10,11,12,13,14,15,16,17,17,18,18,19,19,20,21,21,22,22,22,22],\r
+               'comment': '情報処理点字 バックスラッシュではなく円記号',\r
+               },\r
+       {\r
+               'text': '"\'`',\r
+               'input': '”’‘',\r
+               #'output': '⠶⠄⠐⠑',\r
+               'inpos2': [0,1,2],\r
+               'comment': '「”’‘」は正規化',\r
+               },\r
+       {\r
+               'text': '@{}[]', # ()\r
+               'input': '⠠⠦@{}[]⠠⠴', # ()\r
+               'output': '⠠⠦⠪⠣⠜⠷⠾⠠⠴', # ⠦⠴\r
+               'inpos2': [0,0,0,1,2,3,4,4,4],\r
+               'inpos1': [0,1,2,3,4,5,6,7,8],\r
+               'inpos':  [0,0,0,1,2,3,4,4,4],\r
+               },\r
+       {\r
+               'text': 'アドレスはnvda@nvda.jpです。',\r
+               'input': 'アドレスワ ⠠⠦nvda@nvda.jp⠠⠴ デス。',\r
+               'output': '⠁⠐⠞⠛⠹⠄ ⠠⠦⠝⠧⠙⠁⠪⠝⠧⠙⠁⠲⠚⠏⠠⠴ ⠐⠟⠹⠲',\r
+               'inpos2': [0,1,2,3,4,4,5,5,5,6,7,8,9,10,11,12,13,14,15,16,16,16,16,17,18,19],\r
+               'inpos1': [0,1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,23,24,25],\r
+               'inpos':  [0,1,1,2,3,4,4,5,5,5,6,7,8,9,10,11,12,13,14,15,16,16,16,16,17,17,18,19],\r
+               'comment': '情報処理点字',\r
+               },\r
+       {\r
+               'text': 'アドレスはabc@123.jpです。',\r
+               'input': 'アドレスワ ⠠⠦abc@123.jp⠠⠴ デス。',\r
+               'output': '⠁⠐⠞⠛⠹⠄ ⠠⠦⠁⠃⠉⠪⠼⠁⠃⠉⠲⠰⠚⠏⠠⠴ ⠐⠟⠹⠲',\r
+               'inpos2': [0,1,2,3,4,4,5,5,5,6,7,8,9,10,11,12,13,14,14,14,14,15,16,17],\r
+               'inpos1': [0,1,1,2,3,4,5,6,7,8,9,10,11,12,12,13,14,15,16,16,17,18,19,20,21,21,22,23],\r
+               'inpos':  [0,1,1,2,3,4,4,5,5,5,6,7,8,9,9,10,11,12,13,13,14,14,14,14,15,15,16,17],\r
+               'comment': '情報処理点字。数字、ピリオドのあとにa~jが続くときは小文字フラグ(56)が必要。',\r
+               },\r
+       {\r
+               'text': 'アドレスはa-b_c@123.jpです。',\r
+               'input': 'アドレスワ ⠠⠦a-b_c@123.jp⠠⠴ デス。',\r
+               'output': '⠁⠐⠞⠛⠹⠄ ⠠⠦⠁⠤⠃⠐⠤⠉⠪⠼⠁⠃⠉⠲⠰⠚⠏⠠⠴ ⠐⠟⠹⠲',\r
+               'inpos2': [0,1,2,3,4,4,5,5,5,6,7,8,9,10,11,12,13,14,15,16,16,16,16,17,18,19],\r
+               'inpos1': [0,1,1,2,3,4,5,6,7,8,9,10,11,11,12,13,14,14,15,16,17,18,18,19,20,21,22,23,23,24,25],\r
+               'inpos':  [0,1,1,2,3,4,4,5,5,5,6,7,8,8,9,10,11,11,12,13,14,15,15,16,16,16,16,17,17,18,19],\r
+               'comment': '情報処理点字。jの前に小文字フラグ。',\r
+               },\r
+       {\r
+               'text': 'アドレスはhttp://abc.123.jp/~a/?a&b#a+b-c%56です。',\r
+               'input': 'アドレスワ ⠠⠦http://abc.123.jp/~a/?a&b#a+b-c%56⠠⠴ デス。',\r
+               'output': '⠁⠐⠞⠛⠹⠄ ⠠⠦⠓⠞⠞⠏⠐⠂⠌⠌⠁⠃⠉⠲⠼⠁⠃⠉⠲⠰⠚⠏⠌⠐⠉⠁⠌⠐⠦⠁⠯⠃⠩⠁⠬⠃⠤⠉⠻⠼⠑⠋⠠⠴ ⠐⠟⠹⠲',\r
+               'inpos2': [0,1,2,3,4,4,5,5,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,38,38,38,39,40,41],\r
+               'inpos1': [0,1,1,2,3,4,5,6,7,8,9,10,11,12,12,13,14,15,16,17,18,19,19,20,21,22,23,23,24,25,26,26,27,28,29,29,30,31,32,33,34,35,36,37,38,39,40,40,41,42,43,44,45,45,46,47],\r
+               'inpos':  [0,1,1,2,3,4,4,5,5,5,6,7,8,9,9,10,11,12,13,14,15,16,16,17,18,19,20,20,21,22,23,23,24,25,26,26,27,28,29,30,31,32,33,34,35,36,37,37,38,38,38,38,39,39,40,41],\r
+               'comment': '情報処理点字。jの前に小文字フラグ。',\r
+               },\r
+       {\r
+               'text': 'アドレスはabc.123.jpです。',\r
+               'input': 'アドレスワ ⠦abc.123.jp⠴ デス。',\r
+               'output': '⠁⠐⠞⠛⠹⠄ ⠦⠁⠃⠉⠲⠼⠁⠃⠉⠲⠚⠏⠴ ⠐⠟⠹⠲',\r
+               'inpos2': [0,1,2,3,4,4,5,5,6,7,8,9,10,11,12,13,14,14,14,15,16,17],\r
+               'inpos1': [0,1,1,2,3,4,5,6,7,8,9,10,11,11,12,13,14,15,16,17,18,19,19,20,21],\r
+               'inpos':  [0,1,1,2,3,4,4,5,5,6,7,8,9,9,10,11,12,13,14,14,14,15,15,16,17],\r
+               'comment': '外国語引用符。数字の後ろのドットは小数点ではない。',\r
+               },\r
+       {\r
+               'text': 'C:\\Program Files',\r
+               'input': '⠠⠦C:\\Program Files⠠⠴',\r
+               'output': '⠠⠦⠠⠉⠐⠂⠫⠠⠏⠗⠕⠛⠗⠁⠍ ⠠⠋⠊⠇⠑⠎⠠⠴',\r
+               'inpos1': [0,1,2,2,3,3,4,5,5,6,7,8,9,10,11,12,13,13,14,15,16,17,18,19],\r
+               'comment': '情報処理点字',\r
+               },\r
+       {\r
+               'text': 'C:\\Users\\ユーザー',\r
+               'input': '⠠⠦C:\\Users\\⠠⠴ ユーザー',\r
+               'output': '⠠⠦⠠⠉⠐⠂⠫⠠⠥⠎⠑⠗⠎⠫⠠⠴ ⠬⠒⠐⠱⠒',\r
+               'inpos1': [0,1,2,2,3,3,4,5,5,6,7,8,9,10,11,12,13,14,15,16,16,17],\r
+               'comment': '情報処理点字を前半のみに使う',\r
+               },\r
+       {\r
+               'text': 'v1.4',\r
+               'input': '⠦v1.4⠴',\r
+               'output': '⠦⠧⠼⠁⠂⠙⠴',\r
+               'inpos2': [0,0,1,2,3,3],\r
+               'inpos1': [0,1,2,2,3,4,5],\r
+               'inpos':  [0,0,1,1,2,3,3],\r
+               'comment': 'nvdajp ticket 28226 (comment 2012-05-16)',\r
+               },\r
+       {\r
+               'text': 'c:\\',\r
+               'input': '⠠⠦c:\\⠠⠴',\r
+               'output': '⠠⠦⠉⠐⠂⠫⠠⠴',\r
+               'inpos1': [0,1,2,3,3,4,5,6],\r
+               'comment': '円記号',\r
+               },\r
+       {\r
+               'text': 'c:\\work\\nvda\\jpmain>',\r
+               'input': '⠠⠦c:\\work\\nvda\\jpmain>⠠⠴',\r
+               'output': '⠠⠦⠉⠐⠂⠫⠺⠕⠗⠅⠫⠝⠧⠙⠁⠫⠚⠏⠍⠁⠊⠝⠢⠢⠠⠴',\r
+               'inpos1': [0,1,2,3,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,21,22,23],\r
+               'comment': '円記号 jpとmainが既知語であるがマスアケしない',\r
+               },\r
+       {\r
+               'text': '<=>',\r
+               'input': '<=>',\r
+               'output': '⠔⠔⠒⠒⠢⠢',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,1,2,2],\r
+               'inpos':  [0,0,1,1,2,2],\r
+               },\r
+       {\r
+               'input': 'アー',\r
+               'output': '⠁⠒',\r
+               'inpos1': [0,1],\r
+               },\r
+       {\r
+               'text': 'きゃりーぱみゅぱみゅ',\r
+               'input': 'キャリーパミュパミュ',\r
+               'output': '⠈⠡⠓⠒⠠⠥⠈⠽⠠⠥⠈⠽',\r
+               'inpos2': [0,1,2,3,4,5,6,7,8,9],\r
+               'inpos1': [0,0,2,3,4,4,5,5,7,7,8,8],\r
+               'inpos':  [0,0,2,3,4,4,5,5,7,7,8,8],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき 第4章 その1 句読符',\r
+               'input': 'ア、イ。',\r
+               'output': '⠁⠰ ⠃⠲',\r
+               'inpos1': [0,1,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき 第4章 その1 句読符',\r
+               'input': 'ア?ア?',\r
+               'output': '⠁⠢ ⠁⠢',\r
+               'inpos1': [0,1,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき 第4章 その1 句読符',\r
+               'input': 'ア!ア!',\r
+               'output': '⠁⠖ ⠁⠖',\r
+               'inpos1': [0,1,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき 第4章 その1 句読符',\r
+               'text': 'いいえ。はい、そうです。',\r
+               'input': 'イイエ。ハイ、ソーデス。',\r
+               'output': '⠃⠃⠋⠲  ⠥⠃⠰ ⠺⠒⠐⠟⠹⠲',\r
+               'inpos2': [0,1,2,3,4,5,6,7,8,9,10,11],\r
+               'inpos1': [0,1,2,3,3,3,4,5,6,6,7,8,9,9,10,11],\r
+               'inpos':  [0,1,2,3,3,3,4,5,6,6,7,8,9,9,10,11],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき 第4章 その1 句読符 4.中点',\r
+               'input': 'ア・イ',\r
+               'output': '⠁⠐ ⠃',\r
+               'inpos1': [0,1,1,2],\r
+               },\r
+       {\r
+               'input': '123アイウ',\r
+               'output': '⠼⠁⠃⠉⠤⠁⠃⠉',\r
+               'inpos1': [0,0,1,2,2,3,4,5],\r
+               'comment': 'numbers and kana characters should be separated by 36 symbol.',\r
+               },\r
+       {\r
+               'input': '0ア1イ2ウ3エ4オ5ラ6リ7ル8レ9ロ',\r
+               'output': '⠼⠚⠤⠁⠼⠁⠤⠃⠼⠃⠤⠉⠼⠉⠤⠋⠼⠙⠤⠊⠼⠑⠤⠑⠼⠋⠤⠓⠼⠛⠤⠙⠼⠓⠤⠛⠼⠊⠤⠚',\r
+               'comment': 'numbers and some kana characters should be separated by 36 symbol.',\r
+               },\r
+       {\r
+               'input': '123キャ',\r
+               'output': '⠼⠁⠃⠉⠈⠡',\r
+               'comment': 'should not be separated by 36 symbol.',\r
+               },\r
+       {\r
+               'input': '0カ1キ2ク3ケ4コ5サ6シ7ス8セ9ソ0タ1チ2ツ3テ4ト5ナ6ニ7ヌ8ネ9ノ',\r
+               'output': '⠼⠚⠡⠼⠁⠣⠼⠃⠩⠼⠉⠫⠼⠙⠪⠼⠑⠱⠼⠋⠳⠼⠛⠹⠼⠓⠻⠼⠊⠺⠼⠚⠕⠼⠁⠗⠼⠃⠝⠼⠉⠟⠼⠙⠞⠼⠑⠅⠼⠋⠇⠼⠛⠍⠼⠓⠏⠼⠊⠎',\r
+               'comment': 'should not be separated by 36 symbol.',\r
+               },\r
+       {\r
+               'input': '1ア1キャ1ア',\r
+               'output': '⠼⠁⠤⠁⠼⠁⠈⠡⠼⠁⠤⠁',\r
+               'comment': 'numbers and some kana characters should be separated by 36 symbol.',\r
+               },\r
+       {\r
+               'input': '123a',\r
+               'output': '⠼⠁⠃⠉⠰⠁',\r
+               },\r
+       {\r
+               'input': '123A',\r
+               'output': '⠼⠁⠃⠉⠰⠠⠁',\r
+               },\r
+       {\r
+               'input': '1アa1aキャA1Aア',\r
+               'output': '⠼⠁⠤⠁⠰⠁⠼⠁⠰⠁⠤⠈⠡⠰⠠⠁⠼⠁⠰⠠⠁⠤⠁',\r
+               },\r
+       {\r
+               'input': '⠀ア',\r
+               'output': ' ⠁',\r
+               'inpos1': [0,1],\r
+               'comment': 'braille space should be changed to 0x20.',\r
+               },\r
+       {\r
+               'input': '⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟',\r
+               'output': '⠁⠂⠃⠄⠅⠆⠇⠈⠉⠊⠋⠌⠍⠎⠏⠐⠑⠒⠓⠔⠕⠖⠗⠘⠙⠚⠛⠜⠝⠞⠟',\r
+               'inpos1': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30],\r
+               'comment': 'braille code should not be changed.',\r
+               },\r
+       {\r
+               'input': '⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿',\r
+               'output': '⠠⠡⠢⠣⠤⠥⠦⠧⠨⠩⠪⠫⠬⠭⠮⠯⠰⠱⠲⠳⠴⠵⠶⠷⠸⠹⠺⠻⠼⠽⠾⠿',\r
+               'inpos1': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31],\r
+               'comment': 'braille code should not be changed.',\r
+               },\r
+       {\r
+               'text': '《本章のねらい》',\r
+               'input': '《ホンショーノ ネライ》',\r
+               'output': '⠐⠶⠮⠴⠈⠺⠒⠎ ⠏⠑⠃⠶⠂',\r
+               },\r
+       {\r
+               'text': '二十五',\r
+               'input': '25',\r
+               'output': '⠼⠃⠑',\r
+               'inpos1': [0,0,1],\r
+               },\r
+       {\r
+               'text': 'ピクチャ3の12',\r
+               'input': 'ピクチャ3ノ 12',\r
+               'output': '⠠⠧⠩⠈⠕⠼⠉⠎ ⠼⠁⠃',\r
+               },\r
+       {\r
+               'text': '    雨。  晴れ。',\r
+               'input': '    アメ。  ハレ。',\r
+               'output': '    ⠁⠿⠲    ⠥⠛⠲',\r
+               'comment': '先頭のスペースを除去しない'\r
+               },\r
+       {\r
+               'text': '大文字',\r
+               'input': 'オーモジ',\r
+               },\r
+       {\r
+               'text': 'システムキャレット', \r
+               'input': 'システム キャレット',\r
+               },\r
+       {\r
+               'text': 'フィードバック',\r
+               'input': 'フィード バック',\r
+               },\r
+       {\r
+               'text': 'インターフェース',\r
+               'input': 'インター フェース',\r
+               },\r
+       {\r
+               'text': 'オペレーティングシステム',\r
+               'input': 'オペレーティング システム',\r
+               },\r
+       #{\r
+       #       'text': 'トーキングインストーラー',\r
+       #       'input': 'トーキング インストーラー',\r
+       #       },\r
+       {\r
+               'text': 'アイスクリーム', \r
+               'input': 'アイス クリーム',\r
+               },\r
+       {\r
+               'text': '日本点字図書館',\r
+               'input': 'ニッポン テンジ トショカン'\r
+               },\r
+       {\r
+               'text': '通り',\r
+               'input': 'トオリ',\r
+               },\r
+       {\r
+               'text': 'ねえ',\r
+               'input': 'ネエ',\r
+               },\r
+       {\r
+               'text': '通り', 'input': 'トオリ'\r
+               },\r
+       {\r
+               'text': '狼', 'input': 'オオカミ'\r
+               },\r
+       {\r
+               'text': '通る', 'input': 'トオル'\r
+               },\r
+       {\r
+               'text': '多い', 'input': 'オオイ'\r
+               },\r
+       {\r
+               'text': '多く', 'input': 'オオク'\r
+               },\r
+       {\r
+               'text': '大晦日', 'input': 'オオミソカ'\r
+               },\r
+       {\r
+               'text': '手作り', 'input': 'テヅクリ'\r
+               },\r
+       {\r
+               'text': '南半球', 'input': 'ミナミ ハンキュー'\r
+               },\r
+       {       \r
+               'text': 'アメリカ合衆国', 'input': 'アメリカ ガッシューコク'\r
+               },\r
+       {\r
+               'text': '第一人者', 'input': 'ダイ1ニンシャ'\r
+               },\r
+       {\r
+               'text': '一流', 'input': '1リュー'\r
+               },\r
+       {\r
+               'text': '一月', 'input': '1ガツ'\r
+               },\r
+       {\r
+               'text': '二月', 'input': '2ガツ'\r
+               },\r
+       {\r
+               'text': '四方', 'input': '4ホー'\r
+               },\r
+       {\r
+               'text': '六法全書', 'input': '6ポー ゼンショ'\r
+               },\r
+       {\r
+               'text': '百人一首', 'input': '100ニン 1シュ'\r
+               },\r
+       {\r
+               'text': 'ヱビスビール', 'input': 'エビス ビール'\r
+               },\r
+       {\r
+               'text': '日本コロムビア', 'input': 'ニッポン コロムビア'\r
+               },\r
+       {\r
+               'text': 'ビタミンE', 'input': 'ビタミン E'\r
+               },\r
+       {\r
+               'text': '劇団四季', 'input': 'ゲキダン 4キ'\r
+               },\r
+       {\r
+               'text': '四季', 'input': '4キ'\r
+               },\r
+       {\r
+               'text': '四半期', 'input': '4ハンキ'\r
+               },\r
+       {\r
+               'text': '四角形', 'input': '4カクケイ'\r
+               },\r
+       {\r
+               'text': '四条', 'input': '4ジョー'\r
+               },\r
+       {\r
+               'text': '二男', 'input': '2ナン'\r
+               },\r
+       {\r
+               'text': '十数', 'input': '10スー'\r
+               },\r
+       {\r
+               'text': '一輪車', 'input': '1リンシャ'\r
+               },\r
+       {\r
+               'text': '三塁打', 'input': '3ルイダ'\r
+               },\r
+       {\r
+               'text': '一汁一菜', 'input': '1ジュー 1サイ'\r
+               },\r
+       {\r
+               'text': '五臓六腑', 'input': '5ゾー 6プ'\r
+               },\r
+       {\r
+               'text': '一段', 'input': '1ダン'\r
+               },\r
+       {\r
+               'text': '七転び八起き', 'input': 'ナナコロビ ヤオキ'\r
+               },\r
+       {\r
+               'text': '十重二十重', 'input': 'トエ ハタエ'\r
+               },\r
+       {\r
+               'text': '3ラン', 'input': '3ラン'\r
+               },\r
+       {\r
+               'text': 'さんりんしゃ', 'input': '3リンシャ'\r
+               },\r
+       {\r
+               'text': 'いちばん', 'input': '1バン'\r
+               },\r
+       {\r
+               'text': 'X線', 'input': 'Xセン'\r
+               },\r
+\r
+       {'text':'触読', 'input':'ショクドク'},\r
+       {'text':'触読式時計', 'input':'ショクドクシキ トケイ'},\r
+       {'text':'触手話', 'input':'ショクシュワ'},\r
+       {'text':'触読手話', 'input':'ショクドク シュワ'},\r
+\r
+       {'text':'泉質', 'input':'センシツ'},\r
+       {'text':'硫酸塩', 'input':'リューサンエン'},\r
+       {'text':'硫酸塩泉', 'input':'リューサンエンセン'},\r
+       {'text':'塩化物泉', 'input':'エンカブッセン'},\r
+       {'text':'泉温', 'input':'センオン'},\r
+       {'text':'冷鉱泉', 'input':'レイコーセン'},\r
+       {'text':'微温泉', 'input':'ビオンセン'},\r
+       {'text':'療養泉', 'input':'リョーヨーセン'},\r
+       {'text':'低張性', 'input':'テイチョーセイ'},\r
+       {'text':'等張性', 'input':'トーチョーセイ'},\r
+       {'text':'高張性', 'input':'コーチョーセイ'},\r
+       {'text':'酸性泉', 'input':'サンセイセン'},\r
+       {'text':'放射能泉', 'input':'ホーシャノーセン'},\r
+\r
+       {'text':'晴れ所により一時雨', 'input':'ハレ トコロニ ヨリ イチジ アメ'},\r
+\r
+       { 'note': '+ NVDA点字表示の誤りへの対応 +' },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.1',\r
+               'text': '誤判定',\r
+               'input': 'ゴハンテイ',\r
+               'output': '⠐⠪⠥⠴⠟⠃',\r
+               },\r
+       {\r
+               'text': '判定',\r
+               'input': 'ハンテイ',\r
+               'output': '⠥⠴⠟⠃',\r
+               'inpos1': [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.2',\r
+               'text': '50音順',\r
+               'input': '50オンジュン',\r
+               'output': '⠼⠑⠚⠤⠊⠴⠘⠹⠴',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.3',\r
+               'text': '下矢印',\r
+               'input': 'シタヤジルシ',\r
+               'output': '⠳⠕⠌⠐⠳⠙⠳',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.4',\r
+               'text': '上矢印',\r
+               'input': 'ウエヤジルシ',\r
+               'output': '⠉⠋⠌⠐⠳⠙⠳',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.5',\r
+               'text': '大見出し',\r
+               'input': 'オオミダシ',\r
+               'output': '⠊⠊⠷⠐⠕⠳',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.6',\r
+               'text': '前景色',\r
+               'input': 'ゼンケイショク',\r
+               'output': '⠐⠻⠴⠫⠃⠈⠺⠩',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.7',\r
+               'text': '表計算',\r
+               'input': 'ヒョーケイサン',\r
+               'output': '⠈⠮⠒⠫⠃⠱⠴',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.8',\r
+               'text': '材販',\r
+               'input': 'ザイハン',\r
+               'output': '⠐⠱⠃⠥⠴',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.9',\r
+               'text': '孫正義',\r
+               'input': 'ソン マサヨシ',\r
+               'output': '⠺⠴ ⠵⠱⠜⠳',\r
+               'inpos1': [0,1,2,3,4,5,6],\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.10',\r
+               'text': '昔々',\r
+               'input': 'ムカシ ムカシ',\r
+               'output': '⠽⠡⠳ ⠽⠡⠳',\r
+               'inpos1': [0,1,2,3,4,5,6],\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.11',\r
+               'text': '梅雨前線',\r
+               'input': 'バイウ ゼンセン',\r
+               'output': '⠐⠥⠃⠉ ⠐⠻⠴⠻⠴',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.12',\r
+               'text': '八ッ場ダム',\r
+               'input': 'ヤンバダム',\r
+               'output': '⠌⠴⠐⠥⠐⠕⠽',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.13',\r
+               'text': '1都5県',\r
+               'input': 'イットゴケン',\r
+               'output': '⠃⠂⠞⠐⠪⠫⠴',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.14',\r
+               'text': 'お姉さん',\r
+               'input': 'オネエサン',\r
+               'output': '⠊⠏⠋⠱⠴',\r
+               'inpos1': [0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.15',\r
+               'text': 'お兄さん',\r
+               'input': 'オニイサン',\r
+               'output': '⠊⠇⠃⠱⠴',\r
+               'inpos1': [0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.16',\r
+               'text': 'お婆さん',\r
+               'input': 'オバアサン',\r
+               'output': '⠊⠐⠥⠁⠱⠴',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.17',\r
+               'text': 'お爺さん',\r
+               'input': 'オジイサン',\r
+               'output': '⠊⠐⠳⠃⠱⠴',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.18',\r
+               'text': '1月',\r
+               'input': '1ガツ',\r
+               'output': '⠼⠁⠐⠡⠝',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.19',\r
+               'text': '盲ろう者',\r
+               'input': 'モーローシャ',\r
+               'output': '⠾⠒⠚⠒⠈⠱',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.20',\r
+               'text': 'のように',\r
+               'input': 'ノヨーニ',\r
+               'output': '⠎⠜⠒⠇',\r
+               'inpos1': [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.21',\r
+               'text': '1回',\r
+               'input': '1カイ',\r
+               'output': '⠼⠁⠡⠃',\r
+               },\r
+       {\r
+               'comment': 'NVDA点字表示の誤り No.22',\r
+               'text': 'いいんですけど',\r
+               'input': 'イインデスケド',\r
+               'output': '⠃⠃⠴⠐⠟⠹⠫⠐⠞',\r
+               },\r
+       { 'note': '+ 点訳のてびき第3版 +' },\r
+       { 'note': '== 第2章 語の書き表し方 ==' },\r
+       { 'note': '=== その1 仮名遣い ===' },\r
+       { 'note': '==== 1 基本的な仮名遣い ====' },\r
+       { 'note': '1、直音(清音・濁音・半濁音)は、現代仮名遣いに準じて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 1 No.1',\r
+               'text': '未曾有',\r
+               'input': 'ミゾウ',\r
+               'output': '⠷⠐⠺⠉',\r
+               },\r
+       { 'note': '【備考1】助詞の「を」は、発音に関わりなく「ヲ」と書くが、助詞の「は」「へ」は、発音するとおりに「ワ」「エ」と書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 1 No.17',\r
+               'text': '駅へは',\r
+               'input': 'エキエワ',\r
+               'output': '⠋⠣⠋⠄',\r
+               'inpos1': [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 1 No.22',\r
+               'text': 'えきへは',\r
+               'input': 'エキエワ',\r
+               'output': '⠋⠣⠋⠄',\r
+               'inpos1': [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 1 No.23',\r
+               'text': 'ははへの',\r
+               'input': 'ハハエノ',\r
+               'output': '⠥⠥⠋⠎',\r
+               'inpos1': [0,1,2,3],\r
+               },\r
+       { 'note': '【備考2】「言う」の語幹は、「ユ」と発音しても常に「イ」と書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 1 No.25',\r
+               'text': '言うて',\r
+               'input': 'イウテ',\r
+               'output': '⠃⠉⠟',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       { 'note': '2、拗音(拗濁音・拗半濁音を含む)は、拗音点字を用いて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 2 No.1',\r
+               'text': '距離',\r
+               'input': 'キョリ',\r
+               'output': '⠈⠪⠓',\r
+               },\r
+\r
+       { 'note': '3、撥音(ん)は、撥音符を用いて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 3 No.4',\r
+               'text': '何百',\r
+               'input': 'ナンビャク',\r
+               'output': '⠅⠴⠘⠥⠩',\r
+               },\r
+       { 'note': '4、促音(っ)は、促音符を用いて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 4 No.11',\r
+               'text': '夫',\r
+               'input': 'オット',\r
+               'output': '⠊⠂⠞',\r
+               },\r
+       { 'note': '〈処理〉「き」「く」「つ」が促音化しているかどうかは、辞書で確認するが、辞書によって表記が異なるなど判断が難しい場合は、促音符を用いず、その部分を「キ」「ク」「ツ」と書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 4 No.10',\r
+               'text': '万国旗',\r
+               'input': 'バンコクキ',\r
+               'output': '⠐⠥⠴⠪⠩⠣',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 4 No.11',\r
+               'text': '多角形',\r
+               'input': 'タカクケイ',\r
+               'output': '⠕⠡⠩⠫⠃',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 4 No.14',\r
+               'text': '高脂血症',\r
+               'input': 'コーシケツショー',\r
+               'output': '⠪⠒⠳⠫⠝⠈⠺⠒',\r
+               },\r
+       { 'note': '5、長音の書き表し方' },\r
+       { 'note': '(1)ア列の長音はア列の仮名に「ア」を添え、イ列とエ列の長音はイ列・エ列の仮名に「イ」を添えて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.1',\r
+               'text': 'ああ',\r
+               'input': 'アア',\r
+               'output': '⠁⠁',\r
+               'inpos1': [0,1],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.2',\r
+               'text': 'お母さん',\r
+               'input': 'オカアサン',\r
+               'output': '⠊⠡⠁⠱⠴',\r
+               'inpos1': [0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.3',\r
+               'text': 'いいえ',\r
+               'input': 'イイエ',\r
+               'output': '⠃⠃⠋',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,1,2],\r
+               'inpos':  [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.4',\r
+               'text': 'お兄さん',\r
+               'input': 'オニイサン',\r
+               'output': '⠊⠇⠃⠱⠴',\r
+               'inpos1': [0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.5',\r
+               'text': '先生',\r
+               'input': 'センセイ',\r
+               'output': '⠻⠴⠻⠃',\r
+               'inpos1': [0,1,2,3],\r
+               },\r
+       { 'note': '【備考】エ列の長音のうち和語は「エ」を添えて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.13',\r
+               'text': 'お姉さん',\r
+               'input': 'オネエサン',\r
+               'output': '⠊⠏⠋⠱⠴',\r
+               'inpos1': [0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.14',\r
+               'text': 'へえ',\r
+               'input': 'ヘエ',\r
+               'output': '⠯⠋',\r
+               'inpos2': [0,1],\r
+               'inpos1': [0,1],\r
+               'inpos':  [0,1],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.15',\r
+               'text': 'べらんめえ',\r
+               'input': 'ベランメエ',\r
+               'output': '⠐⠯⠑⠴⠿⠋',\r
+               'inpos2': [0,1,2,3,4],\r
+               'inpos1': [0,0,1,2,3,4],\r
+               'inpos':  [0,0,1,2,3,4],\r
+               },\r
+       { 'note': '〈処理1〉原文で小文字の仮名が長音を表しているときは、原文に使われている仮名を添えて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.16',\r
+               'text': 'やったぁ',\r
+               'input': 'ヤッタア',\r
+               'output': '⠌⠂⠕⠁',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,1,2,3],\r
+               'inpos':  [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.17',\r
+               'text': '君ィ',\r
+               'input': 'キミイ',\r
+               'output': '⠣⠷⠃',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       { 'note': '〈処理2〉原文に長音符号(-)が使われているときは、それにしたがって長音符を用いて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.18',\r
+               'text': 'はんたーい',\r
+               'input': 'ハンターイ',\r
+               'output': '⠥⠴⠕⠒⠃',\r
+               'inpos2': [0,1,2,3,4],\r
+               'inpos1': [0,1,2,3,4],\r
+               'inpos':  [0,1,2,3,4],\r
+               },\r
+       { 'note': '(2)ウ列とオ列の長音は、ウ列・オ列の仮名に長音符を添えて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.22',\r
+               'text': '宇宙',\r
+               'input': 'ウチュー',\r
+               'output': '⠉⠈⠝⠒',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.30',\r
+               'text': 'お父さん',\r
+               'input': 'オトーサン',\r
+               'output': '⠊⠞⠒⠱⠴',\r
+               'inpos1': [0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.34',\r
+               'text': '八日',\r
+               'input': 'ヨーカ',\r
+               'output': '⠜⠒⠡',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.35',\r
+               'text': '絵を見よう',\r
+               'input': 'エヲ ミヨー',\r
+               'output': '⠋⠔ ⠷⠜⠒',\r
+               'inpos1': [0,1,2,3,4,5],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.36',\r
+               'text': '運動しよう',\r
+               'input': 'ウンドー シヨー',\r
+               'output': '⠉⠴⠐⠞⠒ ⠳⠜⠒',\r
+               'inpos1': [0,1,2,2,3,4,5,6,7],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.37',\r
+               'text': 'そのような',\r
+               'input': 'ソノヨーナ',\r
+               'output': '⠺⠎⠜⠒⠅',\r
+               'inpos1': [0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.38',\r
+               'text': 'そうだろう',\r
+               'input': 'ソーダロー',\r
+               'output': '⠺⠒⠐⠕⠚⠒',\r
+               'inpos2': [0,1,2,3,4],\r
+               'inpos1': [0,1,2,2,3,4],\r
+               'inpos':  [0,1,2,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.39',\r
+               'text': '何と言おうか',\r
+               'input': 'ナント イオーカ',\r
+               'output': '⠅⠴⠞ ⠃⠊⠒⠡',\r
+               'inpos1': [0,1,2,3,4,5,6,7],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.40',\r
+               'text': '見まごうばかり',\r
+               'input': 'ミマゴーバカリ',\r
+               'output': '⠷⠵⠐⠪⠒⠐⠥⠡⠓',\r
+               'inpos2': [0,1,2,3,4,5,6],\r
+               'inpos1': [0,1,2,2,3,4,4,5,6],\r
+               'inpos':  [0,1,2,2,3,4,4,5,6],\r
+               },\r
+       { 'note': '【備考1】動詞の語尾の「う」は、「ウ」と書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.42',\r
+               'text': '縫う',\r
+               'input': 'ヌウ',\r
+               'output': '⠍⠉',\r
+               'inpos1': [0,1],\r
+               },\r
+       { 'note': '【備考2】ウ音便はウ列・オ列の長音の表記との関連で、長音符を用いて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.50',\r
+               'text': 'ゆうて',\r
+               'input': 'ユーテ',\r
+               'output': '⠬⠒⠟',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,1,2],\r
+               'inpos':  [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.51',\r
+               'text': '思うて',\r
+               'input': 'オモーテ',\r
+               'output': '⠊⠾⠒⠟',\r
+               'inpos1': [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.52',\r
+               'text': '吸うたり',\r
+               'input': 'スータリ',\r
+               'output': '⠹⠒⠕⠓',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,1,2,3],\r
+               'inpos':  [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.53',\r
+               'text': '繕うたり',\r
+               'input': 'ツクロータリ',\r
+               'output': '⠝⠩⠚⠒⠕⠓',\r
+               'inpos1': [0,1,2,3,4,5],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.54',\r
+               'text': '縫うた',\r
+               'input': 'ヌータ',\r
+               'output': '⠍⠒⠕',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,1,2],\r
+               'inpos':  [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.55',\r
+               'text': '買うた',\r
+               'input': 'コータ',\r
+               'output': '⠪⠒⠕',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,1,2],\r
+               'inpos':  [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.56',\r
+               'text': 'うれしゅう',\r
+               'input': 'ウレシュー',\r
+               'output': '⠉⠛⠈⠹⠒',\r
+               'inpos2': [0,1,2,3,4],\r
+               'inpos1': [0,1,2,2,4],\r
+               'inpos':  [0,1,2,2,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.57',\r
+               'text': '面白うて',\r
+               'input': 'オモシローテ',\r
+               'output': '⠊⠾⠳⠚⠒⠟',\r
+               'inpos1': [0,1,2,3,4,5],\r
+               },\r
+       { 'note': '【備考3】オ列の長音のうち、次の一覧表に掲げた和語とその派生語や複合語は「オ」を添えて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.58',\r
+               'text': '多い',\r
+               'input': 'オオイ',\r
+               'output': '⠊⠊⠃',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.59',\r
+               'text': '覆う',\r
+               'input': 'オオウ',\r
+               'output': '⠊⠊⠉',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.60',\r
+               'text': '狼',\r
+               'input': 'オオカミ',\r
+               'output': '⠊⠊⠡⠷',\r
+               'inpos2': [0,0,0,0],\r
+               'inpos1': [0,1,2,3],\r
+               'inpos':  [0,0,0,0],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.61',\r
+               'text': '大きい',\r
+               'input': 'オオキイ',\r
+               'output': '⠊⠊⠣⠃',\r
+               'inpos1': [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.62',\r
+               'text': '仰せ',\r
+               'input': 'オオセ',\r
+               'output': '⠊⠊⠻',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.63',\r
+               'text': '為おおせる',\r
+               'input': 'シオオセル',\r
+               'output': '⠳⠊⠊⠻⠙',\r
+               'inpos2': [0,1,2,3,4],\r
+               'inpos1': [0,1,2,3,4],\r
+               'inpos':  [0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.64',\r
+               'text': '車前草',\r
+               'input': 'オオバコ',\r
+               'output': '⠊⠊⠐⠥⠪',\r
+               'inpos1': [0,1,2,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.65',\r
+               'text': '概ね',\r
+               'input': 'オオムネ',\r
+               'output': '⠊⠊⠽⠏',\r
+               'inpos1': [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.66',\r
+               'text': '公',\r
+               'input': 'オオヤケ',\r
+               'output': '⠊⠊⠌⠫',\r
+               'inpos2': [0,0,0,0],\r
+               'inpos1': [0,1,2,3],\r
+               'inpos':  [0,0,0,0],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.67',\r
+               'text': '凡そ',\r
+               'input': 'オオヨソ',\r
+               'output': '⠊⠊⠜⠺',\r
+               'inpos1': [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.68',\r
+               'text': '氷',\r
+               'input': 'コオリ',\r
+               'output': '⠪⠊⠓',\r
+               'inpos2': [0,0,0],\r
+               'inpos1': [0,1,2],\r
+               'inpos':  [0,0,0],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.69',\r
+               # 'text': '郡',\r
+               'input': 'コオリ',\r
+               'output': '⠪⠊⠓',\r
+               'inpos1': [0,1,2],\r
+               'comment': '郡: 文脈がないと読みを確定できない',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.70',\r
+               'text': '凍る',\r
+               'input': 'コオル',\r
+               'output': '⠪⠊⠙',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.71',\r
+               'text': '滞る',\r
+               'input': 'トドコオル',\r
+               'output': '⠞⠐⠞⠪⠊⠙',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.72',\r
+               'text': '蟋蟀',\r
+               'input': 'コオロギ',\r
+               'output': '⠪⠊⠚⠐⠣',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.73',\r
+               'text': '装う',\r
+               'input': 'ヨソオウ',\r
+               'output': '⠜⠺⠊⠉',\r
+               'inpos1': [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.74',\r
+               # 'text': '十',\r
+               'input': 'トオ',\r
+               'output': '⠞⠊',\r
+               'inpos1': [0,1],\r
+               'comment': '十: 文脈がないと読みを確定できない',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.75',\r
+               'text': '遠い',\r
+               'input': 'トオイ',\r
+               'output': '⠞⠊⠃',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.76',\r
+               'text': '通る',\r
+               'input': 'トオル',\r
+               'output': '⠞⠊⠙',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.77',\r
+               'text': '憤る',\r
+               'input': 'イキドオル',\r
+               'output': '⠃⠣⠐⠞⠊⠙',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.78',\r
+               'text': 'いとおしい',\r
+               'input': 'イトオシイ',\r
+               'output': '⠃⠞⠊⠳⠃',\r
+               'inpos1': [0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.79',\r
+               'text': '炎',\r
+               'input': 'ホノオ',\r
+               'output': '⠮⠎⠊',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.80',\r
+               'text': '頬',\r
+               'input': 'ホオ',\r
+               'output': '⠮⠊',\r
+               'inpos1': [0,1],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.81',\r
+               'text': '朴',\r
+               'input': 'ホオ',\r
+               'output': '⠮⠊',\r
+               'inpos1': [0,1],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.82',\r
+               'text': '酸漿',\r
+               'input': 'ホオズキ',\r
+               'output': '⠮⠊⠐⠹⠣',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.83',\r
+               'text': '催す',\r
+               'input': 'モヨオス',\r
+               'output': '⠾⠜⠊⠹',\r
+               'inpos1': [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.84',\r
+               'text': '大目',\r
+               'input': 'オオメ',\r
+               'output': '⠊⠊⠿',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.85',\r
+               'text': '大通り',\r
+               'input': 'オオドオリ',\r
+               'output': '⠊⠊⠐⠞⠊⠓',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.86',\r
+               'text': '凍り付く',\r
+               'input': 'コオリツク',\r
+               'output': '⠪⠊⠓⠝⠩',\r
+               'inpos1': [0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.87',\r
+               'text': '透徹る',\r
+               'input': 'スキトオル',\r
+               'output': '⠹⠣⠞⠊⠙',\r
+               'inpos1': [0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.88',\r
+               'text': '十日',\r
+               'input': 'トオカ',\r
+               'output': '⠞⠊⠡',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.89',\r
+               'text': '遠ざかる',\r
+               'input': 'トオザカル',\r
+               'output': '⠞⠊⠐⠱⠡⠙',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.90',\r
+               'text': '通す',\r
+               'input': 'トオス',\r
+               'output': '⠞⠊⠹',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 5 No.91',\r
+               'text': '頬張る',\r
+               'input': 'ホオバル',\r
+               'output': '⠮⠊⠐⠥⠙',\r
+               },\r
+       { 'note': '6、「ジ ズ ジャ ジュ ジョ」と「ヂ ヅ ヂャ ヂョ」の使い分け' },\r
+       { 'note': '(1)サ行を用いることを原則とする。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.1',\r
+               'text': '根治',\r
+               'input': 'コンジ',\r
+               'output': '⠪⠴⠐⠳',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.2',\r
+               'text': '砂地',\r
+               'input': 'スナジ',\r
+               'output': '⠹⠅⠐⠳',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.3',\r
+               'text': '無花果',\r
+               'input': 'イチジク',\r
+               'output': '⠃⠗⠐⠳⠩',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.10',\r
+               'text': '砂利道',\r
+               'input': 'ジャリミチ',\r
+               'output': '⠘⠱⠓⠷⠗',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.20',\r
+               'text': '少しずつ',\r
+               'input': 'スコシズツ',\r
+               'output': '⠹⠪⠳⠐⠹⠝',\r
+               },\r
+       { 'note': '(2)タ行同音の連呼によって後ろの音節が濁る場合は、「ヂ」「ヅ」を用いて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.25',\r
+               'text': '縮む',\r
+               'input': 'チヂム',\r
+               'output': '⠗⠐⠗⠽',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.26',\r
+               'text': '縮れ',\r
+               'input': 'チヂレ',\r
+               'output': '⠗⠐⠗⠛',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.27',\r
+               'text': '続く',\r
+               'input': 'ツヅク',\r
+               'output': '⠝⠐⠝⠩',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.28',\r
+               'text': '手続き',\r
+               'input': 'テツヅキ',\r
+               'output': '⠟⠝⠐⠝⠣',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.29',\r
+               'text': '綴る',\r
+               'input': 'ツヅル',\r
+               'output': '⠝⠐⠝⠙',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.30',\r
+               'text': '綴り方',\r
+               'input': 'ツヅリカタ',\r
+               'output': '⠝⠐⠝⠓⠡⠕',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.31',\r
+               'text': '約やか',\r
+               'input': 'ツヅマヤカ',\r
+               'output': '⠝⠐⠝⠵⠌⠡',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.32',\r
+               'text': '鼓',\r
+               'input': 'ツヅミ',\r
+               'output': '⠝⠐⠝⠷',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.33',\r
+               'text': '葛籠',\r
+               'input': 'ツヅラ',\r
+               'output': '⠝⠐⠝⠑',\r
+               },\r
+       { 'note': '(3)2語の複合によってタ行の後半の語頭が濁音に変わる連濁の場合は、「ヂ」「ヅ」「ヂャ」「ヂュ」「ヂョ」を用いて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.34',\r
+               'text': '鼻血',\r
+               'input': 'ハナヂ',\r
+               'output': '⠥⠅⠐⠗',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.35',\r
+               'text': '身近',\r
+               'input': 'ミヂカ',\r
+               'output': '⠷⠐⠗⠡',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.36',\r
+               'text': '底力',\r
+               'input': 'ソコヂカラ',\r
+               'output': '⠺⠪⠐⠗⠡⠑',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.37',\r
+               'text': '湯呑茶碗',\r
+               'input': 'ユノミヂャワン',\r
+               'output': '⠬⠎⠷⠘⠕⠄⠴',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.38',\r
+               'text': '一本調子',\r
+               'input': 'イッポンヂョーシ',\r
+               'output': '⠃⠂⠠⠮⠴⠘⠞⠒⠳',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.39',\r
+               'text': '紅提灯',\r
+               'input': 'ベニヂョーチン',\r
+               'output': '⠐⠯⠇⠘⠞⠒⠗⠴',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.40',\r
+               'text': '三日月',\r
+               'input': 'ミカヅキ',\r
+               'output': '⠷⠡⠐⠝⠣',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.41',\r
+               'text': '気付く',\r
+               'input': 'キヅク',\r
+               'output': '⠣⠐⠝⠩',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.42',\r
+               'text': '小突く',\r
+               'input': 'コヅク',\r
+               'output': '⠪⠐⠝⠩',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.43',\r
+               'text': '近づく',\r
+               'input': 'チカヅク',\r
+               'output': '⠗⠡⠐⠝⠩',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.44',\r
+               'text': 'つくづく',\r
+               'input': 'ツクヅク',\r
+               'output': '⠝⠩⠐⠝⠩',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.45',\r
+               'text': '基づく',\r
+               'input': 'モトヅク',\r
+               'output': '⠾⠞⠐⠝⠩',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.46',\r
+               'text': '心尽くし',\r
+               'input': 'ココロヅクシ',\r
+               'output': '⠪⠪⠚⠐⠝⠩⠳',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.47',\r
+               'text': '小包',\r
+               'input': 'コヅツミ',\r
+               'output': '⠪⠐⠝⠝⠷',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.48',\r
+               'text': '手綱',\r
+               'input': 'タヅナ',\r
+               'output': '⠕⠐⠝⠅',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.49',\r
+               'text': '常々',\r
+               'input': 'ツネヅネ',\r
+               'output': '⠝⠏⠐⠝⠏',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.50',\r
+               'text': '働き詰め',\r
+               'input': 'ハタラキヅメ',\r
+               'output': '⠥⠕⠑⠣⠐⠝⠿',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.51',\r
+               'text': '理詰め',\r
+               'input': 'リヅメ',\r
+               'output': '⠓⠐⠝⠿',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 6 No.52',\r
+               'text': '我慢強い',\r
+               'input': 'ガマンヅヨイ',\r
+               'output': '⠐⠡⠵⠴⠐⠝⠜⠃',\r
+               },\r
+\r
+       { 'note': '7、現代仮名遣いで書かれた文章の中に歴史的仮名遣いが混じっているときは、現代仮名遣いに直して書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 7 No.1',\r
+               'text': 'まづ',\r
+               'input': 'マズ',\r
+               'output': '⠵⠐⠹',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 7 No.2',\r
+               'text': '一つづつ',\r
+               'input': 'ヒトツズツ',\r
+               'output': '⠧⠞⠝⠐⠹⠝',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 7 No.3',\r
+               # 'text': 'なほ',\r
+               'input': 'ナオ',\r
+               'output': '⠅⠊',\r
+               'inpos1': [0,1],\r
+               'comment': '人名「なほ」と区別がつかない',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 7 No.4',\r
+               'text': '思ふ',\r
+               'input': 'オモウ',\r
+               'output': '⠊⠾⠉',\r
+               'inpos1': [0,1,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 7 No.5',\r
+               'text': '大きう',\r
+               'input': 'オオキュー',\r
+               'output': '⠊⠊⠈⠩⠒',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 7 No.6',\r
+               'text': 'うれしう',\r
+               'input': 'ウレシュー',\r
+               'output': '⠉⠛⠈⠹⠒',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 7 No.7',\r
+               'text': 'もみぢ',\r
+               'input': 'モミジ',\r
+               'output': '⠾⠷⠐⠳',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,1,2,2],\r
+               'inpos':  [0,1,2,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 1 7 No.8',\r
+               'text': 'みづうみ',\r
+               'input': 'ミズウミ',\r
+               'output': '⠷⠐⠹⠉⠷',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,1,1,2,3],\r
+               'inpos':  [0,1,1,2,3],\r
+               },\r
+       # 第2章 語の書き表し方\r
+       # その1 仮名遣い\r
+       { 'note': '==== 2 その他の仮名遣い ====' },\r
+       { 'note': '1.外来語や外国語は原文の表記に従って書くことを原則とする。'},\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.1',\r
+               'text': 'フィルム',\r
+               'input': 'フィルム',\r
+               'output': '⠢⠧⠙⠽',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,0,2,3],\r
+               'inpos':  [0,0,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.2',\r
+               'text': 'フイルム',\r
+               'input': 'フイルム',\r
+               'output': '⠭⠃⠙⠽',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,1,2,3],\r
+               'inpos':  [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.3',\r
+               'text': 'バイオリン',\r
+               'input': 'バイオリン',\r
+               'output': '⠐⠥⠃⠊⠓⠴',\r
+               'inpos2': [0,1,2,3,4],\r
+               'inpos1': [0,0,1,2,3,4],\r
+               'inpos':  [0,0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.4',\r
+               'text': 'ヴァイオリン',\r
+               'input': 'ヴァイオリン',\r
+               'output': '⠲⠥⠃⠊⠓⠴',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.5',\r
+               'text': 'ビタミン',\r
+               'input': 'ビタミン',\r
+               'output': '⠐⠧⠕⠷⠴',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.6',\r
+               'text': 'ヴィタミン',\r
+               'input': 'ヴィタミン',\r
+               'output': '⠲⠧⠕⠷⠴',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.7',\r
+               'text': 'カルシウム',\r
+               'input': 'カルシウム',\r
+               'output': '⠡⠙⠳⠉⠽',\r
+               'inpos1': [0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.8',\r
+               'text': 'カルシューム',\r
+               'input': 'カルシューム',\r
+               'output': '⠡⠙⠈⠹⠒⠽',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.9',\r
+               'text': 'パーティー',\r
+               'input': 'パーティー',\r
+               'output': '⠠⠥⠒⠈⠗⠒',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.10',\r
+               'text': 'パーティ',\r
+               'input': 'パーティ',\r
+               'output': '⠠⠥⠒⠈⠗',\r
+               },\r
+       { 'note': '<処理1>外来語外国語に使われている「ヂ」「ヅ」「ヂャ」「ヂュ」「ヂョ」は、「ジ」「ズ」「ジャ」「ジュ」「ジョ」を用いて書いてよい。なお、特に必要があれば原文のかなづかいで書くことができる。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.22',\r
+               'text': 'ラヂオ',\r
+               'input': 'ラジオ',\r
+               'output': '⠑⠐⠳⠊',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.23',\r
+               'text': 'ヂャケット',\r
+               'input': 'ジャケット',\r
+               'output': '⠘⠱⠫⠂⠞',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.24',\r
+               'text': '映画「ラヂオの時間」',\r
+               'input': 'エイガ 「ラジオノ ジカン」',\r
+               'output': '⠋⠃⠐⠡ ⠤⠑⠐⠳⠊⠎ ⠐⠳⠡⠴⠤', # 「」に 36 を使う\r
+               },\r
+       { 'note': '<処理2>外来語や外国語に使われている「ヰ」「ヱ」「ヲ」は、「イ」「エ」「オ」あるいは「ウィ」「ウェ」「ウォ」を用いて書いてよい。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.25',\r
+               'text': 'ウヰスキー',\r
+               'input': 'ウイスキー',\r
+               'output': '⠉⠃⠹⠣⠒',\r
+               'inpos1': [0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.26',\r
+               'text': 'スヰフト',\r
+               'input': 'スイフト', #スウィフト\r
+               'output': '⠹⠃⠭⠞',\r
+               'inpos1': [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.27',\r
+               'text': 'ヱルテル',\r
+               'input': 'ウェルテル',\r
+               'output': '⠢⠋⠙⠟⠙',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.28',\r
+               'text': 'ヲルポール',\r
+               'input': 'ウォルポール',\r
+               'output': '⠢⠊⠙⠠⠮⠒⠙',\r
+               },\r
+       { 'note': '<処理3>児童書などで、全文ひらがな書きのため長音符を使わずに書かれている外来語や外国語は、発音を考慮して適宜長音符に書き換えてよい。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.29',\r
+               'text': 'ヘリコプタア',\r
+               'input': 'ヘリコプター',\r
+               'output': '⠯⠓⠪⠠⠭⠕⠒',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.30',\r
+               'text': 'ちゅうりっぷ',\r
+               'input': 'チューリップ',\r
+               'output': '⠈⠝⠒⠓⠂⠠⠭',\r
+               },\r
+       { 'note': '<処理4>漢字で書かれた外来語や外国語を原文で書く場合は、ルビや辞書などで示される仮名の表記に従って書いてよい。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 1 No.31',\r
+               # 'text': '老酒',\r
+               'input': 'ラオチュウ',\r
+               'output': '⠑⠊⠈⠝⠉',\r
+               'comment': '老酒: ルビがないと読みを確定できない',\r
+               },\r
+       { 'note': '2.擬声語・擬態語・嘆声などは「基本的な仮名遣い」に準じて書くが、原文に長音記号や特殊音が使われているときは、それに従って長音符や特殊音点字を用いて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 2 No.3',\r
+               'text': 'シーンと',\r
+               'input': 'シーント',\r
+               'output': '⠳⠒⠴⠞',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,1,2,3],\r
+               'inpos':  [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 2 No.4',\r
+               'text': 'しいんと',\r
+               'input': 'シイント',\r
+               'output': '⠳⠃⠴⠞',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,1,2,3],\r
+               'inpos':  [0,1,2,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 2 No.5',\r
+               #'text': 'ちゅうちゅう',\r
+               'input': 'チューチュー',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 2 No.6',\r
+               #'text': 'ぐうぐう',\r
+               'input': 'グーグー',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 2 No.10',\r
+               #'text': 'めえめえ',\r
+               'input': 'メエメエ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 2 No.12',\r
+               #'text': 'ごおごお',\r
+               'input': 'ゴオゴオ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 2 No.13',\r
+               #'text': 'ぎゃおーっ',\r
+               'input': 'ギャオーッ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 2 No.14',\r
+               #'text': 'があーん',\r
+               'input': 'ガアーン',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 2 No.17',\r
+               #'text': 'がおううううう',\r
+               'input': 'ガオウウウウー',\r
+               },\r
+       { 'note': '<処理>原文で長音記号に代えて波線や棒線などが使われているときも、長音符を用いて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 2 No.18',\r
+               'text': 'ふにゃ~',\r
+               'input': 'フニャー',\r
+               'output': '⠭⠈⠅⠒',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,1,1,3],\r
+               'inpos':  [0,1,1,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 2 No.19',\r
+               #'text': 'まぁ――っ',\r
+               'input': 'マアーッ',\r
+               },\r
+       { 'note': '3.方言は原文の表記に従って書くことを原則とするが、長音は「基本的な仮名遣い」に準じて書いてよい。なお、原文に長音符号が使われているときは、それに従って長音符を用いて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 3 No.2',\r
+               'text': 'しぇんしぇい',\r
+               'input': 'シェンシェイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 3 No.4',\r
+               'text': 'おおきに',\r
+               'input': 'オオキニ',\r
+               },\r
+       { 'note': '<処理>原文の表記に従うと不自然な音になる場合は、その発音に使いと思われる点字を用いて書いてよい。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 3 No.6',\r
+               'text': 'おみやぁさん',\r
+               'input': 'オミャアサン',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 3 No.7',\r
+               'text': '先生ぇさまぁ',\r
+               'input': 'センセエサマア',\r
+               },\r
+       { 'note': '4.原文に特殊音点字を用いても書き表せない文字が使われているときは、なるべくその発音に近い点字を用いて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 4 No.1',\r
+               'text': 'おとゥ、おかァ',\r
+               'input': 'オトー、オカア',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 4 No.2',\r
+               'text': 'ヱ゛ルレエヌ',\r
+               'input': 'ヴェルレエヌ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 4 No.3',\r
+               'text': 'ヲ゛ルガ',\r
+               'input': 'ヴォルガ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 4 No.4',\r
+               'text': 'ガリワ゛ー',\r
+               'input': 'ガリヴァー',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 4 No.5',\r
+               'text': 'クヮルテット',\r
+               'input': 'クァルテット',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 4 No.6',\r
+               'text': 'ヂェスチャー',\r
+               'input': 'ジェスチャー',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 4 No.7',\r
+               'text': 'スェーター',\r
+               'input': 'スエーター',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 4 No.8',\r
+               'text': 'ヒァーッたまげた',\r
+               'input': 'ヒャーッ タマゲタ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 4 No.9',\r
+               'text': 'あ゛ー',\r
+               'input': 'アー',\r
+               },\r
+       { 'note': '5.固有名詞の仮名遣い' },\r
+       { 'note': '(1) 漢字で書かれた固有名詞は「基本的な仮名遣い」に準じて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 5 No.1',\r
+               'text': '大阪',\r
+               'input': 'オオサカ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 5 No.2',\r
+               'text': '遠野',\r
+               'input': 'トオノ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 5 No.3',\r
+               'text': '東井',\r
+               'input': 'トーイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 5 No.10',\r
+               'text': '青梅',\r
+               'input': 'オーメ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 5 No.11',\r
+               'text': '透',\r
+               'input': 'トオル',\r
+               },\r
+\r
+       { 'note': '(2)仮名で書かれた固有名詞は原本の仮名遣いに従って書くが、長音は「基本的な仮名遣い」に準じて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 5 No.13',\r
+               'text': 'みさを',\r
+               'input': 'ミサヲ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 5 No.14',\r
+               'text': 'かほる',\r
+               'input': 'カホル',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 5 No.19',\r
+               #'text': 'さをり織り',\r
+               'input': 'サヲリオリ',\r
+               },\r
+       { 'note': '<処理1>ワ行の「ヱ」は、感嘆符と形が同じなので、ア行の「エ」に変えることを原則とする。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 5 No.22',\r
+               'text': 'ヱビスビール',\r
+               'input': 'エビス ビール',\r
+               },\r
+       { 'note': '<処理2>原文で長音符号が使われているときは、長音符を用いて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 5 No.23',\r
+               #'text': 'オーヤマ書店',\r
+               'input': 'オーヤマ ショテン',\r
+               },\r
+       { 'note': '<処理3>主となる固有名詞部分以外の語に使われている歴史的仮名遣いは、現代仮名遣いに直して書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 5 No.24',\r
+               'text': 'みやこをどり',\r
+               'input': 'ミヤコ オドリ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 5 No.25',\r
+               'text': '青木をりがみ教室',\r
+               'input': 'アオキ オリガミ キョーシツ',\r
+               },\r
+       { 'note': '<処理4>外来語や疑似外来語などを使って仮名で表記されている法人名や商品名などは、その仮名遣いに従って書いてよい。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 5 No.26',\r
+               'text': '日本コロムビア',\r
+               'input': 'ニッポン コロムビア',\r
+               },\r
+       { 'note': '6.歴史的仮名遣いで書かれた文や語句が現代文の中に挿入されているときは、次の4種類の方法の中から原文に応じて最もふさわしい方法を選んで点訳する。なお、特に差し支えがない場合は(ア)の方法を用いる。' },\r
+       { 'note': '(ア)現代文の仮名遣いで書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 6 No.3',\r
+               #'text': '問ふ',\r
+               'input': 'トウ',\r
+               },\r
+       { 'note': '(イ)現代文の仮名遣いで書いたあとに、古文の仮名遣いをカッコ類で囲んで書く。' },\r
+       { 'note': '(ウ)古文の仮名遣いで書いたあとに、現代文の仮名遣いをカッコ類で囲んで書く。' },\r
+       { 'note': '(エ)古文の仮名遣いで書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 6 No.10',\r
+               #'text': 'あはれ',\r
+               'input': 'アハレ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 6 No.11',\r
+               # 'text': '弥生',\r
+               'input': 'ヤヨヒ',\r
+               'output': '⠌⠜⠧',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 6 No.12',\r
+               # 'text': '問ふ',\r
+               'input': 'トフ',\r
+               'output': '⠞⠭',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 6 No.13',\r
+               # 'text': '末',\r
+               'input': 'スヱ',\r
+               'output': '⠹⠖',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 6 No.14',\r
+               # 'text': '居り',\r
+               'input': 'ヲリ',\r
+               'output': '⠔⠓',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第2章 その1 2 6 No.15',\r
+               # 'text': '静けさ',\r
+               'input': 'シヅケサ',\r
+               'output': '⠳⠐⠝⠫⠱',\r
+               },\r
+\r
+       { 'note': '=== その2 数字 ===' },\r
+       { 'note': '==== 1 数の書き方 ====' },\r
+       { 'note': '1.数字は数符(⠼)を前置し、4桁までは一続きに書く。' },\r
+       {\r
+               'text': '1',\r
+               'input': '1',\r
+               'output': '⠼⠁',\r
+               'inpos2': [0],\r
+               'inpos1': [0,0],\r
+               'inpos':  [0,0],\r
+               },\r
+       {\r
+               'text': '二十三',\r
+               'input': '23',\r
+               },\r
+       {\r
+               'text': '五百',\r
+               'input': '500',\r
+               },\r
+       {\r
+               'text': '二千三百',\r
+               'input': '2300',\r
+               },\r
+       {\r
+               'text': '2001',\r
+               'input': '2001',\r
+               'output': '⠼⠃⠚⠚⠁',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,0,1,2,3],\r
+               'inpos':  [0,0,1,2,3],\r
+               },\r
+       {\r
+               'text': '5000',\r
+               'input': '5000',\r
+               'output': '⠼⠑⠚⠚⠚',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,0,1,2,3],\r
+               'inpos':  [0,0,1,2,3],\r
+               },\r
+       {\r
+               #'text': '一千万',\r
+               'input': '1センマン',\r
+               },\r
+       {\r
+               #'text': '三千億',\r
+               'input': '3ゼンオク',\r
+               },\r
+       { 'note': '2.万・億・兆などはその発音を仮名で書き、4桁ごとに区切る。' },\r
+       {\r
+               #'text': '54309',\r
+               'input': '5マン 4309',\r
+               },\r
+       {\r
+               #'text': '10500',\r
+               'input': '1マン 500',\r
+               },\r
+       {\r
+               'text': '三兆二千四百万',\r
+               'input': '3チョー 2400マン',\r
+               },\r
+       { 'note': '3.小数は小数点(⠂)を用いて書く。' },\r
+       {\r
+               'text': '3.14',\r
+               'input': '3.14',\r
+               'output': '⠼⠉⠂⠁⠙',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,0,1,2,3],\r
+               'inpos':  [0,0,1,2,3],\r
+               },\r
+       {\r
+               'text': '0.01',\r
+               'input': '0.01',\r
+               'output': '⠼⠚⠂⠚⠁',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,0,1,2,3],\r
+               'inpos':  [0,0,1,2,3],\r
+               },\r
+       { 'note': '4.分数' },\r
+       { 'note': '5.「千」「百」「十」が位を表している場合には、それぞれの仮名を用いて書く。' },\r
+       {\r
+               'text': '数千',\r
+               'input': 'スーセン',\r
+               },\r
+       {\r
+               'text': '数百',\r
+               'input': 'スーヒャク',\r
+               },\r
+       {\r
+               'text': '何百',\r
+               'input': 'ナンビャク',\r
+               },\r
+       {\r
+               'text': '何十',\r
+               'input': 'ナンジュー', # ナン10\r
+               },\r
+       { 'note': '6.およその数で数が重なる場合は、読点などを用いず、それぞれに数符を前置して続けて書く。' },\r
+       {\r
+               'text': '二、三',\r
+               'input': '2⠼3',\r
+               'output': '⠼⠃⠼⠉',\r
+               },\r
+       {\r
+               #'text': '二百五、六十',\r
+               'input': '2ヒャク 5⠼60',\r
+               'output': '⠼⠃⠈⠥⠩ ⠼⠑⠼⠋⠚',\r
+               },\r
+       { 'note': '7.特に必要があればそのまま数字を並べて書くことができる。その場合は3桁ごとに位取り点(⠄)を用いて書いてよい。' },\r
+       {\r
+               'text': '53,000',\r
+               'input': '53,000',\r
+               'output': '⠼⠑⠉⠄⠚⠚⠚',\r
+               'inpos2': [0,1,2,3,4,5],\r
+               'inpos1': [0,0,1,2,3,4,5],\r
+               'inpos':  [0,0,1,2,3,4,5],\r
+               },\r
+       { 'note': '8.年号の略記に使われているアポストロフィは、数符の直後にアポストロフィ(3)を用いて書く。' },\r
+       {\r
+               'text': "'02",\r
+               'input': "'02", # text2mecab で全角に変換されるが元に戻す\r
+               'output': '⠼⠄⠚⠃',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,2],\r
+               'inpos':  [0,0,1,2],\r
+               },\r
+       { 'note': '==== 2 数を含む言葉の書き方 ====' },\r
+       { 'note': '1.数字を漢字音で発音する場合' },\r
+       { 'note': '(1) 数を含む言葉は数字で表すことを原則とし、数字に続く言葉(助数詞など)は続けて書く。また、数に続く言葉はア行・ラ行のいずれかで始まる場合は、数字と形が同じなので、第一つなぎ符(36)をはさんで続けて書く。' },\r
+       {\r
+               'text': '1枚',\r
+               'input': '1マイ',\r
+               },\r
+       {\r
+               'text': '三十センチメートル',\r
+               'input': '30センチメートル',\r
+               },\r
+       {\r
+               'text': '五割',\r
+               'input': '5ワリ',\r
+               },\r
+       {\r
+               'text': '六百人',\r
+               'input': '600ニン',\r
+               },\r
+       {\r
+               'text': '一流品',\r
+               'input': '1リューヒン',\r
+               },\r
+       {\r
+               'text': '第2章',\r
+               'input': 'ダイ2ショー',\r
+               },\r
+       {\r
+               'text': '中2階',\r
+               'input': 'チュー2カイ',\r
+               },\r
+       {\r
+               #'text': 'お三方',\r
+               'input': 'オ3カタ',\r
+               },\r
+       {\r
+               #'text': '3三振',\r
+               'input': '3⠼3シン',\r
+               'output': '⠼⠉⠼⠉⠳⠴',\r
+               },\r
+       {\r
+               'text': '四季',\r
+               'input': '4キ',\r
+               },\r
+       {\r
+               'text': '四半期',\r
+               'input': '4ハンキ',\r
+               },\r
+       {\r
+               'text': '四角形',\r
+               'input': '4カクケイ',\r
+               },\r
+       {\r
+               #'text': '二男一女',\r
+               'input': '2ナン 1ジョ',\r
+               },\r
+       {\r
+               'text': '十数人',\r
+               'input': '10スーニン',\r
+               },\r
+       {\r
+               #'text': '五千円札',\r
+               'input': '5センエンサツ',\r
+               },\r
+       {\r
+               #'text': '1000万光年',\r
+               'input': '1センマンコーネン',\r
+               },\r
+       {\r
+               'text': '西暦2000年',\r
+               'input': 'セイレキ 2000ネン',\r
+               },\r
+       {\r
+               'text': '零時十五分',\r
+               'input': '0ジ 15フン',\r
+               },\r
+       {\r
+               'text': '一列',\r
+               'input': '1レツ',\r
+               'output': '⠼⠁⠤⠛⠝',\r
+               },\r
+       {\r
+               'text': '一輪車',\r
+               'input': '1リンシャ',\r
+               'output': '⠼⠁⠤⠓⠴⠈⠱',\r
+               },\r
+       {\r
+               'text': '二億年',\r
+               'input': '2オクネン',\r
+               'output': '⠼⠃⠤⠊⠩⠏⠴',\r
+               },\r
+       {\r
+               'text': '三塁打',\r
+               'input': '3ルイダ',\r
+               'output': '⠼⠉⠤⠙⠃⠐⠕',\r
+               },\r
+       {\r
+               'text': '五十円',\r
+               'input': '50エン',\r
+               'output': '⠼⠑⠚⠤⠋⠴',\r
+               },\r
+       { 'note': '【備考】数字の後ろに助詞・助動詞が続く場合も続けて書く。その場合、ア行・ラ行で始まる助詞・助動詞との間は、第一つなぎ符をはさんで続けて書く。' },\r
+       {\r
+               'text': '101の',\r
+               'input': '101ノ',\r
+               'output': '⠼⠁⠚⠁⠎',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,0,1,2,3],\r
+               'inpos':  [0,0,1,2,3],\r
+               },\r
+       {\r
+               'text': '3です',\r
+               'input': '3デス',\r
+               'output': '⠼⠉⠐⠟⠹',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,1,1,2],\r
+               'inpos':  [0,0,1,1,2],\r
+               },\r
+       {\r
+               'text': '4120へ',\r
+               'input': '4120エ',\r
+               'output': '⠼⠙⠁⠃⠚⠤⠋',\r
+               'inpos2': [0,1,2,3,4],\r
+               'inpos1': [0,0,1,2,3,3,4],\r
+               'inpos':  [0,0,1,2,3,3,4],\r
+               },\r
+       {\r
+               'text': '18らしい',\r
+               'input': '18ラシイ',\r
+               'output': '⠼⠁⠓⠤⠑⠳⠃',\r
+               'inpos2': [0,1,2,3,4],\r
+               'inpos1': [0,0,1,1,2,3,4],\r
+               'inpos':  [0,0,1,1,2,3,4],\r
+               },\r
+       { 'note': '<処理>数字に続く言葉との関係で数字の読みが促音化しても、促音符は用いず、数字の後ろに仮名を続けて書く。' },\r
+       {\r
+               'text': '1足',\r
+               'input': '1ソク',\r
+               },\r
+       {\r
+               #'text': '10本',\r
+               'input': '10ポン',\r
+               },\r
+       {\r
+               'text': '一汁一菜',\r
+               'input': '1ジュー 1サイ',\r
+               },\r
+       {\r
+               'text': '一丁目一番地',\r
+               'input': '1チョーメ 1バンチ',\r
+               },\r
+       {\r
+               'text': '五臓六腑',\r
+               'input': '5ゾー 6プ',\r
+               },\r
+       { 'note': '(2) 一語中で、月と日を省略して書いてあるときや、数字が並んでいるときは、中点などを省略して続けて書く。' },\r
+       {\r
+               'text': '二・二六事件',\r
+               'input': '2⠼26 ジケン',\r
+               'output': '⠼⠃⠼⠃⠋ ⠐⠳⠫⠴',\r
+               'inpos1': [0,0,1,2,3,4,5,5,6,7],\r
+               },\r
+       {\r
+               'text': '七・五・三',\r
+               'input': '7⠼5⠼3',\r
+               'output': '⠼⠛⠼⠑⠼⠉',\r
+               'inpos1': [0,0,1,2,3,4],\r
+               },\r
+       {\r
+               'text': '六・三・三制',\r
+               'input': '6⠼3⠼3セイ',\r
+               'output': '⠼⠋⠼⠉⠼⠉⠻⠃',\r
+               'inpos1': [0,0,1,2,3,4,5,6],\r
+               },\r
+       { 'note': '(3) 数量や順序の意味が薄れた言葉や、漢数字の形を表している場合などは仮名で書く。' },\r
+       {\r
+               'text': '青二才',\r
+               'input': 'アオニサイ',\r
+               },\r
+       {\r
+               'text': '一足飛び',\r
+               'input': 'イッソクトビ',\r
+               },\r
+       {\r
+               'text': '一般的',\r
+               'input': 'イッパンテキ',\r
+               },\r
+       {\r
+               'text': '一生',\r
+               'input': 'イッショー',\r
+               },\r
+       {\r
+               'text': '無二',\r
+               'input': 'ムニ',\r
+               },\r
+       {\r
+               'text': '一辺倒',\r
+               'input': 'イッペントー',\r
+               },\r
+       {\r
+               'text': '四角い',\r
+               'input': 'シカクイ',\r
+               },\r
+       {\r
+               'text': '七面鳥',\r
+               'input': 'シチメンチョー',\r
+               },\r
+       {\r
+               'text': '零下30度',\r
+               'input': 'レイカ 30ド',\r
+               },\r
+       {\r
+               'text': '真一文字',\r
+               'input': 'マイチモンジ',\r
+               },\r
+       {\r
+               'text': '十字路',\r
+               'input': 'ジュージロ',\r
+               },\r
+       {\r
+               #'text': '八の字をよせる',\r
+               'input': 'ハチノジヲ ヨセル',\r
+               },\r
+       { 'note': '<処理>明らかにアラビア数字の形を表している場合は、数字を用いて書く。' },\r
+       {\r
+               #'text': '8の字形',\r
+               'input': '8ノジガタ',\r
+               },\r
+       { 'note': '(4) 同じ発音の語でも、数量や順序の意味のあるなしで、数字と仮名に書き分ける。' },\r
+       {\r
+               #'text': '一番になった',\r
+               'input': '1バンニ ナッタ',\r
+               },\r
+       {\r
+               'text': '一番大きい',\r
+               'input': 'イチバン オオキイ',\r
+               },\r
+       {\r
+               'text': '一段昇る',\r
+               'input': '1ダン ノボル',\r
+               },\r
+       {\r
+               'text': '一段ときれいだ',\r
+               'input': 'イチダント キレイダ',\r
+               },\r
+       {\r
+               #'text': 'ちょっと一杯',\r
+               'input': 'チョット 1パイ',\r
+               },\r
+       {\r
+               #'text': '一杯になった',\r
+               'input': 'イッパイニ ナッタ',\r
+               },\r
+       {\r
+               'text': '第一段階',\r
+               'input': 'ダイ1 ダンカイ',\r
+               },\r
+       {\r
+               #'text': '第一、金がない',\r
+               'input': 'ダイイチ、カネガ ナイ',\r
+               },\r
+       { 'note': '(5) 数字の読みが仮名で書かれていても、数量や順序の意味がある場合は数字を用いて書く。' },\r
+       {\r
+               #'text': 'いちにち',\r
+               'input': '1ニチ',\r
+               },\r
+       {\r
+               #'text': 'もういちど',\r
+               'input': 'モー 1ド',\r
+               },\r
+       {\r
+               #'text': 'いちばん星',\r
+               'input': '1バンボシ',\r
+               },\r
+       {\r
+               'text': 'さんりんしゃ',\r
+               'input': '3リンシャ',\r
+               },\r
+       { 'note': '2.数字を和語読みする場合' },\r
+       { 'note': ' (1) 数を含む言葉で、和語読みするものは仮名で書く。' },\r
+       {\r
+               'text': '一人',\r
+               'input': 'ヒトリ',\r
+               },\r
+       {\r
+               'text': '二人',\r
+               'input': 'フタリ',\r
+               },\r
+       {\r
+               'text': '一言',\r
+               'input': 'ヒトコト',\r
+               },\r
+       {\r
+               'text': '三日月',\r
+               'input': 'ミカヅキ',\r
+               },\r
+       {\r
+               'text': '四隅',\r
+               'input': 'ヨスミ',\r
+               },\r
+       {\r
+               'text': '五十路',\r
+               'input': 'イソジ',\r
+               },\r
+       {\r
+               'text': '明け六つ',\r
+               'input': 'アケムツ',\r
+               },\r
+       {\r
+               'text': '七草',\r
+               'input': 'ナナクサ',\r
+               },\r
+       {\r
+               'text': '七転び八起き',\r
+               'input': 'ナナコロビ ヤオキ',\r
+               },\r
+       {\r
+               'text': '九重',\r
+               'input': 'ココノエ',\r
+               },\r
+       {\r
+               'text': '十重二十重',\r
+               'input': 'トエ ハタエ',\r
+               },\r
+       {\r
+               'text': '二十日',\r
+               'input': 'ハツカ',\r
+               },\r
+       {\r
+               'text': '二十歳',\r
+               'input': 'ハタチ',\r
+               },\r
+       #{\r
+       #       'text': '三十日',\r
+       #       'input': '30ニチ', # 'ミソカ',\r
+       #       },\r
+       {\r
+               'text': '一つから十',\r
+               'input': 'ヒトツカラ 10', # 'ヒトツカラ トオ',\r
+               },\r
+       {\r
+               'text': '一日から十日',\r
+               'input': 'ツイタチカラ トオカ',\r
+               },\r
+       {\r
+               'text': '1日から10日',\r
+               'input': 'ツイタチカラ トオカ',\r
+               },\r
+       {\r
+               'text': '一日から一〇日',\r
+               'input': 'ツイタチカラ トオカ',\r
+               },\r
+       {\r
+               'text': '1から10',\r
+               'input': '1カラ 10',\r
+               },\r
+\r
+       { 'note': '【備考】漢字音と和語読みが混じる場合も、和語読みの部分は仮名で書く。' },\r
+       {\r
+               'text': '3泊4日',\r
+               'input': '3パク ヨッカ',\r
+               },\r
+       {\r
+               'text': '二百十日',\r
+               'input': '2ヒャク トオカ',\r
+               },\r
+       { 'note': '(2) 漢字音の系列に入っているものは、読み替えによって和語と同じ発音になっても数字で書く。' },\r
+       {\r
+               'text': '四時',\r
+               'input': '4ジ',\r
+               },\r
+       {\r
+               'text': '四人',\r
+               'input': '4ニン',\r
+               },\r
+       {\r
+               'text': '四冊',\r
+               'input': '4サツ',\r
+               },\r
+       {\r
+               'text': '十四日',\r
+               'input': '14カ',\r
+               },\r
+       {\r
+               'text': '二十四日',\r
+               'input': '24カ',\r
+               },\r
+       {\r
+               #'text': '三、四日',\r
+               'input': '3⠼4カ',\r
+               },\r
+       {\r
+               'text': '三三七拍子',\r
+               'input': '3⠼3⠼7ビョーシ',\r
+               },\r
+       {\r
+               'text': '七個',\r
+               'input': '7コ',\r
+               },\r
+       {\r
+               'text': '十七歳',\r
+               'input': '17サイ',\r
+               },\r
+       {\r
+               'text': '百十番',\r
+               'input': '110バン',\r
+               },\r
+\r
+       { 'text': '1日', 'input': 'ツイタチ',},\r
+       { 'text': '2日', 'input': 'フツカ',},\r
+       { 'text': '3日', 'input': 'ミッカ',},\r
+       { 'text': '4日', 'input': 'ヨッカ',},\r
+       { 'text': '5日', 'input': 'イツカ',},\r
+       { 'text': '6日', 'input': 'ムイカ',},\r
+       { 'text': '7日', 'input': 'ナノカ',},\r
+       { 'text': '8日', 'input': 'ヨーカ',},\r
+       { 'text': '9日', 'input': 'ココノカ',},\r
+       { 'text': '10日', 'input': 'トオカ',},\r
+       { 'text': '11日', 'input': '11ニチ',},\r
+       { 'text': '12日', 'input': '12ニチ',},\r
+       { 'text': '13日', 'input': '13ニチ',},\r
+       { 'text': '14日', 'input': '14カ',},\r
+       { 'text': '15日', 'input': '15ニチ',},\r
+       { 'text': '16日', 'input': '16ニチ',},\r
+       { 'text': '17日', 'input': '17ニチ',},\r
+       { 'text': '18日', 'input': '18ニチ',},\r
+       { 'text': '19日', 'input': '19ニチ',},\r
+       { 'text': '20日', 'input': 'ハツカ',},\r
+       { 'text': '21日', 'input': '21ニチ',},\r
+       { 'text': '22日', 'input': '22ニチ',},\r
+       { 'text': '23日', 'input': '23ニチ',},\r
+       { 'text': '24日', 'input': '24カ',},\r
+       { 'text': '25日', 'input': '25ニチ',},\r
+       { 'text': '26日', 'input': '26ニチ',},\r
+       { 'text': '27日', 'input': '27ニチ',},\r
+       { 'text': '28日', 'input': '28ニチ',},\r
+       { 'text': '29日', 'input': '29ニチ',},\r
+       { 'text': '30日', 'input': '30ニチ',},\r
+       { 'text': '31日', 'input': '31ニチ',},\r
+\r
+       { 'text': '一日', 'input': 'ツイタチ',},\r
+       { 'text': '二日', 'input': 'フツカ',},\r
+       { 'text': '三日', 'input': 'ミッカ',},\r
+       { 'text': '四日', 'input': 'ヨッカ',},\r
+       { 'text': '五日', 'input': 'イツカ',},\r
+       { 'text': '六日', 'input': 'ムイカ',},\r
+       { 'text': '七日', 'input': 'ナノカ',},\r
+       { 'text': '八日', 'input': 'ヨーカ',},\r
+       { 'text': '九日', 'input': 'ココノカ',},\r
+       { 'text': '一〇日', 'input': 'トオカ',},\r
+       { 'text': '一一日', 'input': '11ニチ',},\r
+       { 'text': '一二日', 'input': '12ニチ',},\r
+       { 'text': '一三日', 'input': '13ニチ',},\r
+       { 'text': '一四日', 'input': '14カ',},\r
+       { 'text': '一五日', 'input': '15ニチ',},\r
+       { 'text': '一六日', 'input': '16ニチ',},\r
+       { 'text': '一七日', 'input': '17ニチ',},\r
+       { 'text': '一八日', 'input': '18ニチ',},\r
+       { 'text': '一九日', 'input': '19ニチ',},\r
+       { 'text': '二〇日', 'input': 'ハツカ',},\r
+       { 'text': '二一日', 'input': '21ニチ',},\r
+       { 'text': '二二日', 'input': '22ニチ',},\r
+       { 'text': '二三日', 'input': '23ニチ',},\r
+       { 'text': '二四日', 'input': '24カ',},\r
+       { 'text': '二五日', 'input': '25ニチ',},\r
+       { 'text': '二六日', 'input': '26ニチ',},\r
+       { 'text': '二七日', 'input': '27ニチ',},\r
+       { 'text': '二八日', 'input': '28ニチ',},\r
+       { 'text': '二九日', 'input': '29ニチ',},\r
+       { 'text': '三〇日', 'input': '30ニチ',},\r
+       { 'text': '三一日', 'input': '31ニチ',},\r
+\r
+       { 'text': '十日', 'input': 'トオカ',},\r
+       { 'text': '十一日', 'input': '11ニチ',},\r
+       { 'text': '十二日', 'input': '12ニチ',},\r
+       { 'text': '十三日', 'input': '13ニチ',},\r
+       { 'text': '十四日', 'input': '14カ',},\r
+       { 'text': '十五日', 'input': '15ニチ',},\r
+       { 'text': '十六日', 'input': '16ニチ',},\r
+       { 'text': '十七日', 'input': '17ニチ',},\r
+       { 'text': '十八日', 'input': '18ニチ',},\r
+       { 'text': '十九日', 'input': '19ニチ',},\r
+       { 'text': '二十日', 'input': 'ハツカ',},\r
+       { 'text': '二十一日', 'input': '21ニチ',},\r
+       { 'text': '二十二日', 'input': '22ニチ',},\r
+       { 'text': '二十三日', 'input': '23ニチ',},\r
+       { 'text': '二十四日', 'input': '24カ',},\r
+       { 'text': '二十五日', 'input': '25ニチ',},\r
+       { 'text': '二十六日', 'input': '26ニチ',},\r
+       { 'text': '二十七日', 'input': '27ニチ',},\r
+       { 'text': '二十八日', 'input': '28ニチ',},\r
+       { 'text': '二十九日', 'input': '29ニチ',},\r
+       { 'text': '三十日', 'input': '30ニチ',},\r
+       { 'text': '三十一日', 'input': '31ニチ',},\r
+\r
+       { 'note': '3.外国語の読みをする場合は漢字音に準じて書く。' },\r
+       {\r
+               'text': 'ボーイング747',\r
+               'input': 'ボーイング 747',\r
+               },\r
+       {\r
+               'text': 'ベスト10',\r
+               'input': 'ベスト 10',\r
+               },\r
+       {\r
+               'text': '3ランホームラン',\r
+               'input': '3ラン ホームラン',\r
+               },\r
+       { 'note': '4.地名や人名などの固有名詞の中に使われている数字は、仮名で書くことを原則とする。' },\r
+       {\r
+               'text': '八戸市',\r
+               'input': 'ハチノヘシ',\r
+               },\r
+       {\r
+               'text': '九州',\r
+               'input': 'キューシュー',\r
+               },\r
+       {\r
+               'text': '四国',\r
+               'input': 'シコク',\r
+               },\r
+       {\r
+               #'text': '八幡平',\r
+               'input': 'ハチマンタイ',\r
+               },\r
+       {\r
+               'text': '一郎',\r
+               'input': 'イチロー',\r
+               },\r
+       {\r
+               'text': '直木三十五',\r
+               'input': 'ナオキ サンジューゴ',\r
+               },\r
+       {\r
+               'text': '赤十字社',\r
+               'input': 'セキジュージシャ',\r
+               },\r
+       { 'note': '【備考】固有名詞であっても、数量や順序の意味を明確にする必要がある場合などには数字を用いて書く。' },\r
+       {\r
+               'text': 'ルイ十四世',\r
+               'input': 'ルイ 14セイ',\r
+               },\r
+       {\r
+               'text': '二月堂',\r
+               'input': '2ガツドー',\r
+               },\r
+       {\r
+               #'text': '市立一中',\r
+               'input': 'シリツ 1チュー',\r
+               },\r
+       {\r
+               'text': '三十三間堂',\r
+               'input': '33ゲンドー',\r
+               },\r
+       {\r
+               'text': '四条河原町',\r
+               'input': '4ジョー カワラマチ',\r
+               },\r
+       {\r
+               'text': '劇団四季',\r
+               'input': 'ゲキダン 4キ',\r
+               },\r
+       { 'note': '5.アルファベットやハイフンなど他の記号と一緒に使われている数字や、4桁で区切ったり仮名で書くと不自然になるような数字は、原文の表記に従って書く。' },\r
+       {\r
+               'text': '連絡先090-8000-7603',\r
+               'input': 'レンラクサキ 090-8000-7603',\r
+               'output': '⠛⠴⠑⠩⠱⠣ ⠼⠚⠊⠚⠤⠼⠓⠚⠚⠚⠤⠼⠛⠋⠚⠉',\r
+               'inpos1': [0,1,2,3,4,5,6,7,7,8,9,10,11,11,12,13,14,15,16,16,17,18,19],\r
+               },\r
+       {\r
+               'text': '振替00150-8-44522',\r
+               'input': 'フリカエ 00150-8-44522',\r
+               'output': '⠭⠓⠡⠋ ⠼⠚⠚⠁⠑⠚⠤⠼⠓⠤⠼⠙⠙⠑⠃⠃',\r
+               'inpos1': [0,1,2,3,4,5,5,6,7,8,9,10,11,11,12,13,13,14,15,16,17],\r
+               },\r
+       {\r
+               'text': 'ISBN 4-925053-14-0',\r
+               'input': 'ISBN 4-925053-14-0',\r
+               'output': '⠰⠠⠠⠊⠎⠃⠝ ⠼⠙⠤⠼⠊⠃⠑⠚⠑⠉⠤⠼⠁⠙⠤⠼⠚',\r
+               'inpos2': [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17],\r
+               'inpos1': [0,0,0,0,1,2,3,4,5,5,6,7,7,8,9,10,11,12,13,14,14,15,16,17,17],\r
+               'inpos':  [0,0,0,0,1,2,3,4,5,5,6,7,7,8,9,10,11,12,13,14,14,15,16,17,17],\r
+               },\r
+       {\r
+               'text': 'No.2514269',\r
+               'input': 'No. 2514269',\r
+               'output': '⠰⠠⠝⠕⠲ ⠼⠃⠑⠁⠙⠃⠋⠊',\r
+               'inpos1': [0,0,0,1,2,3,4,4,5,6,7,8,9,10],\r
+               },\r
+\r
+       { 'note': '==== 3 ローマ数字の書き方 ===='},\r
+       {\r
+               'text': 'ⅰ',\r
+               'input': 'i',\r
+               'output': '⠰⠊',\r
+               'inpos2': [0],\r
+               'inpos1': [0,0],\r
+               'inpos':  [0,0],\r
+               },\r
+       {\r
+               'text': 'Ⅴ',\r
+               'input': 'V',\r
+               'output': '⠰⠠⠧',\r
+               'inpos2': [0],\r
+               'inpos1': [0,0,0],\r
+               'inpos':  [0,0,0],\r
+               },\r
+       {\r
+               'text': 'Ⅶ',\r
+               'input': 'VII',\r
+               'output': '⠰⠠⠠⠧⠊⠊',\r
+               'inpos1': [0,0,0,0,1,2],\r
+               },\r
+       {\r
+               'text': 'Ⅹ',\r
+               'input': 'X',\r
+               'output': '⠰⠠⠭',\r
+               'inpos2': [0],\r
+               'inpos1': [0,0,0],\r
+               'inpos':  [0,0,0],\r
+               },\r
+\r
+       { 'note': '=== その3 アルファベット ===' },\r
+       { 'note': '==== 1 文字として書き表す場合 ====' },\r
+       { 'note': '1.アルファベットは外字符(56)を前置して書く。略字など2文字以上の場合でも、一つの外字符に続けて書く。大文字は該当する文字に大文字符(6)を前置して書くが、一続きの文字がすべて大文字の場合は、外字符の直後に二重大文字符(6)を続けて書く。なお、一続きの文字の一部でも、後ろに続く文字すべてが大文字であれば、その位置に二重大文字符を用いて書くことができる。' },\r
+       {\r
+               'text': 'ビタミンE',\r
+               'input': 'ビタミン E',\r
+               'output': '⠐⠧⠕⠷⠴ ⠰⠠⠑',\r
+               'inpos1': [0,0,1,2,3,4,5,5,5],\r
+               },\r
+       {\r
+               'text': 'TV',\r
+               'input': 'TV',\r
+               'output': '⠰⠠⠠⠞⠧',\r
+               'inpos2': [0,1],\r
+               'inpos1': [0,0,0,0,1],\r
+               'inpos':  [0,0,0,0,1],\r
+               },\r
+       {\r
+               'text': 'PTA',\r
+               'input': 'PTA',\r
+               'output': '⠰⠠⠠⠏⠞⠁',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,0,0,1,2],\r
+               'inpos':  [0,0,0,0,1,2],\r
+               },\r
+       {\r
+               'text': 'OPEC',\r
+               'input': 'OPEC',\r
+               'output': '⠰⠠⠠⠕⠏⠑⠉',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,0,0,0,1,2,3],\r
+               'inpos':  [0,0,0,0,1,2,3],\r
+               },\r
+       {\r
+               'text': 'AM',\r
+               'input': 'AM',\r
+               'output': '⠰⠠⠠⠁⠍',\r
+               'inpos2': [0,1],\r
+               'inpos1': [0,0,0,0,1],\r
+               'inpos':  [0,0,0,0,1],\r
+               },\r
+       {\r
+               'text': 'AMe',\r
+               'input': 'AMe',\r
+               'output': '⠰⠠⠁⠠⠍⠑',\r
+               'inpos2': [0,1,2],\r
+               'inpos1': [0,0,0,1,1,2],\r
+               'inpos':  [0,0,0,1,1,2],\r
+               },\r
+       {\r
+               'text': 'AMeDAS',\r
+               'input': 'AMeDAS',\r
+               'output': '⠰⠠⠁⠠⠍⠑⠠⠙⠠⠁⠠⠎',\r
+               'inpos2': [0,1,2,3,4,5],\r
+               'inpos1': [0,0,0,1,1,2,3,3,4,4,5,5],\r
+               'inpos':  [0,0,0,1,1,2,3,3,4,4,5,5],\r
+               'comment': '大文字と小文字が混在する単語では二重大文字符を使わないほうが読みやすい',\r
+               },\r
+       { 'note': '【備考1】' },\r
+       {\r
+               #'text': 'P・T・A',\r
+               'input': 'PTA',\r
+               'output': '⠰⠠⠠⠏⠞⠁',\r
+               'inpos1': [0,0,0,0,1,2],\r
+               },\r
+       { 'note': '【備考2】' },\r
+       {\r
+               #'text': 'U.S.A.',\r
+               'input': 'USA',\r
+               'output': '⠰⠠⠠⠥⠎⠁',\r
+               'inpos1': [0,0,0,0,1,2],\r
+               },\r
+       { 'note': '【備考3】二つ以上の略称がハイフンで結ばれているときは、それぞれに外字符や大文字符・二重大文字符を前置し、第1つなぎ符を用いて書く。' },\r
+       {\r
+               'text': 'MS-DOS',\r
+               'input': 'MS-DOS',\r
+               'output': '⠰⠠⠠⠍⠎⠤⠰⠠⠠⠙⠕⠎',\r
+               'inpos2': [0,1,2,3,4,5],\r
+               'inpos1': [0,0,0,0,1,2,3,3,3,3,4,5],\r
+               'inpos':  [0,0,0,0,1,2,3,3,3,3,4,5],\r
+               'comment': '36でつなぐとカナに戻る(ハイフンで外字符の効力がなくなる)',\r
+               },\r
+       {\r
+               'text': 'MS-DOS',\r
+               'input': 'MS-DOS',\r
+               'output': '⠰⠠⠠⠍⠎⠤⠰⠠⠠⠙⠕⠎',\r
+               'inpos2': [0,1,2,3,4,5],\r
+               'inpos1': [0,0,0,0,1,2,3,3,3,3,4,5],\r
+               'inpos':  [0,0,0,0,1,2,3,3,3,3,4,5],\r
+               },\r
+       { 'note': '【備考4】アルファベットで書かれた略称の間の「/」に限り、(34) の記号を用いて書く。一つの外字符にアルファベットと記号を続けて書くが、大文字符や二重大文字符は改めて前置する。' },\r
+       {\r
+               'text': 'DOS/V',\r
+               'input': 'DOS/V',\r
+               'output': '⠰⠠⠠⠙⠕⠎⠌⠠⠧',\r
+               'inpos2': [0,1,2,3,4],\r
+               'inpos1': [0,0,0,0,1,2,3,4,4],\r
+               'inpos':  [0,0,0,0,1,2,3,4,4],\r
+               'comment': '/は456-34という新記号がある',\r
+               },\r
+       {\r
+               'text': 'DOS/V',\r
+               'input': 'DOS/V',\r
+               'output': '⠰⠠⠠⠙⠕⠎⠌⠠⠧',\r
+               'inpos2': [0,1,2,3,4],\r
+               'inpos1': [0,0,0,0,1,2,3,4,4],\r
+               'inpos':  [0,0,0,0,1,2,3,4,4],\r
+               'comment': '/は456-34という新記号がある',\r
+               },\r
+       { 'note': '2.一続きに書き表すべき1語中のアルファベットと仮名の間は、第1つなぎ符をはさんで続けて書く。' },\r
+       {\r
+               'text': 'A型',\r
+               'input': 'Aガタ',\r
+               'output': '⠰⠠⠁⠤⠐⠡⠕',\r
+               'inpos1': [0,0,0,0,1,1,2],\r
+               },\r
+       {\r
+               'text': 'X線',\r
+               'input': 'Xセン',\r
+               'output': '⠰⠠⠭⠤⠻⠴',\r
+               'inpos1': [0,0,0,0,1,2],\r
+               },\r
+       { 'note': '【備考】アルファベットや省略符としてのピリオドの後ろに助詞・助動詞が続く場合は、間を区切って書く。' },\r
+       {\r
+               'text': 'Aは',\r
+               'input': 'A ワ',\r
+               },\r
+       {\r
+               'text': 'NHKまで',\r
+               'input': 'NHK マデ',\r
+               },\r
+       {\r
+               'text': 'PRだった',\r
+               'input': 'PR ダッタ',\r
+               },\r
+       {\r
+               'text': 'No.を',\r
+               'input': 'No. ヲ',\r
+               },\r
+       { 'note': '3.一続きに書き表すべき1語中の仮名とアルファベットの間は続けて書く。' },\r
+       {\r
+               'text': '何㎝',\r
+               'input': 'ナンcm',\r
+               },\r
+       {\r
+               'text': '何cm',\r
+               'input': 'ナンcm',\r
+               },\r
+       {\r
+               'text': '数㎏',\r
+               'input': 'スーkg',\r
+               },\r
+       {\r
+               'text': '数kg',\r
+               'input': 'スーkg',\r
+               },\r
+       { 'note': '4.一続きに書き表すべき1語中のアルファベットと数字、数字とアルファベットの間は続けて書く。' },\r
+       {\r
+               'text': 'p105',\r
+               'input': 'p105',\r
+               'output': '⠰⠏⠼⠁⠚⠑',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,0,1,1,2,3],\r
+               'inpos':  [0,0,1,1,2,3],\r
+               },\r
+       {\r
+               'text': 'B5判',\r
+               'input': 'B5ハン',\r
+               },\r
+       { 'note': '<処理>アルファベットに省略符としてのピリオドが付いているときは、後ろに続く数字との間を区切って書く。' },\r
+       {\r
+               'text': 'No.1から',\r
+               'input': 'No. 1カラ',\r
+               'output': '⠰⠠⠝⠕⠲ ⠼⠁⠡⠑',\r
+               'inpos1': [0,0,0,1,2,3,4,4,5,6],\r
+               },\r
+       { 'note': '==== 2 語や文を書き表す場合 ====' },\r
+       { 'note': '1.アルファベットで書かれた語句や文は、その前後ろを外国語引用符(236~356)で囲んで書く。外国語引用符の内側は英文記号を用いて、英語点字の表記法に従って書く。' },\r
+       {\r
+               'text': 'チェコ製のglass',\r
+               'input': 'チェコセイノ glass',\r
+               'output': '⠈⠟⠪⠻⠃⠎ ⠰⠛⠇⠁⠎⠎',\r
+               'inpos1': [0,0,2,3,4,5,6,7,7,8,9,10,11],\r
+               'comment': '規則変更→ 空白をはさまない1単語は外国語引用符ではなく外字符でもよい',\r
+               },\r
+       {\r
+               'text': '世界保健機関(World Health Organization)の活動',\r
+               'input': 'セカイ ホケン キカン(⠦World Health Organization⠴)ノ カツドー',\r
+               'output': '⠻⠡⠃ ⠮⠫⠴ ⠣⠡⠴⠶⠦⠠⠺⠕⠗⠇⠙ ⠠⠓⠑⠁⠇⠞⠓ ⠠⠕⠗⠛⠁⠝⠊⠵⠁⠞⠊⠕⠝⠴⠶⠎ ⠡⠝⠐⠞⠒',\r
+               },\r
+       {\r
+               'text': 'MY FAIR LADY, a Broadway play, is a musical.',\r
+               'input': '⠦MY FAIR LADY, a Broadway play, is a musical.⠴',\r
+               },\r
+       { 'note': '2.一続きに書き表すべき1語中の外国語引用符と仮名の間は、第1つなぎ符をはさんで続けて書き、仮名と外国語引用符の間は続けて書く。' },\r
+       { 'note': '規則変更→ 外国語引用符の後は必ずマスアケする' },\r
+       {\r
+               'text': 'Gift券',\r
+               'input': 'Giftケン',\r
+               'output': '⠰⠠⠛⠊⠋⠞⠤⠫⠴',\r
+               'inpos1': [0,0,0,1,2,3,3,4,5],\r
+               'comment': '規則変更→1単語なので外字符を使う。マスアケではなくつなぎ符を使う。'\r
+               },\r
+       {\r
+               'text': '赤wine',\r
+               'input': 'アカwine',\r
+               'output': '⠁⠡⠰⠺⠊⠝⠑',\r
+               'inpos1': [0,1,2,2,3,4,5],\r
+               },\r
+       {\r
+               'text': '名speech集',\r
+               'input': 'メイspeechシュー',\r
+               'output': '⠿⠃⠰⠎⠏⠑⠑⠉⠓⠤⠈⠹⠒',\r
+               'inpos1': [0,1,2,2,3,4,5,6,7,7,8,8,10],\r
+               },\r
+       { 'note': '【備考】外国語引用符の後ろに助詞・助動詞が続く場合は、間を区切って書く。' },\r
+       {\r
+               'text': 'I love you.に相当する日本語は何か',\r
+               'input': '⠦I love you.⠴ ニ ソートー スル ニホンゴワ ナニカ',\r
+               'output': '⠦⠠⠊ ⠇⠕⠧⠑ ⠽⠕⠥⠲⠴ ⠇ ⠺⠒⠞⠒ ⠹⠙ ⠇⠮⠴⠐⠪⠄ ⠅⠇⠡',\r
+               'inpos1': [0,1,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,27,28,29,30,31,32],\r
+               },\r
+       {\r
+               'text': 'tea roomらしい',\r
+               'input': '⠦tea room⠴ ラシイ',\r
+               'output': '⠦⠞⠑⠁ ⠗⠕⠕⠍⠴ ⠑⠳⠃',\r
+               'inpos1': [0,1,2,3,4,5,6,7,8,9,10,11,12,13],\r
+               },\r
+       {\r
+               'text': 'Windows Live メール',\r
+               'input': '⠦Windows Live⠴ メール',\r
+               },\r
+       { 'note': '3.一般書に挿入されているドイツ語やフランス語など' },\r
+\r
+       { 'note': '4.ローマ字で書かれた日本語' },\r
+\r
+       { 'note': '5.人名は、原文の書き方によって外国語引用符と外字符を使い分ける。なお、外国語引用符の中ではピリオドは省略することができない。' },\r
+\r
+       { 'note': '== 第3章 語の書き表し方 ==' },\r
+       { 'note': '=== その1 分かち書き ===' },\r
+       { 'note': '1.自立語は前を区切って書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 1',\r
+               'text': '美しい山桜',\r
+               'input': 'ウツクシイ ヤマザクラ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 1',\r
+               'text': '早くする',\r
+               'input': 'ハヤク スル',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 1',\r
+               'text': 'ゆっくり歩く',\r
+               'input': 'ユックリ アルク',\r
+               },\r
+       {\r
+               'text': '運動をした。',\r
+               'input': 'ウンドーヲ シタ。',\r
+               },\r
+       {\r
+               'text': 'マッサージをしている。',\r
+               'input': 'マッサージヲ シテ イル。',\r
+               },\r
+       {\r
+               'text': '取り止めにした。',\r
+               'input': 'トリヤメニ シタ。',\r
+               },\r
+       { 'note': '2.付属語(助詞・助動詞は)は、自立語または他の付属語に続けて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 2 No.14',\r
+               'text': '山ん中',\r
+               'input': 'ヤマン ナカ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 2 No.16',\r
+               'text': '好かんやつ',\r
+               'input': 'スカン ヤツ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 2 No.17',\r
+               'text': '嘘みたいな話',\r
+               'input': 'ウソミタイナ ハナシ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 2 No.18',\r
+               'text': 'どうなのですか',\r
+               'input': 'ドーナノデスカ',\r
+               },\r
+       { 'note': '【備考1】ア行・ラ行で始まる助詞・助動詞が数字の後ろに続く場合は、第1つなぎ符をはさんで続けて書く。' },\r
+       { 'note': '【備考2】助詞・助動詞がアルファベットや省略符としてのピリオド、および外国語引用符の後ろに続く場合は、前を区切って書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 2 No.31',\r
+               'text': 'CDを聞く',\r
+               'input': 'CD ヲ キク',\r
+               'output': '⠰⠠⠠⠉⠙ ⠔ ⠣⠩',\r
+               'inpos1': [0,0,0,0,1,2,3,4,5,6],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 2 No.32',\r
+               'text': 'SFみたいな話',\r
+               'input': 'SF ミタイナ ハナシ',\r
+               'output': '⠰⠠⠠⠎⠋ ⠷⠕⠃⠅ ⠥⠅⠳',\r
+               'inpos1': [0,0,0,0,1,2,3,4,5,6,7,8,9,10],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 2 No.33',\r
+               'text': 'cf.は参照を示す',\r
+               'input': 'cf. ワ サンショーヲ シメス',\r
+               'output': '⠰⠉⠋⠲ ⠄ ⠱⠴⠈⠺⠒⠔ ⠳⠿⠹',\r
+               'inpos1': [0,0,1,2,3,4,5,6,7,8,8,10,11,12,13,14,15],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 2 No.34',\r
+               'text': 'あなたのモットーはchallengeですね',\r
+               'input': 'アナタノ モットーワ challenge デスネ',\r
+               'output': '⠁⠅⠕⠎ ⠾⠂⠞⠒⠄ ⠰⠉⠓⠁⠇⠇⠑⠝⠛⠑ ⠐⠟⠹⠏',\r
+               'inpos1': [0,1,2,3,4,5,6,7,8,9,10,11,11,12,13,14,15,16,17,18,19,20,21,21,22,23],\r
+               'comment': '規則変更→1単語は外国語引用符を使わない'\r
+               },\r
+       { 'note': '<処理>アルファベットで書かれた外国語に「な」や「だ」などが続いて、形容動詞と考えられる場合でも、助詞・助動詞と同様に区切って書いてよい。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 2 No.35',\r
+               'text': 'Basicな装い',\r
+               'input': 'Basic ナ ヨソオイ',\r
+               'output': '⠰⠠⠃⠁⠎⠊⠉ ⠅ ⠜⠺⠊⠃',\r
+               'inpos1': [0,0,0,1,2,3,4,5,6,7,8,9,10,11],\r
+               },\r
+       { 'note': '3.実質的な意味が薄れた名詞(形容詞なども)、自立語であるから前を区切って書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.36', \r
+               'text': '東京辺り', \r
+               'input': 'トーキョー アタリ',   \r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.37', \r
+               'text': '力の限り', \r
+               'input': 'チカラノ カギリ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.38', \r
+               'text': '悲しみのあまり',\r
+               'input': 'カナシミノ アマリ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.39', \r
+               'text': '忘れずに読むこと',\r
+               'input': 'ワスレズニ ヨム コト',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.40', \r
+               'text': 'わたしの生まれた頃',\r
+               'input': 'ワタシノ ウマレタ コロ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.41', \r
+               'text': '遅れたため',\r
+               'input': 'オクレタ タメ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.42', \r
+               #'text': '1時間近く',\r
+               'input': '1ジカン チカク',\r
+               'output': '⠼⠁⠐⠳⠡⠴ ⠗⠡⠩',\r
+               'inpos1': [0,0,1,1,2,3,4,5,6,7],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.43', \r
+               'text': 'その点について',\r
+               'input': 'ソノ テンニ ツイテ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.51',\r
+               'text': 'そういうわけ',\r
+               'input': 'ソー イウ ワケ',\r
+               },\r
+\r
+       { 'note': '【備考1】次のような言葉は、接尾語や助詞なので前に続けて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.52',\r
+               'text': '一人当り10個ずつ',\r
+               'input': 'ヒトリアタリ 10コズツ',\r
+               'output': '⠧⠞⠓⠁⠕⠓ ⠼⠁⠚⠪⠐⠹⠝',\r
+               'inpos1': [0,1,2,3,4,5,6,7,7,8,9,10,10,11],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.54',\r
+               'text': 'いく度か',\r
+               'input': 'イクドカ', # 'イクタビカ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.55',\r
+               'text': 'まあ楽しみですこと',\r
+               'input': 'マア タノシミデスコト',\r
+               },\r
+       { 'note': '<処理>同じ漢字でも読み方の違いによって書き分ける。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.59',\r
+               'text': 'ここら辺り',\r
+               'input': 'ココラ アタリ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.63',\r
+               'text': 'その後',\r
+               'input': 'ソノゴ',# ソノ アト, ソノ ノチ, ソノ ウシロ\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 3 No.64',\r
+               'text': '今月末',\r
+               'input': 'コンゲツマツ', # コンゲツ スエ\r
+               },\r
+       { 'note': '【備考2】会話などで名詞の語形や音韻が変化した場合でも、前を区切って書いてよい。' },\r
+       { 'note': '4.本来の意味が薄れて付属語的に用いられている動詞(補助動詞など)も、自立語なので前を区切って書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.75',\r
+               'text': 'お読み頂く',\r
+               'input': 'オヨミ イタダク',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.76',\r
+               'text': '発車いたします',\r
+               'input': 'ハッシャ イタシマス',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.77',\r
+               'text': '行っていらっしゃい',\r
+               'input': 'イッテ イラッシャイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.78',\r
+               'text': '見ている',\r
+               'input': 'ミテ イル',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.79',\r
+               'text': '現代における',\r
+               'input': 'ゲンダイニ オケル',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.80',\r
+               'text': 'しまっておく',\r
+               'input': 'シマッテ オク',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.81',\r
+               'text': '日本に於て',\r
+               'input': 'ニッポンニ オイテ', # 'ニホンニ オイテ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.82',\r
+               'text': '出てきた',\r
+               'input': 'デテ キタ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.83',\r
+               'text': '行ってくる',\r
+               'input': 'イッテ クル',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.84',\r
+               'text': 'ごめんください',\r
+               'input': 'ゴメン クダサイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.85',\r
+               'text': 'お遊びください',\r
+               'input': 'オアソビ クダサイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.86',\r
+               'text': 'おはようございます',\r
+               'input': 'オハヨー ゴザイマス',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.87',\r
+               'text': '休館日につき',\r
+               'input': 'キューカンビニ ツキ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.88',\r
+               'text': 'これについて',\r
+               'input': 'コレニ ツイテ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.89',\r
+               'text': '彼にとって',\r
+               'input': 'カレニ トッテ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 4 No.96',\r
+               'text': '計画により',\r
+               'input': 'ケイカクニ ヨリ',\r
+               },\r
+       { 'note': '5.副詞「こう・そう・ああ・どう」、連体詞「この・その・あの・どの・ある・わが」なども自立語なので、いずれも後ろの自立語との間を区切って書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.2',\r
+               'text': 'そういう',\r
+               'input': 'ソー イウ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.5',\r
+               'text': 'どうして帰りましょう',\r
+               'input': 'ドー シテ カエリマショー',\r
+               },\r
+       { 'note': '【備考】後ろの語と結びついて1語になっている場合は続ける。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.20',\r
+               'text': 'この間',\r
+               'input': 'コノアイダ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.21',\r
+               'text': 'この期',\r
+               'input': 'コノゴ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.22',\r
+               'text': 'この程',\r
+               'input': 'コノホド',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.23',\r
+               'text': 'この度',\r
+               'input': 'コノタビ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.26',\r
+               'text': 'そのくせ',\r
+               'input': 'ソノクセ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.30',\r
+               'text': 'そのうちに',\r
+               'input': 'ソノウチニ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.31',\r
+               'text': 'そのまま',\r
+               'input': 'ソノママ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.32',\r
+               'text': 'その節',\r
+               'input': 'ソノセツ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.36',\r
+               'text': 'わがまま',\r
+               'input': 'ワガママ',\r
+               },\r
+       { 'note': '6.「にして」「をして」「ずして」などの、「して」が文語的表現の助詞である場合は前に続けて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.37',\r
+               'text': '不幸にして',\r
+               'input': 'フコーニシテ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.38',\r
+               'text': '今にして',\r
+               'input': 'イマニシテ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.39',\r
+               'text': '居ながらにして',\r
+               'input': 'イナガラニシテ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.40',\r
+               'text': '労せずして',\r
+               'input': 'ローセズシテ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.41',\r
+               'text': '私をして言わしむれば',\r
+               'input': 'ワタシヲシテ イワシムレバ', # 'ワタクシヲシテ イワシムレバ'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.42',\r
+               'text': '年わかくして',\r
+               'input': 'トシ ワカクシテ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.43',\r
+               'text': '水清くして',\r
+               'input': 'ミズ キヨクシテ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.45',\r
+               #'text': '二人して',\r
+               'input': 'フタリシテ', # 2ニンシテ\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.46',\r
+               'text': 'それだからして',\r
+               'input': 'ソレダカラシテ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.48',\r
+               'text': '見るべくして',\r
+               'input': 'ミルベクシテ',\r
+               },\r
+       { 'note': '【備考1】' },\r
+       { 'note': '【備考2】' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.50',\r
+               'text': '人として',\r
+               'input': 'ヒトト シテ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.51',\r
+               'text': '私としては',\r
+               'input': 'ワタシト シテワ', # 'ワタクシト シテワ',\r
+               },\r
+       { 'note': '7.「なさい・なさる」などが、独立の動詞であれば前を区切って書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.65',\r
+               'text': '立ってなさい',\r
+               'input': 'タッテ ナサイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.66',\r
+               'text': '見てなさい',\r
+               'input': 'ミテ ナサイ',\r
+               },\r
+       { 'note': '【備考】動詞の連用形に続く場合は続けて書く。「い」が省略されているときは続けて書く。「お」がついて名詞化した語に「なさい・なさる」が続く場合は区切って書いてよい。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.67',\r
+               'text': 'お黙りなさい',\r
+               'input': 'オダマリ ナサイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.70',\r
+               'text': 'お休みなされる',\r
+               'input': 'オヤスミ ナサレル',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.71',\r
+               'text': 'お読みなされ',\r
+               'input': 'オヨミ ナサレ',\r
+               },\r
+       { 'note': '8.形容詞の「ない」は前を区切って書き、助動詞の「ない」は前に続けて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8',\r
+               'text': '関係ない',\r
+               'input': 'カンケイ ナイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8',\r
+               'text': '異存なければ',\r
+               'input': 'イゾン ナケレバ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.74',\r
+               'text': '問題なかった',\r
+               'input': 'モンダイ ナカッタ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.75',\r
+               'text': 'わかりっこない',\r
+               'input': 'ワカリッコ ナイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.76',\r
+               'text': '間違いなし',\r
+               'input': 'マチガイ ナシ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8',\r
+               'text': '声なき声',\r
+               'input': 'コエ ナキ コエ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8',\r
+               'text': 'こだわりなく',\r
+               'input': 'コダワリ ナク',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.79',\r
+               'text': 'そうじゃない',\r
+               'input': 'ソージャ ナイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.80',\r
+               'text': '目じゃない',\r
+               'input': 'メジャ ナイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8',\r
+               'text': '意気地ない',\r
+               'input': 'イクジ ナイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8',\r
+               'text': '自信なげ',\r
+               'input': 'ジシン ナゲ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8',\r
+               'text': '起きない',\r
+               'input': 'オキナイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8',\r
+               'text': '歩かない',\r
+               'input': 'アルカナイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8',\r
+               'text': '捨てない',\r
+               'input': 'ステナイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8',\r
+               'text': '間違えない',\r
+               'input': 'マチガエナイ',\r
+               },\r
+       { 'note': '【備考】「ない」などが前の語と複合して、1語になっている場合は続けて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.87',\r
+               'text': '味気ない',\r
+               'input': 'アジケナイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8 備考',\r
+               'text': '呆気ない',\r
+               'input': 'アッケナイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.95',\r
+               'text': '隈なく',\r
+               'input': 'クマナク',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8 備考',\r
+               'text': '難なく',\r
+               'input': 'ナンナク',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8 備考',\r
+               'text': '何となく',\r
+               'input': 'ナントナク',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.98',\r
+               'text': '心置きなく',\r
+               'input': 'ココロオキナク',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.99',\r
+               'text': '満遍無く',\r
+               'input': 'マンベンナク',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8 備考',\r
+               'text': '程なく',\r
+               'input': 'ホドナク',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8 備考',\r
+               'text': '形なし',\r
+               'input': 'カタナシ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8 備考',\r
+               'text': '底無し',\r
+               'input': 'ソコナシ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8 備考',\r
+               'text': '意気地無し',\r
+               'input': 'イクジナシ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8 備考',\r
+               'text': 'ろくでなし',\r
+               'input': 'ロクデナシ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 8 備考',\r
+               'text': '事も無げ',\r
+               'input': 'コトモナゲ',\r
+               },\r
+       { 'note': '<処理>「て」「で」に続く「ない」は、「ない」の前を区切って書いてよい。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.106',\r
+               'text': '彼にはまだ話してない',\r
+               'input': 'カレニワ マダ ハナシテ ナイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.107',\r
+               'text': 'しばらく休んでない',\r
+               'input': 'シバラク ヤスンデ ナイ',\r
+               },\r
+       { 'note': '9.形容詞などの「~く」の後ろは区切って書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.110',\r
+               'text': '良くない',\r
+               'input': 'ヨク ナイ',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.112',\r
+               'text': '食べたくなくなる',\r
+               'input': 'タベタク ナク ナル',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その1 5 No.114',\r
+               'text': 'それどころではなくなる',\r
+               'input': 'ソレドコロデワ ナク ナル',\r
+               },\r
+\r
+       { 'note': '=== その2 複合語 ===' },\r
+       { 'note': '1.区切ると意味の理解を損なう短い複合語や短い略語は、一続きに書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 1',\r
+               'text': '朝夕', \r
+               'input': 'アサユー'\r
+               },\r
+       { 'note': '【備考】内部に助詞などを含んでいても、1語として熟している短い複合語は一続きに書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 1 備考',\r
+               'text': '息の根', \r
+               'input': 'イキノネ'\r
+               },\r
+       { 'note': '2.接頭語・接尾語・造語要素と自立語の間は続けて書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 2',\r
+               'text': '相たずさえる', \r
+               'input': 'アイタズサエル'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 2',\r
+               'text': '各種', \r
+               'input': 'カクシュ'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 2',\r
+               'text': '各国', \r
+               'input': 'カッコク'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 2',\r
+               'text': '旧街道', \r
+               'input': 'キューカイドー'\r
+               },\r
+       { 'note': '【備考1】接頭語・接尾語・造語要素であっても、意味の理解を助ける場合には、発音上の切れ目を考慮して区切って書いてよい。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 2 備考1',\r
+               'text': '各党', \r
+               'input': 'カク トー'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 2 備考1',\r
+               'text': '各方面', \r
+               'input': 'カク ホーメン'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 2 備考1',\r
+               'text': '旧陸軍', \r
+               'input': 'キュー リクグン'\r
+               },\r
+       { 'note': '【備考2】語頭にある接頭語や造語要素が、マスあけを含む複合語全体にかかる場合には、その後ろを区切って書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 2 備考2',\r
+               'text': '新東京名所', \r
+               'input': 'シン トーキョー メイショ'\r
+               },\r
+       { 'note': '【備考3】外来語の接辞も続けて書くが、意味の理解を助ける場合には、区切って書いてよい。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 2 備考3',\r
+               'text': 'フレンドシップ', \r
+               'input': 'フレンドシップ'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 2 備考3',\r
+               'text': 'インターネット', \r
+               'input': 'インター ネット'\r
+               },\r
+       { 'note': '<処理>「等」は「など」「ら」と読む場合には前に続けて書くが、「とう」と読む場合は前を区切って書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 2 処理',\r
+               'text': '山や川等', \r
+               'input': 'ヤマヤ カワナド'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 2 処理',\r
+               'text': '我等は', \r
+               'input': 'ワレラワ'\r
+               },\r
+       { 'note': '3.複合名詞の内部に、3拍以上の意味のまとまりが二つ以上あれば、その境目で区切って書くことを原則とする。' },\r
+       {   'comment': '点訳のてびき第3版 第3章 その2 3.',\r
+               'text': '桜並木', 'input': 'サクラ ナミキ' },\r
+       {   'comment': '点訳のてびき第3版 第3章 その2 3.',\r
+               'text': '花嫁姿', 'input': 'ハナヨメ スガタ' },\r
+       #{   'comment': '点訳のてびき第3版 第3章 その2 3.',\r
+       #       'text': '一人娘', 'input': 'ヒトリ ムスメ' },\r
+       {   'comment': '点訳のてびき第3版 第3章 その2 3.',\r
+               'text': '左半身', 'input': 'ヒダリ ハンシン' },\r
+\r
+       { 'note': '【備考1】接尾語的に用いられている語であっても、3拍以上の漢語は区切って書いてよい。' },\r
+       #{  'comment': '点訳のてびき第3版 第3章 その2 3. 備考1',\r
+       #   'text': '手当たり次第', 'input': 'テアタリ シダイ' },\r
+       {   'comment': '点訳のてびき第3版 第3章 その2 3. 備考1',\r
+               'text': '若者同士', 'input': 'ワカモノ ドーシ' },\r
+\r
+       { 'note': '【備考2】複合動詞や複合形容詞から転成したものや、形容詞の語幹を含んでいる場合など、区切ると意味の理解を損なうおそれのある語は続けて書く。' },\r
+       #{   'comment': '点訳のてびき第3版 第3章 その2 3. 備考2',\r
+       #       'text': '扱い始め', 'input': 'アツカイハジメ' },\r
+\r
+       { 'note': '【備考3】動詞から転成した3拍以上の語も区切って書くが、自立性が弱いと思われるものは続けて書いてよい。' },\r
+       { 'note': '【備考4】外来語の複合名詞で、区切ると意味の理解を損なうおそれのある語は続けて書く。' },\r
+       {   'comment': '点訳のてびき第3版 第3章 その2 3. 備考4', 'text': 'プラットホーム', 'input': 'プラットホーム' },\r
+\r
+       { 'note': '4.複合名詞内部の2拍以下の意味のまとまりは、続けて書くことを原則とする。' },\r
+       #{   'comment': '点訳のてびき第3版 第3章 その2 4.',\r
+       #       'text': '松並木', 'input': 'マツナミキ' },\r
+       {   'comment': '点訳のてびき第3版 第3章 その2 4.',\r
+               'text': '蝉時雨', 'input': 'セミシグレ' },\r
+       {   'comment': '点訳のてびき第3版 第3章 その2 4.',\r
+               'text': '右半身', 'input': 'ミギハンシン' },\r
+       {   'comment': '点訳のてびき第3版 第3章 その2 4.',\r
+               'text': '腕次第', 'input': 'ウデシダイ' },\r
+\r
+       { 'note': '【備考1】2字漢語は、2拍であっても3拍以上の意味のまとまりと同様に扱う。' },\r
+       #{   'comment': '点訳のてびき第3版 第3章 その2 4. 備考1',\r
+       #       'text': '母子年金', 'input': 'ボシ ネンキン' },\r
+\r
+       { 'note': '【備考2】複合名詞などの意味のまとまりが2拍以下であっても、自立性が強く、意味の理解を助ける場合には、区切って書いてよい。' },\r
+       #{   'comment': '点訳のてびき第3版 第3章 その2 4. 備考2',\r
+       #       'text': '要問い合わせ', 'input': 'ヨー トイアワセ' },\r
+\r
+       { 'note': '<処理>2拍の外来語を含む混種語は、意味の理解を助ける場合には区切って書いてよい。' },\r
+       #{   'comment': '点訳のてびき第3版 第3章 その2 4. 備考2',\r
+       #       'text': 'バス停留所', 'input': 'バス テイリュージョ' },\r
+\r
+       { 'note': '5.内部に二つ以上の意味のまとまりがない場合や、区切ると意味の理解を損なうおそれのある複合名詞は続けて書く。' },\r
+       {   'comment': '点訳のてびき第3版 第3章 その2 5.',\r
+               'text': '小中学校', 'input': 'ショーチューガッコー' },\r
+\r
+       { 'note': '6.アルファベットを含む複合名詞は、語句のまとまりを考慮して続けて書くか、適宜区切って書く。' },\r
+       { 'note': '7.漢字1字ずつが対等な関係で並んでいる複合名詞などは、意味の理解を容易にするために、語句のまとまりや発音などを考慮して適宜区切るか、すべてを続けて書く。' },\r
+       { 'note': '8.複合名詞は続けて書くことを原則とする。' },\r
+       {   'comment': '点訳のてびき第3版 第3章 その2 8.',\r
+               'text': '飛び込む', 'input': 'トビコム' },\r
+\r
+       { 'note': '【備考】内部に助詞「て」を含む場合は「て」の後ろで区切って書いてよい。' },\r
+       {   'comment': '点訳のてびき第3版 第3章 その2 8. 備考',\r
+               'text': 'やってくる', 'input': 'ヤッテ クル' },\r
+\r
+       { 'note': '9.名詞や副詞に動詞の「する」が続く場合は、「する」の前を区切って書くことを原則とする。' },\r
+       { 'note': '【備考1】1字漢語などに「する」が続いて音韻が変化したり、連濁する語は続けて書く。' },\r
+       { 'note': '【備考2】1字漢語に「する」が続く場合は一続きに書くが、「する」の前に助詞「を」をはさむことができる場合は区切って書いてよい。' },\r
+       { 'note': '【備考3】和語に「する」が続く語は、区切って書くが、和語の自立性が弱いと思われる場合は続けて書いてよい。' },\r
+       { 'note': '10.複合形容詞は続けて書く。' },\r
+       #{   'comment': '点訳のてびき第3版 第3章 その2 10.',\r
+       #       'text': '面白おかしい', 'input': 'オモシロオカシイ' },\r
+\r
+       { 'note': '11.接続詞句や副詞句は、意味の理解を容易にするために、発音上の切れ目などを考慮して適宜区切って書く。' },\r
+       { 'note': '12.連濁を生じた複合語は続けて書く。' },\r
+       {   'comment': '点訳のてびき第3版 第3章 その2 12.',\r
+               'text': '柱時計', 'input': 'ハシラドケイ' },\r
+\r
+       { 'note': '13.短い語からなる慣用句などは、すべて続けて書くか、意味のまとまりを目安に適宜区切って書く。' },\r
+       { 'note': '14.年月日や名数などは、その段階ごとに区切って書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 14',\r
+               'text': '4月15日', \r
+               'input': '4ガツ 15ニチ'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その2 14',\r
+               'text': '04月', \r
+               'input': '04ガツ'\r
+               },\r
+       { 'note': '【備考】年月日や名数などの後ろに続く2拍以下の語は、意味の理解を助ける場合には発音上の切れ目を考慮して区切って書いてよい。' },\r
+       { 'note': '15.二つ以上の意味のまとまりからなる繰り返し言葉は、区切って書くことを原則とする。' },\r
+       { 'note': '【備考1】連濁する語は続けて書く。' },\r
+       { 'note': '【備考2】区切ると意味の理解を損なう場合は続けて書く。' },\r
+       { 'note': '【備考3】擬声語・擬態語は、3拍以上の繰り返しは区切って書き、2拍以下の繰り返しは続けて書く。' },\r
+       { 'note': '16.動植物名や理化学用語なども、複合動詞の切れ続きに準じて書くことを原則とする。' },\r
+       { 'note': '【備考】区切ると意味の理解を損なうと思われる場合は、第1つなぎ符をはさんで続けて書くか、一続きに書くことができる。' },\r
+       { 'note': '17.医学用語などは、発音や意味のまとまりに留意して、複合動詞の切れ続きに準じて書く。' },\r
+\r
+       { 'note': '=== その3 固有名詞 ===' },\r
+       { 'note': '1.人名の名字と名前の間は、区切って書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 1.',\r
+               'text': '湯川秀樹', \r
+               'input': 'ユカワ ヒデキ'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 1.',\r
+               'text': '石川倉次', \r
+               'input': 'イシカワ クラジ'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 1.',\r
+               'text': '武者小路実篤', \r
+               'input': 'ムシャノコージ サネアツ'\r
+               },\r
+       { 'note': '3.人名に続く「さん」「様」「君」「殿」「氏(し)」「氏(うじ)」は、区切って書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 3.',\r
+               'text': '鈴木さん', 'input': 'スズキ サン'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 3.',\r
+               'text': '鈴木様', 'input': 'スズキ サマ'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 3.',\r
+               'text': '鈴木さま', 'input': 'スズキ サマ'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 3.',\r
+               'text': '鈴木君', 'input': 'スズキ クン'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 3.',\r
+               'text': '鈴木くん', 'input': 'スズキ クン'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 3.',\r
+               'text': '鈴木殿', 'input': 'スズキ ドノ'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 3.',\r
+               'text': '鈴木氏', 'input': 'スズキ シ'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 3.',\r
+               'text': '一郎君', 'input': 'イチロー クン'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 3.',\r
+               'text': '一郎くん', 'input': 'イチロー クン'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 3. 備考1',\r
+               'text': '魚屋さん', 'input': 'サカナヤサン'\r
+               },\r
+\r
+       { 'note': '4.地名(国名を含む)および地名と接尾語や造語要素または普通名詞などとの複合語は、段階(都道府県・市区町村)ごとに区切って書く。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 4.',\r
+               'text': '東京都千代田区永田町1の7',\r
+               'input': 'トーキョート チヨダク ナガタチョー 1ノ 7'\r
+               },\r
+       {\r
+               'text': '東京都千代田区永田町1-7',\r
+               'input': 'トーキョート チヨダク ナガタチョー 1-7'\r
+               },\r
+       {\r
+               'text': '東京都千代田区永田町一の七',\r
+               'input': 'トーキョート チヨダク ナガタチョー 1ノ 7'\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第3章 その3 4.',\r
+               'text': '福島県伊達市月舘町月舘',\r
+               'input': 'フクシマケン ダテシ ツキダテマチ ツキダテ'\r
+               },\r
+       {'text':'綾部市保健福祉センター', 'input':'アヤベシ ホケン フクシ センター'},\r
+       {'text':'東京都交通局', 'input':'トーキョート コーツーキョク'},\r
+       {'text':'府中町役場', 'input':'フチューマチ ヤクバ'},\r
+       {'text':'町役場', 'input':'マチヤクバ'},\r
+\r
+       { 'note': '=== その4 方言・古文など ===' },\r
+\r
+       { 'note': '== 第4章 記号類の使い方 ==' },\r
+       { 'note': '=== その1 句読符 ===' },\r
+       { 'note': '==== 1.句点 ====' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その1 1.',\r
+               'text': '雨が降っていた。けれどぼくは出かけた。',\r
+               'input': 'アメガ フッテ イタ。ケレド ボクワ デカケタ。',\r
+               'output': '⠁⠿⠐⠡ ⠭⠂⠟ ⠃⠕⠲  ⠫⠛⠐⠞ ⠐⠮⠩⠄ ⠐⠟⠡⠫⠕⠲',\r
+               'inpos1': [0,1,2,2,3,4,5,6,7,8,9,10,10,10,11,12,13,13,14,15,15,16,17,18,19,19,20,21,22,23],\r
+               },\r
+       { 'note': '==== 2.疑問符、感嘆符 ====' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その1 2.',\r
+               'text': 'お元気? 久しぶりですね。',\r
+               'input': 'オゲンキ? ヒサシブリデスネ。',\r
+               'output': '⠊⠐⠫⠴⠣⠢  ⠧⠱⠳⠐⠭⠓⠐⠟⠹⠏⠲',\r
+               'inpos1': [0,1,1,2,3,4,4,5,6,7,8,9,9,10,11,11,12,13,14],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その1 2.',\r
+               'text': 'えっ! 彼が哲学者!?',\r
+               'input': 'エッ! カレガ テツガクシャ!?',\r
+               #'output': '⠋⠂⠖  ⠡⠛⠐⠡ ⠟⠝⠐⠡⠩⠈⠱⠖⠢',\r
+               },\r
+       { 'note': '==== 3.読点 ====' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その1 3.',\r
+               'text': '森には、いろいろな動物が住んでいる。',\r
+               'input': 'モリニワ、イロイロナ ドーブツガ スンデ イル。',\r
+               'output': '⠾⠓⠇⠄⠰ ⠃⠚⠃⠚⠅ ⠐⠞⠒⠐⠭⠝⠐⠡ ⠹⠴⠐⠟ ⠃⠙⠲',\r
+               'inpos1': [0,1,2,3,4,4,5,6,7,8,9,10,11,11,12,13,13,14,15,15,16,17,18,19,19,20,21,22,23],\r
+               },\r
+       { 'note': '==== 4.中点 ====' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その1 4.',\r
+               'text': '松・杉・檜は、針葉樹です。',\r
+               'input': 'マツ・スギ・ヒノキワ、シンヨージュデス。',\r
+               'output': '⠵⠝⠐ ⠹⠐⠣⠐ ⠧⠎⠣⠄⠰ ⠳⠴⠜⠒⠘⠹⠐⠟⠹⠲',\r
+               'inpos1': [0,1,2,2,3,4,4,5,5,6,7,8,9,10,10,11,12,13,14,15,15,17,17,18,19],\r
+               },\r
+       { 'note': '=== その2 囲みの記号 ===' },\r
+       { 'note': '==== 1.カギ類 ====' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その2 1.',\r
+               'text': '「住所」「氏名」「電話番号」を書いてください。',\r
+               'input': '「ジューショ」 「シメイ」 「デンワ バンゴー」ヲ カイテ クダサイ。',\r
+               #'output': '⠤⠘⠹⠒⠈⠺⠤ ⠤⠳⠿⠃⠤ ⠤⠐⠟⠴⠄ ⠐⠥⠴⠐⠪⠒⠤⠔ ⠡⠃⠟ ⠩⠐⠕⠱⠃⠲',\r
+               },\r
+       { 'note': '==== 2.カッコ類 ====' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その2 2.',\r
+               'text': 'Au(金)の比重',\r
+               'input': 'Au(キン)ノ ヒジュー',\r
+               'output': '⠰⠠⠁⠥⠶⠣⠴⠶⠎ ⠧⠘⠹⠒',\r
+               'inpos1': [0,0,0,1,2,3,4,5,6,7,8,9,9,11],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その2 2.',\r
+               'text': 'すぐ(に)(副詞)陽が暮れる。', # 日が暮れる→読み付与誤り回避の変更\r
+               'input': 'スグ(ニ) (フクシ) ヒガ クレル。',\r
+               'output': '⠹⠐⠩⠶⠇⠶ ⠶⠭⠩⠳⠶ ⠧⠐⠡ ⠩⠛⠙⠲',\r
+               'inpos1': [0,1,1,2,3,4,5,6,7,8,9,10,11,12,13,13,14,15,16,17,18],\r
+               },\r
+       { 'note': '==== 3.指示符類 ====' },\r
+       { 'note': '==== 4.外国語引用符 ====' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その2 4.',\r
+               #'text': '“MODERN TIMES”',\r
+               'input': '⠦MODERN TIMES⠴',\r
+               'output': '⠦⠠⠠⠍⠕⠙⠑⠗⠝ ⠠⠠⠞⠊⠍⠑⠎⠴',\r
+               'inpos1': [0,1,1,1,2,3,4,5,6,7,8,8,8,9,10,11,12,13],\r
+               },\r
+       { 'note': '==== 5.発音記号符 ====' },\r
+       { 'note': '==== 6.点訳者挿入符 ====' },\r
+       { 'note': '==== 7.段落挿入符類 ====' },\r
+\r
+       { 'note': '=== その3 線類 ===' },\r
+       { 'note': '==== 1.棒線・点線 ====' },\r
+       { 'note': '==== 2.矢印類 ====' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その3 2.',\r
+               'text': '札幌→東京',\r
+               'input': 'サッポロ→トーキョー',\r
+               'output': '⠱⠂⠠⠮⠚ ⠒⠒⠕ ⠞⠒⠈⠪⠒',\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その3 2.',\r
+               'text': '札幌←東京',\r
+               'input': 'サッポロ←トーキョー',\r
+               'output': '⠱⠂⠠⠮⠚ ⠪⠒⠒ ⠞⠒⠈⠪⠒',\r
+               },\r
+       { 'note': '==== 3.波線 ====' },\r
+\r
+       { 'note': '=== その4 その他の記号類 ===' },\r
+       { 'note': '==== 1.つなぎ符類 ====' },\r
+       { 'note': '【備考1】数字に続く「ワ」の後ろにア行・ラ行のカナが3つ続くときは、位取り点と誤読されるので、その場合に限り第1つなぎ符を用いる。' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その4 1. 備考1',\r
+               'text': '4割入り',\r
+               'input': '4ワリイリ',\r
+               'output': '⠼⠙⠤⠄⠓⠃⠓',\r
+               'inpos1': [0,0,0,1,2,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その4 1. 備考1に該当しない場合',\r
+               'text': '4割抜き',\r
+               'input': '4ワリ ヌキ',\r
+               'output': '⠼⠙⠄⠓ ⠍⠣',\r
+               'inpos1': [0,0,1,2,3,4,5],\r
+               },\r
+       { 'note': '==== 2.小見出し符類 ====' },\r
+       { 'note': '==== 3.文中注記符 ====' },\r
+       { 'note': '==== 4.星印類 ====' },\r
+       {\r
+               'comment': '白星印を 56-2346-2 と定義',\r
+               'text': '☆',\r
+               'input': '☆',\r
+               'output': '⠰⠮⠂',\r
+               },\r
+       {\r
+               'comment': '黒星印を 56-2346-23 と定義',\r
+               'text': '★',\r
+               'input': '★',\r
+               'output': '⠰⠮⠆',\r
+               },\r
+       {\r
+               'comment': '第1星印 35-35 (後ろを1マスあける)',\r
+               'text': '※あ',\r
+               'input': '※ア',\r
+               'output': '⠔⠔ ⠁',\r
+               },\r
+       { 'note': '==== 5.詩行符類 ====' },\r
+       { 'note': '==== 6.空欄符号 ====' },\r
+       { 'note': '==== 7.伏せ字 ====' },\r
+       {\r
+               'comment': '白丸を 6-1356-2 と定義',\r
+               'text': '○',\r
+               'input': '○',\r
+               'output': '⠠⠵⠂',\r
+               },\r
+       {\r
+               'comment': '黒丸を 6-1356-23 と定義',\r
+               'text': '●',\r
+               'input': '●',\r
+               'output': '⠠⠵⠆',\r
+               },\r
+       {\r
+               'comment': '二重丸を 6-1356-256 と定義',\r
+               'text': '◎',\r
+               'input': '◎',\r
+               'output': '⠠⠵⠲',\r
+               },\r
+       {\r
+               'comment': '白四角を 6-1256-2 と定義',\r
+               'text': '□',\r
+               'input': '□',\r
+               'output': '⠠⠳⠂',\r
+               },\r
+       {\r
+               'comment': '黒四角を 6-1256-23 と定義',\r
+               'text': '■', \r
+               'input': '■',\r
+               'output': '⠠⠳⠆',\r
+               },\r
+       {\r
+               'comment': '白上向き三角を 6-156-2 と定義', \r
+               'text': '△', \r
+               'input': '△',\r
+               'output': '⠠⠱⠂',\r
+               },\r
+       {\r
+               'comment': '黒上向き三角を 6-156-23 と定義', \r
+               'text': '▲', \r
+               'input': '▲',\r
+               'output': '⠠⠱⠆',\r
+               },\r
+       {\r
+               'comment': '白下向き三角を 56-156-2 と定義', \r
+               'text': '▽', \r
+               'input': '▽',\r
+               'output': '⠰⠱⠂',\r
+               },\r
+       {\r
+               'comment': '黒下向き三角を 56-156-23 と定義', \r
+               'text': '▼', \r
+               'input': '▼',\r
+               'output': '⠰⠱⠆',\r
+               },\r
+       {\r
+               'comment': '白菱形を 46-1236-2 と定義(1236=ひ)',\r
+               'text': '◇',\r
+               'input': '◇',\r
+               'output': '⠨⠧⠂',\r
+               },\r
+       {\r
+               'comment': '黒菱形を 46-1256-23 と定義(1236=ひ)',\r
+               'text': '◆', \r
+               'input': '◆',\r
+               'output': '⠨⠧⠆',\r
+               },\r
+       {\r
+               'comment': 'バツ印を 56-16-2 と定義', \r
+               'text': '×', \r
+               'input': '×',\r
+               'output': '⠰⠡⠂',\r
+               },\r
+       { 'note': '==== 8.パーセント ====' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その4 8.',\r
+               'text': '100%',\r
+               'input': '100%',\r
+               'output': '⠼⠁⠚⠚⠰⠏',\r
+               'inpos2': [0,1,2,3],\r
+               'inpos1': [0,0,1,2,3,3],\r
+               'inpos':  [0,0,1,2,3,3],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その4 8.',\r
+               'text': '数%',\r
+               'input': 'スー%',\r
+               'output': '⠹⠒⠰⠏',\r
+               'inpos1': [0,1,2,2],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その4 8.',\r
+               'text': 'A%',\r
+               'input': 'A%',\r
+               'output': '⠰⠠⠁⠰⠏',\r
+               'inpos2': [0,1],\r
+               'inpos1': [0,0,0,1,1],\r
+               'inpos':  [0,0,0,1,1],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その4 8.',\r
+               'text': '25%引き',\r
+               'input': '25%ビキ',\r
+               'output': '⠼⠃⠑⠰⠏⠐⠧⠣',\r
+               'inpos2': [0,1,2,3,4],\r
+               'inpos1': [0,0,1,2,2,3,3,4],\r
+               'inpos':  [0,0,1,2,2,3,3,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その4 8.',\r
+               'text': '××%',\r
+               'input': '××%',\r
+               #'output': '⠐⠿⠐⠿⠤⠰⠏',\r
+               'inpos2': [0,1,2],\r
+               },\r
+       { 'note': '==== 9.アンドマーク ====' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その4 9.',\r
+               'text': 'Q&A',\r
+               'input': 'Q & A',\r
+               'output': '⠰⠠⠟ ⠰⠯ ⠰⠠⠁',\r
+               'inpos1': [0,0,0,1,2,2,3,4,4,4],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その4 9.',\r
+               'text': 'シャープス&フラッツ',\r
+               'input': 'シャープス & フラッツ',\r
+               'output': '⠈⠱⠒⠠⠭⠹ ⠰⠯ ⠭⠑⠂⠝',\r
+               'inpos1': [0,0,2,3,3,4,5,6,6,7,8,9,10,11],\r
+               },\r
+       { 'note': '==== 10.ナンバーマーク ====' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その4 10.',\r
+               'text': '4#で応答メッセージが録音できます。',\r
+               'input': '4# デ オートー メッセージガ ロクオン デキマス。',\r
+               'output': '⠼⠙⠰⠩ ⠐⠟ ⠊⠒⠞⠒ ⠿⠂⠻⠒⠐⠳⠐⠡ ⠚⠩⠊⠴ ⠐⠟⠣⠵⠹⠲',\r
+               'inpos1': [0,0,1,1,2,3,3,4,5,6,7,8,9,10,11,12,13,14,14,15,15,16,17,18,19,20,21,22,22,23,24,25,26],\r
+               },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その4 10.',\r
+               'text': '#50のミシン糸',\r
+               'input': '#50ノ ミシンイト',\r
+               'output': '⠰⠩⠼⠑⠚⠎ ⠷⠳⠴⠃⠞',\r
+               'inpos1': [0,0,1,1,2,3,4,5,6,7,8,9],\r
+               },\r
+       { 'note': '==== 11.アステリスク ====' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その4 11.',\r
+               'text': '*または#を押すたびに',\r
+               'input': '* マタワ # ヲ オス タビニ',\r
+               'output': '⠰⠡ ⠵⠕⠄ ⠰⠩ ⠔ ⠊⠹ ⠕⠐⠧⠇',\r
+               'inpos1': [0,0,1,2,3,4,5,6,6,7,8,9,10,11,12,13,14,14,15],\r
+               },\r
+       { 'note': '==== 12.小文字符 ====' },\r
+       {\r
+               'comment': '点訳のてびき第3版 第4章 その4 12.',\r
+               #'text': '「ァ」は、',\r
+               'input': '「ァ」ワ、',\r
+               #'output': '⠤⠘⠁⠤⠄⠰',\r
+               },\r
+       { 'note': '+ ポジションマッピング +' },\r
+       {\r
+               'text': '12345 ',\r
+               'input': '12345 ',\r
+               'output': '⠼⠁⠃⠉⠙⠑ ',\r
+               'inpos2': [0,1,2,3,4,5],\r
+               'inpos1': [0,0,1,2,3,4,5],\r
+               'inpos':  [0,0,1,2,3,4,5],\r
+               'comment': '行末の空白を保存する',\r
+               },\r
+       {\r
+               'text': 'やっぱり ',\r
+               'input': 'ヤッパリ ',\r
+               'output': '⠌⠂⠠⠥⠓ ',\r
+               'inpos2': [0,1,2,3,4],\r
+               'inpos1': [0,1,2,2,3,4],\r
+               'inpos':  [0,1,2,2,3,4],\r
+               },\r
+       {\r
+               'text': '機能 ',\r
+               'input': 'キノー ',\r
+               'output': '⠣⠎⠒ ',\r
+               'inpos2': [0,0,1,2],\r
+               'inpos1': [0,1,2,3],\r
+               'inpos':  [0,0,1,2],\r
+               },\r
+       {\r
+               'text': '実技 ',\r
+               'input': 'ジツギ ',\r
+               'output': '⠐⠳⠝⠐⠣ ',\r
+               'inpos2': [0,0,1,2],\r
+               'inpos1': [0,0,1,2,2,3],\r
+               'inpos':  [0,0,0,1,1,2],\r
+               },\r
+\r
+       { 'note': '+ 点字表記辞典 +' },\r
+       {       'text': '相対する', 'input': 'アイタイスル'},\r
+       {       'text': '相たずさえて', 'input': 'アイタズサエテ'},\r
+       {       'text': '相整う', 'input': 'アイトトノウ'},\r
+       {       'text': '相憐れむ', 'input': 'アイアワレム'},\r
+       {       'text': '木立の間', 'input': 'コダチノ アイダ'},\r
+       {       'text': '開いた口', 'input': 'アイタ クチ'},\r
+       {       'text': '相無く', 'input': 'アイナク'},\r
+       {       'text': 'お生憎様', 'input': 'オアイニクサマ'},\r
+       {       'text': '開かずの間', 'input': 'アカズノ マ'},\r
+       {       'text': '不開の間', 'input': 'アカズノ マ'},\r
+       {       'text': '山田県主', 'input': 'ヤマダノ アガタヌシ'},\r
+       {       'text': '暁闇', 'input': 'アカツキヤミ'},\r
+       {       'text': '上がり降り', 'input': 'アガリオリ'},\r
+       {       'text': '四条上ル', 'input': '4ジョー アガル'},\r
+       {       'text': '秋津国', 'input': 'アキツクニ'},\r
+       {       'text': '現つ神', 'input': 'アキツカミ'},\r
+       {       'text': '阿Q正伝', 'input': 'アQ セイデン'},\r
+       {       'text': '悪源太', 'input': 'アクゲンタ'},\r
+       {       'text': '明くる朝', 'input': 'アクル アサ'},\r
+       {       'text': '明くる年', 'input': 'アクル トシ'},\r
+       {       'text': '明の星', 'input': 'アケノ ホシ'},\r
+       {       'text': '麻布十番', 'input': 'アザブ ジューバン'},\r
+       {       'text': '男漁り', 'input': 'オトコ アサリ'},\r
+       {       'text': '古本漁り', 'input': 'フルホン アサリ'},\r
+       {       'text': '足の甲', 'input': 'アシノ コー'},\r
+       {       'text': '日の足', 'input': 'ヒノアシ'},\r
+       {       'text': '醤油味', 'input': 'ショーユ アジ'},\r
+       {       'text': '源朝臣頼政', 'input': 'ミナモトノ アソン ヨリマサ'},\r
+       {       'text': '兄貴風を吹かす', 'input': 'アニキカゼヲ フカス'},\r
+       {       'text': '東漢直駒', 'input': 'ヤマトノ アヤノ アタイノ コマ'},\r
+       {   'text': '天照大神', 'input': 'アマテラス オオミカミ'},\r
+       {   'text': '天の岩戸', 'input': 'アマノ イワト'},\r
+       {   'text': '天香具山', 'input': 'アマノ カグヤマ'},\r
+       {   'text': '天の羽衣', 'input': 'アマノ ハゴロモ'},\r
+       {   'text': '天の原', 'input': 'アマノハラ'},\r
+       {   'text': '天鈿女命', 'input': 'アメノ ウズメノ ミコト'},\r
+       {   'text': '水争', 'input': 'ミズアラソイ'},\r
+       #{   'text': 'あらぬ方を向く', 'input': 'アラヌ カタヲ ムク'},\r
+       {   'text': '蟻の塔草', 'input': 'アリノトーグサ'},\r
+       {   'text': '有りの儘に打ち明ける', 'input': 'アリノママニ ウチアケル'},\r
+       {   'text': '有りの実', 'input': 'アリノミ'},\r
+       {   'text': '栄えある', 'input': 'ハエ アル'},\r
+       {   'text': '或る程度', 'input': 'アル テイド'},\r
+       {   'text': '有るが儘', 'input': 'アルガ ママ'},\r
+       {   'text': 'アルカリ泉', 'input': 'アルカリセン'},\r
+       {   'text': '合わせ鏡', 'input': 'アワセ カガミ'},\r
+       {   'text': '鬘合わせ', 'input': 'カツラ アワセ'},\r
+       {   'text': '暗順応', 'input': 'アンジュンノー'},\r
+\r
+       ]\r
+\r
diff --git a/jptools/jpBrailleRunner.py b/jptools/jpBrailleRunner.py
new file mode 100644 (file)
index 0000000..f08d56f
--- /dev/null
@@ -0,0 +1,248 @@
+# -*- coding: utf-8 -*-\r
+#jptools/jpBrailleRunner.py\r
+#A part of NonVisual Desktop Access (NVDA)\r
+#This file is covered by the GNU General Public License.\r
+#See the file COPYING for more details.\r
+#Copyright (C) 2013 Masataka.Shinke, Takuya Nishimoto\r
+# h1: カナと記号のテスト\r
+# h2: テキスト解析とマスあけのテスト\r
+\r
+# from __future__ import unicode_literals\r
+import sys\r
+sys.path.append(r'..\source\synthDrivers\jtalk')\r
+from harness import tests\r
+import os\r
+import sys\r
+import optparse\r
+import datetime\r
+import cStringIO\r
+import timeit\r
+\r
+jtalk_dir = os.path.join(os.getcwdu(), '..', 'source', 'synthDrivers', 'jtalk')\r
+sys.path.append(jtalk_dir)\r
+\r
+import translator1\r
+import translator2\r
+\r
+def __write(file, s=""):\r
+       file.write(s.encode('utf-8', 'ignore'))\r
+\r
+def __writeln(file, s=""):\r
+       file.write(s.encode('utf-8', 'ignore') + "\n")\r
+\r
+output = None\r
+\r
+def __print(s=""):\r
+       global output\r
+       output.write(s.encode('utf-8', 'ignore') + "\n")\r
+\r
+def dot_numbers(s):\r
+       ret = []\r
+       for c in s:\r
+               code = ord(c)\r
+               if code == 0x20 or code == 0x2800:\r
+                       ret.append('0')\r
+               elif 0x2801 <= code and code <= 0x28ff:\r
+                       ar = []\r
+                       if code & 0x01: ar.append('1')\r
+                       if code & 0x02: ar.append('2')\r
+                       if code & 0x04: ar.append('3')\r
+                       if code & 0x08: ar.append('4')\r
+                       if code & 0x10: ar.append('5')\r
+                       if code & 0x20: ar.append('6')\r
+                       if code & 0x40: ar.append('7')\r
+                       if code & 0x80: ar.append('8')\r
+                       ret.append(u''.join(ar))\r
+       return u' '.join(ret)\r
+\r
+def pass1():\r
+       global output\r
+       outfile = '__h1output.txt'\r
+       with open(outfile, 'w') as f:\r
+               count = 0\r
+               for t in tests:\r
+                       if t.has_key('output'):\r
+                               result, inpos1 = translator1.translateWithInPos(t['input'])\r
+                               if t.has_key('inpos1'):\r
+                                       correct_inpos1 = ','.join(['%d' % n for n in t['inpos1'] ])\r
+                               else:\r
+                                       correct_inpos1 = None\r
+                               result_inpos1 = ','.join(['%d' % n for n in inpos1])\r
+                               if result != t['output'] or \\r
+                                               (correct_inpos1 and result_inpos1 != correct_inpos1) or \\r
+                                               (len(result) != len(inpos1)):\r
+                                       count+=1 \r
+                                       f.write("input: " + t['input'].encode('utf-8') + "\n")\r
+                                       f.write("result: " + result.encode('utf-8') + "\n")\r
+                                       f.write("correct: " + t['output'].encode('utf-8') + "\n")\r
+                                       if correct_inpos1:\r
+                                               f.write("correct_inpos1: " + correct_inpos1 + "\n")\r
+                                       f.write("result_inpos1: " + result_inpos1 + "\n")\r
+                                       if 'comment' in t:\r
+                                               f.write("comment: " + t['comment'].encode('utf-8') + "\n")\r
+                                       f.write("\n")\r
+               print 'h1: %d error(s). see %s' % (count, outfile)\r
+       \r
+def pass2(verboseMode=False):\r
+       global output\r
+       outfile = '__h2output.txt'\r
+       with open(outfile, 'w') as f:\r
+               output = cStringIO.StringIO()\r
+               translator2.initialize(jtalk_dir, __print)\r
+               log = output.getvalue()\r
+               output.close()\r
+               f.write(log)\r
+               f.write("\n")\r
+               count = 0\r
+               for t in tests:\r
+                       if t.has_key('text'):\r
+                               output = cStringIO.StringIO()\r
+                               result, pat, inpos1, inpos2 = translator2.translateWithInPos2(\r
+                                       t['text'], logwrite=__print)\r
+                               log = output.getvalue()\r
+                               output.close()\r
+                               # inpos2\r
+                               if t.has_key('inpos2'):\r
+                                       correct_inpos2 = ','.join(['%d' % n for n in t['inpos2'] ])\r
+                               else:\r
+                                       correct_inpos2 = None\r
+                               # inpos1\r
+                               if t.has_key('inpos1'):\r
+                                       correct_inpos1 = ','.join(['%d' % n for n in t['inpos1'] ])\r
+                               else:\r
+                                       correct_inpos1 = None\r
+                               # merged inpos\r
+                               inpos, outpos = translator2.mergePositionMap(\r
+                                       inpos1, inpos2, len(pat), len(t['text']))\r
+                               if t.has_key('inpos'):\r
+                                       correct_inpos = ','.join(['%d' % n for n in t['inpos'] ])\r
+                               else:\r
+                                       correct_inpos = None\r
+                               # result\r
+                               result_inpos2 = ','.join(['%d' % n for n in inpos2])\r
+                               result_inpos1 = ','.join(['%d' % n for n in inpos1])\r
+                               result_inpos  = ','.join(['%d' % n for n in inpos])\r
+                               result_outpos = ','.join(['%d' % n for n in outpos])\r
+                               # output\r
+                               isError = False\r
+                               if result != t['input'] or \\r
+                                               (correct_inpos2 and result_inpos2 != correct_inpos2) or \\r
+                                               (correct_inpos and result_inpos != correct_inpos):\r
+                                       isError = True\r
+                                       count+=1 \r
+                               if isError or verboseMode:\r
+                                       f.write("text   : " + t['text'].encode('utf-8') + "\n")\r
+                                       f.write("correct: " + t['input'].encode('utf-8') + "\n")\r
+                                       f.write("result : " + result.encode('utf-8') + "\n")\r
+                                       f.write("pat    : " + pat.encode('utf-8') + "\n")\r
+                                       if correct_inpos2:\r
+                                               f.write("cor_in2: " + correct_inpos2 + "\n")\r
+                                       if correct_inpos1:\r
+                                               f.write("cor_in1: " + correct_inpos1 + "\n")\r
+                                       if correct_inpos:\r
+                                               f.write("cor_in : " + correct_inpos + "\n")\r
+                                       f.write("res_in2: " + result_inpos2 + "\n")\r
+                                       f.write("res_in1: " + result_inpos1 + "\n")\r
+                                       f.write("res_in : " + result_inpos + "\n")\r
+                                       f.write("res_out: " + result_outpos + "\n")\r
+                                       if 'comment' in t and t['comment']:\r
+                                               f.write("comment: " + t['comment'].encode('utf-8') + "\n")\r
+                                       f.write("\n")\r
+                                       f.write(log)\r
+                                       f.write("\n")\r
+               print 'h2: %d error(s). see %s' % (count, outfile)\r
+\r
+def make_doc():\r
+       outfile = '__jpBrailleHarness.t2t'\r
+       timestamp = datetime.datetime.now().strftime('%Y%m%d-%H%M%S')\r
+       with open(outfile, 'w') as f:\r
+               __writeln(f, u"""\r
+NVDA 日本語版 点訳テストケース """ + timestamp + u"""\r
+\r
+%!Target: xhtml\r
+%!Encoding: UTF-8\r
+\r
+目次\r
+%%toc\r
+\r
+""")\r
+               count = 0\r
+               for t in tests:\r
+                       # 'note' はテストケースではなく説明の記述\r
+                       if t.has_key('note'):\r
+                               __writeln(f)\r
+                               __writeln(f, t['note'])\r
+                               __writeln(f)\r
+                               continue\r
+                       count += 1\r
+                       __writeln(f, u"番号: %d" % count)\r
+                       \r
+                       if t.has_key('text'):\r
+                               __writeln(f, u"- 日本語: " + t['text'].replace(u' ', u'□').replace(' ', u'□'))\r
+                       if t.has_key('input'):\r
+                               __writeln(f, u"- カナ表記: " + t['input'].replace(' ', u'□'))\r
+                       if t.has_key('output'):\r
+                               __writeln(f, u"- 点字: " + t['output'].replace(' ', u'□'))\r
+                       if t.has_key('output'):\r
+                               __writeln(f, u"- ドット番号: " + dot_numbers(t['output']))\r
+                       if t.has_key('comment'):\r
+                               __writeln(f, u"- コメント: " + t['comment'])\r
+                       __writeln(f, u"-")\r
+\r
+if __name__ == '__main__':\r
+       parser = optparse.OptionParser()\r
+       parser.add_option("-1", "--pass1only",\r
+                                         action="store_true",\r
+                                         dest="pass1_only",\r
+                                         default="False",\r
+                                         help="pass1 only timeit")\r
+       parser.add_option("-2", "--pass2only",\r
+                                         action="store_true",\r
+                                         dest="pass2_only",\r
+                                         default="False",\r
+                                         help="pass2 only timeit")\r
+       parser.add_option("-v", "--verbose",\r
+                                         action="store_true",\r
+                                         dest="verbose",\r
+                                         default="False",\r
+                                         help="pass2 only timeit")\r
+       parser.add_option("-m", "--makedoc",\r
+                                         action="store_true",\r
+                                         dest="make_doc",\r
+                                         default="False",\r
+                                         help="make t2t document of harness")\r
+       parser.add_option("-n", "--number",\r
+                                         action="store",\r
+                                         dest="number",\r
+                                         type="int",\r
+                                         default=1,\r
+                                         help="number for timeit")\r
+       parser.add_option("-o", "--outposTest",\r
+                                         action="store_true",\r
+                                         dest="outpos_test",\r
+                                         default=False,\r
+                                         help="outpos test")\r
+       (options, args) = parser.parse_args()\r
+\r
+       if options.outpos_test == True:\r
+               # translate([b'louis/tables/en-us-g2.ctb'], 'Hello world!')\r
+               inPos  = [0, 0, 1, 2, 3, 4, 5, 6, 6, 11]\r
+               inlen  = len('Hello world!')\r
+               outlen = len(',hello _w6')\r
+               outPos = translator2.makeOutPos(inPos, inlen, outlen)\r
+               print outPos \r
+               assert outPos == [1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7, 9]\r
+       elif options.make_doc == True:\r
+               make_doc()\r
+       elif options.pass1_only == True:\r
+               t = timeit.Timer(stmt=pass1)\r
+               print t.timeit(number=options.number)\r
+       elif options.pass2_only == True:\r
+               t = timeit.Timer(stmt=pass2)\r
+               print t.timeit(number=options.number)\r
+       elif options.verbose == True:\r
+               pass2(verboseMode=True)\r
+       else:\r
+               pass1()\r
+               pass2()\r
+\r
diff --git a/jptools/jtalkPredicTest.py b/jptools/jtalkPredicTest.py
new file mode 100644 (file)
index 0000000..e87fe11
--- /dev/null
@@ -0,0 +1,78 @@
+# jtalkPredicTest.py \r
+# -*- coding: utf-8 -*-\r
+\r
+from __future__ import unicode_literals, print_function\r
+import os\r
+import sys\r
+sys.path.append(r'..\source\synthDrivers\jtalk')\r
+from _jtalk_core import *\r
+from _nvdajp_unicode import unicode_normalize\r
+import _nvdajp_predic\r
+\r
+tests = [\r
+       ['ー', 'チョーオン'],\r
+       ['ン', 'ウン'],\r
+       ['あ ー', 'あ チョーオン'],\r
+       ['あ ン', 'あ ウン'],\r
+       ['0123345', ' ゼロ イチ ニー サン サン ヨン ゴー '],\r
+       ['人々', '人人'],\r
+       ['昔々', '昔昔'],\r
+       ['家々', '家家'],\r
+       ['山々', '山山'],\r
+       ['は', 'ハ'],\r
+       ['あ は', 'あ ハ'],\r
+       ['A', 'a'],\r
+       ['59 名', '59名'],\r
+       ['4行', '4ギョー'],\r
+       ['2 分前更新', '2分マエコーシン'],\r
+       ['1MB', '1メガバイト'],\r
+       ['10MB', '10メガバイト'],\r
+       ['1.2MB', '1.2メガバイト'],\r
+       ['0.5MB', '0.5メガバイト'],\r
+       ['321.1MB', '321.1メガバイト'],\r
+       ['123.45MB', '123.45メガバイト'],\r
+       ['2.7GB', '2.7ギガバイト'],\r
+       ['10KB', '10キロバイト'],\r
+       ['1 MB', '1メガバイト'],\r
+       ['10 MB', '10メガバイト'],\r
+       ['1.2 MB', '1.2メガバイト'],\r
+       ['0.5 MB', '0.5メガバイト'],\r
+       ['321.0 MB', '321.0メガバイト'],\r
+       ['123.45 MB', '123.45メガバイト'],\r
+       ['2.7 GB', '2.7ギガバイト'],\r
+       ['10 KB', '10キロバイト'],\r
+       ['12.01 KB', '12.01キロバイト'],\r
+       ['12.01', '12.01'],\r
+       ['12.35', '12.35'],\r
+       ['01234', ' ゼロ イチ ニー サン ヨン '],\r
+       ['1.01', '1.01'],\r
+       ['1.10', '1.10'],\r
+       ['2011.03.11', '2011テン ゼロ サン テン11'],\r
+       ['2011.11.11', '2011テン11テン11'],\r
+       ['7.0.1', '7テン0テン1'],\r
+       ['7.0.10', '7テン0テン10'],\r
+       ['1.2.3', '1テン2テン3'],\r
+       ['7.01.45', '7テン ゼロ イチ テン45'],\r
+       ['7.1.45', '7テン1テン45'],\r
+       ['7.01.01', '7テン ゼロ イチ テン ゼロ イチ '],\r
+       ['7.1.01', '7テン1テン ゼロ イチ '],\r
+       ['0.0.0.1', '0テン0テン0テン1'],\r
+       ['1,234円', '1234円'],\r
+       ['0,1', '0カンマ1'],\r
+       ['134,554', '134554'],\r
+       ['2013年2月10日', '2013年2月10日'],\r
+       ['2013‎年‎2‎月‎10‎日', '2013年2月10日'], # remove U+200E LEFT-TO-RIGHT MARK\r
+       ['2013‎年‎2‎月‎10‎日、‏‎23:45:19', '2013年2月10日、23:45:19'], # remove U+200E U+200F\r
+]\r
+\r
+def _print(s):\r
+       print(s.encode('utf-8', 'ignore'))\r
+\r
+if __name__ == '__main__':\r
+       _nvdajp_predic.setup()\r
+       for item in tests:\r
+               msg = item[0]\r
+               msg = unicode_normalize(msg)\r
+               s = _nvdajp_predic.convert(msg)\r
+               if item[1] != s:\r
+                       _print('expected:%s result:%s' % (item[1], s))\r
diff --git a/jptools/jtalkRunner.py b/jptools/jtalkRunner.py
new file mode 100644 (file)
index 0000000..614bda8
--- /dev/null
@@ -0,0 +1,88 @@
+# _jtalk_runner.py 
+# -*- coding: utf-8 -*-
+# Japanese speech engine test module
+# by Takuya Nishimoto
+# http://ja.nishimotz.com/project:libopenjtalk
+# Usage:
+# > cd source
+# > python synthDrivers/jtalk/_jtalk_runner.py
+
+import os
+import sys
+sys.path.append(r'..\source\synthDrivers\jtalk')
+from _jtalk_core import *
+
+import _nvdajp_predic 
+#JT_DIR = unicode(os.path.abspath(os.path.dirname(__file__)), 'mbcs')
+JT_DIR = r'..\source\synthDrivers\jtalk'
+JT_DLL = os.path.join(JT_DIR, 'libopenjtalk.dll')
+VOICE_DIR = os.path.join(JT_DIR, 'm001')
+
+# for miscdep/include/jtalk
+#JT_DIR = os.path.join(os.getcwdu(), '..', '..', 'source', 'synthDrivers', 'jtalk')
+#JT_DLL = os.path.join(JT_DIR, 'libopenjtalk.dll')
+#VOICE_DIR = os.path.join(JT_DIR, 'm001')
+
+def pa_play(data, samp_rate = 16000):
+       # requires pyaudio (PortAudio wrapper)
+       # http://people.csail.mit.edu/hubert/pyaudio/
+       import time
+       import pyaudio
+       p = pyaudio.PyAudio()
+       stream = p.open(format = p.get_format_from_width(2),
+               channels = 1, rate = samp_rate, output = True)
+       size = len(data)
+       pos = 0 # byte count
+       while pos < size:
+               a = stream.get_write_available() * 2
+               o = data[pos:pos+a]
+               stream.write(o)
+               pos += a
+       time.sleep(float(size) / 2 / samp_rate)
+       stream.close()
+       p.terminate()
+
+def __print(s):
+       print s.encode('cp932', 'ignore')
+
+def print_code(msg):
+       s = ''
+       for c in msg:
+               s += '%04x ' % ord(c)
+       print s
+
+if __name__ == '__main__':
+       njd = NJD()
+       jpcommon = JPCommon()
+       engine = HTS_Engine()
+       voice_args = {"id": "V1", "name": "m001", "lang":"ja", "samp_rate": 48000, "fperiod": 240, "alpha": 0.55, "lf0_base":5.0,  "use_lpf":1, "speaker_attenuation":1.0, "dir": VOICE_DIR}
+       libjt = libjt_initialize(JT_DLL, **voice_args)
+       libjt_load(voice_args['dir'].encode('mbcs'))
+       Mecab_initialize(__print, JT_DIR)
+       #
+       #msg = u'100.25ドル。ウェルカムトゥー nvda テンキーのinsertキーとメインのinsertキーの両方がnvdaキーとして動作します'
+       #msg = u'YouTube iTunes Store sjis co jp'
+       #msg = u'十五絡脈病証。' # nvdajp ticket 29828
+       #msg = u'マーク。まーく。' # nvdajp ticket 29859
+       msg = u'∫⣿♪ ウェルカムトゥー 鈹噯呃瘂蹻脘鑱涿癃 十五絡脈病証 マーク。まーく。ふぅー。ふぅぅぅぅぅー。ぅー。ぅぅー。'
+       _nvdajp_predic.setup()
+       msg = _nvdajp_predic.convert(msg)
+       s = Mecab_text2mecab(msg, CODE_='utf-8')
+       __print("utf-8: (%s)" % s.decode('utf-8', 'ignore'))
+       mf = MecabFeatures()
+       Mecab_analysis(s, mf)
+       Mecab_print(mf, __print, CODE_='utf-8')
+       Mecab_correctFeatures(mf, CODE_='utf-8')
+       Mecab_utf8_to_cp932(mf)
+       Mecab_print(mf, __print, CODE_='cp932')
+       fperiod = voice_args['fperiod']
+       data = libjt_synthesis(mf.feature, mf.size, fperiod_ = fperiod, logwrite_ = __print)
+       mf = None
+       if data: 
+               pa_play(data, voice_args['samp_rate'])
+               import wave
+               w = wave.Wave_write("_test.wav")
+               w.setparams( (1, 2, voice_args['samp_rate'], len(data)/2, 'NONE', 'not compressed') )
+               w.writeframes(data)
+               w.close()
+       libjt_clear()
diff --git a/jptools/make_html.cmd b/jptools/make_html.cmd
new file mode 100644 (file)
index 0000000..9bf5aa8
--- /dev/null
@@ -0,0 +1,3 @@
+python jpBrailleRunner.py -m\r
+python ..\txt2tags.py -t xhtml --toc __jpBrailleHarness.t2t\r
+python -c "import sys;lines = [line.strip() for line in sys.stdin.readlines()];import re;p = re.compile(r'<a href=\x22(mailto|http):[^>]+>([^<]+)</a>');print '\n'.join(map(lambda l:p.sub(r'\2', l), lines))" < __jpBrailleHarness.xhtml > c:\users\nishimotz\dropbox\public\jpBrailleHarness.xhtml\r
diff --git a/source/synthDrivers/jtalk/__init__.py b/source/synthDrivers/jtalk/__init__.py
new file mode 100644 (file)
index 0000000..056c129
--- /dev/null
@@ -0,0 +1,5 @@
+from synthDriverHandler import SynthDriver\r
+class SynthDriver(SynthDriver):\r
+       @classmethod\r
+       def check(cls):\r
+               return False\r
diff --git a/source/synthDrivers/jtalk/_bgthread.py b/source/synthDrivers/jtalk/_bgthread.py
new file mode 100644 (file)
index 0000000..ed7abd5
--- /dev/null
@@ -0,0 +1,61 @@
+# _bgthread.py \r
+# -*- coding: utf-8 -*-\r
+#A part of NonVisual Desktop Access (NVDA)\r
+#Copyright (C) 2006-2010 NVDA Contributors <http://www.nvda-project.org/>\r
+#Copyright (C) 2010-2012 Takuya Nishimoto (nishimotz.com)\r
+#Copyright (C) 2013 Masamitsu Misono (043.jp)\r
+#This file is covered by the GNU General Public License.\r
+#See the file COPYING for more details.\r
+#\r
+# based on NVDA (synthDrivers/_espeak.py)\r
+\r
+from logHandler import log\r
+import threading\r
+import Queue\r
+\r
+bgThread = None\r
+bgQueue = None\r
+isSpeaking = False\r
+\r
+class BgThread(threading.Thread):\r
+       def __init__(self):\r
+               threading.Thread.__init__(self)\r
+               self.setDaemon(True)\r
+\r
+       def run(self):\r
+               global isSpeaking\r
+               while True:\r
+                       func, args, kwargs = bgQueue.get()\r
+                       if not func:\r
+                               break\r
+                       try:\r
+                               func(*args, **kwargs)\r
+                       except:\r
+                               log.error("Error running function from queue", exc_info=True)\r
+                       finally:\r
+                               isSpeaking = False\r
+                               bgQueue.task_done()\r
+\r
+def execWhenDone(func, *args, **kwargs):\r
+       global bgQueue\r
+       # This can't be a kwarg in the function definition because it will consume the first non-keywor dargument which is meant for func.\r
+       mustBeAsync = kwargs.pop("mustBeAsync", False)\r
+       if mustBeAsync or bgQueue.unfinished_tasks != 0:\r
+               # Either this operation must be asynchronous or There is still an operation in progress.\r
+               # Therefore, run this asynchronously in the background thread.\r
+               bgQueue.put((func, args, kwargs))\r
+       else:\r
+               func(*args, **kwargs)\r
+\r
+def initialize():\r
+       global bgThread, bgQueue\r
+       bgQueue = Queue.Queue()\r
+       bgThread = BgThread()\r
+       bgThread.start()\r
+\r
+def terminate():\r
+       global bgThread, bgQueue\r
+       bgQueue.put((None, None, None))\r
+       bgThread.join()\r
+       bgThread = None\r
+       bgQueue = None\r
diff --git a/source/synthDrivers/jtalk/_jtalk_core.py b/source/synthDrivers/jtalk/_jtalk_core.py
new file mode 100644 (file)
index 0000000..a9939d8
--- /dev/null
@@ -0,0 +1,495 @@
+# _jtalk_core.py 
+# -*- coding: utf-8 -*-
+#A part of NonVisual Desktop Access (NVDA)
+#Copyright (C) 2010-2012 Takuya Nishimoto (NVDA Japanese Team)
+#This file is covered by the GNU General Public License.
+#See the file COPYING for more details.
+
+# Japanese speech engine wrapper for Open JTalk
+# http://ja.nishimotz.com/project:libopenjtalk
+
+import codecs
+import re
+import string
+import os
+import struct
+import sys
+from mecab import *
+
+############################################
+
+# htsengineapi/include/HTS_engine.h
+
+# size of structure:
+# HTS_Global     56
+# HTS_ModelSet   76
+# HTS_Label      24
+# HTS_SStreamSet 24
+# HTS_PStreamSet 12
+# HTS_GStreamSet 20
+
+class HTS_ModelSet(Structure):
+       _fields_ = [
+               ("_dummy", c_byte * 56),
+       ]
+
+class HTS_Label(Structure):
+       _fields_ = [
+               ("_dummy", c_byte * 76),
+       ]
+HTS_Label_ptr = POINTER(HTS_Label)
+
+class HTS_SStreamSet(Structure):
+       _fields_ = [
+               ("_dummy", c_byte * 24),
+       ]
+
+class HTS_PStreamSet(Structure):
+       _fields_ = [
+               ("_dummy", c_byte * 12),
+       ]
+
+class HTS_GStream(Structure):
+       _fields_ = [
+               ("static_length", c_int), # int static_length;  /* static features length */
+               ("par", c_double_p_p), # double **par; /* generated parameter */
+       ]
+
+HTS_GStream_ptr = POINTER(HTS_GStream)
+
+# FIXME: engine.gss.total_nsample is always 0
+class HTS_GStreamSet(Structure):
+       _fields_ = [
+               ("total_nsample", c_int), # int total_nsample; /* total sample */
+               ("total_frame", c_int), # int total_frame; /* total frame */
+               ("nstream", c_int), # int nstream; /* # of streams */
+               ("gstream", HTS_GStream_ptr), # HTS_GStream *gstream; /* generated parameter streams */
+               ("gspeech", c_short_p), # short *gspeech; /* generated speech */
+       ]
+HTS_GStreamSet_ptr = POINTER(HTS_GStreamSet)
+
+class HTS_Global(Structure):
+       _fields_ = [
+               ("state", c_int),               # /* Gamma=-1/stage : if stage=0 then Gamma=0 */
+               ("use_log_gain", c_int),        # HTS_Boolean (TRUE=1) /* log gain flag (for LSP) */
+               ("sampling_rate", c_int),       # /* sampling rate */
+               ("fperiod", c_int),             # /* frame period */
+               ("alpha", c_double),            # /* all-pass constant */
+               ("beta", c_double),             # /* postfiltering coefficient */
+               ("audio_buff_size", c_int),     # /* audio buffer size (for audio device) */
+               ("msd_threshold", c_double_p),  # /* MSD thresholds */
+               ("duration_iw", c_double_p),    # /* weights for duration interpolation */
+               ("parameter_iw", c_double_p_p), # /* weights for parameter interpolation */
+               ("gv_iw", c_double_p_p),        # /* weights for GV interpolation */
+               ("gv_weight", c_double_p),      # /* GV weights */
+       ]
+HTS_Global_ptr = POINTER(HTS_Global)
+
+class HTS_Engine(Structure):
+       _fields_ = [
+               ("global", HTS_Global),
+               ("audio", c_void_p), # HTS_Audio (requires nvdajp miscdep 86 or later)
+               ("ms", HTS_ModelSet),
+               ("label", HTS_Label),
+               ("sss", HTS_SStreamSet),
+               ("pss", HTS_PStreamSet),
+               ("gss", HTS_GStreamSet),
+               ("lf0_offset", c_double),
+               ("lf0_amp", c_double),
+       ]
+HTS_Engine_ptr = POINTER(HTS_Engine)
+
+############################################
+
+class NJD(Structure):
+       _fields_ = [
+               ("_dummy", c_byte * 8),
+       ]
+NJD_ptr = POINTER(NJD)
+
+class JPCommonNode(Structure):
+       pass
+JPCommonNode_ptr = POINTER(JPCommonNode)
+JPCommonNode._fields_ = [
+               ('pron', c_char_p),
+               ('pos', c_char_p),
+               ('ctype', c_char_p),
+               ('cform', c_char_p),
+               ('acc', c_int),
+               ('chain_flag', c_int),
+               ('prev', JPCommonNode_ptr),
+               ('next', JPCommonNode_ptr),
+       ]
+
+class JPCommonLabelBreathGroup(Structure):
+       pass
+JPCommonLabelBreathGroup_ptr = POINTER(JPCommonLabelBreathGroup)
+
+class JPCommonLabelAccentPhrase(Structure):
+       pass
+JPCommonLabelAccentPhrase_ptr = POINTER(JPCommonLabelAccentPhrase)
+
+class JPCommonLabelWord(Structure):
+       pass
+JPCommonLabelWord_ptr = POINTER(JPCommonLabelWord)
+
+class JPCommonLabelMora(Structure):
+       pass
+JPCommonLabelMora_ptr = POINTER(JPCommonLabelMora)
+
+class JPCommonLabelPhoneme(Structure):
+       pass
+JPCommonLabelPhoneme_ptr = POINTER(JPCommonLabelPhoneme)
+
+# jpcommon/jpcommon.h
+class JPCommonLabel(Structure):
+       _fields_ = [
+               ('size', c_int),
+               ('feature', c_char_p_p),
+               ('breath_head', JPCommonLabelBreathGroup_ptr),
+               ('breath_tail', JPCommonLabelBreathGroup_ptr),
+               ('accent_head', JPCommonLabelAccentPhrase_ptr),
+               ('accent_tail', JPCommonLabelAccentPhrase_ptr),
+               ('word_head', JPCommonLabelWord_ptr),
+               ('word_tail', JPCommonLabelWord_ptr),
+               ('mora_head', JPCommonLabelMora_ptr),
+               ('mora_tail', JPCommonLabelMora_ptr),
+               ('phoneme_head', JPCommonLabelPhoneme_ptr),
+               ('phoneme_tail', JPCommonLabelPhoneme_ptr),
+               ('short_pause_flag', c_int),
+       ]
+JPCommonLabel_ptr = POINTER(JPCommonLabel)
+
+class JPCommon(Structure):
+       _fields_ = [
+               ("head", JPCommonNode_ptr),
+               ("tail", JPCommonNode_ptr),
+               ("label", JPCommonLabel_ptr),
+       ]
+JPCommon_ptr = POINTER(JPCommon)
+
+# for debug
+def JPC_label_print(feature, size, logwrite_):
+       if logwrite_ is None: return
+       if feature is None or size is None: 
+               logwrite_( "JPC_label_print size: 0" )
+               return
+       s2 = "JPC_label_print size: %d\n" % size
+       for i in xrange(0, size):
+               s = string_at(feature[i])
+               if s:
+                       s2 += "%s\n" % s
+               else:
+                       s2 += "[None]"
+       logwrite_(s2)
+
+#############################################
+
+FNLEN = 1000
+FILENAME = c_char * FNLEN
+FILENAME_ptr = POINTER(FILENAME)
+FILENAME_ptr_ptr = POINTER(FILENAME_ptr)
+FILENAME_ptr_x3 = FILENAME_ptr * 3
+FILENAME_ptr_x3_ptr = POINTER(FILENAME_ptr_x3)
+
+libjt = None
+njd = NJD()
+jpcommon = JPCommon()
+engine = HTS_Engine()
+use_lpf = 0
+
+def libjt_version():
+       if libjt is None: return "libjt version none"
+       return libjt.jt_version()
+
+def libjt_initialize(JT_DLL, **args):
+       global libjt, njd, jpcommon, engine, use_lpf
+       use_lpf = args['use_lpf']
+       
+       if libjt is None: libjt = cdll.LoadLibrary(JT_DLL.encode('mbcs'))
+       libjt.jt_version.restype = c_char_p
+       
+       libjt.NJD_initialize.argtypes = [NJD_ptr]
+       libjt.NJD_initialize(njd)
+
+       libjt.JPCommon_initialize.argtypes = [JPCommon_ptr]
+       libjt.JPCommon_initialize(jpcommon)
+
+       libjt.HTS_Engine_initialize.argtypes = [HTS_Engine_ptr, c_int]
+       if use_lpf:
+               libjt.HTS_Engine_initialize(engine, 3)
+       else:
+               libjt.HTS_Engine_initialize(engine, 2)
+       
+       libjt.HTS_Engine_set_sampling_rate.argtypes = [HTS_Engine_ptr, c_int]
+       libjt.HTS_Engine_set_sampling_rate(engine, args['samp_rate']) # 16000
+       
+       libjt.HTS_Engine_set_fperiod.argtypes = [HTS_Engine_ptr, c_int]
+       libjt.HTS_Engine_set_fperiod(engine, args['fperiod']) # if samping-rate is 16000: 80(point=5ms) frame period
+
+       libjt.HTS_Engine_set_alpha.argtypes = [HTS_Engine_ptr, c_double]
+       libjt.HTS_Engine_set_alpha(engine, args['alpha']) # 0.42
+
+       libjt.HTS_Engine_set_gamma.argtypes = [HTS_Engine_ptr, c_int]
+       libjt.HTS_Engine_set_gamma(engine, 0)
+       
+       libjt.HTS_Engine_set_log_gain.argtypes = [HTS_Engine_ptr, c_int]
+       libjt.HTS_Engine_set_log_gain(engine, 0)
+       
+       libjt.HTS_Engine_set_beta.argtypes = [HTS_Engine_ptr, c_double]
+       libjt.HTS_Engine_set_beta(engine, 0.0)
+       
+       libjt.HTS_Engine_set_audio_buff_size.argtypes = [HTS_Engine_ptr, c_int]
+       libjt.HTS_Engine_set_audio_buff_size(engine, 1600)
+       
+       libjt.HTS_Engine_set_msd_threshold.argtypes = [HTS_Engine_ptr, c_int, c_double]
+       libjt.HTS_Engine_set_msd_threshold(engine, 1, 0.5)
+       
+       libjt.HTS_Engine_set_gv_weight.argtypes = [HTS_Engine_ptr, c_int, c_double]
+       libjt.HTS_Engine_set_gv_weight(engine, 0, 1.0)
+       libjt.HTS_Engine_set_gv_weight(engine, 1, 0.7)
+       if use_lpf:
+               libjt.HTS_Engine_set_gv_weight(engine, 2, 1.0)
+       
+       # for libjt_synthesis()
+       libjt.mecab2njd.argtypes = [NJD_ptr, FEATURE_ptr_array_ptr, c_int]
+       libjt.njd_set_pronunciation.argtypes = [NJD_ptr]
+       libjt.njd_set_digit.argtypes = [NJD_ptr]
+       libjt.njd_set_accent_phrase.argtypes = [NJD_ptr]
+       libjt.njd_set_accent_type.argtypes = [NJD_ptr]
+       libjt.njd_set_unvoiced_vowel.argtypes = [NJD_ptr]
+       libjt.njd_set_long_vowel.argtypes = [NJD_ptr]
+       libjt.njd2jpcommon.argtypes = [JPCommon_ptr, NJD_ptr]
+       libjt.JPCommon_make_label.argtypes = [JPCommon_ptr]
+       libjt.JPCommon_get_label_size.argtypes = [JPCommon_ptr]
+       libjt.JPCommon_get_label_size.argtypes = [JPCommon_ptr]
+       libjt.JPCommon_get_label_feature.argtypes = [JPCommon_ptr]
+       libjt.JPCommon_get_label_feature.restype = c_char_p_p
+       libjt.JPCommon_get_label_size.argtypes = [JPCommon_ptr]
+       libjt.HTS_Engine_load_label_from_string_list.argtypes = [
+               HTS_Engine_ptr, c_char_p_p, c_int]
+
+       libjt.HTS_Engine_create_sstream.argtypes = [HTS_Engine_ptr]
+       libjt.HTS_Engine_create_pstream.argtypes = [HTS_Engine_ptr]
+       libjt.HTS_Engine_create_gstream.argtypes = [HTS_Engine_ptr]
+       libjt.HTS_Engine_refresh.argtypes = [HTS_Engine_ptr]
+       libjt.JPCommon_refresh.argtypes = [JPCommon_ptr]
+       libjt.NJD_refresh.argtypes = [NJD_ptr]
+       libjt.HTS_GStreamSet_get_total_nsample.argtypes = [HTS_GStreamSet_ptr]
+       libjt.HTS_GStreamSet_get_speech.argtypes = [HTS_GStreamSet_ptr, c_int]
+       libjt.NJD_print.argtypes = [NJD_ptr]
+       libjt.JPCommon_print.argtypes = [JPCommon_ptr]
+       libjt.JPCommonLabel_print.argtypes = [JPCommonLabel_ptr]
+
+       libjt.jt_total_nsample.argtypes = [HTS_Engine_ptr]
+       libjt.jt_speech_ptr.argtypes = [HTS_Engine_ptr]
+       libjt.jt_speech_ptr.restype = c_short_p
+       libjt.jt_save_logs.argtypes = [c_char_p, HTS_Engine_ptr, NJD_ptr]
+       libjt.jt_save_riff.argtypes = [c_char_p, HTS_Engine_ptr]
+       libjt.jt_speech_normalize.argtypes = [HTS_Engine_ptr, c_short, c_int]
+       libjt.jt_trim_silence.argtypes = [HTS_Engine_ptr, c_short, c_short]
+       libjt.jt_trim_silence.restype = c_int
+
+       libjt.NJD_clear.argtypes = [NJD_ptr]
+       libjt.JPCommon_clear.argtypes = [JPCommon_ptr]
+       libjt.HTS_Engine_clear.argtypes = [HTS_Engine_ptr]
+       
+       libjt.HTS_Engine_set_lf0_offset_amp.argtypes = [HTS_Engine_ptr, c_double, c_double]
+
+       # for libjt_jpcommon_make_label()
+       libjt.JPCommonLabel_clear.argtypes = [JPCommonLabel_ptr]
+       libjt.JPCommonLabel_initialize.argtypes = [JPCommonLabel_ptr]
+       libjt.JPCommonNode_get_pron.restype = c_char_p
+       libjt.JPCommonNode_get_pos.restype = c_char_p
+       libjt.JPCommonNode_get_ctype.restype = c_char_p
+       libjt.JPCommonNode_get_cform.restype = c_char_p
+       libjt.JPCommonNode_get_acc.restype = c_int
+       libjt.JPCommonNode_get_chain_flag.restype = c_int
+       libjt.JPCommonLabel_push_word.argtype = [JPCommonLabel_ptr, c_char_p, c_char_p, c_char_p, c_char_p, c_int, c_int]
+
+def libjt_load(VOICE):
+       global libjt, engine, use_lpf
+       VOICE = VOICE.encode('mbcs')
+       libjt.HTS_Engine_load_duration_from_fn.argtypes = [
+               HTS_Engine_ptr, FILENAME_ptr_ptr, FILENAME_ptr_ptr, c_int]
+       
+       fn_ms_dur_buf = create_string_buffer(os.path.join(VOICE, "dur.pdf"))
+       fn_ms_dur_buf_ptr = cast(byref(fn_ms_dur_buf), FILENAME_ptr)
+       fn_ms_dur = cast(byref(fn_ms_dur_buf_ptr), FILENAME_ptr_ptr)
+       fn_ts_dur_buf = create_string_buffer(os.path.join(VOICE, "tree-dur.inf"))
+       fn_ts_dur_buf_ptr = cast(byref(fn_ts_dur_buf), FILENAME_ptr)
+       fn_ts_dur = cast(byref(fn_ts_dur_buf_ptr), FILENAME_ptr_ptr)
+       libjt.HTS_Engine_load_duration_from_fn(engine, fn_ms_dur, fn_ts_dur, 1)
+       
+       libjt.HTS_Engine_load_parameter_from_fn.argtypes = [
+               HTS_Engine_ptr, FILENAME_ptr_ptr, FILENAME_ptr_ptr,
+               FILENAME_ptr_x3_ptr, c_int, c_int, c_int, c_int]
+       
+       fn_ms_mcp_buf = create_string_buffer(os.path.join(VOICE, "mgc.pdf"))
+       fn_ms_mcp_buf_ptr = cast(byref(fn_ms_mcp_buf), FILENAME_ptr)
+       fn_ms_mcp = cast(byref(fn_ms_mcp_buf_ptr), FILENAME_ptr_ptr)
+       fn_ts_mcp_buf = create_string_buffer(os.path.join(VOICE, "tree-mgc.inf"))
+       fn_ts_mcp_buf_ptr = cast(byref(fn_ts_mcp_buf), FILENAME_ptr)
+       fn_ts_mcp = cast(byref(fn_ts_mcp_buf_ptr), FILENAME_ptr_ptr)
+       fn_ws_mcp_buf_1 = create_string_buffer(os.path.join(VOICE, "mgc.win1"))
+       fn_ws_mcp_buf_2 = create_string_buffer(os.path.join(VOICE, "mgc.win2"))
+       fn_ws_mcp_buf_3 = create_string_buffer(os.path.join(VOICE, "mgc.win3"))
+       fn_ws_mcp_buf_ptr_x3 = FILENAME_ptr_x3(
+               cast(byref(fn_ws_mcp_buf_1), FILENAME_ptr),
+               cast(byref(fn_ws_mcp_buf_2), FILENAME_ptr),
+               cast(byref(fn_ws_mcp_buf_3), FILENAME_ptr))
+       fn_ws_mcp = cast(byref(fn_ws_mcp_buf_ptr_x3), FILENAME_ptr_x3_ptr)
+       libjt.HTS_Engine_load_parameter_from_fn(
+               engine, fn_ms_mcp, fn_ts_mcp, fn_ws_mcp, 
+               0, 0, 3, 1)
+       
+       fn_ms_lf0_buf = create_string_buffer(os.path.join(VOICE, "lf0.pdf"))
+       fn_ms_lf0_buf_ptr = cast(byref(fn_ms_lf0_buf), FILENAME_ptr)
+       fn_ms_lf0 = cast(byref(fn_ms_lf0_buf_ptr), FILENAME_ptr_ptr)
+       fn_ts_lf0_buf = create_string_buffer(os.path.join(VOICE, "tree-lf0.inf"))
+       fn_ts_lf0_buf_ptr = cast(byref(fn_ts_lf0_buf), FILENAME_ptr)
+       fn_ts_lf0 = cast(byref(fn_ts_lf0_buf_ptr), FILENAME_ptr_ptr)
+       fn_ws_lf0_buf_1 = create_string_buffer(os.path.join(VOICE, "lf0.win1"))
+       fn_ws_lf0_buf_2 = create_string_buffer(os.path.join(VOICE, "lf0.win2"))
+       fn_ws_lf0_buf_3 = create_string_buffer(os.path.join(VOICE, "lf0.win3"))
+       fn_ws_lf0_buf_ptr_x3 = FILENAME_ptr_x3(
+               cast(byref(fn_ws_lf0_buf_1), FILENAME_ptr),
+               cast(byref(fn_ws_lf0_buf_2), FILENAME_ptr),
+               cast(byref(fn_ws_lf0_buf_3), FILENAME_ptr))
+       fn_ws_lf0 = cast(byref(fn_ws_lf0_buf_ptr_x3), FILENAME_ptr_x3_ptr)
+       libjt.HTS_Engine_load_parameter_from_fn(
+               engine, fn_ms_lf0, fn_ts_lf0, fn_ws_lf0, 
+               1, 1, 3, 1)
+       
+       if use_lpf:
+               fn_ms_lpf_buf = create_string_buffer(os.path.join(VOICE, "lpf.pdf"))
+               fn_ms_lpf_buf_ptr = cast(byref(fn_ms_lpf_buf), FILENAME_ptr)
+               fn_ms_lpf = cast(byref(fn_ms_lpf_buf_ptr), FILENAME_ptr_ptr)
+               fn_ts_lpf_buf = create_string_buffer(os.path.join(VOICE, "tree-lpf.inf"))
+               fn_ts_lpf_buf_ptr = cast(byref(fn_ts_lpf_buf), FILENAME_ptr)
+               fn_ts_lpf = cast(byref(fn_ts_lpf_buf_ptr), FILENAME_ptr_ptr)
+               fn_ws_lpf_buf_1 = create_string_buffer(os.path.join(VOICE, "lpf.win1"))
+               fn_ws_lpf_buf_ptr_x3 = FILENAME_ptr_x3(
+                       cast(byref(fn_ws_lpf_buf_1), FILENAME_ptr), 
+                       cast(0, FILENAME_ptr), 
+                       cast(0, FILENAME_ptr))
+               fn_ws_lpf = cast(byref(fn_ws_lpf_buf_ptr_x3), FILENAME_ptr_x3_ptr)
+               libjt.HTS_Engine_load_parameter_from_fn(engine, fn_ms_lpf, fn_ts_lpf, fn_ws_lpf, 2, 0, 1, 1)
+       
+       libjt.HTS_Engine_load_gv_from_fn.argtypes = [
+               HTS_Engine_ptr, FILENAME_ptr_ptr, FILENAME_ptr_ptr, 
+               c_int, c_int]
+
+       fn_ms_gvm_buf = create_string_buffer(os.path.join(VOICE, "gv-mgc.pdf"))
+       fn_ms_gvm_buf_ptr = cast(byref(fn_ms_gvm_buf), FILENAME_ptr)
+       fn_ms_gvm = cast(byref(fn_ms_gvm_buf_ptr), FILENAME_ptr_ptr)
+       fn_ts_gvm_buf = create_string_buffer(os.path.join(VOICE, "tree-gv-mgc.inf"))
+       fn_ts_gvm_buf_ptr = cast(byref(fn_ts_gvm_buf), FILENAME_ptr)
+       fn_ts_gvm = cast(byref(fn_ts_gvm_buf_ptr), FILENAME_ptr_ptr)
+       libjt.HTS_Engine_load_gv_from_fn(
+               engine, fn_ms_gvm, fn_ts_gvm, 0, 1)
+
+       fn_ms_gvl_buf = create_string_buffer(os.path.join(VOICE, "gv-lf0.pdf"))
+       fn_ms_gvl_buf_ptr = cast(byref(fn_ms_gvl_buf), FILENAME_ptr)
+       fn_ms_gvl = cast(byref(fn_ms_gvl_buf_ptr), FILENAME_ptr_ptr)
+       fn_ts_gvl_buf = create_string_buffer(os.path.join(VOICE, "tree-gv-lf0.inf"))
+       fn_ts_gvl_buf_ptr = cast(byref(fn_ts_gvl_buf), FILENAME_ptr)
+       fn_ts_gvl = cast(byref(fn_ts_gvl_buf_ptr), FILENAME_ptr_ptr)
+       libjt.HTS_Engine_load_gv_from_fn(
+               engine, fn_ms_gvl, fn_ts_gvl, 1, 1)
+
+       libjt.HTS_Engine_load_gv_switch_from_fn.argtypes = [
+               HTS_Engine_ptr, FILENAME_ptr]
+
+       fn_gv_switch_buf = create_string_buffer(os.path.join(VOICE, "gv-switch.inf"))
+       fn_gv_switch = cast(byref(fn_gv_switch_buf), FILENAME_ptr)
+       libjt.HTS_Engine_load_gv_switch_from_fn(
+               engine, fn_gv_switch)
+
+def libjt_refresh():
+       libjt.HTS_Engine_refresh(engine)
+       libjt.JPCommon_refresh(jpcommon)
+       libjt.NJD_refresh(njd)
+
+def libjt_clear():
+       libjt.NJD_clear(njd)
+       libjt.JPCommon_clear(jpcommon)
+       libjt.HTS_Engine_clear(engine)
+
+#def libjt_jpcommon_make_label(jpcommon, logwrite_=None):
+#      if jpcommon.label:
+#              libjt.JPCommonLabel_clear(jpcommon.label)
+#      else:
+#              jpcommon.label = cast(mc_calloc(1, sizeof(JPCommonLabel)), JPCommonLabel_ptr)
+#      libjt.JPCommonLabel_initialize(jpcommon.label)
+#      node = jpcommon.head
+#      while node:
+#              label = jpcommon.label
+#              pron = libjt.JPCommonNode_get_pron(node)
+#              pos = libjt.JPCommonNode_get_pos(node)
+#              ctype = libjt.JPCommonNode_get_ctype(node)
+#              cform = libjt.JPCommonNode_get_cform(node)
+#              acc = libjt.JPCommonNode_get_acc(node)
+#              flag = libjt.JPCommonNode_get_chain_flag(node)
+#              if logwrite_ : logwrite_('%s,%s,%d,%d' % (pron, pos, acc, flag))
+#              libjt.JPCommonLabel_push_word(label, pron, pos, ctype, cform, acc, flag)
+#              node = cast(node[0].next, JPCommonNode_ptr)
+#      libjt.JPCommonLabel_make(jpcommon.label)
+
+def libjt_synthesis(feature, size, fperiod_=80, feed_func_=None, is_speaking_func_=None, thres_=32, thres2_=32, level_=32767, logwrite_=None, lf0_offset_=0.0, lf0_amp_=1.0):
+       if feature is None or size is None: return None
+       if logwrite_ : logwrite_('libjt_synthesis start.')
+       try:
+               libjt.HTS_Engine_set_lf0_offset_amp(engine, lf0_offset_, lf0_amp_)
+               libjt.HTS_Engine_set_fperiod(engine, fperiod_) # 80(point=5ms) frame period
+               libjt.mecab2njd(njd, feature, size)
+               libjt.njd_set_pronunciation(njd)
+               libjt.njd_set_digit(njd)
+               libjt.njd_set_accent_phrase(njd)
+       except WindowsError:
+               if logwrite_ : logwrite_('libjt_synthesis error #1 ')
+       # exception: access violation reading 0x00000000
+       # https://github.com/nishimotz/libopenjtalk/commit/10d3abda6835e0547846fb5e12a36c1425561aaa#diff-66
+       try:
+               libjt.njd_set_accent_type(njd)
+       except WindowsError:
+               if logwrite_ : logwrite_('libjt_synthesis njd_set_accent_type() error ')
+       try:
+               libjt.njd_set_unvoiced_vowel(njd)
+               libjt.njd_set_long_vowel(njd)
+               libjt.njd2jpcommon(jpcommon, njd)
+               libjt.JPCommon_make_label(jpcommon)
+       except WindowsError:
+               if logwrite_ : logwrite_('libjt_synthesis error #2 ')
+       if is_speaking_func_ and not is_speaking_func_() :
+               libjt_refresh()
+               return None
+       try:
+               s = libjt.JPCommon_get_label_size(jpcommon)
+       except WindowsError:
+               if logwrite_ : logwrite_('libjt_synthesis JPCommon_get_label_size() error ')
+       buf = None
+       if s > 2:
+               try:
+                       f = libjt.JPCommon_get_label_feature(jpcommon)
+                       libjt.HTS_Engine_load_label_from_string_list(engine, f, s)
+                       libjt.HTS_Engine_create_sstream(engine)
+                       libjt.HTS_Engine_create_pstream(engine)
+                       libjt.HTS_Engine_create_gstream(engine)
+               except WindowsError:
+                       if logwrite_ : logwrite_('libjt_synthesis error #3 ')
+               if is_speaking_func_ and not is_speaking_func_() :
+                       libjt_refresh()
+                       return None
+               try:
+                       total_nsample = libjt.jt_trim_silence(engine, thres_, thres2_)
+                       libjt.jt_speech_normalize(engine, level_, total_nsample)
+                       speech_ptr = libjt.jt_speech_ptr(engine)
+                       byte_count = total_nsample * sizeof(c_short)
+                       buf = string_at(speech_ptr, byte_count)
+                       if feed_func_: feed_func_(buf)
+                       #libjt.jt_save_logs("_logfile", engine, njd)
+               except WindowsError:
+                       if logwrite_ : logwrite_('libjt_synthesis error #5 ')
+       if logwrite_ : logwrite_('libjt_synthesis done.')
+       return buf
diff --git a/source/synthDrivers/jtalk/_nvdajp_espeak.py b/source/synthDrivers/jtalk/_nvdajp_espeak.py
new file mode 100644 (file)
index 0000000..8d10c81
--- /dev/null
@@ -0,0 +1,250 @@
+# _nvdajp_espeak.py \r
+# -*- coding: utf-8 -*-\r
+\r
+from __future__ import unicode_literals\r
+import translator2\r
+from logHandler import log\r
+import re\r
+import copy\r
+from _nvdajp_unicode import unicode_normalize\r
+from speech import CharacterModeCommand\r
+\r
+_logwrite = log.debug\r
+\r
+def isJapaneseLang(msg):\r
+       for i in msg:\r
+               c = ord(i)\r
+               if (0x3040 <= c <= 0x30ff) or (0x3100 <= c <= 0x9fff):\r
+                       return True\r
+       return False\r
+\r
+kanadic = None\r
+\r
+def load_kanadic():\r
+       return [\r
+               [re.compile('キュ'), 'cu'],\r
+               [re.compile('キョ'), 'co'],\r
+               [re.compile('ギャ'), 'ga'],\r
+               [re.compile('ギュ'), 'gu'],\r
+               [re.compile('ギョ'), 'go'],\r
+\r
+               [re.compile('シャ'), 'sha'],\r
+               [re.compile('シュ'), 'shu'],\r
+               [re.compile('ショ'), 'sho'],\r
+\r
+               [re.compile('ジャ'), 'jar'],\r
+               [re.compile('ジュ'), 'ju'],\r
+               [re.compile('ジョ'), 'jo'],\r
+               [re.compile('ヂャ'), 'jar'],\r
+               [re.compile('ヂュ'), 'ju'],\r
+               [re.compile('ヂョ'), 'jo'],\r
+               [re.compile('ニャ'), 'nyar'],\r
+               [re.compile('ニュ'), 'new'],\r
+               [re.compile('ニョ'), 'no'],\r
+\r
+               [re.compile('ヒャ'), 'hyar'],\r
+               [re.compile('ヒュ'), 'hu'],\r
+               [re.compile('ヒョ'), 'ho'],\r
+               [re.compile('ビャ'), 'bar'],\r
+               [re.compile('ビュ'), 'bu'],\r
+               [re.compile('ビョ'), 'bo'],\r
+               [re.compile('ピャ'), 'pyar'],\r
+               [re.compile('ピュ'), 'pew'],\r
+               [re.compile('ピョ'), 'po'],\r
+\r
+               [re.compile('ミャ'), 'ma'],\r
+               [re.compile('ミュ'), 'mu'],\r
+               [re.compile('ミョ'), 'mo'],\r
+               [re.compile('リャ'), 'ra'],\r
+               [re.compile('リュ'), 'ru'],\r
+               [re.compile('リョ'), 'ro'],\r
+\r
+               [re.compile('イェ'), 'yiay'],\r
+               [re.compile('キェ'), 'kyay'],\r
+               [re.compile('シェ'), 'shay'],\r
+               [re.compile('チェ'), 'chay'],\r
+               [re.compile('ニェ'), 'nyay'],\r
+               [re.compile('ヒェ'), 'hyay'],\r
+               [re.compile('スィ'), 'si'],\r
+               [re.compile('ティ'), 'tee'],\r
+               [re.compile('ジェ'), 'jay'],\r
+               [re.compile('ズィ'), 'zee'],\r
+               [re.compile('ディ'), 'di'],\r
+               [re.compile('ウィ'), 'we'],\r
+               [re.compile('ウェ'), 'way'],\r
+               [re.compile('ウォ'), 'wo'],\r
+               [re.compile('トゥ'), 'tu'],\r
+               [re.compile('クァ'), 'kwa'],\r
+               [re.compile('クィ'), 'kwee'],\r
+               [re.compile('クェ'), 'kway'],\r
+               [re.compile('クォ'), 'kwo'],\r
+               [re.compile('ドゥ'), 'du'],\r
+               [re.compile('グァ'), 'gwa'],\r
+               [re.compile('グィ'), 'gwee'],\r
+               [re.compile('グェ'), 'gway'],\r
+               [re.compile('グォ'), 'gwo'],\r
+               [re.compile('テュ'), 'tu'],\r
+               [re.compile('フュ'), 'fu'],\r
+               [re.compile('フョ'), 'fo'],\r
+               [re.compile('ツァ'), 'tsar'],\r
+               [re.compile('ツィ'), 'tsee'],\r
+               [re.compile('ツェ'), 'tsay'],\r
+               [re.compile('ツォ'), 'tso'],\r
+               [re.compile('デュ'), 'du'],\r
+               [re.compile('ヴュ'), 'vu'],\r
+               [re.compile('ヴョ'), 'vo'],\r
+               [re.compile('ファ'), 'far'],\r
+               [re.compile('フィ'), 'fi'],\r
+               [re.compile('フェ'), 'fe'],\r
+               [re.compile('フォ'), 'fo'],\r
+               [re.compile('ヴァ'), 'var'],\r
+               [re.compile('ヴィ'), 'vee'],\r
+               [re.compile('ヴェ'), 'vay'],\r
+               [re.compile('ヴォ'), 'vo'],\r
+               [re.compile('ヴ'), 'vu'],\r
+\r
+               [re.compile('カ'), 'ca'],\r
+               [re.compile('キ'), 'kee'],\r
+               [re.compile('ク'), 'cu'],\r
+               [re.compile('ケ'), 'kay'],\r
+               [re.compile('コ'), 'co'],\r
+\r
+               [re.compile('ガ'), 'ga'],\r
+               [re.compile('ギ'), 'gi'],\r
+               [re.compile('グ'), 'gu'],\r
+               [re.compile('ゲ'), 'gay'],\r
+               [re.compile('ゴ'), 'go'],\r
+\r
+               [re.compile('サ'), 'sa'],\r
+               [re.compile('シ'), 'shi'],\r
+               [re.compile('ス'), 'su'],\r
+               [re.compile('セ'), 'say'],\r
+               [re.compile('ソ'), 'so'],\r
+\r
+               [re.compile('ザ'), 'za'],\r
+               [re.compile('ジ'), 'zee'],\r
+               [re.compile('ズ'), 'zu'],\r
+               [re.compile('ゼ'), 'zay'],\r
+               [re.compile('ゾ'), 'zo'],\r
+\r
+               [re.compile('タ'), 'ta'],\r
+               [re.compile('チ'), 'chee'],\r
+               [re.compile('ツ'), 'tsu'],\r
+               [re.compile('テ'), 'tay'],\r
+               [re.compile('ト'), 'tau'],\r
+\r
+               [re.compile('ダ'), 'da'],\r
+               [re.compile('ヂ'), 'gee'],\r
+               [re.compile('ヅ'), 'zu'],\r
+               [re.compile('デ'), 'day'],\r
+               [re.compile('ド'), 'dau'],\r
+\r
+               [re.compile('ナ'), 'na'],\r
+               [re.compile('ニ'), 'nee'],\r
+               [re.compile('ヌ'), 'nu'],\r
+               [re.compile('ネ'), 'nay'],\r
+               [re.compile('ノ'), 'no'],\r
+\r
+               [re.compile('ハ'), 'ha'],\r
+               [re.compile('ヒ'), 'hee'],\r
+               [re.compile('フ'), 'fu'],\r
+               [re.compile('ヘ'), 'hay'],\r
+               [re.compile('ホ'), 'ho'],\r
+\r
+               [re.compile('バ'), 'ba'],\r
+               [re.compile('ビ'), 'bee'],\r
+               [re.compile('ブ'), 'boo'],\r
+               [re.compile('ベ'), 'bay'],\r
+               [re.compile('ボ'), 'bo'],\r
+\r
+               [re.compile('パ'), 'pa'],\r
+               [re.compile('ピ'), 'pee'],\r
+               [re.compile('プ'), 'pu'],\r
+               [re.compile('ペ'), 'pay'],\r
+               [re.compile('ポ'), 'po'],\r
+\r
+               [re.compile('マ'), 'ma'],\r
+               [re.compile('ミ'), 'mee'],\r
+               [re.compile('ム'), 'mu'],\r
+               [re.compile('メ'), 'may'],\r
+               [re.compile('モ'), 'mo'],\r
+\r
+               [re.compile('ヤ'), 'ya'],\r
+               [re.compile('ユ'), 'yu'],\r
+               [re.compile('ヨ'), 'yo'],\r
+\r
+               [re.compile('ラ'), 'la'],\r
+               [re.compile('リ'), ' lee'],\r
+               [re.compile('ル'), 'lu'],\r
+               [re.compile('レ'), ' lay'],\r
+               [re.compile('ロ'), ' low'],\r
+\r
+               [re.compile('ワ'), 'wa'],\r
+               [re.compile('ヲ'), 'wo'],\r
+\r
+               [re.compile('ン'), 'n '],\r
+\r
+               [re.compile('ア'), ' ah '],\r
+               [re.compile('イ'), ' ee '],\r
+               [re.compile('ウ'), ' u '],\r
+               [re.compile('エ'), ' a '],\r
+               [re.compile('オ'), ' o '],\r
+\r
+               [re.compile('ァ'), 'ah'],\r
+               [re.compile('ィ'), 'ee'],\r
+               [re.compile('ゥ'), 'u'],\r
+               [re.compile('ェ'), 'a'],\r
+               [re.compile('ォ'), 'o'],\r
+\r
+               [re.compile('ャ'), 'ya'],\r
+               [re.compile('ュ'), 'yu'],\r
+               [re.compile('ョ'), 'yo'],\r
+\r
+               [re.compile('ッ'), ' '],\r
+               [re.compile('ー'), ' '],\r
+\r
+               # Braille\r
+               [re.compile('[\u2800-\u28ff]+'), ''],\r
+\r
+               # Japanese & CJK\r
+               [re.compile('[\u3040-\u9fff]+'), ''],\r
+               ]\r
+\r
+def replaceJapanese(msg):\r
+       if not translator2.mecab_initialized:\r
+               translator2.initialize()\r
+       msg = translator2.japanese_braille_separate(msg, _logwrite)[0]\r
+\r
+       global kanadic\r
+       if kanadic is None:\r
+               kanadic = load_kanadic()\r
+       for p in kanadic:\r
+               try:\r
+                       msg = re.sub(p[0], p[1], msg)\r
+               except:\r
+                       pass\r
+       return msg\r
+\r
+def replaceJapaneseFromSpeechSequence(speechSequence):\r
+       # we don't want to use CharacterMode for replaced Japanese text\r
+       a = []\r
+       charmode = False\r
+       for item in speechSequence:\r
+               disableCharMode = False\r
+               if isinstance(item, basestring):\r
+                       item = unicode_normalize(item)\r
+                       if isJapaneseLang(item):\r
+                               item = replaceJapanese(item)\r
+                               if charmode:\r
+                                       disableCharMode = True\r
+               elif isinstance(item, CharacterModeCommand):\r
+                       cmstate = item.state\r
+               if disableCharMode:\r
+                       a.append(CharacterModeCommand(False))\r
+                       a.append(item)\r
+                       if charmode:\r
+                               a.append(CharacterModeCommand(True))\r
+                       disableCharMode = False\r
+               else:\r
+                       a.append(item)\r
+       return a\r
diff --git a/source/synthDrivers/jtalk/_nvdajp_jtalk.py b/source/synthDrivers/jtalk/_nvdajp_jtalk.py
new file mode 100644 (file)
index 0000000..107ed6f
--- /dev/null
@@ -0,0 +1,296 @@
+# _nvdajp_jtalk.py 
+# -*- coding: utf-8 -*-
+#A part of NonVisual Desktop Access (NVDA)
+# speech engine nvdajp_jtalk
+# Copyright (C) 2010-2012 Takuya Nishimoto (nishimotz.com)
+# based on Open JTalk (bin/open_jtalk.c) http://github.com/nishimotz/libopenjtalk/
+
+from logHandler import log
+import time
+import Queue
+import os
+import codecs
+import re
+import string
+import ctypes
+import baseObject
+import copy
+import nvwave
+from .. import _espeak
+import _jtalk_core
+import _nvdajp_predic 
+from _nvdajp_unicode import unicode_normalize
+import _bgthread
+import sys
+import time
+import watchdog
+import config
+
+jtalk_dir = unicode(os.path.dirname(__file__), 'mbcs')
+if hasattr(sys,'frozen'):
+       d = os.path.join(os.getcwdu(), 'synthDrivers', 'jtalk')
+       if os.path.isdir(d):
+               jtalk_dir = d
+
+DEBUG = False
+
+RATE_BOOST_MULTIPLIER = 1.5
+
+# math.log(150) = 5.0, math.log(350) = 5.86
+_jtalk_voices = [
+       {"id": "V1",
+        "name": "m001",
+        "lang":"ja",
+        "samp_rate": 48000,
+        "fperiod": 240,
+        "alpha": 0.55,
+        "lf0_base": 5.0,
+        "pitch_bias": 0,
+        "use_lpf": 1,
+        "speaker_attenuation": 1.0,
+        "dir": "m001",
+        "espeak_variant": "max"},
+       {"id": "V2",
+        "name": "mei",
+        "lang":"ja",
+        "samp_rate": 48000,
+        "fperiod": 240,
+        "alpha": 0.55,
+        "lf0_base": 5.86,
+        "pitch_bias": -10,
+        "use_lpf": 1,
+        "speaker_attenuation": 0.5,
+        "dir": "mei_normal",
+        "espeak_variant": "f1"},
+       {"id": "V3",
+        "name": "lite",
+        "lang":"ja",
+        "samp_rate": 16000,
+        "fperiod": 80,
+        "alpha": 0.42,
+        "lf0_base": 5.0,
+        "pitch_bias": 0,
+        "use_lpf": 0,
+        "speaker_attenuation": 1.0,
+        "dir": "voice",
+        "espeak_variant": "max"},
+]
+default_jtalk_voice = _jtalk_voices[1] # V2
+voice_args = None
+
+class VoiceProperty(baseObject.AutoPropertyObject):
+       def __init__(self):
+               super(VoiceProperty,self).__init__()
+
+# if samp_rate==16000: normal speed = 80samples period
+fperiod = 240
+
+# gain control
+max_level = 32000
+thres_level = 128
+thres2_level = 128
+speaker_attenuation = 1.0
+
+logwrite = None
+lastIndex = None
+currIndex = None
+lastIndex = None
+player = None
+currentEngine = 0 # 1:espeak 2:jtalk
+
+def isSpeaking():
+       return _bgthread.isSpeaking
+
+def setSpeaking(b):
+       _bgthread.isSpeaking = b
+
+def _jtalk_speak(msg, index=None, prop=None):
+       if prop is None: return
+       global currIndex, buff
+       global currentEngine
+       currIndex = index
+       if prop.characterMode:
+               fperiod_current = voice_args['fperiod']
+       else:
+               fperiod_current = fperiod
+       msg = unicode_normalize(msg)
+       msg = _nvdajp_predic.convert(msg)
+       lw = None
+       if DEBUG: lw = logwrite
+       setSpeaking(True)
+       currentEngine = 2
+       if DEBUG: logwrite("p:%d i:%d msg:%s" % (prop.pitch, prop.inflection, msg))
+       la = 0.020 * prop.inflection # 50 = original range
+       ls = 0.015 * (prop.pitch - 50.0 + voice_args['pitch_bias']) # 50 = no shift
+       lo = ls + voice_args['lf0_base'] * (1 - la)
+       if DEBUG: logwrite("lo:%f la:%f" % (lo, la))
+       for m in string.split(msg):
+               try:
+                       if DEBUG: logwrite("unicode (%s)" % m)
+                       s = _jtalk_core.Mecab_text2mecab(m)
+                       if DEBUG: logwrite("utf-8 (%s)" % s.decode('utf-8', 'ignore'))
+                       if not isSpeaking(): _jtalk_core.libjt_refresh(); return
+                       mf = _jtalk_core.MecabFeatures()
+                       _jtalk_core.Mecab_analysis(s, mf, logwrite_=logwrite)
+                       if DEBUG: _jtalk_core.Mecab_print(mf, logwrite)
+                       _jtalk_core.Mecab_correctFeatures(mf)
+                       if DEBUG: _jtalk_core.Mecab_print(mf, logwrite)
+                       _jtalk_core.Mecab_utf8_to_cp932(mf)
+                       if DEBUG: _jtalk_core.Mecab_print(mf, logwrite, CODE_='cp932')
+                       if DEBUG: logwrite("Mecab_analysis done")
+                       if not isSpeaking(): _jtalk_core.libjt_refresh(); return
+                       _jtalk_core.libjt_synthesis(mf.feature, mf.size, 
+                               fperiod_ = fperiod_current, 
+                               feed_func_ = player.feed, # player.feed() is called inside
+                               is_speaking_func_ = isSpeaking, 
+                               thres_ = thres_level,
+                               thres2_ = thres2_level,
+                               level_ = int(max_level * speaker_attenuation),
+                               logwrite_ = lw,
+                               lf0_offset_ = lo,
+                               lf0_amp_ = la)
+                       mf = None
+                       if DEBUG: logwrite("libjt_synthesis done")
+                       _jtalk_core.libjt_refresh()
+               except WindowsError:
+                       if DEBUG: logwrite("WindowsError")
+       player.sync()
+       global lastIndex
+       lastIndex = currIndex
+       currIndex = None
+       setSpeaking(False)
+       currentEngine = 0
+
+espeakMark = 10000
+
+def _espeak_speak(msg, lang, index=None, prop=None):
+       global currentEngine, lastIndex, espeakMark
+       currentEngine = 1
+       msg = unicode(msg)
+       msg.translate({ord(u'\01'):None,ord(u'<'):u'&lt;',ord(u'>'):u'&gt;'})
+       msg = u"<voice xml:lang=\"%s\">%s</voice>" % (lang, msg)
+       msg += u"<mark name=\"%d\" />" % espeakMark
+       _espeak.speak(msg)
+       while currentEngine == 1 and _espeak.lastIndex != espeakMark:
+               time.sleep(0.1)
+               watchdog.alive()
+       time.sleep(0.4)
+       watchdog.alive()
+       lastIndex = index
+       currentEngine = 0
+       espeakMark += 1
+
+# call from BgThread
+def _speak(arg):
+       msg, lang, index, prop = arg
+       if DEBUG: logwrite('[' + lang + ']' + msg)
+       if DEBUG: logwrite("_speak(%s)" % msg)
+       if lang == 'ja':
+               _jtalk_speak(msg, index, prop)
+       else:
+               _espeak_speak(msg, lang, index, prop)
+
+def speak(msg, lang, index=None, voiceProperty_=None):
+       msg = msg.strip()
+       if len(msg) == 0: return
+       if voiceProperty_ is None: return
+       arg = [msg, lang, index, copy.deepcopy(voiceProperty_)]
+       _bgthread.execWhenDone(_speak, arg, mustBeAsync=True)
+
+def stop():
+       global currentEngine
+       if currentEngine == 1:
+               _espeak.stop()
+               currentEngine = 0
+               return
+       # Kill all speech from now.
+       # We still want parameter changes to occur, so requeue them.
+       params = []
+       stop_task_count = 0 # for log.info()
+       try:
+               while True:
+                       item = _bgthread.bgQueue.get_nowait() # [func, args, kwargs]
+                       if item[0] != _speak:
+                               params.append(item)
+                       else:
+                               stop_task_count = stop_task_count + 1
+                       _bgthread.bgQueue.task_done()
+       except Queue.Empty:
+               # Let the exception break us out of this loop, as queue.empty() is not reliable anyway.
+               pass
+       for item in params:
+               _bgthread.bgQueue.put(item)
+       setSpeaking(False)
+       if DEBUG: logwrite("stop: %d task(s) stopping" % stop_task_count)
+       player.stop()
+       lastIndex = None
+
+def pause(switch):
+       if currentEngine == 1:
+               _espeak.pause(switch)
+       elif currentEngine == 2:
+               player.pause(switch)
+
+def initialize(voice = default_jtalk_voice):
+       _espeak.initialize()
+       _espeak.setVoiceByLanguage("en")
+       _espeak.setVoiceAndVariant(variant=voice["espeak_variant"])
+       log.info("jtalk using eSpeak version %s" % _espeak.info())
+       global player, logwrite, voice_args
+       global speaker_attenuation
+       voice_args = voice
+       speaker_attenuation = voice_args['speaker_attenuation']
+       player = nvwave.WavePlayer(channels=1, samplesPerSec=voice_args['samp_rate'], bitsPerSample=16, outputDevice=config.conf["speech"]["outputDevice"])
+       _bgthread.initialize()
+
+       jt_dll = os.path.join(jtalk_dir, 'libopenjtalk.dll')
+       log.info('jt_dll %s' % jt_dll)
+       _jtalk_core.libjt_initialize(jt_dll, **voice_args)
+       voice_dir = os.path.join(jtalk_dir, voice_args['dir'])
+       if not os.path.isdir(voice_dir):
+               log.error('%s is not voice directory.' % voice_dir)
+               return
+       log.debug('loading %s' % voice_dir)
+       _jtalk_core.libjt_load(voice_dir)
+       logwrite = log.debug
+       _jtalk_core.Mecab_initialize(logwrite)
+       _nvdajp_predic.setup()
+       try:
+               logwrite(_jtalk_core.libjt_version())
+       except:
+               logwrite("libopenjtalk version unavailable")
+       if DEBUG: logwrite("jtalk for NVDA started. voice:" + voice_args['dir'])
+
+def terminate():
+       global player
+       stop()
+       _bgthread.terminate()
+       player.close()
+       player = None
+       _espeak.terminate()
+
+def get_rate(rateBoost):
+       f = fperiod
+       if not rateBoost:
+               f = fperiod / RATE_BOOST_MULTIPLIER
+       if voice_args['samp_rate'] == 16000:
+               return int(160 - 2 * f)
+       if voice_args['samp_rate'] == 48000:
+               return int((240 - f) / 1.5)
+       return 0
+
+def set_rate(rate, rateBoost):
+       global fperiod
+       if voice_args['samp_rate'] == 16000:
+               fperiod = int(80 - int(rate) / 2) # 80..30
+       if voice_args['samp_rate'] == 48000:
+               fperiod = int(240 - 1.5 * int(rate)) # 240..90
+       if not rateBoost:
+               fperiod = int(fperiod * RATE_BOOST_MULTIPLIER)
+
+def set_volume(vol):
+       global max_level, thres_level, thres2_level
+       max_level = int(326.67 * int(vol) + 100) # 100..32767
+       thres_level = 128
+       thres2_level = 128
+
diff --git a/source/synthDrivers/jtalk/_nvdajp_predic.py b/source/synthDrivers/jtalk/_nvdajp_predic.py
new file mode 100644 (file)
index 0000000..87a9ba6
--- /dev/null
@@ -0,0 +1,103 @@
+# _nvdajp_predic.py 
+# -*- coding: utf-8 -*-
+# A part of speech engine nvdajp_jtalk
+# Copyright (C) 2010-2011 Takuya Nishimoto (nishimotz.com)
+
+import re
+
+predic = None
+
+def setup():
+       global predic
+       if predic is None:
+               predic = load()
+
+def convert(msg):
+       for p in predic:
+               try:
+                       msg = re.sub(p[0], p[1], msg)
+               except:
+                       pass
+       msg = msg.lower()
+       return msg
+
+def load():
+       return [
+               [re.compile(u'^ー$'), u'チョーオン'],
+               [re.compile(u'^ン$'), u'ウン'],
+               [re.compile(u'\\sー$'), u' チョーオン'],
+               [re.compile(u'\\sン$'), u' ウン'],
+
+               ## 人々 昔々 家々 山々 
+               [re.compile(u'(.)々'), u'\\1\\1'],
+
+               ## isolated hiragana HA (mecab replaces to WA)
+               ## は 
+               [re.compile(u'^は$'), u'ハ'],
+               [re.compile(u'\\sは$'), u' ハ'],
+               
+               ## 59 名
+               [re.compile(u'(\\d) 名'), u'\\1名'],
+               ## 4行 ヨンコー -> ヨンギョー
+               [re.compile(u'(\\d)行'), u'\\1ギョー'],
+               ## 2 分前更新
+               [re.compile(u'(\\d)+ 分前更新'), u'\\1分マエコーシン'],
+               
+               ## 1MB 10MB 1.2MB 0.5MB 321.0MB 123.45MB 2.7GB
+               ## 1 MB 10 MB 1.2 MB 0.5 MB 321.0 MB 123.45 MB 2.7 GB
+               [re.compile(u'(\\d+)\\s*KB'), u'\\1キロバイト'],
+               [re.compile(u'(\\d+)\\s*MB'), u'\\1メガバイト'],
+               [re.compile(u'(\\d+)\\s*GB'), u'\\1ギガバイト'],
+               [re.compile(u'(\\d+)\\s*MHz'), u'\\1メガヘルツ'],
+               [re.compile(u'(\\d+)\\s*GHz'), u'\\1ギガヘルツ'],
+
+               ## 2013 年 1 月 2 日
+               [re.compile(u'(\\d+)\\s+年\\s+(\\d+)\\s+月\\s+(\\d+)\\s+日'), u'\\1年\\2月\\3日'],
+
+               ### zenkaku symbols convert
+               ## 2011.03.11
+               ## 1,234円
+               [re.compile(u'.'), u'.'],
+               [re.compile(u','), u','],
+
+               ## 1,234
+               ## 1,234,567
+               ## 1,234,567,890
+               ## 1,23 = ichi comma niju san
+               ## 1,0 = ichi comma zero
+               [re.compile(u'(\\d)\\,(\\d{3})'), u'\\1\\2'],
+               [re.compile(u'(\\d{2})\\,(\\d{3})'), u'\\1\\2'],
+               [re.compile(u'(\\d{3})\\,(\\d{3})'), u'\\1\\2'],
+               [re.compile(u'(\\d)\\,(\\d{1,2})'), u'\\1カンマ\\2'],
+
+               [re.compile(u'(\\d{1,4})\\.(\\d{1,4})\\.(\\d{1,4})\\.(\\d{1,4})'), u'\\1テン\\2テン\\3テン\\4'],
+               [re.compile(u'(\\d{1,4})\\.(\\d{1,4})\\.(\\d{1,4})'), u'\\1テン\\2テン\\3'],
+
+               # do not replace '0' after '.' to phonetic symbols (prepare)
+               [re.compile(u'\\.0'), u'.00'],
+
+               [re.compile(u'\\b0(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)'), u'  00  0\\1  0\\2  0\\3  0\\4  0\\5  0\\6  0\\7  0\\8  0\\9 '],
+               [re.compile(u'\\b0(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)'), u'  00  0\\1  0\\2  0\\3  0\\4  0\\5  0\\6  0\\7  0\\8 '],
+               [re.compile(u'\\b0(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)'), u'  00  0\\1  0\\2  0\\3  0\\4  0\\5  0\\6  0\\7 '],
+               [re.compile(u'\\b0(\\d)(\\d)(\\d)(\\d)(\\d)(\\d)'), u'  00  0\\1  0\\2  0\\3  0\\4  0\\5  0\\6 '],
+               [re.compile(u'\\b0(\\d)(\\d)(\\d)(\\d)(\\d)'), u'  00  0\\1  0\\2  0\\3  0\\4  0\\5 '],
+               [re.compile(u'\\b0(\\d)(\\d)(\\d)(\\d)'), u'  00  0\\1  0\\2  0\\3  0\\4 '],
+               [re.compile(u'\\b0(\\d)(\\d)(\\d)'), u'  00  0\\1  0\\2  0\\3 '],
+               [re.compile(u'\\b0(\\d)(\\d)'), u'  00  0\\1  0\\2 '],
+               [re.compile(u'\\b0(\\d)'), u'  00  0\\1 '],
+
+               [re.compile(u' 00'), u'ゼロ'],
+               [re.compile(u' 01'), u'イチ'],
+               [re.compile(u' 02'), u'ニー'],
+               [re.compile(u' 03'), u'サン'],
+               [re.compile(u' 04'), u'ヨン'],
+               [re.compile(u' 05'), u'ゴー'],
+               [re.compile(u' 06'), u'ロク'],
+               [re.compile(u' 07'), u'ナナ'],
+               [re.compile(u' 08'), u'ハチ'],
+               [re.compile(u' 09'), u'キュー'],
+
+               # do not replace '0' after '.' to phonetic symbols (finalize)
+               [re.compile(u'\\.00'), u'.0'],
+       ]
+
diff --git a/source/synthDrivers/jtalk/_nvdajp_spellchar.py b/source/synthDrivers/jtalk/_nvdajp_spellchar.py
new file mode 100644 (file)
index 0000000..7d2c284
--- /dev/null
@@ -0,0 +1,131 @@
+# _nvdajp_spellchar.py 
+# -*- coding: utf-8 -*-
+#A part of NonVisual Desktop Access (NVDA)
+#Copyright (C) 2010-2011 Takuya Nishimoto (nishimotz.com)
+#This file is covered by the GNU General Public License.
+#See the file COPYING for more details.
+
+# workaround for msspeech Haruka with "Use spelling functionality"
+
+import re
+_dic = None
+
+def init():
+       global _dic
+       if _dic : return
+       _dic = [
+               ### zenkaku alphabet convert
+               [re.compile(u'A'), u'A'],
+               [re.compile(u'B'), u'B'],
+               [re.compile(u'C'), u'C'],
+               [re.compile(u'D'), u'D'],
+               [re.compile(u'E'), u'E'],
+               [re.compile(u'F'), u'F'],
+               [re.compile(u'G'), u'G'],
+               [re.compile(u'H'), u'H'],
+               [re.compile(u'I'), u'I'],
+               [re.compile(u'J'), u'J'],
+               [re.compile(u'K'), u'K'],
+               [re.compile(u'L'), u'L'],
+               [re.compile(u'M'), u'M'],
+               [re.compile(u'N'), u'N'],
+               [re.compile(u'O'), u'O'],
+               [re.compile(u'P'), u'P'],
+               [re.compile(u'Q'), u'Q'],
+               [re.compile(u'R'), u'R'],
+               [re.compile(u'S'), u'S'],
+               [re.compile(u'T'), u'T'],
+               [re.compile(u'U'), u'U'],
+               [re.compile(u'V'), u'V'],
+               [re.compile(u'W'), u'W'],
+               [re.compile(u'X'), u'X'],
+               [re.compile(u'Y'), u'Y'],
+               [re.compile(u'Z'), u'Z'],
+               
+               [re.compile(u'a'), u'a'],
+               [re.compile(u'b'), u'b'],
+               [re.compile(u'c'), u'c'],
+               [re.compile(u'd'), u'd'],
+               [re.compile(u'e'), u'e'],
+               [re.compile(u'f'), u'f'],
+               [re.compile(u'g'), u'g'],
+               [re.compile(u'h'), u'h'],
+               [re.compile(u'i'), u'i'],
+               [re.compile(u'j'), u'j'],
+               [re.compile(u'k'), u'k'],
+               [re.compile(u'l'), u'l'],
+               [re.compile(u'm'), u'm'],
+               [re.compile(u'n'), u'n'],
+               [re.compile(u'o'), u'o'],
+               [re.compile(u'p'), u'p'],
+               [re.compile(u'q'), u'q'],
+               [re.compile(u'r'), u'r'],
+               [re.compile(u's'), u's'],
+               [re.compile(u't'), u't'],
+               [re.compile(u'u'), u'u'],
+               [re.compile(u'v'), u'v'],
+               [re.compile(u'w'), u'w'],
+               [re.compile(u'x'), u'x'],
+               [re.compile(u'y'), u'y'],
+               [re.compile(u'z'), u'z'],
+               
+               ### zenkaku numbers convert
+               [re.compile(u'0'), u'0'],
+               [re.compile(u'1'), u'1'],
+               [re.compile(u'2'), u'2'],
+               [re.compile(u'3'), u'3'],
+               [re.compile(u'4'), u'4'],
+               [re.compile(u'5'), u'5'],
+               [re.compile(u'6'), u'6'],
+               [re.compile(u'7'), u'7'],
+               [re.compile(u'8'), u'8'],
+               [re.compile(u'9'), u'9'],
+               
+               [re.compile(u'0'), u'ゼロ '],
+               [re.compile(u'1'), u'イチ '],
+               [re.compile(u'2'), u'ニイ '],
+               [re.compile(u'3'), u'サン '],
+               [re.compile(u'4'), u'ヨン '],
+               [re.compile(u'5'), u'ゴオ '],
+               [re.compile(u'6'), u'ロク '],
+               [re.compile(u'7'), u'ナナ '],
+               [re.compile(u'8'), u'ハチ '],
+               [re.compile(u'9'), u'キュウ '],
+               
+               [re.compile(u'(a|A)'), u'エイ '],
+               [re.compile(u'(b|B)'), u'ビイー '],
+               [re.compile(u'(c|C)'), u'シイ '],
+               [re.compile(u'(d|D)'), u'ディイ '],
+               [re.compile(u'(e|E)'), u'イイー '],
+               [re.compile(u'(f|F)'), u'エフ '],
+               [re.compile(u'(g|G)'), u'ジイ '],
+               [re.compile(u'(h|H)'), u'エイチ '],
+               [re.compile(u'(i|I)'), u'アイ '],
+               [re.compile(u'(j|J)'), u'ジェイ '],
+               [re.compile(u'(k|K)'), u'ケイ '],
+               [re.compile(u'(l|L)'), u'エル '],
+               [re.compile(u'(m|M)'), u'エム '],
+               [re.compile(u'(n|N)'), u'エヌ '],
+               [re.compile(u'(o|O)'), u'オオ '],
+               [re.compile(u'(p|P)'), u'ピイイ '],
+               [re.compile(u'(q|Q)'), u'キュウ '],
+               [re.compile(u'(r|R)'), u'アール '],
+               [re.compile(u'(s|S)'), u'エス '],
+               [re.compile(u'(t|T)'), u'ティイ '],
+               [re.compile(u'(u|U)'), u'ユウ '],
+               [re.compile(u'(v|V)'), u'ブイ '],
+               [re.compile(u'(w|W)'), u'ダブリュウ '],
+               [re.compile(u'(x|X)'), u'エックス '],
+               [re.compile(u'(y|Y)'), u'ワイ '],
+               [re.compile(u'(z|Z)'), u'ゼッド '],
+       ]
+
+def convert(msg):
+       global _dic
+       if _dic is None: init()
+       for p in _dic:
+               try:
+                       msg = re.sub(p[0], p[1], msg)
+               except:
+                       pass
+       return msg
diff --git a/source/synthDrivers/jtalk/_nvdajp_unicode.py b/source/synthDrivers/jtalk/_nvdajp_unicode.py
new file mode 100644 (file)
index 0000000..272d541
--- /dev/null
@@ -0,0 +1,18 @@
+# _nvdajp_unicode.py \r
+# -*- coding: utf-8 -*-\r
+\r
+from __future__ import unicode_literals\r
+import unicodedata\r
+\r
+def unicode_normalize(s):\r
+       s = s.replace('\ufffd', '')   # Unicode REPLACEMENT CHARACTER\r
+       s = s.replace('\u200e', '')   # Unicode LEFT-TO-RIGHT MARK\r
+       s = s.replace('\u200f', '')   # Unicode RIGHT-TO-LEFT MARK\r
+       # Mecab_text2mecab() で全角に変換され NFKC で戻せない文字\r
+       s = s.replace('.', '.')\r
+       s = unicodedata.normalize('NFKC', s)\r
+       s = s.replace('\u2212', '-')  # 0x2212 MUNUS SIGN to 0x002D HYPHEN-MINUS\r
+       s = s.replace('\u00a5', '\\') # 0x00A5 YEN SIGN\r
+       s = s.replace('\u301c', '~')  # 0x301C WAVE DASH\r
+       return s\r
+\r
diff --git a/source/synthDrivers/jtalk/mecab.py b/source/synthDrivers/jtalk/mecab.py
new file mode 100644 (file)
index 0000000..cf5b8da
--- /dev/null
@@ -0,0 +1,429 @@
+# coding: UTF-8\r
+#nvdajptext/mecab.py \r
+#A part of NonVisual Desktop Access (NVDA)\r
+#This file is covered by the GNU General Public License.\r
+#See the file COPYING for more details.\r
+#Copyright (C) 2010-2012 Masataka.Shinke, Takuya Nishimoto\r
+\r
+CODE = 'utf-8'\r
+\r
+from ctypes import *\r
+import codecs\r
+import re\r
+import string\r
+import os\r
+import struct\r
+import unicodedata\r
+import threading\r
+import sys\r
+\r
+DEFAULT_JTALK_DIR = unicode(os.path.dirname(__file__), 'mbcs')\r
+if hasattr(sys,'frozen'):\r
+       d = os.path.join(os.getcwdu(), 'synthDrivers', 'jtalk')\r
+       if os.path.isdir(d):\r
+               DEFAULT_JTALK_DIR = d\r
+\r
+c_double_p = POINTER(c_double)\r
+c_double_p_p = POINTER(c_double_p) \r
+c_short_p = POINTER(c_short)\r
+c_char_p_p = POINTER(c_char_p) \r
+\r
+##############################################\r
+\r
+# http://mecab.sourceforge.net/libmecab.html\r
+# c:/mecab/sdk/mecab.h\r
+MECAB_NOR_NODE = 0\r
+MECAB_UNK_NODE = 1\r
+MECAB_BOS_NODE = 2\r
+MECAB_EOS_NODE = 3\r
+class mecab_token_t(Structure):\r
+       pass\r
+mecab_token_t_ptr = POINTER(mecab_token_t)\r
+\r
+class mecab_path_t(Structure):\r
+       pass\r
+mecab_path_t_ptr = POINTER(mecab_path_t)\r
+\r
+class mecab_node_t(Structure):\r
+       pass\r
+mecab_node_t_ptr = POINTER(mecab_node_t)\r
+mecab_node_t_ptr_ptr = POINTER(mecab_node_t_ptr)\r
+mecab_node_t._fields_ = [\r
+               ("prev", mecab_node_t_ptr),\r
+               ("next", mecab_node_t_ptr),\r
+               ("enext", mecab_node_t_ptr),\r
+               ("bnext", mecab_node_t_ptr),\r
+               ("rpath", mecab_path_t_ptr),\r
+               ("lpath", mecab_path_t_ptr),\r
+               # ("begin_node_list", mecab_node_t_ptr_ptr),\r
+               # ("end_node_list", mecab_node_t_ptr_ptr),\r
+               ("surface", c_char_p),\r
+               ("feature", c_char_p),\r
+               ("id", c_uint),\r
+               ("length", c_ushort),\r
+               ("rlength", c_ushort),\r
+               ("rcAttr", c_ushort),\r
+               ("lcAttr", c_ushort),\r
+               ("posid", c_ushort),\r
+               ("char_type", c_ubyte),\r
+               ("stat", c_ubyte),\r
+               ("isbest", c_ubyte),\r
+               # ("sentence_length", c_uint),\r
+               ("alpha", c_float),\r
+               ("beta", c_float),\r
+               ("prob", c_float),\r
+               ("wcost", c_short),\r
+               ("cost", c_long),\r
+               # ("token", mecab_token_t_ptr),\r
+       ]\r
+\r
+############################################\r
+\r
+# typedef struct _Mecab{\r
+#    char **feature;\r
+#    int size;\r
+#    mecab_t *mecab;\r
+# } Mecab;\r
+\r
+FELEN   = 1000 # string len\r
+FECOUNT = 1000\r
+FEATURE = c_char * FELEN\r
+FEATURE_ptr = POINTER(FEATURE)\r
+FEATURE_ptr_array = FEATURE_ptr * FECOUNT\r
+FEATURE_ptr_array_ptr = POINTER(FEATURE_ptr_array)\r
+\r
+mecab = None\r
+libmc = None\r
+lock = threading.Lock()\r
+\r
+mc_malloc = cdll.msvcrt.malloc\r
+mc_malloc.restype = POINTER(c_ubyte)\r
+mc_calloc = cdll.msvcrt.calloc\r
+mc_calloc.restype = POINTER(c_ubyte)\r
+mc_free = cdll.msvcrt.free\r
+\r
+class NonblockingMecabFeatures(object):\r
+       def __init__(self):\r
+               self.size = 0\r
+               self.feature = FEATURE_ptr_array()\r
+               for i in xrange(0, FECOUNT):\r
+                       buf = mc_malloc(FELEN) \r
+                       self.feature[i] = cast(buf, FEATURE_ptr)\r
+\r
+       def __del__(self):\r
+               for i in xrange(0, FECOUNT):\r
+                       try:\r
+                               mc_free(self.feature[i]) \r
+                       except:\r
+                               pass\r
+\r
+class MecabFeatures(NonblockingMecabFeatures):\r
+       def __init__(self):\r
+               global lock\r
+               lock.acquire()\r
+               super(MecabFeatures, self).__init__()\r
+\r
+       def __del__(self):\r
+               global lock\r
+               super(MecabFeatures, self).__del__()\r
+               lock.release()\r
+\r
+predic = None\r
+\r
+def text2mecab_setup():\r
+       global predic\r
+       if predic is None:\r
+               predic = [\r
+                       [re.compile(u" "), u" "],\r
+                       [re.compile(u"!"), u"!"],\r
+                       [re.compile(u"\""), u"”"],\r
+                       [re.compile(u"#"), u"#"],\r
+                       [re.compile(u"\\$"), u"$"],\r
+                       [re.compile(u"%"), u"%"],\r
+                       [re.compile(u"&"), u"&"],\r
+                       [re.compile(u"'"), u"’"],\r
+                       [re.compile(u"\\("), u"("],\r
+                       [re.compile(u"\\)"), u")"],\r
+                       [re.compile(u"\\*"), u"*"],\r
+                       [re.compile(u"\\+"), u"+"],\r
+                       [re.compile(u","), u","],\r
+                       [re.compile(u"\\-"), u"−"],\r
+                       [re.compile(u"\\."), u"."],\r
+                       [re.compile(u"\\/"), u"/"],\r
+                       [re.compile(u"0"), u"0"],\r
+                       [re.compile(u"1"), u"1"],\r
+                       [re.compile(u"2"), u"2"],\r
+                       [re.compile(u"3"), u"3"],\r
+                       [re.compile(u"4"), u"4"],\r
+                       [re.compile(u"5"), u"5"],\r
+                       [re.compile(u"6"), u"6"],\r
+                       [re.compile(u"7"), u"7"],\r
+                       [re.compile(u"8"), u"8"],\r
+                       [re.compile(u"9"), u"9"],\r
+                       [re.compile(u":"), u":"],\r
+                       [re.compile(u";"), u";"],\r
+                       [re.compile(u"<"), u"<"],\r
+                       [re.compile(u"="), u"="],\r
+                       [re.compile(u">"), u">"],\r
+                       [re.compile(u"\?"), u"?"],\r
+                       [re.compile(u"@"), u"@"],\r
+                       [re.compile(u"A"), u"A"],\r
+                       [re.compile(u"B"), u"B"],\r
+                       [re.compile(u"C"), u"C"],\r
+                       [re.compile(u"D"), u"D"],\r
+                       [re.compile(u"E"), u"E"],\r
+                       [re.compile(u"F"), u"F"],\r
+                       [re.compile(u"G"), u"G"],\r
+                       [re.compile(u"H"), u"H"],\r
+                       [re.compile(u"I"), u"I"],\r
+                       [re.compile(u"J"), u"J"],\r
+                       [re.compile(u"K"), u"K"],\r
+                       [re.compile(u"L"), u"L"],\r
+                       [re.compile(u"M"), u"M"],\r
+                       [re.compile(u"N"), u"N"],\r
+                       [re.compile(u"O"), u"O"],\r
+                       [re.compile(u"P"), u"P"],\r
+                       [re.compile(u"Q"), u"Q"],\r
+                       [re.compile(u"R"), u"R"],\r
+                       [re.compile(u"S"), u"S"],\r
+                       [re.compile(u"T"), u"T"],\r
+                       [re.compile(u"U"), u"U"],\r
+                       [re.compile(u"V"), u"V"],\r
+                       [re.compile(u"W"), u"W"],\r
+                       [re.compile(u"X"), u"X"],\r
+                       [re.compile(u"Y"), u"Y"],\r
+                       [re.compile(u"Z"), u"Z"],\r
+                       [re.compile(u"\\["), u"["],\r
+                       [re.compile(u"\\\\"), u"¥"],\r
+                       [re.compile(u"\\]"), u"]"],\r
+                       [re.compile(u"\\^"), u"^"],\r
+                       [re.compile(u"_"), u"_"],\r
+                       [re.compile(u"`"), u"‘"],\r
+                       [re.compile(u"a"), u"a"],\r
+                       [re.compile(u"b"), u"b"],\r
+                       [re.compile(u"c"), u"c"],\r
+                       [re.compile(u"d"), u"d"],\r
+                       [re.compile(u"e"), u"e"],\r
+                       [re.compile(u"f"), u"f"],\r
+                       [re.compile(u"g"), u"g"],\r
+                       [re.compile(u"h"), u"h"],\r
+                       [re.compile(u"i"), u"i"],\r
+                       [re.compile(u"j"), u"j"],\r
+                       [re.compile(u"k"), u"k"],\r
+                       [re.compile(u"l"), u"l"],\r
+                       [re.compile(u"m"), u"m"],\r
+                       [re.compile(u"n"), u"n"],\r
+                       [re.compile(u"o"), u"o"],\r
+                       [re.compile(u"p"), u"p"],\r
+                       [re.compile(u"q"), u"q"],\r
+                       [re.compile(u"r"), u"r"],\r
+                       [re.compile(u"s"), u"s"],\r
+                       [re.compile(u"t"), u"t"],\r
+                       [re.compile(u"u"), u"u"],\r
+                       [re.compile(u"v"), u"v"],\r
+                       [re.compile(u"w"), u"w"],\r
+                       [re.compile(u"x"), u"x"],\r
+                       [re.compile(u"y"), u"y"],\r
+                       [re.compile(u"z"), u"z"],\r
+                       [re.compile(u"{"), u"{"],\r
+                       [re.compile(u"\\|"), u"|"],\r
+                       [re.compile(u"}"), u"}"],\r
+                       [re.compile(u"~"), u"〜"],\r
+               ]\r
+\r
+def text2mecab_convert(s):\r
+       for p in predic:\r
+               try:\r
+                       s = re.sub(p[0], p[1], s)\r
+               except:\r
+                       pass\r
+       return s\r
+\r
+def Mecab_text2mecab(txt, CODE_=CODE):\r
+       text2mecab_setup()\r
+       txt = unicodedata.normalize('NFKC', txt)\r
+       txt = text2mecab_convert(txt)\r
+       return txt.encode(CODE_, 'ignore')\r
+\r
+def Mecab_initialize(logwrite_ = None, jtalk_dir = DEFAULT_JTALK_DIR):\r
+       #if logwrite_: logwrite_('mecab init begin')\r
+       mecab_dll = os.path.join(jtalk_dir, 'libmecab.dll')\r
+       global libmc\r
+       if libmc is None:\r
+               libmc = cdll.LoadLibrary(mecab_dll.encode('mbcs'))\r
+               libmc.mecab_version.restype = c_char_p\r
+               libmc.mecab_strerror.restype = c_char_p\r
+               libmc.mecab_sparse_tonode.restype = mecab_node_t_ptr\r
+               libmc.mecab_new.argtypes = [c_int, c_char_p_p]\r
+       global mecab\r
+       if mecab is None:\r
+               dic = os.path.join(jtalk_dir, 'dic')\r
+               if logwrite_: logwrite_('dic: %s' % dic)\r
+               f = open(os.path.join(dic, "DIC_VERSION"))\r
+               s = f.read().strip()\r
+               f.close()\r
+               logwrite_('mecab:' + libmc.mecab_version() + ' ' + s)\r
+               # check utf-8 dictionary\r
+               if not CODE in s:\r
+                       raise RuntimeError('utf-8 dictionary for mecab required.')\r
+               mecabrc = os.path.join(jtalk_dir, 'mecabrc')\r
+               args = (c_char_p * 5)('mecab', '-d', dic.encode('utf-8'), '-r', mecabrc.encode('utf-8'))\r
+               mecab = libmc.mecab_new(5, args)\r
+               if logwrite_:\r
+                       if not mecab: logwrite_('mecab_new failed.')\r
+                       logwrite_(libmc.mecab_strerror(mecab))\r
+       #if logwrite_: logwrite_('mecab init end')\r
+\r
+def Mecab_analysis(src, features, logwrite_ = None):\r
+       if not src:\r
+               if logwrite_: logwrite('src empty')\r
+               features.size = 0\r
+               return\r
+       head = libmc.mecab_sparse_tonode(mecab, src)\r
+       if head is None:\r
+               if logwrite_: logwrite('mecab_sparse_tonode result empty')\r
+               features.size = 0\r
+               return\r
+       features.size = 0\r
+\r
+       # make array of features\r
+       node = head\r
+       i = 0\r
+       while node:\r
+               s = node[0].stat\r
+               if s != MECAB_BOS_NODE and s != MECAB_EOS_NODE:\r
+                       c = node[0].length\r
+                       s = string_at(node[0].surface, c) + "," + string_at(node[0].feature)\r
+                       if logwrite_: logwrite_(s.decode(CODE, 'ignore'))\r
+                       buf = create_string_buffer(s)\r
+                       dst_ptr = features.feature[i]\r
+                       src_ptr = byref(buf)\r
+                       memmove(dst_ptr, src_ptr, len(s)+1)\r
+                       i += 1\r
+               node = node[0].next\r
+               features.size = i\r
+               if i > FECOUNT: \r
+                       if logwrite_: logwrite('too many nodes')\r
+                       return\r
+       return\r
+\r
+# for debug\r
+def Mecab_print(mf, logwrite_ = None, CODE_ = CODE, output_header = True):\r
+       if logwrite_ is None: return\r
+       feature = mf.feature\r
+       size = mf.size\r
+       if feature is None or size is None: \r
+               if output_header:\r
+                       logwrite_( "Mecab_print size: 0" )\r
+               return\r
+       s2 = ''\r
+       if output_header:\r
+               s2 += "Mecab_print size: %d\n" % size\r
+       for i in xrange(0, size):\r
+               s = string_at(feature[i])\r
+               if s:\r
+                       if CODE_ is None:\r
+                               s2 += "%d %s\n" % (i, s)\r
+                       else:\r
+                               s2 += "%d %s\n" % (i, s.decode(CODE_, 'ignore'))\r
+               else:\r
+                       s2 += "[None]\n"\r
+       logwrite_(s2)\r
+\r
+def Mecab_getFeature(mf, pos, CODE_ = CODE):\r
+       s = string_at(mf.feature[pos])\r
+       return s.decode(CODE_, 'ignore')\r
+\r
+def Mecab_setFeature(mf, pos, s, CODE_ = CODE):\r
+       s = s.encode(CODE_, 'ignore')\r
+       buf = create_string_buffer(s)\r
+       dst_ptr = mf.feature[pos]\r
+       src_ptr = byref(buf)\r
+       memmove(dst_ptr, src_ptr, len(s)+1)\r
+\r
+def getMoraCount(s):\r
+       # 1/3 => 3\r
+       # */* => 0\r
+       m = s.split('/')\r
+       if len(m) == 2:\r
+               m2 = m[1]\r
+               if m2 != '*':\r
+                       return int(m2)\r
+       return 0\r
+\r
+# PATTERN 1\r
+# before:\r
+# 1 五絡脈病証,名詞,数,*,*,*,*,*\r
+#\r
+# after:\r
+# 1 五絡脈病証,名詞,普通名詞,*,*,*,*,五絡脈病証,ゴミャクラクビョウショウ,\r
+# ゴミャクラクビョーショー,1/9,C0\r
+# \r
+# PATTERN 2\r
+# before:\r
+# 0 ∫⣿♪ ,名詞,サ変接続,*,*,*,*,*\r
+#\r
+# after:\r
+# 0 ∫⣿♪ ,名詞,サ変接続,*,*,*,*,∫♪ ,セキブンキゴーイチニーサンヨンゴーロクナナ\r
+# ハチノテンオンプ,セキブンキゴーイチニーサンヨンゴーロクナナハチノテンオンプ,1/29,C0\r
+# \r
+# PATTERN 3\r
+# before:\r
+# 0 ま,接頭詞,名詞接続,*,*,*,*,ま,マ,マ,1/1,P2\r
+# 1 ー,名詞,一般,*,*,*,*,*\r
+#\r
+# after:\r
+# 0 ま,接頭詞,名詞接続,*,*,*,*,まー,マー,マー,1/2,P2\r
+# 1 ー,名詞,一般,*,*,*,*,*\r
+def Mecab_correctFeatures(mf, CODE_ = CODE):\r
+       for pos in xrange(0, mf.size):\r
+               ar = Mecab_getFeature(mf, pos, CODE_=CODE_).split(',')\r
+               need_fix = False\r
+               if ar[2] == u'数' and ar[7] == u'*': \r
+                       need_fix = True\r
+               if ar[1] == u'名詞' and ar[2] == u'サ変接続' and ar[7] == u'*': \r
+                       need_fix = True\r
+               if need_fix:\r
+                       hyoki = ar[0]\r
+                       yomi = ''\r
+                       pron = ''\r
+                       mora = 0\r
+                       nbmf = NonblockingMecabFeatures()\r
+                       for c in hyoki:\r
+                               Mecab_analysis(Mecab_text2mecab(c, CODE_=CODE_), nbmf)\r
+                               for pos2 in xrange(0, nbmf.size):\r
+                                       ar2 = Mecab_getFeature(nbmf, pos2, CODE_=CODE_).split(',')\r
+                                       if len(ar2) > 10:\r
+                                               yomi += ar2[8]\r
+                                               pron += ar2[9]\r
+                                               mora += getMoraCount(ar2[10])\r
+                       nbmf = None\r
+                       feature = u'{h},名詞,普通名詞,*,*,*,*,{h},{y},{p},1/{m},C0'.format(h=hyoki, y=yomi, p=pron, m=mora)\r
+                       Mecab_setFeature(mf, pos, feature, CODE_=CODE_)\r
+               elif pos > 0 and ar[0] == u'ー' and ar[1] == u'名詞' and ar[2] == u'一般':\r
+                       ar2 = Mecab_getFeature(mf, pos-1, CODE_=CODE_).split(',')\r
+                       if len(ar2) > 10:\r
+                               hyoki = ar2[0] + u'ー'\r
+                               hin1 = ar2[1]\r
+                               hin2 = ar2[2]\r
+                               yomi = ar2[8] + u'ー'\r
+                               pron = ar2[9] + u'ー'\r
+                               mora = getMoraCount(ar2[10]) + 1\r
+                               feature = u'{h},{h1},{h2},*,*,*,*,{h},{y},{p},1/{m},C0'.format(h=hyoki, h1=hin1, h2=hin2, y=yomi, p=pron, m=mora)\r
+                               Mecab_setFeature(mf, pos-1, feature, CODE_=CODE_)\r
+                       elif pos >= 2:\r
+                               ar3 = Mecab_getFeature(mf, pos-2, CODE_=CODE_).split(',')\r
+                               if len(ar3) > 10 and ar3[1] != u'記号':\r
+                                       hyoki = ar3[0] + ar2[0] + u'ー'\r
+                                       hin1 = ar3[1]\r
+                                       hin2 = ar3[2]\r
+                                       yomi = ar3[8] + ar2[0] + u'ー'\r
+                                       pron = ar3[9] + ar2[0] + u'ー'\r
+                                       mora = getMoraCount(ar3[10]) + len(ar2[0]) + 1\r
+                                       feature = u'{h},{h1},{h2},*,*,*,*,{h},{y},{p},1/{m},C0'.format(h=hyoki, h1=hin1, h2=hin2, y=yomi, p=pron, m=mora)\r
+                                       Mecab_setFeature(mf, pos-2, feature, CODE_=CODE_)\r
+\r
+def Mecab_utf8_to_cp932(mf):\r
+       for pos in xrange(0, mf.size):\r
+               s = Mecab_getFeature(mf, pos, CODE_ = 'utf-8')\r
+               Mecab_setFeature(mf, pos, s, CODE_ = 'cp932')\r
diff --git a/source/synthDrivers/jtalk/translator1.py b/source/synthDrivers/jtalk/translator1.py
new file mode 100644 (file)
index 0000000..0326c4c
--- /dev/null
@@ -0,0 +1,524 @@
+# coding: UTF-8\r
+#translator1.py (Japanese Braille translator Phase 1)\r
+#A part of NonVisual Desktop Access (NVDA)\r
+#Copyright (C) 2012 Masataka.Shinke, Takuya Nishimoto\r
+#Copyright (C) 2013 Takuya Nishimoto (NVDA Japanese Team)\r
+#This file is covered by the GNU General Public License.\r
+#See the file COPYING for more details.\r
+\r
+from __future__ import unicode_literals\r
+import unicodedata\r
+import re\r
+\r
+kana1_dic = {\r
+       'ア':'⠁',\r
+       'イ':'⠃',\r
+       'ウ':'⠉',\r
+       'エ':'⠋',\r
+       'オ':'⠊',\r
+       'カ':'⠡',\r
+       'キ':'⠣',\r
+       'ク':'⠩',\r
+       'ケ':'⠫',\r
+       'コ':'⠪',\r
+       'サ':'⠱',\r
+       'シ':'⠳',\r
+       'ス':'⠹',\r
+       'セ':'⠻',\r
+       'ソ':'⠺',\r
+       'タ':'⠕',\r
+       'チ':'⠗',\r
+       'ツ':'⠝',\r
+       'テ':'⠟',\r
+       'ト':'⠞',\r
+       'ナ':'⠅',\r
+       'ニ':'⠇',\r
+       'ヌ':'⠍',\r
+       'ネ':'⠏',\r
+       'ノ':'⠎',\r
+       'ハ':'⠥',\r
+       'ヒ':'⠧',\r
+       'フ':'⠭',\r
+       'ヘ':'⠯',\r
+       'ホ':'⠮',\r
+       'マ':'⠵',\r
+       'ミ':'⠷',\r
+       'ム':'⠽',\r
+       'メ':'⠿',\r
+       'モ':'⠾',\r
+       'ヤ':'⠌',\r
+       'ユ':'⠬',\r
+       'ヨ':'⠜',\r
+       'ラ':'⠑',\r
+       'リ':'⠓',\r
+       'ル':'⠙',\r
+       'レ':'⠛',\r
+       'ロ':'⠚',\r
+       'ワ':'⠄',\r
+       'ヰ':'⠆',\r
+       'ヱ':'⠖',\r
+       'ヲ':'⠔',\r
+       'ン':'⠴',\r
+       'ッ':'⠂',\r
+       'ヴ':'⠐⠉',\r
+       'ガ':'⠐⠡',\r
+       'ギ':'⠐⠣',\r
+       'グ':'⠐⠩',\r
+       'ゲ':'⠐⠫',\r
+       'ゴ':'⠐⠪',\r
+       'ザ':'⠐⠱',\r
+       'ジ':'⠐⠳',\r
+       'ズ':'⠐⠹',\r
+       'ゼ':'⠐⠻',\r
+       'ゾ':'⠐⠺',\r
+       'ダ':'⠐⠕',\r
+       'ヂ':'⠐⠗',\r
+       'ヅ':'⠐⠝',\r
+       'デ':'⠐⠟',\r
+       'ド':'⠐⠞',\r
+       'バ':'⠐⠥',\r
+       'ビ':'⠐⠧',\r
+       'ブ':'⠐⠭',\r
+       'ベ':'⠐⠯',\r
+       'ボ':'⠐⠮',\r
+       'パ':'⠠⠥',\r
+       'ピ':'⠠⠧',\r
+       'プ':'⠠⠭',\r
+       'ペ':'⠠⠯',\r
+       'ポ':'⠠⠮',\r
+       }\r
+kana2_dic = {\r
+       'イェ':'⠈⠋',\r
+       'キャ':'⠈⠡',\r
+       'キュ':'⠈⠩',\r
+       'キェ':'⠈⠫',\r
+       'キョ':'⠈⠪',\r
+       'シャ':'⠈⠱',\r
+       'スィ':'⠈⠳',\r
+       'シュ':'⠈⠹',\r
+       'シェ':'⠈⠻',\r
+       'ショ':'⠈⠺',\r
+       'チャ':'⠈⠕',\r
+       'ティ':'⠈⠗',\r
+       'チュ':'⠈⠝',\r
+       'チェ':'⠈⠟',\r
+       'チョ':'⠈⠞',\r
+       'ニャ':'⠈⠅',\r
+       'ニュ':'⠈⠍',\r
+       'ニェ':'⠈⠏',\r
+       'ニョ':'⠈⠎',\r
+       'ヒャ':'⠈⠥',\r
+       'ヒュ':'⠈⠭',\r
+       'ヒェ':'⠈⠯',\r
+       'ヒョ':'⠈⠮',\r
+       'ミャ':'⠈⠵',\r
+       'ミュ':'⠈⠽',\r
+       'ミェ':'⠈⠿',\r
+       'ミョ':'⠈⠾',\r
+       'リャ':'⠈⠑',\r
+       'リュ':'⠈⠙',\r
+       'リェ':'⠈⠛',\r
+       'リョ':'⠈⠚',\r
+       'ギャ':'⠘⠡',\r
+       'ギュ':'⠘⠩',\r
+       'ギェ':'⠘⠫',\r
+       'ギョ':'⠘⠪',\r
+       'ジャ':'⠘⠱',\r
+       'ズィ':'⠘⠳',\r
+       'ジュ':'⠘⠹',\r
+       'ジェ':'⠘⠻',\r
+       'ジョ':'⠘⠺',\r
+       'ヂャ':'⠘⠕',\r
+       'ディ':'⠘⠗',\r
+       'ヂュ':'⠘⠝',\r
+       'ヂェ':'⠘⠟',\r
+       'ヂョ':'⠘⠞',\r
+       'ビャ':'⠘⠥',\r
+       'ビュ':'⠘⠭',\r
+       'ビェ':'⠘⠯',\r
+       'ビョ':'⠘⠮',\r
+       'テュ':'⠨⠝',\r
+       'ピャ':'⠨⠥',\r
+       'ピュ':'⠨⠭',\r
+       'ピョ':'⠨⠮',\r
+       'フュ':'⠨⠬',\r
+       'フョ':'⠨⠜',\r
+       'デュ':'⠸⠝',\r
+       'ヴュ':'⠸⠬',\r
+       'ヴョ':'⠸⠜',\r
+       'ウァ':'⠢⠁',\r
+       'ウィ':'⠢⠃',\r
+       'ウェ':'⠢⠋',\r
+       'ウォ':'⠢⠊',\r
+       'クァ':'⠢⠡',\r
+       'クィ':'⠢⠣',\r
+       'クェ':'⠢⠫',\r
+       'クォ':'⠢⠪',\r
+       'ツァ':'⠢⠕',\r
+       'ツィ':'⠢⠗',\r
+       'トゥ':'⠢⠝',\r
+       'ツェ':'⠢⠟',\r
+       'ツォ':'⠢⠞',\r
+       'ファ':'⠢⠥',\r
+       'フィ':'⠢⠧',\r
+       'フェ':'⠢⠯',\r
+       'フォ':'⠢⠮',\r
+       'グァ':'⠲⠡',\r
+       'グィ':'⠲⠣',\r
+       'グェ':'⠲⠫',\r
+       'グォ':'⠲⠪',\r
+       'ヅァ':'⠲⠕',\r
+       'ヅィ':'⠲⠗',\r
+       'ドゥ':'⠲⠝',\r
+       'ヅェ':'⠲⠟',\r
+       'ヅォ':'⠲⠞',\r
+       'ヴァ':'⠲⠥',\r
+       'ヴィ':'⠲⠧',\r
+       'ヴェ':'⠲⠯',\r
+       'ヴォ':'⠲⠮',\r
+       }\r
+jp_symbol_dic = {\r
+       '+':'⠢',\r
+       '-':'⠤',\r
+       ':':'⠐⠂',\r
+       '\\':'⠫', # yen mark\r
+       '?':'⠢ ', # one space\r
+       '@':'⠪',\r
+       '<':'⠔⠔',\r
+       '>':'⠢⠢',\r
+       '=':'⠒⠒',\r
+       '#':'⠰⠩',\r
+       '$':'⠹',\r
+       '%':'⠰⠏',\r
+       '&':'⠰⠯',\r
+       '*':'⠰⠡',\r
+       ';':'⠆',\r
+       '|':'⠳',\r
+       '"':'⠶',\r
+       # "'":'⠄',\r
+       #'/':'⠌',\r
+       '.':'⠲',\r
+       '!':'⠖ ', # one space\r
+       '^':'⠘',\r
+       '`':'⠐⠑',\r
+       '_':'⠐⠤',\r
+       '~':'⠐⠉',\r
+       'ー':'⠒',\r
+       '、':'⠰ ', # one space\r
+       '。':'⠲  ', # two spaces\r
+       '・':'⠐ ', # one space\r
+       '|':'⠶',\r
+       '_':'⠤',\r
+       '「':'⠤',\r
+       '」':'⠤',\r
+       '『':'⠰⠤',\r
+       '』':'⠤⠆',\r
+       '「':'⠤',\r
+       '」':'⠤',\r
+       '(':'⠶',\r
+       ')':'⠶',\r
+       '(':'⠶',\r
+       ')':'⠶',\r
+       '[':'⠐⠶',\r
+       ']':'⠶⠂',\r
+       '“':'⠐⠶',\r
+       '”':'⠶⠂',\r
+       '{':'⠐⠶',\r
+       '}':'⠶⠂',\r
+       '‘':'⠐⠶',\r
+       '’':'⠶⠂',\r
+       '〔':'⠐⠶',\r
+       '〕':'⠶⠂',\r
+       '〈':'⠐⠶',\r
+       '〉':'⠶⠂',\r
+       '《':'⠐⠶',\r
+       '》':'⠶⠂',\r
+       '【':'⠐⠶',\r
+       '】':'⠶⠂',\r
+       '〝':'⠐⠶',\r
+       '〟':'⠶⠂',\r
+       '☆':'⠰⠮⠂',\r
+       '★':'⠰⠮⠆',\r
+       '○':'⠠⠵⠂',\r
+       '●':'⠠⠵⠆',\r
+       '◎':'⠠⠵⠲',\r
+       '□':'⠠⠳⠂',\r
+       '■':'⠠⠳⠆',\r
+       '△':'⠠⠱⠂',\r
+       '▲':'⠠⠱⠆',\r
+       '▽':'⠰⠱⠂',\r
+       '×':'⠰⠡⠂',\r
+       '▼':'⠰⠱⠆',\r
+       '◇':'⠨⠧⠂',\r
+       '◆':'⠨⠧⠆',\r
+       '※':'⠔⠔ ', # 第1星印 35-35 (後ろを1マスあける)\r
+       '→':' ⠒⠒⠕ ', # 矢印 前後に1マスあける\r
+       '←':' ⠪⠒⠒ ', # 矢印 前後に1マスあける\r
+       }\r
+info_symbol_dic = {\r
+       ',':'⠂',\r
+       '?':'⠐⠦',\r
+       '+':'⠬',\r
+       "'":'⠄',\r
+       '.':'⠲',\r
+       '!':'⠖',\r
+       '(':'⠦',\r
+       ')':'⠴',\r
+       '{':'⠣',\r
+       '}':'⠜',\r
+       '[':'⠷',\r
+       ']':'⠾',\r
+       '%': '⠻',\r
+       '&':'⠯',\r
+       '#':'⠩',\r
+       '*':'⠡',\r
+       }\r
+num_dic = {\r
+       '0':'⠚',\r
+       '1':'⠁',\r
+       '2':'⠃',\r
+       '3':'⠉',\r
+       '4':'⠙',\r
+       '5':'⠑',\r
+       '6':'⠋',\r
+       '7':'⠛',\r
+       '8':'⠓',\r
+       '9':'⠊',\r
+       }\r
+num_symbol_dic = {\r
+       '.':'⠂',\r
+       ',':'⠄',\r
+       }\r
+alpha_dic = {\r
+       'a':'⠁',\r
+       'b':'⠃',\r
+       'c':'⠉',\r
+       'd':'⠙',\r
+       'e':'⠑',\r
+       'f':'⠋',\r
+       'g':'⠛',\r
+       'h':'⠓',\r
+       'i':'⠊',\r
+       'j':'⠚',\r
+       'k':'⠅',\r
+       'l':'⠇',\r
+       'm':'⠍',\r
+       'n':'⠝',\r
+       'o':'⠕',\r
+       'p':'⠏',\r
+       'q':'⠟',\r
+       'r':'⠗',\r
+       's':'⠎',\r
+       't':'⠞',\r
+       'u':'⠥',\r
+       'v':'⠧',\r
+       'w':'⠺',\r
+       'x':'⠭',\r
+       'y':'⠽',\r
+       'z':'⠵',\r
+       }\r
+alpha_cap_dic = {\r
+       'A':'⠁',\r
+       'B':'⠃',\r
+       'C':'⠉',\r
+       'D':'⠙',\r
+       'E':'⠑',\r
+       'F':'⠋',\r
+       'G':'⠛',\r
+       'H':'⠓',\r
+       'I':'⠊',\r
+       'J':'⠚',\r
+       'K':'⠅',\r
+       'L':'⠇',\r
+       'M':'⠍',\r
+       'N':'⠝',\r
+       'O':'⠕',\r
+       'P':'⠏',\r
+       'Q':'⠟',\r
+       'R':'⠗',\r
+       'S':'⠎',\r
+       'T':'⠞',\r
+       'U':'⠥',\r
+       'V':'⠧',\r
+       'W':'⠺',\r
+       'X':'⠭',\r
+       'Y':'⠽',\r
+       'Z':'⠵',\r
+       }\r
+\r
+def is_ara(c):\r
+       # 数字の後につなぎ符が必要\r
+       return c in 'アイウエオラリルレロ'\r
+\r
+def translateWithInPos(text):\r
+       retval = ''\r
+       pos = 0\r
+       latin = False # 外字符モード\r
+       num = False # 数符モード\r
+       capital = False # 二重大文字符モード\r
+       quote_mode = False # 外国語引用符モード\r
+       info_mode = False # 情報処理点字モード\r
+       text = unicodedata.normalize('NFKC', text)\r
+       inPos = []\r
+\r
+       while pos < len(text):\r
+               #space\r
+               if text[pos] == ' ':\r
+                       retval += ' '\r
+                       inPos.append(pos)\r
+                       capital = latin = num = False\r
+                       pos += 1\r
+               #Numeric\r
+               elif text[pos] in num_dic:\r
+                       latin = False\r
+                       if not num:\r
+                               retval += '⠼'\r
+                               inPos.append(pos)\r
+                               num = True\r
+                       while text[pos] in num_dic:\r
+                               retval += num_dic[text[pos]]\r
+                               inPos.extend([pos] * len(num_dic[text[pos]]))\r
+                               pos += 1\r
+                               if pos >= len(text):\r
+                                       break\r
+               # info symbol\r
+               elif info_mode and text[pos] in info_symbol_dic:\r
+                       retval += info_symbol_dic[text[pos]]\r
+                       inPos.extend([pos] * len(info_symbol_dic[text[pos]]))\r
+                       num = capital = False\r
+                       pos += 1\r
+               #Numeric symbols\r
+               elif num and text[pos] in num_symbol_dic and \\r
+                               pos+1 < len(text) and text[pos+1].isdigit():\r
+                       retval += num_symbol_dic[text[pos]]\r
+                       inPos.extend([pos] * len(num_symbol_dic[text[pos]]))\r
+                       pos += 1\r
+               # halfshape apostrophe symbol\r
+               elif text[pos] == "'":\r
+                       if pos+1 < len(text) and text[pos+1].isdigit():\r
+                               retval += '⠼⠄'\r
+                               inPos.extend([pos, pos])\r
+                               num = True\r
+                       pos += 1\r
+               # slash symbol\r
+               elif text[pos] == '/':\r
+                       retval += '⠌'\r
+                       inPos.append(pos)\r
+                       num = capital = False\r
+                       pos += 1\r
+               #Japanese symbols\r
+               elif text[pos] in jp_symbol_dic:\r
+                       retval += jp_symbol_dic[text[pos]]\r
+                       inPos.extend([pos] * len(jp_symbol_dic[text[pos]]))\r
+                       latin = num = False\r
+                       pos += 1\r
+               # lower/upper case alphabet\r
+               elif text[pos] in alpha_dic or text[pos] in alpha_cap_dic:\r
+                       if not latin and not quote_mode:\r
+                               retval += '⠰'\r
+                               inPos.append(pos)\r
+                       elif info_mode and pos >= 2 and \\r
+                                       text[pos-2].isdigit() and \\r
+                                       text[pos-1] == '.' and \\r
+                                       text[pos] in 'abcdefghij':\r
+                               # 情報処理で数字、ピリオドのあとにa~jが続くときは小文字フラグ\r
+                               retval += '⠰'\r
+                               inPos.append(pos)\r
+                       latin = True\r
+                       num = False\r
+                       # 大文字または小文字が続く範囲の終点を tpos に格納\r
+                       tpos = pos\r
+                       upper_count = lower_count = 0\r
+                       while tpos < len(text):\r
+                               if text[tpos] in alpha_cap_dic:\r
+                                       upper_count += 1\r
+                                       tpos += 1\r
+                               elif text[tpos] in alpha_dic:\r
+                                       lower_count += 1\r
+                                       tpos += 1\r
+                               else:\r
+                                       break\r
+                       # 大文字だけが2文字以上連続する場合は二重大文字符\r
+                       if upper_count > 1 and lower_count == 0:\r
+                               retval += '⠠⠠'\r
+                               inPos.extend([pos, pos])\r
+                               capital = True\r
+                       else:\r
+                               capital = False\r
+                       # アルファベットの続く部分を変換\r
+                       while pos < tpos:\r
+                               if not capital and text[pos] in alpha_cap_dic:\r
+                                       retval += '⠠'\r
+                                       inPos.append(pos)\r
+                               retval += alpha_dic[text[pos].lower()]\r
+                               inPos.append(pos)\r
+                               pos += 1\r
+               #Two kana characters\r
+               elif pos+1 < len(text) and text[pos:pos+2] in kana2_dic:\r
+                       if latin:\r
+                               retval += '⠤'\r
+                               inPos.append(pos - 1) # つなぎ符は直前の文字に対応\r
+                       elif num and is_ara(text[pos:pos+1]):\r
+                               retval += '⠤'\r
+                               inPos.append(pos - 1) # つなぎ符は直前の文字に対応\r
+                       retval += kana2_dic[text[pos:pos+2]]\r
+                       inPos.extend([pos] * len(kana2_dic[text[pos:pos+2]]))\r
+                       latin = num = False\r
+                       pos += 2\r
+               #One kana character\r
+               elif text[pos] in kana1_dic:\r
+                       if latin:\r
+                               retval += '⠤'\r
+                               inPos.append(pos - 1) # つなぎ符は直前の文字に対応\r
+                       elif num:\r
+                               if is_ara(text[pos]):\r
+                                       retval += '⠤'\r
+                                       inPos.append(pos - 1) # つなぎ符は直前の文字に対応\r
+                               elif text[pos] == 'ワ' and pos+3 < len(text) and \\r
+                                               is_ara(text[pos+1]) and is_ara(text[pos+2]) and is_ara(text[pos+3]):\r
+                                       retval += '⠤'\r
+                                       inPos.append(pos - 1) # つなぎ符は直前の文字に対応\r
+                       retval += kana1_dic[text[pos]]\r
+                       inPos.extend([pos] * len(kana1_dic[text[pos]]))\r
+                       latin = num = False\r
+                       pos += 1\r
+               #Braille should not be changed\r
+               elif 0x2800 <= ord(text[pos]) and ord(text[pos]) <= 0x28ff:\r
+                       latin = False\r
+                       #数字モード\r
+                       if text[pos] == '⠼':\r
+                               num = True\r
+                       else:\r
+                               num = False\r
+                       #外国語引用符モード切替\r
+                       if not quote_mode and text[pos] == '⠦':\r
+                               quote_mode = True\r
+                       if quote_mode and text[pos] == '⠴':\r
+                               quote_mode = False\r
+                       #情報処理モード切替\r
+                       if text[pos] == '⠠' and pos+1 < len(text):\r
+                               if text[pos+1] == '⠦':\r
+                                       info_mode = True\r
+                               elif text[pos+1] == '⠴':\r
+                                       info_mode = False\r
+\r
+                       if ord(text[pos]) == 0x2800:\r
+                               retval += ' ' # use 0x20\r
+                               inPos.append(pos)\r
+                       else:\r
+                               retval += text[pos]\r
+                               inPos.append(pos)\r
+                       pos += 1\r
+               #Exception\r
+               else:\r
+                       latin = num = False\r
+                       retval += '□'\r
+                       inPos.append(pos)\r
+                       pos += 1\r
+       # rstrip with inPos\r
+       outbuf = retval\r
+       if text[-1] != ' ':\r
+               while outbuf[-1:] == ' ':\r
+                       outbuf = outbuf[:-1]\r
+                       inPos.pop()\r
+       return (outbuf, inPos)\r
diff --git a/source/synthDrivers/jtalk/translator2.py b/source/synthDrivers/jtalk/translator2.py
new file mode 100644 (file)
index 0000000..a766db8
--- /dev/null
@@ -0,0 +1,987 @@
+# coding: UTF-8\r
+#translator2.py (Japanese Braille translator Phase 2)\r
+#A part of NonVisual Desktop Access (NVDA)\r
+#Copyright (C) 2012-2013 Takuya Nishimoto (NVDA Japanese Team)\r
+#This file is covered by the GNU General Public License.\r
+#See the file COPYING for more details.\r
+\r
+from __future__ import unicode_literals\r
+import os\r
+import copy\r
+from _nvdajp_unicode import unicode_normalize\r
+from mecab import *\r
+import translator1\r
+\r
+_logwrite = None\r
+\r
+try:\r
+       from logHandler import log\r
+       _logwrite = log.debug\r
+except:\r
+       def __print(s): print s\r
+       _logwrite = __print\r
+\r
+CONNECTED_MORPHS = {\r
+       'について': [\r
+               ['に', 'ニ', '0/1', None, None, '*'],\r
+               ['ついて', 'ツイテ', '1/3', '動詞', '*', '*'],\r
+               ],\r
+       'により': [\r
+               ['に', 'ニ', '0/1', None, None, '*'],\r
+               ['より', 'ヨリ', '0/2', '動詞', '*', '*'],\r
+               ],\r
+       'による': [\r
+               ['に', 'ニ', '0/1', None, None, '*'],\r
+               ['よる', 'ヨル', '0/2', '動詞', '*', '*'],\r
+               ],\r
+       'において': [\r
+               ['に', 'ニ', '0/1', None, None, '*'],\r
+               ['おいて', 'オイテ', '0/3', '動詞', '*', '*'],\r
+               ],\r
+       'における': [\r
+               ['に', 'ニ', '0/1', None, None, '*'],\r
+               ['おける', 'オケル', '0/3', '動詞', '*', '*'],\r
+               ],\r
+       'によって': [\r
+               ['に', 'ニ', '0/1', None, None, '*'],\r
+               ['よって', 'ヨッテ', '0/3', '動詞', '*', '*'],\r
+               ],\r
+       'にとって': [\r
+               ['に', 'ニ', '0/1', None, None, '*'],\r
+               ['とって', 'トッテ', '0/3', '動詞', '*', '*'],\r
+               ],\r
+       'に対して': [\r
+               ['に', 'ニ', '0/1', None, None, '*'],\r
+               ['対して', 'タイシテ', '1/4', '動詞', '*', '*'],\r
+               ],\r
+       'に関して': [\r
+               ['に', 'ニ', '0/1', None, None, '*'],\r
+               ['関して', 'カンシテ', '1/4', '動詞', '*', '*'],\r
+               ],\r
+       'につき': [\r
+               ['に', 'ニ', '0/1', None, None, '*'],\r
+               ['つき', 'ツキ', '1/2', '動詞', '*', '*'],\r
+               ],\r
+       'という': [\r
+               ['と', 'ト', '0/1', None, None, '*'],\r
+               ['いう', 'イウ', '0/2', '動詞', '*', '*'],\r
+               ],\r
+       'どうして': [\r
+               ['どう', 'ドー', '0/2', None, None, '*'],\r
+               ['して', 'シテ', '0/2', '動詞', '*', '*'],\r
+               ],\r
+       'として': [\r
+               ['と', 'ト', '1/1', None, None, '*'],\r
+               ['して', 'シテ', '0/2', '動詞', '*', '*'],\r
+               ],\r
+       'なくなる': [\r
+               ['なく', 'ナク', '2/2', None, None, None],\r
+               ['なる', 'ナル', '1/2', '動詞', '自立', None],\r
+               ],\r
+}\r
+\r
+class MecabMorph(object):\r
+       __slots__ = ('hyouki', 'nhyouki', 'hinshi1', 'hinshi2', 'hinshi3', 'hinshi4', \r
+                                'type1', 'type2', 'kihon',\r
+                                'kana', 'yomi', 'accent', 'output', 'sepflag')\r
+\r
+       def __init__(self):\r
+               self.hyouki = '' # 表記\r
+               self.nhyouki = '' # Unicode 正規化された表記\r
+               self.hinshi1 = ''\r
+               self.hinshi2 = ''\r
+               self.hinshi3 = ''\r
+               self.hinshi4 = ''\r
+               self.type1 = ''\r
+               self.type2 = ''\r
+               self.kihon = ''\r
+               self.kana = ''\r
+               self.yomi = ''\r
+               self.accent = ''\r
+               self.output = ''\r
+               self.sepflag = False # この後でマスアケをするか?\r
+               \r
+       # 付属語\r
+       def is_substantive_word(self):\r
+               if self.hinshi1 == '記号': return False\r
+               if self.hinshi2 == '接頭': return True\r
+               if self.hinshi2 == '接尾': return True\r
+               if self.hinshi1 == '助動詞' and self.hyouki == 'ない': return False\r
+               if self.hinshi1 == '名詞' and self.hyouki == 'の': return True\r
+               if self.hinshi1 == '形容詞' and self.hyouki == 'なく': return True\r
+               if self.hinshi1 in ('助動詞', '助詞'): return True\r
+               return False\r
+\r
+       # 自立語\r
+       def is_independent_word(self):\r
+               if self.hinshi1 == '記号': return False\r
+               return not self.is_substantive_word()\r
+\r
+       def write(self, logwrite):\r
+               logwrite("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%d" % \r
+                                (self.hyouki, self.nhyouki, \r
+                                 self.hinshi1, self.hinshi2, self.hinshi3, self.hinshi4,\r
+                                 self.type1, self.type2, self.kihon,\r
+                                 self.kana, self.yomi, self.accent, self.output, self.sepflag))\r
+\r
+def update_phonetic_symbols(mo):\r
+       for p in range(0, len(mo.yomi)):\r
+               # 点訳のてびき第3版 第2章 その1 1 5\r
+               # 5、長音の書き表し方 (1), (2)\r
+               # before: ああ,ああ,感動詞,*,*,*,アア,アー,1/2,アー,0\r
+               # after:  ああ,ああ,感動詞,*,*,*,アア,アー,1/2,アア,0\r
+               if mo.yomi[p] == 'ー' and mo.kana[p] in 'アイエ':\r
+                       mo.output = mo.output[:p] + mo.kana[p] + mo.output[p+1:]\r
+\r
+               # 点訳のてびき第3版 第2章 その1 1 6\r
+               # 6、「ジ ズ ジャ ジュ ジョ」と「ヂ ヅ ヂャ ヂョ」の使い分け\r
+               # before: 綴る,綴る,動詞,自立,*,*,ツヅル,ツズル,0/3,ツズル,0\r
+               # after:  綴る,綴る,動詞,自立,*,*,ツヅル,ツズル,0/3,ツヅル,0\r
+               if (mo.yomi[p] == 'ジ' and mo.kana[p] == 'ヂ') or (\r
+                       mo.yomi[p] == 'ズ' and mo.kana[p] == 'ヅ'):\r
+                       mo.output = mo.output[:p] + mo.kana[p] + mo.output[p+1:]\r
+\r
+def mecab_to_morphs(mf):\r
+       li = []\r
+       if mf is None or mf.feature is None or mf.size is None: \r
+               return li\r
+       for i in xrange(0, mf.size):\r
+               s = string_at(mf.feature[i])\r
+               if s:\r
+                       s = s.decode(CODE, 'ignore')\r
+                       ar = s.split(",")\r
+                       mo = MecabMorph()\r
+                       mo.hyouki = ar[0]\r
+                       mo.nhyouki = unicode_normalize(ar[0])\r
+                       mo.hinshi1 = ar[1]\r
+                       mo.hinshi2 = ar[2]\r
+                       if len(ar) > 3:\r
+                               mo.hinshi3 = ar[3]\r
+                               mo.hinshi4 = ar[4]\r
+                       if len(ar) > 5:\r
+                               mo.type1 = ar[5]\r
+                       if len(ar) > 6:\r
+                               mo.type2 = ar[6]\r
+                       if len(ar) > 7:\r
+                               mo.kihon = ar[7]\r
+                       if len(ar) > 9:\r
+                               mo.kana = ar[8]\r
+                               mo.yomi = ar[9]\r
+                               mo.accent = ar[10]\r
+                               if len(ar) > 12:\r
+                                       # Mecab辞書の拡張フィールドの点訳表記があれば使用する\r
+                                       mo.output = ar[12]\r
+                               else:\r
+                                       mo.output = ar[9]\r
+                                       update_phonetic_symbols(mo)\r
+                       mo.sepflag = False\r
+                       li.append(mo)\r
+       return li\r
+\r
+def replace_morphs(li, dic):\r
+       new_li = []\r
+       for mo in li:\r
+               if mo.hyouki in dic.keys():\r
+                       new_morphs = dic[mo.hyouki]\r
+                       for i in new_morphs:\r
+                               m = copy.deepcopy(mo)\r
+                               m.hyouki = m.nhyouki = i[0] # に\r
+                               if i[3]: m.hinshi1 = i[3]\r
+                               if i[4]: m.hinshi2 = i[4]\r
+                               if i[5]: m.hinshi3 = i[5]\r
+                               m.output = m.kana = m.yomi = i[1] # ニ\r
+                               m.accent = i[2] # 0/1\r
+                               new_li.append(m)\r
+               else:\r
+                       new_li.append(mo)\r
+       return new_li\r
+\r
+RE_KANSUJI = re.compile('^[一二三四五六七八九〇零十拾百千壱二参]+$')\r
+\r
+# http://programminblog.blogspot.jp/2010/11/python.html\r
+def kansuji2arabic(text):\r
+       if not RE_KANSUJI.match(text):\r
+               return None\r
+       result = 0\r
+       digit = 1\r
+       numgroup = 1\r
+       kanindex = len(text)\r
+       while kanindex > 0:\r
+               c = text[(kanindex - 1):kanindex]\r
+               c1 = text[kanindex:(kanindex + 1)]\r
+               kanindex -= 1\r
+               if c in '〇零':\r
+                       digit *= 10\r
+               elif c in '十拾':\r
+                       digit = 10\r
+               elif c == '百':\r
+                       if digit == 10 and c1 and c1 in '十拾':\r
+                               result += digit * numgroup\r
+                       digit = 100\r
+               elif c == '千':\r
+                       if (digit == 10 and c1 and c1 in '十拾') or \\r
+                                       (digit == 100 and c1 and c1 in '百'):\r
+                               result += digit * numgroup\r
+                       digit = 1000\r
+               else:\r
+                       if c in '壱一':\r
+                               result += digit * numgroup\r
+                       elif c in '二弐':\r
+                               result += 2 * digit * numgroup\r
+                       elif c in '三参':\r
+                               result += 3 * digit * numgroup\r
+                       elif c in '四':\r
+                               result += 4 * digit * numgroup\r
+                       elif c in '五':\r
+                               result += 5 * digit * numgroup\r
+                       elif c in '六':\r
+                               result += 6 * digit * numgroup\r
+                       elif c in '七':\r
+                               result += 7 * digit * numgroup\r
+                       elif c in '八':\r
+                               result += 8 * digit * numgroup\r
+                       elif c in '九':\r
+                               result += 9 * digit * numgroup\r
+                       digit *= 10\r
+       if (digit == 10 and text[:1] in '十拾') or \\r
+                       (digit == 100 and text[:1] in '百') or \\r
+                       (digit == 1000 and text[:1] in '千'):\r
+               result += digit * numgroup\r
+       text = '%d' % result\r
+       return text\r
+\r
+def rewrite_number(li):\r
+       new_li = []\r
+       for mo in li:\r
+               m = copy.deepcopy(mo)\r
+               if m.hinshi2 != '固有名詞':\r
+                       ret = kansuji2arabic(m.hyouki)\r
+                       if ret:\r
+                               m.output = ret\r
+               new_li.append(m)\r
+       return new_li\r
+\r
+def concatinate_morphs(li):\r
+       mo = copy.deepcopy(li[0])\r
+       s = ''\r
+       y = ''\r
+       for i in li:\r
+               s += i.hyouki\r
+               y += i.yomi\r
+       mo.hyouki = mo.nhyouki = s\r
+       mo.yomi = mo.kana = mo.output = y\r
+       return mo\r
+\r
+def replace_digit_morphs(li):\r
+       # handle digit number kanji characters\r
+       # input:\r
+       #  十,名詞,数\r
+       #  七,名詞,数\r
+       # output:\r
+       #  十七,名詞,数\r
+       # input:\r
+       #  二,名詞,数\r
+       #  十,名詞,数\r
+       #  五,名詞,数\r
+       # output:\r
+       #  二十五,名詞,数\r
+       # input:\r
+       #  三,名詞,数,*,*,*,*,三,サン,サン,0/2,C3\r
+       #  兆,名詞,数,*,*,*,*,兆,チョウ,チョー,1/2,C3\r
+       #  二,名詞,数,*,*,*,*,二,ニ,ニ,1/1,C3\r
+       #  千,名詞,数,*,*,*,*,千,セン,セン,1/2,C3\r
+       #  四,名詞,数,*,*,*,*,四,ヨン,ヨン,1/2,C1\r
+       #  百,名詞,数,*,*,*,*,百,ヒャク,ヒャク,2/2,C3\r
+       #  万,名詞,数,*,*,*,*,万,マン,マン,1/2,C3\r
+       # output:\r
+       #  三,三,名詞,数,*,*,サン,サン,,サン,0\r
+       #  兆,兆,名詞,数,*,*,チョー,チョー,,チョー,0\r
+       #  二千四百,二千四百,名詞,数,*,*,ニセンヨンヒャク,ニセンヨンヒャク,,ニセンヨンヒャク,0\r
+       #  万,万,名詞,数,*,*,マン,マン,,マン,0\r
+       # (correct: 3チョー 2400マン)\r
+       new_li = []\r
+       num_morphs = []\r
+       for mo in li:\r
+               if mo.hinshi2 == '数' and mo.hyouki == ',':\r
+                       # カンマ\r
+                       m = copy.deepcopy(mo)\r
+                       m.yomi = m.output = ','\r
+                       num_morphs.append(m)\r
+               elif mo.hinshi2 == '数' and not mo.output.isdigit() and \\r
+                               not mo.hyouki in ('・', '万', '億', '兆', '京', '.'):\r
+                       # 漢数字の結合\r
+                       num_morphs.append(mo)\r
+               elif mo.hinshi2 == '数' and mo.hyouki in '0123456789':\r
+                       # 算用数字の結合\r
+                       m = copy.deepcopy(mo)\r
+                       y = unicode_normalize(m.hyouki)\r
+                       m.output = m.hyouki = m.nhyouki = m.yomi = y\r
+                       num_morphs.append(m)\r
+               else:\r
+                       if num_morphs:\r
+                               new_li.append(concatinate_morphs(num_morphs))\r
+                               num_morphs = []\r
+                       new_li.append(mo)\r
+       if num_morphs:\r
+               new_li.append(concatinate_morphs(num_morphs))\r
+       return new_li\r
+\r
+RE_ALPHA = re.compile('^[A-Za-z]+$')\r
+\r
+def is_alpha(s):\r
+       return RE_ALPHA.match(s)\r
+\r
+RE_ASCII_SYMBOLS = re.compile('^[\,\.\:\;\!\?\@\#\\\$\%\&\*\|\+\-\/\=\<\>\"\'\^\`\_\~]+$')\r
+\r
+def replace_alphabet_morphs(li):\r
+       # アルファベットまたは記号だけで表記されている語を結合する\r
+       # 情報処理点字の部分文字列になる記号を前後にまとめる\r
+       # input:\r
+       #  B,B,記号,アルファベット,*,*,ビー,ビー,1/2,B\r
+       #  asi,asi,名詞,一般,*,*,アシー,アシー,0/3,asi\r
+       #  c,c,記号,アルファベット,*,*,シー,シー,1/2,c\r
+       # output:\r
+       #  Basic,Basic,名詞,アルファベット,*,*,ビーアシーシー,ビーアシーシー,1/2,Basic\r
+       new_li = []\r
+       alp_morphs = []\r
+       for pos in range(len(li)):\r
+               mo = li[pos]\r
+               if pos < len(li) - 1:\r
+                       next_mo = li[pos + 1]\r
+               else:\r
+                       next_mo = None\r
+               if is_alpha(mo.nhyouki):\r
+                       alp_morphs.append(mo)\r
+               elif mo.nhyouki in r',+@/#$%&*;<':\r
+                       alp_morphs.append(mo)\r
+               elif mo.nhyouki == '\\':\r
+                       alp_morphs.append(mo)\r
+               elif mo.nhyouki[0] in r',+@/#$%&*;' and \\r
+                               RE_ASCII_SYMBOLS.match(mo.nhyouki):\r
+                       alp_morphs.append(mo)\r
+               elif alp_morphs and mo.nhyouki in ',.' and \\r
+                               ((next_mo and next_mo.nhyouki == ' ') or \\r
+                                        (next_mo and next_mo.hinshi1 in ('助詞', '助動詞')) or \\r
+                                        (not next_mo)):\r
+                       alp_morphs.append(mo)\r
+               elif alp_morphs and mo.nhyouki == ' ' and \\r
+                               next_mo and is_alpha(next_mo.nhyouki):\r
+                       alp_morphs.append(mo)\r
+               elif alp_morphs and mo.nhyouki.isdigit():\r
+                       alp_morphs.append(mo)\r
+               elif alp_morphs and mo.nhyouki in ',.:;!?@#\\$%&*|+-/=<>"\'^`_~{}[]':\r
+                       alp_morphs.append(mo)\r
+               else:\r
+                       if alp_morphs:\r
+                               m = concatinate_morphs(alp_morphs)\r
+                               m.hinshi1 = '名詞'\r
+                               m.hinshi2 = 'アルファベット'\r
+                               m.nhyouki = m.output = unicode_normalize(m.nhyouki)\r
+                               new_li.append(m)\r
+                               alp_morphs = []\r
+                       new_li.append(mo)\r
+       if alp_morphs:\r
+               m = concatinate_morphs(alp_morphs)\r
+               m.hinshi1 = '名詞'\r
+               m.hinshi2 = 'アルファベット'\r
+               m.nhyouki = m.output = unicode_normalize(m.nhyouki)\r
+               new_li.append(m)\r
+       return new_li\r
+\r
+# 日付の和語読み処理\r
+# すでに output 属性に半角数字が格納されている前提\r
+\r
+# 後続する '日' と形態素を結合する\r
+WAGO_DIC = {\r
+       '1': 'ツイタチ', \r
+       '2': 'フツカ',\r
+       '3': 'ミッカ',\r
+       '4': 'ヨッカ',\r
+       '5': 'イツカ',\r
+       '6': 'ムイカ',\r
+       '7': 'ナノカ',\r
+       '8': 'ヨーカ',\r
+       '9': 'ココノカ',\r
+       '10': 'トオカ',\r
+       '20': 'ハツカ',\r
+}\r
+\r
+def fix_japanese_date_morphs(li):\r
+       new_li = []\r
+       for i in xrange(0, len(li)):\r
+               prev_mo = li[i-1] if i-1>=0 else None\r
+               mo = li[i]\r
+               if mo.hyouki == '日' and mo.hinshi3 == '助数詞' and prev_mo is not None:\r
+                       if prev_mo.hyouki in ('14', '24', '十四', '一四', '二四', '二十四'):\r
+                               li[i].output = 'カ'\r
+                               new_li.append(li[i])\r
+                       elif prev_mo.output in WAGO_DIC:\r
+                               m = copy.deepcopy(mo)\r
+                               m.output = WAGO_DIC[prev_mo.output]\r
+                               m.hyouki = m.nhyouki = m.kana = m.yomi = m.output\r
+                               m.hinshi2 = '日付'\r
+                               m.hinshi3 = '*'\r
+                               # FIXME: m.accent\r
+                               new_li.pop()\r
+                               new_li.append(m)\r
+                       else:\r
+                               new_li.append(li[i])\r
+               else:\r
+                       new_li.append(li[i])\r
+       return new_li\r
+\r
+def should_separate(prev2_mo, prev_mo, mo, next_mo):\r
+       if mo.hyouki == 'ー': return False\r
+       if prev_mo.hyouki == 'ー': return False\r
+       if mo.hyouki in 'ぁぃぅぇぉっゃゅょゎァィゥェォッャュョヮヵヶ': return False\r
+\r
+       # )( -> あける\r
+       # )陽が -> あける\r
+       # '02 -> あけない\r
+       if prev_mo.hinshi2 == '括弧閉' and prev_mo.nhyouki != "’":\r
+               if mo.hinshi2 == '括弧開': return True\r
+               if mo.hinshi1 == '名詞': return True\r
+\r
+       # 東京/都 千代田/区\r
+       if prev_mo.hinshi2 == '接尾' and prev_mo.hinshi3 == '地域' and \\r
+                       mo.hinshi2 == '固有名詞' and mo.hinshi3 == '地域':\r
+               return True\r
+       # 東京/都 交通/局\r
+       if prev_mo.hinshi2 == '接尾' and prev_mo.hinshi3 == '地域' and \\r
+                       mo.hinshi1 == '名詞' and mo.hinshi2 == '一般':\r
+               return True\r
+       # 永田町 1\r
+       if prev_mo.hinshi2 == '固有名詞' and prev_mo.hinshi3 == '地域' and \\r
+                       mo.hinshi2 == '数':\r
+               return True\r
+\r
+       # 晴れ/所に より\r
+       if prev_mo.hinshi1 == '名詞' and mo.hyouki == '所により':\r
+               return True\r
+\r
+       # 一時/雨\r
+       if prev_mo.hyouki == '一時' and mo.hyouki == '雨':\r
+               return True\r
+\r
+       # 数字の前のマスアケ\r
+       if prev_mo.nhyouki in ('零下', '西暦', 'ボーイング', 'ベスト', 'ルイ', '先', '振替', 'No.', '一人当り') \\r
+                       and mo.output.isdigit():\r
+               return True\r
+\r
+       # 1月/1日\r
+       if prev_mo.nhyouki[0].isdigit() and prev_mo.nhyouki[-1] == '月' and mo.output.isdigit():\r
+               return True\r
+       # 0/4月 -> 04月\r
+       if prev_mo.output.isdigit() and mo.nhyouki[0].isdigit():\r
+               return False\r
+\r
+       # アラビア数字のあとに単位がきたら続ける\r
+       # 三十,三十,名詞,数,*,*,30,30,1/4,30,1\r
+       # センチメートル,センチメートル,名詞,一般,*,*,センチメートル,センチメートル,4/7,センチメートル,0\r
+       if prev_mo.output.isdigit():\r
+               if mo.hinshi3 == '助数詞': return False\r
+               if mo.hyouki == 'センチメートル': return False\r
+               if mo.nhyouki == '#': return False\r
+\r
+       # 数%\r
+       if prev_mo.hyouki == '数' and prev_mo.yomi == 'スー' and mo.hyouki == '%':\r
+               return False\r
+\r
+       # 三,三,名詞,数,*,*,サン,サン,0/2,3,0\r
+       # 兆,兆,名詞,数,*,*,チョウ,チョー,1/2,チョー,1\r
+       # 二千四百,二千四百,名詞,数,*,*,ニセンヨンヒャク,ニセンヨンヒャク,1/1,2400,0\r
+       # 万,万,名詞,数,*,*,マン,マン,1/2,マン,0\r
+       if prev_mo.hyouki in ('億', '兆', '京') and mo.output.isdigit():\r
+               return True\r
+\r
+       # ち,ち,名詞,一般,*,*,チ,チ,0/1,チ,0\r
+       # ゅうりっぷ,ゅうりっぷ,名詞,一般,*,*,,,,ュウリップ,0\r
+       if mo.hyouki[0] in 'ぁぃぅぇぉっゃゅょゎァィゥェォッャュョヮヵヶ': return False\r
+\r
+       # 外国語引用符、マスアケ、助詞、助動詞\r
+       if prev_mo.output and prev_mo.output.endswith('⠴') and mo.hinshi1 in ('助詞', '助動詞'): return True\r
+\r
+       if prev_mo.hinshi1 == '名詞' and prev_mo.hinshi2 == '接尾':\r
+               # 助数詞のあとにアラビア数字が来たらマスアケ\r
+               # case 1:\r
+               #  零,零,名詞,数,*,*,0,0,1/2,0,0\r
+               #  時,時,名詞,接尾,助数詞,*,ジ,ジ,1/1,ジ,1\r
+               #  十五,十五,名詞,数,*,*,15,15,1/3,15,0\r
+               #  分,分,名詞,接尾,助数詞,*,フン,フン,1/2,フン,0\r
+               # case 2:\r
+               #  一,一,名詞,数,*,*,イチ,イチ,2/2,1,0\r
+               #  人,人,名詞,接尾,助数詞,*,ニン,ニン,1/2,ニン,0\r
+               #  当り,当り,名詞,接尾,一般,*,アタリ,アタリ,1/3,アタリ,1\r
+               #  1,1,名詞,数,*,*,イチ,イチ,2/2,1,0\r
+               #  0,0,名詞,数,*,*,ゼロ,ゼロ,1/2,0,0\r
+               #  個,個,名詞,接尾,助数詞,*,コ,コ,1/1,コ,0\r
+               if mo.output.isdigit(): return True\r
+               if mo.hinshi1 == '動詞' and mo.hinshi2 == '非自立': return False\r
+\r
+       # アルファベットの後の助詞、助動詞\r
+       # CD,CD,名詞,一般,*,*,シーディー,シーディー,3/4,シーディー,0\r
+       # を,を,助詞,格助詞,一般,*,ヲ,ヲ,0/1,ヲ,0\r
+       if is_alpha(prev_mo.nhyouki) and mo.hinshi1 in ('助詞', '助動詞'):\r
+               return True\r
+\r
+       # ピリオドの後の助詞\r
+       if prev_mo.nhyouki.endswith('.') and mo.hinshi1 == '助詞':\r
+               return True\r
+\r
+       # ナンバーマークの後の助詞\r
+       if prev_mo.nhyouki == '#' and mo.hinshi1 == '助詞':\r
+               return True\r
+\r
+       # カナ名詞の後のアルファベット名詞\r
+       if prev_mo.hinshi1 == '名詞' and is_alpha(mo.nhyouki):\r
+               return False\r
+\r
+       # (あける)\r
+       # 映画,映画,名詞,一般,*,*,エイガ,エイガ,0/3,エイガ,1\r
+       # 「,「,記号,括弧開,*,*,「,「,*/*,「,0\r
+       # (あけない)\r
+       # 機関,名詞,一般,*,*,*,*,機関,キカン,キカン,1/3,C1\r
+       # (,記号,括弧開,*,*,*,*,(,(,(,*/*,*\r
+       if prev_mo.hinshi1 == '名詞' and mo.hinshi2 == '括弧開' and mo.nhyouki != '(': return True\r
+\r
+       # 間違い,間違い,名詞,ナイ形容詞語幹,*,*,マチガイ,マチガイ,3/4,マチガイ,1\r
+       # なし,なし,助動詞,*,*,*,ナシ,ナシ,0/2,ナシ,0\r
+       #\r
+       # 味気,味気,名詞,ナイ形容詞語幹,*,*,アジケ,アジケ,0/3,アジケ,0\r
+       # ない,ない,助動詞,*,*,*,ナイ,ナイ,1/2,ナイ,0\r
+       #\r
+       # 良く,形容詞,自立,*,*,形容詞・アウオ段,連用テ接続,良い,ヨク,ヨク,1/2,C3\r
+       # ない,助動詞,*,*,*,特殊・ナイ,基本形,ない,ナイ,ナイ,1/2,動詞%F3@0/形容詞%F2@1\r
+       #\r
+       # で,で,助動詞,*,*,*,デ,デ,1/1,デ,0\r
+       # は,は,助詞,係助詞,*,*,ハ,ワ,0/1,ワ,1\r
+       # なく,なく,助動詞,*,*,*,ナク,ナク,0/2,ナク,1\r
+       #\r
+       # 「問題ない」の「ない」は「点訳のてびき」では形容詞だがMecabでは助動詞\r
+       if mo.hinshi1 == '形容詞' and mo.kihon in ('ない', '無い'):\r
+               # 形容詞「ない」は区切る\r
+               # ただし前の語と複合している場合は前に続ける\r
+               if prev_mo.kihon in ('隈', '心置き', '満遍'):\r
+                       return False\r
+               return True\r
+       if mo.hinshi1 == '助動詞' and mo.kihon in ('ない', '無い'):\r
+               if prev_mo.hinshi1 == '助詞' and prev_mo.kihon == 'は':\r
+                       return True\r
+               if prev_mo.hinshi1 == '形容詞' and prev_mo.kihon == '良い':\r
+                       return True\r
+               if prev_mo.hinshi1 == '名詞' and prev_mo.hinshi2 == 'ナイ形容詞語幹' and \\r
+                               prev_mo.kihon in ('問題', '間違い'):\r
+                       return True\r
+               if prev_mo.hinshi2 == '副助詞': # じゃない\r
+                       return True\r
+               if prev_mo.hinshi1 == '動詞' and prev_mo.hinshi2 == '非自立' and \\r
+                               prev_mo.kihon in ('てる'): # てない\r
+                       return True\r
+               if prev_mo.hinshi1 == '助動詞' and \\r
+                               prev_mo.kihon in ('だ'): # でない\r
+                       return True\r
+               return False\r
+\r
+       # お,黙り,なさい\r
+       # 「お」がついて名詞化した語に「なさい・なさる」が続く場合は区切ってよい\r
+       if prev2_mo and prev2_mo.hinshi1 == '接頭詞' and prev2_mo.hyouki == 'お' and \\r
+                       prev_mo.hinshi1 == '動詞' and prev_mo.type2 == '連用形' and \\r
+                       mo.kihon == 'なさる':\r
+               return True\r
+\r
+       # 労,せ,ず\r
+       if prev_mo.hinshi1 == '名詞' and mo.hyouki == 'せ' and mo.kihon == 'する':\r
+               return False\r
+\r
+       # 不幸,に,し,て\r
+       # 今,に,し,て\r
+       # 居,ながら,に,し,て\r
+       # 労,せ,ず,し,て\r
+       # 若く,し,て\r
+       # 私,を,し,て\r
+       # 「して」が文語的表現の助詞である場合は前に続けて書く\r
+       if mo.hyouki == 'し' and mo.kihon == 'する':\r
+               if prev_mo.hyouki == 'ず' and prev_mo.hinshi1 == '助動詞':\r
+                       return False\r
+               if prev_mo.hinshi1 == '形容詞' and prev_mo.type2 == '連用テ接続':\r
+                       return False\r
+               if prev_mo.hinshi2 == '接続助詞':\r
+                       return False\r
+               if prev_mo.type1 == '文語・ベシ':\r
+                       return False\r
+               if next_mo and next_mo.hyouki == 'て':\r
+                       if prev_mo.hyouki == 'に' and prev_mo.hinshi1 == '助詞':\r
+                               return False\r
+                       if prev2_mo and prev2_mo.hyouki == '私' and prev_mo.hyouki == 'を':\r
+                               return False\r
+\r
+       # 「・・ですこと」の「こと」は接尾語なので前に続ける\r
+       if prev_mo.hyouki == 'です' and mo.hyouki == 'こと':\r
+               return False\r
+\r
+       # 「この程」「この度」\r
+       # 「そのくせ」\r
+       # 後ろの語と結びついて1語になっている場合は続ける\r
+       if prev_mo.hyouki == 'この' and mo.hyouki in ('程', '度'):\r
+               return False\r
+       if prev_mo.hyouki == 'その' and mo.hyouki in ('くせ', 'うち', 'まま'):\r
+               return False\r
+       if prev_mo.hyouki == 'わが' and mo.hyouki == 'まま':\r
+               return False\r
+\r
+       if prev_mo.hinshi1 == '名詞' and mo.hinshi1 == '名詞':\r
+               if mo.hinshi2 == '数': return False\r
+               # 人名\r
+               if prev_mo.hinshi4 in ('姓', '名') and mo.hinshi2 == '接尾' and mo.hinshi3 == '人名': return True\r
+               # 複合名詞内部の2拍以下は切らない\r
+               if not prev_mo.hinshi2 in ('数', 'アルファベット') and not mo.hinshi2 in ('数', 'アルファベット'):\r
+                       if len(prev_mo.yomi) <= 2 and len(mo.yomi) >= 3: return False\r
+                       if len(prev_mo.yomi) >= 3 and len(mo.yomi) <= 2: return False\r
+               if mo.hinshi2 != '接尾': return True\r
+\r
+       if prev_mo.hinshi1 == '形容詞' and mo.hyouki == 'ん': return False # いいんですけど\r
+\r
+       if prev_mo.hinshi1 == '動詞' and prev_mo.hyouki == '見': return False # 見/まごう\r
+       if prev_mo.hinshi1 == '動詞' and prev_mo.hinshi2 == '自立':\r
+               if mo.hyouki == 'および': return True\r
+               if mo.hinshi1 == '動詞' and mo.hinshi2 == '非自立': return False\r
+\r
+       # その,その,連体詞,*,*,*,ソノ,ソノ,0/2,ソノ,1\r
+       # よう,よう,名詞,非自立,助動詞語幹,*,ヨウ,ヨー,1/2,ヨー,0\r
+       if prev_mo.hinshi1 == '連体詞' and mo.hinshi3 == '助動詞語幹': return False\r
+\r
+       if prev_mo.hinshi1 == '接頭詞' and prev_mo.hyouki == '超' and mo.hinshi1 == '名詞': return True\r
+       \r
+       # お兄さん, お姉さん\r
+       if prev_mo.hinshi1 == '接頭詞' and prev_mo.hyouki == 'お': return False\r
+       # 新/東京/名所\r
+       if prev_mo.hinshi1 == '接頭詞' and prev_mo.hinshi2 == '名詞接続' and \\r
+                       mo.hinshi1 == '名詞' and mo.hinshi2 == '固有名詞':\r
+               return True\r
+       if prev_mo.hinshi1 == '接頭詞' and mo.hinshi1 == '名詞': return False\r
+\r
+       if prev_mo.hinshi1 == '助動詞' and prev_mo.hyouki == 'で' and mo.hinshi1 == '助動詞': return True\r
+\r
+       if prev_mo.hinshi1 == '助詞' and mo.hyouki == 'よう': return False # のように\r
+       if prev_mo.hinshi1 == '助詞' and mo.hinshi1 == '接頭詞': return True\r
+\r
+       if prev_mo.is_substantive_word() and mo.is_independent_word(): return True\r
+       if prev_mo.is_independent_word() and mo.is_independent_word(): return True\r
+       return False\r
+\r
+def morphs_to_string(li, inbuf, logwrite):\r
+       outbuf = ''\r
+       inpos2 = []\r
+       p = 0\r
+       for i in range(0, len(li)):\r
+               if not li[i].output:\r
+                       continue\r
+               out = li[i].output\r
+               outlen = len(out)\r
+               outbuf += out\r
+               hyolen = len(li[i].hyouki)\r
+               if hyolen == outlen:\r
+                       inpos2.extend(range(p, p + outlen))\r
+               elif out[:2] == '⠠⠦' and out[-2:] == '⠠⠴':\r
+                       # 情報処理用点字の内側\r
+                       c = outlen - 4\r
+                       inpos2.extend([p] * 2)\r
+                       inpos2.extend(range(p, p + c))\r
+                       inpos2.extend([p + c - 1] * 2)\r
+               elif out[:1] == '⠦' and out[-1:] == '⠴':\r
+                       # 外国語引用符の内側\r
+                       c = outlen - 2\r
+                       inpos2.extend([p])\r
+                       inpos2.extend(range(p, p + c))\r
+                       inpos2.extend([p + c - 1])\r
+               else:\r
+                       # 表記と出力の文字数が変化する場合\r
+                       for x in range(outlen):\r
+                               inpos2.append(p + int(float(x) * hyolen / outlen))\r
+               p += hyolen\r
+               if li[i].sepflag:\r
+                       outbuf += ' '\r
+                       if p > 0:\r
+                               inpos2.append(p - 1) # マスアケは直前の文字に対応\r
+                       else:\r
+                               inpos2.append(p)\r
+       # rstrip with inpos2\r
+       if inbuf[-1] != ' ':\r
+               while outbuf[-1:] == ' ':\r
+                       outbuf = outbuf[:-1]\r
+                       inpos2.pop()\r
+       return (outbuf, inpos2)\r
+\r
+RE_MB_ALPHA_NUM_SPACE = re.compile('^[0-9A-Za-z 0-9A-Za-z ]+$')\r
+RE_ASCII_CHARS = re.compile('^[A-Za-z0-9\.\,\-\+\:\/\~\?\&\%\#\*\$\; ]+$')\r
+RE_INFOMATION = re.compile('^[A-Za-z0-9\+\@\/\#\$\%\&\*\;\.\<\>\-\_\{\}\[\] ]+$')\r
+RE_GAIJI = re.compile('^[A-Za-z][A-Za-z0-9\,\.\+\- ]+$')\r
+RE_KATAKANA = re.compile('^[ァ-ヾ]+$')\r
+RE_HIRAGANA = re.compile('^[ぁ-ゞ]+$')\r
+\r
+def japanese_braille_separate(inbuf, logwrite):\r
+       text = inbuf\r
+       if RE_MB_ALPHA_NUM_SPACE.match(text):\r
+               outbuf = unicode_normalize(text)\r
+               inpos2 = range(len(outbuf))\r
+               return (outbuf, inpos2)\r
+\r
+       # 'あ゛ー' Unicode 正規化されて空白が入るので事前に補正する\r
+       text = text.replace('あ゛', 'あ')\r
+       text = text.replace('ヱ゛', 'ヴェ')\r
+       text = text.replace('ヲ゛', 'ヴォ')\r
+       text = text.replace('ワ゛', 'ヴァ')\r
+\r
+       # 'ふにゃ~'\r
+       text = text.replace('ゃ~', 'ゃー')\r
+\r
+       text = Mecab_text2mecab(text)\r
+       mf = MecabFeatures()\r
+       Mecab_analysis(text, mf)\r
+       Mecab_correctFeatures(mf)\r
+       Mecab_print(mf, logwrite, output_header = False)\r
+       li = mecab_to_morphs(mf)\r
+       mf = None\r
+\r
+       for mo in li:\r
+               if mo.hinshi1 == '空白':\r
+                       mo.output = ' '\r
+               elif mo.hinshi2 == '数' and mo.nhyouki.isdigit():\r
+                       # digit numbers (not kanji characters)\r
+                       mo.output = mo.nhyouki\r
+\r
+       li = replace_morphs(li, CONNECTED_MORPHS)\r
+       li = replace_digit_morphs(li)\r
+       li = rewrite_number(li)\r
+\r
+       # before: う,う,助動詞,*,*,*,ウ,ウ,0/1,ウ,0\r
+       # after:  う,う,助動詞,*,*,*,ウ,ウ,0/1,ー,0\r
+       for mo in li:\r
+               if mo.hyouki == 'う' and mo.hinshi1 == '助動詞':\r
+                       mo.output = 'ー'\r
+\r
+       # before: a,a,記号,アルファベット,*,*,エイ,エイ,1/2,エイ,0\r
+       # after:  a,a,記号,アルファベット,*,*,エイ,エイ,1/2,a,0\r
+       for mo in li:\r
+               if mo.hinshi2 == 'アルファベット':\r
+                       mo.output = mo.nhyouki\r
+\r
+       li = replace_alphabet_morphs(li)\r
+\r
+       for mo in li:\r
+               if mo.hyouki == '〝':\r
+                       mo.hinshi1 = '記号'\r
+                       mo.hinshi2 = '括弧開'\r
+               if mo.hyouki == '〟':\r
+                       mo.hinshi1 = '記号'\r
+                       mo.hinshi2 = '括弧閉'\r
+\r
+       for mo in li:\r
+               if mo.hinshi2 in ('括弧開', '括弧閉'):\r
+                       mo.output = mo.nhyouki\r
+\r
+       # before:  , ,記号,空白,*,*, , ,*/*, ,0\r
+       # after:   , ,記号,空白,*,*, , ,*/*, ,0\r
+       for mo in li:\r
+               if mo.hyouki == ' ': # full shape space\r
+                       mo.output = ' '\r
+\r
+       # 数字の前の全角アポストロフィを半角にする\r
+       # before:\r
+       # ’,’,記号,括弧閉,*,*,’,’,*/*,’,0\r
+       # 0,0,名詞,数,*,*,ゼロ,ゼロ,1/2,0,0\r
+       # after:\r
+       # ’,’,記号,括弧閉,*,*,’,’,*/*,',0\r
+       # 0,0,名詞,数,*,*,ゼロ,ゼロ,1/2,0,0\r
+       for pos in range(0, len(li) - 1):\r
+               if li[pos].hyouki == '’' and li[pos+1].hinshi2 == '数':\r
+                       li[pos].output = "'"\r
+\r
+       # 算用数字ではさまれた読点と中点を数符にする\r
+       # before:\r
+       # 二,二,名詞,数,*,*,2,2,1/2,2,0\r
+       # 、,、,記号,読点,*,*,、,、,*/*,、,0\r
+       # 三,三,名詞,数,*,*,3,3,1/2,3,0\r
+       # after:\r
+       # 二,二,名詞,数,*,*,2,2,1/2,2,0\r
+       # 、,、,記号,読点,*,*,、,、,*/*,⠼,0\r
+       # 三,三,名詞,数,*,*,3,3,1/2,3,0\r
+       for pos in range(1, len(li) - 1):\r
+               if li[pos-1].output.isdigit() and \\r
+                               li[pos].hyouki in ('、', '・') and \\r
+                               li[pos+1].output.isdigit():\r
+                       li[pos].output = '⠼'\r
+\r
+       # 記号を Unicode 正規化\r
+       for mo in li:\r
+               if mo.hinshi1 == '記号' and mo.hinshi2 == '一般':\r
+                       mo.output = mo.nhyouki\r
+               if mo.hyouki == '.' and mo.hinshi1 == '名詞' and mo.hinshi2 == '数':\r
+                       mo.output = '.'\r
+               if mo.hyouki == ',' and mo.hinshi1 == '名詞' and mo.hinshi2 == '数':\r
+                       mo.output = ','\r
+               if mo.hinshi1 == '記号' and mo.hinshi2 == '句点' and mo.nhyouki == '.':\r
+                       mo.output = '.'\r
+               if mo.hinshi1 == '記号' and mo.hinshi2 == '読点' and mo.nhyouki == ',':\r
+                       mo.output = ','\r
+\r
+       # before: ab,ab,名詞,一般,*,*,アブ,アブ,1/2,アブ,0\r
+       # after:  ab,ab,名詞,一般,*,*,アブ,アブ,1/2,ab,0\r
+       # before: No.,No.,接頭詞,数接続,*,*,ナンバー,ナンバー,1/4,ナンバー,0\r
+       # after:  No.,No.,接頭詞,数接続,*,*,ナンバー,ナンバー,1/4,No.,0\r
+       for mo in li:\r
+               if RE_ASCII_CHARS.match(mo.nhyouki):\r
+                       mo.output = mo.nhyouki\r
+\r
+       # before: ヒロイノ,ヒロイノ,名詞,一般,*,*,,,,,0\r
+       # after:  ヒロイノ,ヒロイノ,名詞,一般,*,*,,,,ヒロイノ,0\r
+       # before: ィ,ィ,名詞,一般,*,*,,,,,0\r
+       # after:  ィ,ィ,名詞,一般,*,*,,,,ィ,0\r
+       # before: ぁ,ぁ,名詞,一般,*,*,,,,,0\r
+       # after:  ぁ,ぁ,名詞,一般,*,*,,,,ァ,0\r
+       for mo in li:\r
+               if not mo.output and mo.nhyouki != 'ー':\r
+                       if RE_KATAKANA.match(mo.nhyouki):\r
+                               mo.output = mo.nhyouki\r
+                       elif RE_HIRAGANA.match(mo.nhyouki):\r
+                               mo.output = ''.join([unichr(ord(c) + 0x60) for c in mo.nhyouki])\r
+\r
+       # 単語が小文字カタカナのみであれば修正\r
+       # 表記は修正せず should_separate() で小文字として判定される\r
+       for mo in li:\r
+               if mo.output == 'ァ': mo.output = 'ア'\r
+               if mo.output == 'ィ': mo.output = 'イ'\r
+               if mo.output == 'ゥ': mo.output = 'ウ'\r
+               if mo.output == 'ェ': mo.output = 'エ'\r
+               if mo.output == 'ォ': mo.output = 'オ'\r
+               if mo.output == 'ッ': mo.output = 'ツ'\r
+               if mo.output == 'ャ': mo.output = 'ヤ'\r
+               if mo.output == 'ュ': mo.output = 'ユ'\r
+               if mo.output == 'ョ': mo.output = 'ヨ'\r
+               if mo.output == 'ヮ': mo.output = 'ワ'\r
+               if mo.output == 'ヵ': mo.output = 'カ'\r
+               if mo.output == 'ヶ': mo.output = 'ケ'\r
+\r
+       for mo in li:\r
+               # 情報処理点字の開始記号と終了記号\r
+               if RE_INFOMATION.match(mo.nhyouki) and \\r
+                               ('@' in mo.nhyouki) or ('://' in mo.nhyouki) or ('\\' in mo.nhyouki):\r
+                       mo.output = '⠠⠦' + mo.nhyouki + '⠠⠴'\r
+               # 外国語引用符\r
+               # 空白をはさまない1単語は外国語引用符ではなく外字符で\r
+               elif RE_GAIJI.match(mo.nhyouki) and \\r
+                               (' ' in mo.nhyouki) or ('.' in mo.nhyouki and len(mo.nhyouki) > 3):\r
+                       mo.output = '⠦' + mo.nhyouki + '⠴'\r
+\r
+       for mo in li:\r
+               # 情報処理点字でも外国語引用符でもなく output が & を含む場合は前後をあける\r
+               if not mo.output.startswith('⠠⠦') and not mo.output.startswith('⠦'):\r
+                       # &\r
+                       if mo.output == '&':\r
+                               continue\r
+                       # &xx\r
+                       elif mo.output.startswith('&'):\r
+                               mo.output = mo.output.replace('&', '& ')\r
+                       # xx&\r
+                       elif mo.output.endswith('&'):\r
+                               mo.output = mo.output.replace('&', ' &')\r
+                       # xx&xx\r
+                       else:\r
+                               mo.output = mo.output.replace('&', ' & ')\r
+       \r
+       # 日付の和語読み処理\r
+       li = fix_japanese_date_morphs(li)\r
+\r
+       # 分かち書き判定\r
+       for i in xrange(1, len(li)):\r
+               prev2_mo = li[i-2] if i-2 >= 0 else None\r
+               prev_mo = li[i-1]\r
+               next_mo = li[i+1] if i+1 < len(li) else None\r
+               li[i-1].sepflag = should_separate(prev2_mo, prev_mo, li[i], next_mo)\r
+\r
+       for mo in li:\r
+               mo.write(logwrite)\r
+       logwrite('')\r
+\r
+       outbuf, inpos2 = morphs_to_string(li, inbuf, logwrite)\r
+       return (outbuf, inpos2)\r
+\r
+mecab_initialized = False\r
+\r
+def initialize(jtalk_dir=None, logwrite=_logwrite):\r
+       global mecab_initialized\r
+       if jtalk_dir:\r
+               Mecab_initialize(logwrite, jtalk_dir)\r
+       else:\r
+               Mecab_initialize(logwrite)\r
+       if logwrite: logwrite("initialize() done.")\r
+       mecab_initialized = True\r
+\r
+def terminate():\r
+       global _logwrite\r
+       if _logwrite: _logwrite("terminate() done.")\r
+       global mecab_initialized\r
+       mecab_initialized = False\r
+\r
+def translateWithInPos2(inbuf, logwrite=_logwrite):\r
+       if not mecab_initialized:\r
+               initialize()\r
+       outbuf, inpos2 = japanese_braille_separate(inbuf, logwrite)\r
+       result, inpos1 = translator1.translateWithInPos(outbuf)\r
+       result = result.replace('□', ' ')\r
+       return (outbuf, result, inpos1, inpos2)\r
+\r
+# for brailleViewer\r
+def getReadingAndBraille(text, logwrite=_logwrite):\r
+       return translateWithInPos2(text, logwrite=logwrite)[0:2]\r
+\r
+# returns '\u2801\u2802\u2803\u2804\u2805\u2806\u2807'\r
+def japaneseToUnicodeBraille(text, logwrite=_logwrite):\r
+       return translateWithInPos2(text, logwrite=logwrite)[0]\r
+\r
+def makeOutPos(inPos, inlen, outlen):\r
+       # make outPos\r
+       outPos = [-1] * inlen\r
+       for p in range(outlen):\r
+               if inPos[p] < len(outPos) and (outPos[ inPos[p] ] == -1 or inPos[p] == 0):\r
+                       outPos[ inPos[p] ] = p\r
+       # fill skipped outPos\r
+       prev = 0\r
+       for p in range(inlen):\r
+               if outPos[p] == -1:\r
+                       outPos[p] = prev\r
+               else:\r
+                       prev = outPos[p]\r
+       return outPos\r
+\r
+def mergePositionMap(inpos1, inpos2, outlen, inlen):\r
+       inPos = [0] * outlen\r
+       for p in range(outlen):\r
+               inPos[p] = inpos2[ inpos1[p] ]\r
+       outPos = makeOutPos(inPos, inlen, outlen)\r
+       return inPos, outPos\r
+\r
+# louis-compatible method\r
+# tableList, typeform are not supported.\r
+# mode=dotsIO is default.\r
+def translate(inbuf, cursorPos=0, logwrite=_logwrite, unicodeIO=False):\r
+       """Translate a string of characters, providing position information.\r
+       @param inbuf: The string to translate.\r
+       @type inbuf: str\r
+       @param cursorPos: The position of the cursor in inbuf.\r
+       @type cursorPos: int\r
+       @return: A tuple of:\r
+               the translated string,\r
+               a list of input positions for each position in the output,\r
+               a list of output positions for each position in the input, and\r
+               the position of the cursor in the output.\r
+       @rtype: (str, list of int, list of int, int)\r
+       @raise RuntimeError: If a complete translation could not be done.\r
+       """\r
+       sp, outbuf, inpos1, inpos2 = translateWithInPos2(inbuf, logwrite=logwrite)\r
+       if not unicodeIO:\r
+               pat = outbuf.replace(' ', '\u2800')\r
+               outbuf = ''.join([unichr((ord(c) - 0x2800) + 0x8000) for c in pat])\r
+       inPos, outPos = mergePositionMap(inpos1, inpos2, len(outbuf), len(inbuf))\r
+       cursorPos = outPos[cursorPos]\r
+       return (outbuf, inPos, outPos, cursorPos)\r
diff --git a/source/synthDrivers/nvdajp_jtalk.py b/source/synthDrivers/nvdajp_jtalk.py
new file mode 100644 (file)
index 0000000..4f676a7
--- /dev/null
@@ -0,0 +1,157 @@
+#synthDrivers/nvdajp_jtalk.py\r
+# -*- coding: utf-8 -*-\r
+#A part of NonVisual Desktop Access (NVDA)\r
+#Copyright (C) 2006-2010 NVDA Contributors <http://www.nvda-project.org/>\r
+#This file is covered by the GNU General Public License.\r
+#See the file COPYING for more details.\r
+#\r
+# nvdajp_jtalk (based on Open JTalk and libopenjtalk)\r
+# Copyright (C) 2010-2011 Takuya Nishimoto (nishimotz.com)\r
+# Copyright (C) 2013 Masamitsu Misono (043.jp)\r
+\r
+from synthDriverHandler import SynthDriver,VoiceInfo,BooleanSynthSetting\r
+from collections import OrderedDict\r
+from logHandler import log\r
+import speech\r
+import synthDriverHandler\r
+import languageHandler\r
+from jtalk import _nvdajp_jtalk\r
+from jtalk._nvdajp_jtalk import VoiceProperty\r
+\r
+class SynthDriver(SynthDriver):\r
+       """A Japanese synth driver for NVDAjp.\r
+       """\r
+       name = "nvdajp_jtalk"\r
+       description = "JTalk"\r
+       supportedSettings=(\r
+               SynthDriver.VoiceSetting(),\r
+               SynthDriver.RateSetting(),\r
+               BooleanSynthSetting("rateBoost",_("Rate boos&t")),\r
+               SynthDriver.PitchSetting(),\r
+               SynthDriver.InflectionSetting(),\r
+               SynthDriver.VolumeSetting()\r
+       )\r
+\r
+       @classmethod\r
+       def check(cls):\r
+               return True\r
+\r
+       def __init__(self):\r
+               self.voice_id = 'V2'\r
+               self._volume = 100\r
+               self._pitch = 50\r
+               self._inflection = 50\r
+               self._rateBoost = False\r
+               _nvdajp_jtalk.initialize()\r
+               self.rate = 50\r
+\r
+       def speak(self,speechSequence):\r
+               finalIndex = None\r
+               spellState = False\r
+               defaultLanguage = languageHandler.getLanguage()\r
+               if defaultLanguage[:2] == 'ja': defaultLanguage = 'ja'\r
+               lang = defaultLanguage\r
+               currentLang = lang\r
+               for item in speechSequence:\r
+                       if isinstance(item,basestring):\r
+                               p = VoiceProperty()\r
+                               p.pitch = self._pitch\r
+                               p.inflection = self._inflection\r
+                               p.characterMode = spellState\r
+                               _nvdajp_jtalk.speak(unicode(item), currentLang, index=finalIndex, voiceProperty_=p)\r
+                       elif isinstance(item,speech.IndexCommand):\r
+                               finalIndex = item.index\r
+                       elif isinstance(item,speech.CharacterModeCommand):\r
+                               if item.state: \r
+                                       spellState = True \r
+                               else: \r
+                                       spellState = True \r
+                       elif isinstance(item,speech.LangChangeCommand):\r
+                               lang = (item.lang if item.lang else defaultLanguage).replace('_','-')\r
+                               if lang[:2] == 'ja': lang = 'ja'\r
+                               currentLang = lang\r
+                       elif isinstance(item,speech.SpeechCommand):\r
+                               log.debugWarning("Unsupported speech command: %s"%item)\r
+                       else:\r
+                               log.error("Unknown speech: %s"%item)\r
+\r
+       def cancel(self):\r
+               _nvdajp_jtalk.stop()\r
+\r
+       def pause(self,switch):\r
+               _nvdajp_jtalk.pause(switch)\r
+\r
+       def isSpeaking(self):\r
+               return _nvdajp_jtalk.isSpeaking()\r
+\r
+       def _get_rateBoost(self):\r
+               return self._rateBoost\r
+\r
+       def _set_rateBoost(self, enable):\r
+               if enable == self._rateBoost:\r
+                       return\r
+               rate = self.rate\r
+               self._rateBoost = enable\r
+               self.rate = rate\r
+\r
+       def terminate(self):\r
+               _nvdajp_jtalk.terminate()\r
+\r
+       # The current rate; ranges between 0 and 100\r
+       def _get_rate(self):\r
+               return _nvdajp_jtalk.get_rate(self._rateBoost)\r
+\r
+       def _set_rate(self,rate):\r
+               _nvdajp_jtalk.set_rate(int(rate), self._rateBoost)\r
+\r
+       def _get_pitch(self):\r
+               return self._pitch\r
+\r
+       def _set_pitch(self,pitch):\r
+               self._pitch = int(pitch)\r
+\r
+       def _get_volume(self):\r
+               return self._volume\r
+\r
+       def _set_volume(self,volume_):\r
+               self._volume = int(volume_)\r
+               _nvdajp_jtalk.set_volume(self._volume)\r
+               return\r
+\r
+       def _get_inflection(self):\r
+               return self._inflection\r
+\r
+       def _set_inflection(self,val):\r
+               self._inflection = int(val)\r
+\r
+       def _getAvailableVoices(self):\r
+               log.debug("_getAvailableVoices called")\r
+               voices = OrderedDict()\r
+               for v in _nvdajp_jtalk._jtalk_voices:\r
+                       voices[v['id']] = VoiceInfo(v['id'], v['name'], v['lang'])\r
+               return voices\r
+\r
+       def _get_voice(self):\r
+               log.debug("_get_voice called")\r
+               return self.voice_id\r
+\r
+       def _set_voice(self, identifier):\r
+               log.debug("_set_voice %s" % (identifier))\r
+               rate = _nvdajp_jtalk.get_rate(self._rateBoost)\r
+               for v in _nvdajp_jtalk._jtalk_voices:\r
+                       if v['id'] == identifier:\r
+                               if self.voice_id != identifier:\r
+                                       self.voice_id = identifier\r
+                                       _nvdajp_jtalk.terminate()\r
+                                       _nvdajp_jtalk.initialize(v)\r
+                                       _nvdajp_jtalk.set_rate(rate,self._rateBoost)\r
+                                       _nvdajp_jtalk.set_volume(self._volume)\r
+                                       return\r
+               return\r
+\r
+       def _get_lastIndex(self):\r
+               if _nvdajp_jtalk.lastIndex is None:\r
+                       #log.debug("_get_lastIndex returns None")\r
+                       return None\r
+               #log.debug("_get_lastIndex returns %d" % _nvdajp_jtalk.lastIndex)\r
+               return _nvdajp_jtalk.lastIndex\r