home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1999 March / VPR9903A.BIN / APUPDATE / VC / Tx300d / TX300D.LZH / SPEAK.C < prev    next >
C/C++ Source or Header  |  1997-10-17  |  24KB  |  1,022 lines

  1. // WZ Editor 音声化
  2. // WZ32 3.0以降専用 (WZ16は開発専用)
  3. // 96.4.29 start
  4. // WZを音声化するには、WZのメニューから「ツール|カスタマイズ」を選択し、
  5. // カスタマイズダイアログの[その他]-[音声化]をONにしてWZを再起動してください。
  6. // WZをネットワークで使用している場合、ユーザ毎に音声化するかどうか設定できます。
  7. //3.00A 970501 WZ3.0対応
  8.  
  9. // ああ、ああ。いい、いい。うう、うう。ええ、ええ。おお、おお。
  10. // かか、かか。きききき。くくくく。けけけけ。ここここ。
  11.  
  12. //{###音声化}
  13. // 日本障害者雇用促進協会の「95Reader Version 1.0」を使って、
  14. // WZ Editorを音声化します。
  15. // WZを音声化するには、95Readerを起動しておいてから、
  16. // WZのメニューから「ツール|カスタマイズ」を選択し、
  17. // カスタマイズダイアログの[その他]-[音声化]をONにして、
  18. // WZを再起動してください。
  19. // 音声化をやめるには[その他]-[音声化]をOFFにしてください。
  20. // ※WZ16は音声化できません。
  21.  
  22. #include <windows.h>
  23. #include "dialog.h"
  24. #include "word.h"
  25.  
  26. //##音声発生DLL
  27.  
  28. //3.00A3 970508 soundp.hをWZに添付 許諾済
  29. extern "soundp.dll" {
  30.     #include "soundp.h"
  31. }
  32.  
  33. #define SPEAK_SENTENCE        0        // 滑らか読み
  34. #define SPEAK_CHAR            2        // 1文字説明読み
  35. #define SPEAK_CURSOR        3        // カーソル移動読み
  36. #define SPEAK_ABSOLUTE_OUT    0x40    //3.00A2 970504 必ず出力する
  37.  
  38. //##設定,内部変数
  39.  
  40. permanent int _fSpeakLine = TRUE;    // 行末まで読む?
  41. permanent int _msWaitDelete = 1000;    //3.00A5 970511 「削除」を発声してから待つ時間をカスタマイズできるようにした
  42.  
  43. static int _nRepeatDelete = 0;        // {Delete}が連続して押された回数
  44. static int _nRepeatBackspace = 0;    // {Backspace}が連続して押された回数
  45. static int _idmSearch;                // [検索]-[検索]のidm
  46.  
  47. //##内部関数
  48.  
  49. static mchar* GetTxeName(mchar sztxename[CCHPATHNAME])
  50. {
  51. // 現在のWZがTXEならそのモジュール名(filerなど)を返す。
  52. // そうでなければ""を返す
  53.     sztxename[0] = 0;
  54.     //
  55.     wzlock(LOCK_WZPROCESS);
  56.     {
  57.         int i = textSearch(text->hwndbase);
  58.         if (i != -1) {
  59.             strcpymax(sztxename,text->share->tWzprocess[i].szTxeName,CCHPATHNAME);
  60.         }
  61.     }
  62.     wzunlock(LOCK_WZPROCESS);
  63.     return sztxename;
  64. }
  65.  
  66. static BOOL speak(LPCSTR lpszText,UINT fuType)
  67. {
  68. // 文字列を指定したモードで読み上げる
  69. #ifdef __FLAT__
  70.     #if 1
  71.     if (lpszText[0]) {
  72.         int mode = 0;
  73.         if (fuType & SPEAK_ABSOLUTE_OUT) {//3.00A2 970504 
  74.             mode = PF_ABSOLUTE_OUT;
  75.         }
  76.         switch(fuType) {
  77.             case SPEAK_SENTENCE: mode |= 0;break;
  78.             case SPEAK_CHAR: mode |= PF_DETAIL;break;
  79.             case SPEAK_CURSOR: mode |= PF_CURSOR_MOVE;break;
  80.         }
  81.         SoundMessage(lpszText,mode);
  82.     }
  83.     return TRUE;
  84.     #else
  85.     // for DEBUG
  86.     printf("%s\n",lpszText);
  87.     return TRUE;
  88.     #endif
  89. #else
  90.     printf("%s\n",lpszText);
  91.     return TRUE;
  92. #endif
  93. }
  94.  
  95. static BOOL speakwait(LPCSTR lpszText,UINT fuType)
  96. {
  97. // 文字列を指定したモードで読み上げ、読み上げが終わるまで制御を返さない
  98.     int ret = speak(lpszText,fuType|SPEAK_ABSOLUTE_OUT);
  99. #ifdef __FLAT__
  100.     //3.00A2 970504 読み上げが終わるまで制御を返さない方法がわからないので、
  101.     // とりあえずSleepで待つ。これしないと"削除"や"後退"が読み上げされない。
  102.     Sleep(_msWaitDelete);
  103. #endif
  104.     return ret;
  105. }
  106.  
  107. void TXAPI TXCMD txspeakCurChar(TX* text)
  108. {
  109. // カーソル位置の文字を説明読みで読み上げ
  110.     int size = txGetCharSize(text,text->cur);
  111.     mchar buff[CCHWORD];
  112.     strcpylenmax(buff,text->buff + text->cur,size,CCHWORD);
  113.     speak(buff,SPEAK_CHAR);
  114. }
  115.  
  116. void TXAPI TXCMD txspeakCur(TX* text)
  117. {
  118. // カーソル位置の文字をカーソル移動読みで読み上げ
  119.     int size = txGetCharSize(text,text->cur);
  120.     mchar buff[CCHWORD];
  121.     strcpylenmax(buff,text->buff + text->cur,size,CCHWORD);
  122.     speak(buff,SPEAK_CURSOR);
  123. }
  124.  
  125. void TXAPI TXCMD txspeakCurPrev(TX* text)
  126. {
  127. // カーソルの一つ手前の文字をカーソル移動読みで読み上げ
  128.     if (text->cur0) {
  129.         IMEM off = formchar(text->buff,text->cur0 - 1);
  130.         int size = txGetCharSize(text,off);
  131.         mchar buff[CCHWORD];
  132.         strcpylenmax(buff,text->buff + off,size,CCHWORD);
  133.         speak(buff,SPEAK_CURSOR);
  134.     }
  135. }
  136.  
  137. void TXAPI TXCMD txspeakCurLinePrim(TX* text)
  138. {
  139. // カーソル位置から表示行末まで文字列をなめらか読みで読み上げ
  140. // 最大CCHLINE-1バイトまでの文字列を読めます
  141. //3.00C 971016 new
  142.     mchar buff[CCHLINE];
  143.     IMEM len = text->curysize - (text->cur0 - text->cury);
  144.     if (len) {
  145.         strcpylenmax(buff,text->buff + text->cur,len,CCHLINE);
  146.         speak(buff,SPEAK_SENTENCE);
  147.     }
  148. }
  149.  
  150. void TXAPI TXCMD txspeakCurLine(TX* text)
  151. {
  152. // カーソル位置から表示行末まで文字列をなめらか読みで読み上げ
  153. // 最大CCHLINE-1バイトまでの文字列を読めます
  154. // 設定によっては、カーソル位置の一文字しか読み上げない
  155.     if (_fSpeakLine) {
  156.         txspeakCurLinePrim(text);
  157.     } else {
  158.         txspeakCur(text);
  159.     }
  160. }
  161.  
  162. static void speakAddressCur(TX* text,IFILE adr0)
  163. {
  164. // adr0からカーソル位置までの文字列をなめらか読みで読み上げ
  165. // 最大CCHLINE-1バイトまでの文字列を読めます
  166.     mchar buff[CCHLINE];
  167.     IFILE adr = txGetAddress(text);
  168.     if (adr0 <= adr) {
  169.         // カーソルが右に移動した
  170.         IMEM off0 = 0;
  171.         if (text->temp1 < adr0) {
  172.             off0 = adr0 - text->temp1;
  173.         }
  174.         strcpylenmax(buff,text->buff + off0,text->cur0 - off0,CCHLINE);
  175.         speak(buff,SPEAK_SENTENCE);
  176.     } else {
  177.         // カーソルが左に移動した
  178.         IMEM off0 = text->sizebuff;
  179.         adr0 -= text->temp1;
  180.         adr0 += (text->cur - text->cur0);
  181.         if (adr0 < text->sizebuff) {
  182.             off0 = (IMEM)adr0;
  183.         }
  184.         strcpylenmax(buff,text->buff + text->cur,off0 - text->cur,CCHLINE);
  185.         speak(buff,SPEAK_SENTENCE);
  186.     }
  187. }
  188.  
  189. static int txSearchKuten(TX* text,SEARCHMODE mode)
  190. {
  191.     return txSearchEx(text,"[。。..]",SEARCH_RE|SEARCH_NOSELECT|mode);
  192. }
  193.  
  194. static int txSearchDokuten(TX* text,SEARCHMODE mode)
  195. {
  196.     return txSearchEx(text,"[、、,,]",SEARCH_RE|SEARCH_NOSELECT|mode);
  197. }
  198.  
  199. static void speakCurKuten(TX* text)
  200. {
  201. // カーソル位置の次の文字から次の句点までを読む
  202.     txSetUndispEx(text);
  203.     {
  204.         txRight(text);
  205.         IFILE adr = txGetAddress(text);
  206.         if (txSearchKuten(text,0)) {
  207.         } else {
  208.             txJumpFileEnd(text);
  209.         }
  210.         speakAddressCur(text,adr);
  211.     }
  212.     txSetDispEx(text);
  213. }
  214.  
  215. static void speakCurDokuten(TX* text)
  216. {
  217. // カーソル位置の次の文字から次の読点までを読む
  218.     txSetUndispEx(text);
  219.     {
  220.         txRight(text);
  221.         IFILE adr = txGetAddress(text);
  222.         if (txSearchDokuten(text,0)) {
  223.         } else {
  224.             txJumpFileEnd(text);
  225.         }
  226.         speakAddressCur(text,adr);
  227.     }
  228.     txSetDispEx(text);
  229. }
  230.  
  231. static void speakSelect(TX* text)
  232. {
  233. // 選択されている文字列をなめらか読みで読み上げる
  234. // 読み上げることができる文字列に制限はありません
  235.     if (text->fClip) {
  236.         HCLIP hclip = HCLIP_TS;
  237.         txSelectTsPush(text);
  238.         DWORD size = memClipPaste(NULL,hclip);
  239.         if (size) {
  240.             LPBYTE pmem = memAlloc(size + 1);
  241.             if (pmem) {
  242.                 memClipPaste(pmem,hclip);
  243.                 pmem[size] = 0;
  244.                 speak(pmem,SPEAK_SENTENCE);
  245.                 memFree(pmem);
  246.             }
  247.         }
  248.         clipDeleteTop(hclip);
  249.     }
  250. }
  251.  
  252. static void speakLine(TX* text)
  253. {
  254. // カーソルの行の内容をなめらか読みで読み上げる
  255. // 最大CCHLINE-1バイトまでの文字列を読めます
  256.     txstr sz(CCHLINE);
  257.     txGetLine(text,sz);
  258.     speak(sz,SPEAK_SENTENCE);
  259. }
  260.  
  261. static void speakPara(TX* text)
  262. {
  263. // カーソルの段落の内容をなめらか読みで読み上げる
  264. // 最大CCHLINE-1バイトまでの文字列を読めます
  265.     txstr sz(CCHLINE);
  266.     txGetPara(text,sz);
  267.     speak(sz,SPEAK_SENTENCE);
  268. }
  269.  
  270. static void selectStart(TX* text)
  271. {
  272.     if (!text->fClipMouse) {
  273.         txSelectVz(text);
  274.         text->fClipMouse = TRUE;
  275.     }
  276. }
  277.  
  278. // 選択を取り消したかどうか返す
  279. static BOOL selectEnd(TX* text,int vk)
  280. {
  281.     if (text->fClip && text->fClipMouse) {
  282.         switch(vk) {
  283.             case VK_LEFT: {
  284.                 txJumpSelectTop(text);
  285.                 txspeakCur(text);
  286.                 break;
  287.             }
  288.             case VK_RIGHT: {
  289.                 txJumpSelectEnd(text);
  290.                 txspeakCur(text);
  291.                 break;
  292.             }
  293.             case VK_BACK:
  294.             case VK_DELETE: {
  295.                 speakwait("削除",SPEAK_SENTENCE);
  296.                 speakSelect(text);
  297.                 txSelectDelete(text);
  298.                 return TRUE;
  299.             }
  300.         }
  301.         return txSelectQuit(text);
  302.     }
  303.     return FALSE;
  304. }
  305.  
  306. static BOOL txspeakLineIsNull(TX* text)
  307. {
  308. //3.00C 971016 方向キーで移動中、空行に移動したら「空行」と読み上げる
  309.     txstr buff(10);
  310.     if (txGetPara(text,buff) == 0) {
  311.         speak("空行",SPEAK_SENTENCE);
  312.         return TRUE;
  313.     }
  314.     return FALSE;
  315. }
  316.  
  317. static BOOL txspeakCurIsLineTopOrEnd(TX* text)
  318. {
  319. //3.00C 971016 左右方向キーで「行頭」「行末」読み上げ
  320. #if 0    //3.00C 971016 とりあえずOFFにしておく、"行頭"の後の文字が読まれないため
  321.     if (txIsCurLineTop(text)) {
  322.         speak("行頭",SPEAK_SENTENCE);
  323.         return TRUE;
  324.     } else if (text->cur0 - text->cury + txGetCharSize(text,text->cur) == text->curysize) {
  325.         speak("行末",SPEAK_SENTENCE);
  326.         return TRUE;
  327.     }
  328. #endif
  329.     return FALSE;
  330. }
  331.  
  332. //##コマンド
  333.  
  334. int TXAPI TXCMD txspeakLeft(TX* text)
  335. {
  336. // カーソルを1つ前の文字へ移動
  337. // カーソルを1つ前の文字へ移動して、カーソル位置の文字を読み上げる
  338. // 選択中は、カーソルを範囲の先頭に移動して選択を解除し、カーソル位置の文字を読み上げ
  339.     if (selectEnd(text,VK_LEFT)) return 0;
  340.     int ret = txLeft(text);
  341.     if (ret) {
  342.         if (!txspeakLineIsNull(text)) {
  343.             txspeakCurIsLineTopOrEnd(text);
  344.             txspeakCur(text);
  345.         }
  346.     }
  347.     return ret;
  348. }
  349.  
  350. int TXAPI TXCMD txspeakRight(TX* text)
  351. {
  352. // カーソルを1つ後の文字へ移動
  353. // カーソルを1つ後の文字へ移動して、カーソル位置の文字を読み上げる
  354. // 選択中は、カーソルを範囲の末尾に移動して選択を解除し、カーソル位置の文字を読み上げ
  355.     if (selectEnd(text,VK_RIGHT)) return 0;
  356.     int ret = txRight(text);
  357.     if (ret) {
  358.         if (!txspeakLineIsNull(text)) {
  359.             txspeakCurIsLineTopOrEnd(text);
  360.             txspeakCur(text);
  361.         }
  362.     }
  363.     return ret;
  364. }
  365.  
  366. int TXAPI TXCMD txspeakLinetop(TX* text)
  367. {
  368. // 行頭からカーソルまでを読み上げる
  369. // 選択中は、選択を解除する
  370. //3.00C 971016 new
  371.     selectEnd(text,0);
  372.     speakAddressCur(text,txGetLineTop(text));
  373.     return TRUE;
  374. }
  375.  
  376. int TXAPI TXCMD txspeakLineend(TX* text)
  377. {
  378. // カーソル位置から行末までを読み上げる
  379. // 選択中は、選択を解除する
  380. //3.00C 971016 new
  381.     selectEnd(text,0);
  382.     speakAddressCur(text,txGetLineTail(text));
  383.     return TRUE;
  384. }
  385.  
  386. int TXAPI TXCMD txspeakUp(TX* text)
  387. {
  388. // カーソルを1つ上の行へ移動
  389. // カーソルを1つ上の行へ移動して、カーソル位置から表示行末まで文字列をなめらか読みで読み上げる
  390. // 選択中は、カーソルを範囲の先頭に移動して選択を解除し、カーソル位置の文字を読み上げ
  391.     if (selectEnd(text,VK_LEFT)) return 0;
  392.     int ret = txUp(text);
  393.     if (ret) {
  394.         if (!txspeakLineIsNull(text)) txspeakCurLine(text);
  395.     }
  396.     return ret;
  397. }
  398.  
  399. int TXAPI TXCMD txspeakDown(TX* text)
  400. {
  401. // カーソルを1つ下の行へ移動
  402. // カーソルを1つ下の行へ移動して、カーソル位置から表示行末まで文字列をなめらか読みで読み上げる
  403. // 選択中は、カーソルを範囲の末尾に移動して選択を解除し、カーソル位置の文字を読み上げ
  404.     if (selectEnd(text,VK_RIGHT)) return 0;
  405.     int ret = txDown(text);
  406.     if (ret) {
  407.         if (!txspeakLineIsNull(text)) txspeakCurLine(text);
  408.     }
  409.     return ret;
  410. }
  411.  
  412. int TXAPI TXCMD txspeakLineprev(TX* text)
  413. {
  414. // カーソルの前の表示行の内容を読み上げ
  415. // 選択中は、選択を解除する
  416. //3.00C 971016 new
  417.     selectEnd(text,0);
  418.     txSetUndispExSilent(text);
  419.         int ret = txUp(text);
  420.         if (ret) {
  421.             txJumpLineTop(text);
  422.             if (!txspeakLineIsNull(text)) txspeakCurLinePrim(text);
  423.         } else {
  424.             speak("先頭行",SPEAK_SENTENCE);
  425.         }
  426.     txSetDispExSilent(text);
  427.     return ret;
  428. }
  429.  
  430. int TXAPI TXCMD txspeakLinenext(TX* text)
  431. {
  432. // カーソルの次の表示行の内容を読み上げ
  433. // 選択中は、選択を解除する
  434. //3.00C 971016 new
  435.     selectEnd(text,0);
  436.     txSetUndispExSilent(text);
  437.         int ret = txDown(text);
  438.         if (ret) {
  439.             txJumpLineTop(text);
  440.             if (!txspeakLineIsNull(text)) txspeakCurLinePrim(text);
  441.         } else {
  442.             speak("最終行",SPEAK_SENTENCE);
  443.         }
  444.     txSetDispExSilent(text);
  445.     return ret;
  446. }
  447.  
  448. int TXAPI TXCMD txspeakLeftWord(TX* text)
  449. {
  450. // カーソルを1つ前の単語へ移動
  451. // カーソルを1つ前の単語へ移動して、移動した部分の文字列をなめらか読みで読み上げる
  452. // 選択中は、選択を解除する
  453.     selectEnd(text,0);
  454.     IFILE adr = txGetAddress(text);
  455.     txSelectEx(text,CLIP_MOUSE);//3.00C 971016 Ctrl+左右で読み上げた文節を反転表示
  456.     {
  457.         int ret = txLeftWord(text);
  458.         if (ret) {
  459.             speakAddressCur(text,adr);
  460.         }
  461.         return ret;
  462.     }
  463. }
  464.  
  465. int TXAPI TXCMD txspeakRightWord(TX* text)
  466. {
  467. // カーソルを1つ後の単語へ移動
  468. // カーソルを1つ後の単語へ移動して、移動した部分の文字列をなめらか読みで読み上げる
  469. // 選択中は、選択を解除する
  470.     selectEnd(text,0);
  471.     IFILE adr = txGetAddress(text);
  472.     txSelectEx(text,CLIP_MOUSE);//3.00C 971016 Ctrl+左右で読み上げた文節を反転表示
  473.     {
  474.         int ret = txRightWord(text);
  475.         if (ret) {
  476.             speakAddressCur(text,adr);
  477.         }
  478.         return ret;
  479.     }
  480. }
  481.  
  482. int TXAPI TXCMD txspeakDeleteChar(TX* text)
  483. {
  484. // カーソル位置の文字を読み上げてから削除
  485. // 削除するまえに"削除"を読み上げるが、
  486. // このコマンドを連続して実行したときは、一回目だけ"削除"という。
  487. // 選択中は、"削除"を読み上げてから範囲内を読み上げて、範囲内を削除
  488.     if (selectEnd(text,VK_DELETE)) return 0;
  489.     if (_nRepeatDelete >= 2) {
  490.         // {Delete}が連続して押されたら「削除」と言わない
  491.     } else {
  492.         speakwait("削除",SPEAK_SENTENCE);
  493.     }
  494.     txspeakCur(text);
  495.     return txDeleteChar(text);
  496. }
  497.  
  498. int TXAPI TXCMD txspeakDeletePrev(TX* text)
  499. {
  500. // カーソル位置の1つ前の文字を読み上げてから削除
  501. // 削除するまえに"後退"を読み上げるが、
  502. // このコマンドを連続して実行したときは、一回目だけ"後退"という。
  503. // 選択中は、"削除"を読み上げてから範囲内を読み上げて、範囲内を削除
  504.     if (selectEnd(text,VK_BACK)) return 0;
  505.     if (_nRepeatBackspace >= 2) {
  506.         // {Backspace}が連続して押されたら「後退」と言わない
  507.     } else {
  508.         speakwait("後退",SPEAK_SENTENCE);
  509.     }
  510.     if (txLeft(text)) {
  511.         txspeakCur(text);
  512.         return txDeleteChar(text);
  513.     }
  514.     return 0;
  515. }
  516.  
  517. int TXAPI TXCMD txspeakselectLeft(TX* text)
  518. {
  519. // 選択してカーソルを1つ前の文字へ移動
  520. // 選択してカーソルを1つ前の文字へ移動して、カーソル位置の文字を読み上げる
  521.     selectStart(text);
  522.     int ret = txLeft(text);
  523.     if (ret) {
  524.         txspeakCur(text);
  525.     }
  526.     return ret;
  527. }
  528.  
  529. int TXAPI TXCMD txspeakselectRight(TX* text)
  530. {
  531. // 選択してカーソルを1つ後の文字へ移動
  532. // 選択してカーソルを1つ後の文字へ移動して、カーソル位置の文字を読み上げる
  533.     selectStart(text);
  534.     txspeakCur(text);
  535.     return txRight(text);
  536. }
  537.  
  538. int TXAPI TXCMD txspeakselectUp(TX* text)
  539. {
  540. // 選択してカーソルを1つ上の行へ移動
  541. // 選択してカーソルを1つ上の行へ移動して、カーソル位置の文字を読み上げる
  542.     selectStart(text);
  543.     int ret = txUp(text);
  544.     if (ret) {
  545.         txspeakCur(text);
  546.     }
  547.     return ret;
  548. }
  549.  
  550. int TXAPI TXCMD txspeakselectDown(TX* text)
  551. {
  552. // 選択してカーソルを1つ下の行へ移動
  553. // 選択してカーソルを1つ下の行へ移動して、カーソル位置の文字を読み上げる
  554.     selectStart(text);
  555.     int ret = txDown(text);
  556.     if (ret) {
  557.         txspeakCurPrev(text);
  558.     }
  559.     return ret;
  560. }
  561.  
  562. void TXAPI TXCMD txspeakSwitchInsert(TX* text)
  563. {
  564. // 上書き/挿入モードを切替
  565. // 上書き/挿入モードを切り替えて、現在のモードを読み上げる
  566.     txSwitchInsert(text);
  567.     if (text->fOverWrite) {
  568.         speak("上書き",SPEAK_SENTENCE);
  569.     } else {
  570.         speak("挿入",SPEAK_SENTENCE);
  571.     }
  572. }
  573.  
  574. int TXAPI TXCMD txspeakPrevPara(TX* text)
  575. {
  576. // 1つ上の段落の先頭へ移動
  577. // 1つ上の段落の先頭へ移動して、段落の内容をなめらか読みで読み上げる
  578.     int ret = txPrevPara(text);
  579.     if (ret) {
  580.         speakPara(text);
  581.     }
  582.     return ret;
  583. }
  584.  
  585. int TXAPI TXCMD txspeakNextPara(TX* text)
  586. {
  587. // 1つ下の段落の先頭へ移動
  588. // 1つ下の段落の先頭へ移動して、段落の内容をなめらか読みで読み上げる
  589.     int ret = txNextPara(text);
  590.     if (ret) {
  591.         speakPara(text);
  592.     }
  593.     return ret;
  594. }
  595.  
  596. int TXAPI TXCMD txspeakuiSearch(TX* text)
  597. {
  598. // 音声化検索
  599. // 検索文字列を見つけたら、行の内容をなめらかよみで読み上げ
  600.     static txstr szFind;    // 以前に検索した文字列を覚えておく
  601.     BOOL ret = FALSE;
  602.     HDIALOG hd = dialog("検索(音声付き)");
  603.     dialogStr(hd,"検索(&S):",szFind,12,30);
  604.     if (dialogOpen(hd)) {
  605.         histAdd(HIST_SEARCH,szFind);//3.00A2 970504 
  606.         if (txSearchEx(text,szFind,SEARCH_SELECT)) {
  607.             speakLine(text);
  608.             ret = TRUE;
  609.         }
  610.     }
  611.     return ret;
  612. }
  613.  
  614. int TXAPI TXCMD txspeakuiSearchCharkind(TX* text)
  615. {
  616. // 音声化文字種検索
  617. // 指定した文字種を見つけたら、行の内容をなめらかよみで読み上げ
  618. // 検索できる文字種は次のとおり。
  619. // "全角カタカナ","半角カタカナ","全角英文字","半角英文字","漢字"
  620.     static int kind;    // 以前に文字種を覚えておく
  621.     BOOL ret = FALSE;
  622.     HDIALOG hd = dialog("文字種で検索(音声付き)");
  623.     dialogControlRadioV(hd);
  624.     dialogRadioID(hd,&kind,"全角カタカナ","半角カタカナ","全角英文字","半角英文字","漢字");
  625.     if (dialogOpen(hd)) {
  626.         static mchar *tsz[] = {
  627.             "[ァ-ヶ]","[ヲ-ン]","[A-Za-z]","[A-Za-z]","[亜-黑]",
  628.         };
  629.         if (txSearchEx(text,tsz[kind],SEARCH_RE)) {
  630.             speakLine(text);
  631.         }
  632.     }
  633.     return ret;
  634. }
  635.  
  636. void TXAPI TXCMD txspeakCurAtr(TX* text)
  637. {
  638. // カーソル位置の段落体裁、文字装飾を読み上げ
  639.     mchar sz[CCHLINE];
  640.     mchar*p = sz;
  641.     
  642.     // 段落書式
  643.     if (text->paraatr.modeTitle) {
  644.         sprintf(p,"見出%d ",text->paraatr.modeTitle);
  645.         p += strlen(p);
  646.     }
  647.     if (text->paraatr.modeArticle) {
  648.         strcpy(p,"箇条書き ");
  649.         p += strlen(p);
  650.     }
  651.     if (text->paraatr.lcxIndent) {
  652.         strcpy(p,"字下げ ");
  653.         p += strlen(p);
  654.     }
  655.     switch(paraatrGetAlign(text,&text->paraatr)) {
  656.         case ALIGN_CENTER: {
  657.             strcpy(p,"中央揃え ");
  658.             p += strlen(p);
  659.             break;
  660.         }
  661.         case ALIGN_RIGHT: {
  662.             strcpy(p,"右揃え ");
  663.             p += strlen(p);
  664.             break;
  665.         }
  666.     }
  667.     if (txIsCurTable(text)) {
  668.         strcpy(p,"表 ");
  669.         p += strlen(p);
  670.     } else if (txIsCurTab(text)) {
  671.         strcpy(p,"桁揃え ");
  672.         p += strlen(p);
  673.     }
  674.     *p = 0;
  675.     // 文字装飾
  676.     if (text->charatr.fBold) {
  677.         strcpy(p,"太字 ");
  678.         p += strlen(p);
  679.     }
  680.     if (text->charatr.fUnderline) {
  681.         strcpy(p,"下線 ");
  682.         p += strlen(p);
  683.     }
  684.     if (text->charatr.fItalic) {
  685.         strcpy(p,"斜体 ");
  686.         p += strlen(p);
  687.     }
  688.     *p = 0;
  689.     speak(sz,SPEAK_SENTENCE);
  690. }
  691.  
  692. void TXAPI TXCMD txspeakCurLocate(TX* text)
  693. {
  694. // カーソル位置の段落数、列数を読み上げ
  695. // スクロールバーでのスクロールには対応していない
  696.     int lx = text->lx + 1;
  697.     mchar buff[CCHLINE];
  698.     if (text->editmode == 2) {
  699.         sprintf(buff,"%d頁%d行%d列 %d段落",text->npage,text->nlineByPage,lx,text->npara);
  700.     } else {
  701.         sprintf(buff,"%d段落 %d列",text->npara,lx);
  702.     }
  703.     speak(buff,SPEAK_SENTENCE);
  704. }
  705.  
  706. int TXAPI TXCMD txspeakLeftKuten(TX* text)
  707. {
  708. // 1つ前の文へ移動
  709. // 1つ前の句点(。。..)の1つ後ろの文字へ移動し、次の句点までの文章を読み上げる
  710.     txLeft(text);
  711.     if (txSearchKuten(text,SEARCH_PREV)) {
  712.         txRight(text);
  713.         speakCurKuten(text);
  714.         return TRUE;
  715.     }
  716.     return FALSE;
  717. }
  718.  
  719. int TXAPI TXCMD txspeakRightKuten(TX* text)
  720. {
  721. // 1つ後の文へ移動
  722. // 1つ後の句点(。。..)の1つ後ろの文字へ移動し、次の句点までの文章を読み上げ
  723.     if (txSearchKuten(text,0)) {
  724.         txRight(text);
  725.         speakCurKuten(text);
  726.         return TRUE;
  727.     }
  728.     return FALSE;
  729. }
  730.  
  731. int TXAPI TXCMD txspeakLeftDokuten(TX* text)
  732. {
  733. // 1つ前のセンテンスへ移動
  734. // 1つ前の読点(、、,,)の1つ後ろの文字へ移動し、次の読点までの文章を読み上げ
  735.     txLeft(text);
  736.     if (txSearchDokuten(text,SEARCH_PREV)) {
  737.         txRight(text);
  738.         speakCurDokuten(text);
  739.         return TRUE;
  740.     }
  741.     return FALSE;
  742. }
  743.  
  744. int TXAPI TXCMD txspeakRightDokuten(TX* text)
  745. {
  746. // 1つ後のセンテンスへ移動
  747. // 1つ後の読点(、、,,)の1つ後ろの文字へ移動し、次の読点までの文章を読み上げ
  748.     if (txSearchDokuten(text,0)) {
  749.         txRight(text);
  750.         speakCurDokuten(text);
  751.         return TRUE;
  752.     }
  753.     return FALSE;
  754. }
  755.  
  756. int TXAPI TXCMD txspeakSearchTitlePrev(TX* text)
  757. {
  758. // カーソル位置の1つ前の見出し行へ移動し、行を読み上げ
  759.     int ret = txSearchTitlePrev(text);
  760.     if (ret) {
  761.         speakLine(text);
  762.     }
  763.     return ret;
  764. }
  765.  
  766. int TXAPI TXCMD txspeakSearchTitle(TX* text)
  767. {
  768. // カーソル位置の1つ後の見出し行へ移動し、行を読み上げ
  769.     int ret = txSearchTitle(text);
  770.     if (ret) {
  771.         speakLine(text);
  772.     }
  773.     return ret;
  774. }
  775.  
  776. //## 設定
  777.  
  778. //3.00A5 970511 WZ音声化の設定を付けた
  779. txspeakConfig
  780. {
  781. // WZ音声化の設定
  782. //3.00A5 970511 new
  783.     HDIALOG hd = dialog("WZ音声化の設定");
  784.     dialogSelectID(hd,"上下方向キーで移動後の読み上げ(&Y):",&_fSpeakLine,40,22,"カーソル位置の文字","カーソル位置から行末まで");
  785.     dialogControlGuide(hd,"ミリ秒",6);
  786.     dialogInt(hd,"「削除」・「後退」を発声後の待ち時間(&W):",&_msWaitDelete,40,6);
  787.     dialogOpen(hd);
  788. }
  789.  
  790. //## WZ filer 音声化
  791.  
  792. #include "filer.h"
  793.  
  794. static void speakfilerLine(void)
  795. {
  796. // カーソルの行の内容をなめらか読みで読み上げる
  797. // 最大CCHLINE-1バイトまでの文字列を読めます
  798.     txstr sz(CCHLINE);
  799. #if 1//3.00C1 971017 ファイラーの読み上げで必ずファイル名を最初に読み上げる様にした
  800.     filerGetLineEx(sz);
  801. #else
  802.     filerGetLine(sz);
  803. #endif
  804.     speak(sz,SPEAK_SENTENCE);
  805. }
  806.  
  807. static void speakfilerFilename(void)
  808. {
  809. // カーソルの行のファイル名をなめらか読みで読み上げる
  810. // 最大CCHLINE-1バイトまでの文字列を読めます
  811.     txstr sz(CCHLINE);
  812.     filerGetFilename(sz);
  813.     speak(sz,SPEAK_SENTENCE);
  814. }
  815.  
  816. // WZ Filerでカーソルを1行上に移動し、カーソル行の内容を読み上げ
  817. txspeakfilerUp
  818. {
  819. #if 1///3.00A 970501 
  820.     txkeyUp(text,1);
  821.     speakfilerLine();
  822. #else
  823.     call("filer.up");
  824.     speakfilerLine();
  825. #endif
  826. }
  827.  
  828. // WZ Filerでカーソルを1行下に移動し、カーソル行の内容を読み上げ
  829. txspeakfilerDown
  830. {
  831. #if 1///3.00A 970501 
  832.     txkeyDown(text,1);
  833.     speakfilerLine();
  834. #else
  835.     call("filer.down");
  836.     speakfilerLine();
  837. #endif
  838. }
  839.  
  840. // WZ Filerでカーソルを1行上に移動してから行を選択し、カーソル行のファイル名を読み上げ
  841. txspeakfilerSelectUp
  842. {
  843.     call("filer.sup");
  844.     speakfilerFilename();
  845. }
  846.  
  847. // WZ Filerで現在行を選択してカーソルを1行上に移動し、カーソル行のファイル名を読み上げ
  848. txspeakfilerSelectDown
  849. {
  850.     speakfilerFilename();
  851.     call("filer.sdown");
  852. }
  853.  
  854. // WZ Filerのファイル一覧ウィンドウのタイトルを読み上げ
  855. txspeakfilerTitle
  856. {
  857.     txstr sz;
  858.     filerGetTitle(sz);
  859.     speak(sz,SPEAK_SENTENCE);
  860. }
  861.  
  862. //##初期化、終了処理、フックプロシジャー
  863.  
  864. void TXAPI txspeakSetKey(TX* text)
  865. {
  866. //3.00C 971016 関数化
  867.     if (text->fSpeakOn) {
  868.         mchar sztxename[CCHPATHNAME];
  869.         GetTxeName(sztxename);
  870. //information(sztxename);
  871.         if (!stricmp(sztxename,"filer")) {
  872.             #key
  873.                 .txspeakfilerUp            {Up}
  874.                 .txspeakfilerDown        {Down}
  875.                 .txspeakfilerSelectUp    +{Up}
  876.                 .txspeakfilerSelectDown    +{Down}
  877.                 .txspeakfilerTitle        ^%R
  878.             #end
  879.         } else if (
  880.             !stricmp(sztxename,"") ||
  881.             !stricmp(sztxename,"grep") ||
  882.             !stricmp(sztxename,"stdout")    //3.00B1 970613 WZ Stdoutも音声化対応
  883.         ) {
  884.             #key
  885.                 .txspeakLeft                {Left}
  886.                 .txspeakRight                {Right}
  887.                 .txspeakUp                    {Up}
  888.                 .txspeakDown                {Down}
  889.                 .txspeakLeftWord            ^{Left}
  890.                 .txspeakRightWord            ^{Right}
  891.                 .txspeakDeleteChar            {Delete}
  892.                 .txspeakDeletePrev            {Backspace}
  893.                 .txspeakselectLeft            +{Left}
  894.                 .txspeakselectRight            +{Right}
  895.                 .txspeakselectUp            +{Up}
  896.                 .txspeakselectDown            +{Down}
  897.                 .txspeakSwitchInsert        {Insert}
  898.                 .txspeakuiSearch            ^F
  899.                 .txspeakCurAtr                ^%I
  900.                 .txspeakCurChar                ^%H
  901.                 .txspeakCurLocate            ^%L
  902.                 .txspeakLeftKuten            +^%K
  903.                 .txspeakRightKuten            ^%K
  904.                 .txspeakLeftDokuten            +^%D
  905.                 .txspeakRightDokuten        ^%D
  906.                 .txspeakLinetop                ^%{Home}    //3.00C 971016 
  907.                 .txspeakLineend                ^%{End}        //3.00C 971016 
  908.                 .txspeakLineprev            %{Up}        //3.00C 971016 
  909.                 .txspeakLinenext            %{Down}        //3.00C 971016 
  910.             #end
  911. #if 1//3.00A2 970504 95Readerを起動するとCtrl+Up,Ctrl+Down,Shift+Ctrl+F入力できない
  912.             #key
  913.                 .txspeakPrevPara            ^%{Up}
  914.                 .txspeakNextPara            ^%{Down}
  915.                 .txspeakuiSearchCharkind    ^%F
  916.             #end
  917. #else
  918.             #key
  919.                 .txspeakPrevPara            ^{Up}
  920.                 .txspeakNextPara            ^{Down}
  921.                 .txspeakuiSearchCharkind    +^F
  922.             #end
  923. #endif
  924.             if (!stricmp(GetTxeName(sztxename),"grep")) {
  925. #if 1//3.00A2 970504 Ctrl+TabはWZ3.0から使えないのでキー割り当て変更
  926.                 #key
  927.                     .txspeakSearchTitlePrev    ^R
  928.                     .txspeakSearchTitle        ^C
  929.                 #end
  930. #else
  931.                 #key
  932.                     .txspeakSearchTitlePrev    +^{Tab}
  933.                     .txspeakSearchTitle        ^{Tab}
  934.                 #end
  935. #endif
  936.             }
  937.         }
  938.     }
  939. }
  940.  
  941. main
  942. {
  943.     text->fSpeakOn = text->fSpeakOn ^ 1;
  944.     if (text->fSpeakOn) {
  945.         text->fReport++;//3.00A2 970504 
  946.         txspeakSetKey(text);
  947.         statprintf("スピークモード");
  948.     } else {
  949.         text->fReport--;//3.00A2 970504 
  950.         txKeyLoad(text);
  951.         statprintf("通常モード");
  952.     }
  953. }
  954.  
  955. HOOKRESULT __wndproctext(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  956. {
  957.     TX* text = textTarget;
  958.     if (!text->fSpeakOn) return HOOK_CONTINUE;
  959.     switch(message) {
  960.         case WM_KEYDOWN: {
  961.             if (wParam == VK_DELETE) {
  962.                 _nRepeatDelete++;
  963.             } else {
  964.                 _nRepeatDelete = 0;
  965.             }
  966.             if (wParam == VK_BACK) {
  967.                 _nRepeatBackspace++;
  968.             } else {
  969.                 _nRepeatBackspace = 0;
  970.             }
  971.             break;
  972.         }
  973.         case WM_KEYUP: {
  974.             if (wParam == VK_SHIFT) {
  975.                 if (text->fClipMouse) {
  976.                     speakSelect(text);
  977.                 }
  978.             }
  979.             break;
  980.         }
  981.         case WM_TXREPORT: {
  982.             if (wParam == TXREPORT_KEY_INSERTSTR) {
  983.                 if (!imeGetOpen()) {
  984.                     TXREPORT* r = (LPVOID)lParam;
  985.                     speak(r->pStr,SPEAK_CURSOR);
  986.                 }
  987.             }
  988.             break;
  989.         }
  990.     }
  991.     return HOOK_CONTINUE;
  992. }
  993.  
  994. HOOKRESULT __wndprocbase(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  995. {
  996.     TX* text = textTarget;
  997.     if (!text->fSpeakOn) return HOOK_CONTINUE;
  998.     switch(message) {
  999.         case WM_COMMAND: {
  1000.             int idm = LOWORD(wParam);
  1001.             if (idm == _idmSearch) {
  1002.                 txspeakuiSearch(text);
  1003.                 return HOOK_CAPTURE;
  1004.             }
  1005.             break;
  1006.         }
  1007.     }
  1008.     return HOOK_CONTINUE;
  1009. }
  1010.  
  1011. __new
  1012. {
  1013.     macroHookWndText();
  1014.     macroHookWndBase();
  1015. #if 1//3.00A2 970504 
  1016.     _idmSearch = IDM_WZCMDTOP + wzcmdRegister("search.txkeySearch");
  1017. #else
  1018.     _idmSearch = IDM_WZCMDTOP + wzcmdRegister("search.uiSearchModeless");
  1019. #endif
  1020. }
  1021.  
  1022.