home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1999 October / VPR9910A.BIN / APUPDATE / VC / TXC2M328 / txc2m328.lzh / _EMACSWZ.C next >
C/C++ Source or Header  |  1999-03-03  |  23KB  |  944 lines

  1. /*
  2.     _EMACSWZ.C
  3.         emacs like key assign
  4.         98年11月 1日 日曜 start
  5.     
  6.     EMACS like keybind 実装にあたり、
  7.     中村 学 (Nakamura Manabu)さんのEMACSWZと、
  8.     UK-TaniyamaさんのEMACSWZを参考にさせて頂きました。
  9.     ありがとうございます。
  10.     
  11.     キーボードマクロには、WZ基本コマンドしか記録されません。
  12.     EMACSWZによる拡張コマンドは記録されません。
  13.     
  14.     Emacsキー定義にこのマクロプログラムを使用するには、「TX-Cの設定」で
  15.     イベントマクロに_emacswzを追加してください。
  16. */
  17.  
  18. #ifdef __TXC__
  19.     #include "_wz.h"
  20.     #include "_idmcmd.h"
  21.     #include <windows.h>
  22. #else
  23.     #include "wz.h"
  24. #endif
  25.  
  26. #if defined(__TXC__) || !WINDOWSCE
  27.  
  28. #define EMACSCMD    // コマンド関数であることを表わす
  29.  
  30. struct tag_EMACSWZ_CONTEXT {
  31.     mchar szIsearch[CCHWORD];
  32.     mchar szIsearch0[CCHWORD];
  33.     SEARCHMODE Isearchmode;
  34.     BOOL fIsearching;
  35.     BOOL fIsearchWrapped;
  36.     BOOL fIsearchLastFail;
  37.     IFILE adrIsearch;
  38.     IFILE adrIsearch0;
  39.     int chPrefix;    // {Esc} | Ctrl+X
  40. //    static BOOL _fStatBasePrinting = FALSE;
  41. //    static mchar _chPrefix = 0;
  42. //    static BOOL _fImeOpen = FALSE;//3.00A4 970509 
  43. } EMACSWZ_CONTEXT;
  44.  
  45. static int _idmFirst;
  46. static int _idmLast;
  47. static int _idm_kill_line;
  48. static int _idm_isearch_backward;
  49. static int _idm_isearch_forward;
  50. static int _idm_isearch_forward_regexp;
  51. //
  52. static int _idm_prefix_ctrlx;
  53. static int _idm_prefix_escape;
  54.  
  55. //##incremental-search
  56.  
  57. static void isearch_statprint(TX* text,BOOL find,SEARCHMODE searchmode)
  58. {
  59.     mchar sz[CCHTXSTR] = {0};
  60.     if (!find) strcat(sz,"Failing ");
  61.     if (text->emacswz->fIsearchWrapped) strcat(sz,"Wrapped ");
  62.     if (searchmode & SEARCH_REWZ) strcat(sz,"Regexp ");
  63.     strcat(sz,"I-search");
  64.     if (searchmode & SEARCH_PREV) strcat(sz," backward");
  65.     strcat(sz,": ");
  66.     sstrcat(sz,text->emacswz->szIsearch);
  67.     txStatusbarPrintf(text,sz);
  68. }
  69.  
  70. static BOOL isearchIsContinueIdm(int idm)
  71. {
  72. //WZ4.00Ab 990124 new
  73.     if (idm == _idm_isearch_backward) return TRUE;
  74.     if (idm == _idm_isearch_forward) return TRUE;
  75.     if (idm == _idm_isearch_forward_regexp) return TRUE;
  76.     return FALSE;
  77. }
  78.  
  79. static BOOL isearchIsContinue(TX* text)
  80. {
  81.     return isearchIsContinueIdm(text->idmLast);
  82. }
  83.  
  84. static void isearch_next(TX* text,SEARCHMODE searchmode)
  85. {
  86.     SEARCHMODE mode = SEARCH_FORWARD|SEARCH_NOSENSECASE|searchmode;
  87.     if (text->emacswz->szIsearch[0]) {
  88.         BOOL ret = FALSE;
  89.         IFILE adr = txGetAddress(text);
  90.         IFILE adrCurscreen = txGetAddressCurscreen(text);
  91.         int ly = text->ly;
  92.         txSetUndisp(text);
  93.         if (text->emacswz->fIsearchLastFail) {
  94.             text->emacswz->fIsearchLastFail = FALSE;
  95.             if (mode & SEARCH_PREV) {
  96.                 txJumpFileEnd(text);
  97.             } else {
  98.                 txJumpFileTop(text);
  99.             }
  100.             text->emacswz->fIsearchWrapped = TRUE;
  101.         }
  102.         ret = txSearchEx(text,text->emacswz->szIsearch,mode);
  103.         if (!ret) {
  104.             text->emacswz->fIsearchLastFail = TRUE;
  105.         }
  106.         if (ret) {
  107.             text->emacswz->adrIsearch = txGetAddress(text);
  108.             if ((mode & SEARCH_PREV) && !(mode & SEARCH_CUR)) {
  109.                 // 連続実行時でBackward時は実行しない
  110.             } else {
  111.                 txRightBytes(text,ret-1);
  112.             }
  113.             txSetLy(text,ly);
  114.         } else {
  115.             txJumpAddress(text,adr);
  116.             txSetLyCurscreen(text,adrCurscreen);
  117.         }
  118.         txSetDisp(text);
  119.         isearch_statprint(text,ret,mode);
  120.         strcpy(text->emacswz->szIsearch0,text->emacswz->szIsearch);
  121.     } else {
  122.         isearch_statprint(text,TRUE,searchmode);
  123.     }
  124. }
  125.  
  126. static void isearch(TX* text,SEARCHMODE searchmode)
  127. {
  128.     if (isearchIsContinue(text)) {
  129.         // 連続実行
  130.         if (!text->emacswz->fIsearching) {
  131.             text->emacswz->fIsearching = TRUE;
  132.         }
  133.         if (!text->emacswz->szIsearch[0]) strcpy(text->emacswz->szIsearch,text->emacswz->szIsearch0);
  134.         isearch_next(text,searchmode|text->emacswz->Isearchmode);
  135.     } else {
  136. //        if (!text->emacswz->fIsearching) {
  137.             text->emacswz->fIsearching = TRUE;
  138.             text->emacswz->szIsearch[0] = 0;
  139.             text->emacswz->fIsearchWrapped = FALSE;
  140.             text->emacswz->adrIsearch0 = text->emacswz->adrIsearch = txGetAddress(text);
  141.             text->emacswz->fIsearchLastFail = FALSE;
  142.             text->emacswz->Isearchmode = searchmode & SEARCH_REWZ;
  143. //        }
  144.         isearch_next(text,searchmode|SEARCH_CUR);
  145.     }
  146. }
  147.  
  148. static void EMACSCMD isearch_backward(TX* text)
  149. {
  150. // インクリメンタルサーチ(上方向)
  151.     isearch(text,SEARCH_PREV);
  152. }
  153.  
  154. static void EMACSCMD isearch_forward(TX* text)
  155. {
  156. // インクリメンタルサーチ(下方向)
  157.     isearch(text,0);
  158. }
  159.  
  160. static void EMACSCMD isearch_forward_regexp(TX* text)
  161. {
  162.     isearch(text,SEARCH_REWZ);
  163. }
  164.  
  165. static void EMACSCMD isearch_quit(TX* text)
  166. {
  167. //WZ4.00Ab 990124 new
  168.     if (text->emacswz->fIsearching) {
  169.         text->emacswz->fIsearching = FALSE;
  170.         txStatusbarPrintf(text,NULL);
  171.     }
  172. }
  173.  
  174. //##emacs base function
  175.  
  176. static void EMACSCMD kill_region(TX* text)
  177. {
  178.     txSetUndisp(text);
  179.         txJumpMarkCur(text);
  180.         txSelectEx(text,CLIP_CHAR);
  181.         txJumpMarkCur(text);
  182.         txIdmExec(text,IDM_CUT);
  183.     txSetDisp(text);
  184.     statprintf("Region cuted");
  185. }
  186.  
  187. static void EMACSCMD copy_region_as_kill(TX* text)
  188. {
  189.     txSetUndisp(text);
  190.         txJumpMarkCur(text);
  191.         txSelectEx(text,CLIP_CHAR);
  192.         txJumpMarkCur(text);
  193.         txIdmExec(text,IDM_COPY);    //WZ4.00A 981230 Emacsライクキー定義で、Esc-Wにカットが割り当てられていたが、コピーに変更した。
  194.     txSetDisp(text);
  195.     statprintf("Region copyed");
  196. }
  197.  
  198. static void EMACSCMD fill_paragraph(TX* text)
  199. {
  200.     txIdmExec(text,IDM_FORM);
  201. }
  202.  
  203. static void EMACSCMD goto_line(TX* text)
  204. {
  205.     txIdmExec(text,IDM_UIJUMP);
  206. }
  207.  
  208. static void EMACSCMD transpose_words(TX* text)
  209. {
  210.     mchar src[CCHTXSTR];
  211.     mchar dst[CCHTXSTR];
  212.     txSetUndisp(text);
  213.     //
  214.     txJumpWordTopMi(text);
  215.     txSelectEx(text,CLIP_CHAR);
  216.     txJumpWordEndMi(text);
  217.     if (txGetChar(text) == ' ') {
  218.         txJumpWordEndMi(text);
  219.     }
  220.     txGetWordEx(text,src,cchof(src));
  221.     txSelectDelete(text);
  222.     //
  223.     txSelectEx(text,CLIP_CHAR);
  224.     txLeftWordMi(text);
  225.     if (txGetChar(text) == ' ') {
  226.         txLeftWordMi(text);
  227.     }
  228.     txGetWordEx(text,dst,cchof(dst));
  229.     txSelectDelete(text);
  230.     //
  231.     txInsert(text,src);
  232.     txInsert(text,dst);
  233.     //
  234.     txSetDisp(text);
  235. }
  236.  
  237. static void EMACSCMD back_to_indentation(TX* text)
  238. {
  239.     txSetUndisp(text);
  240.         txJumpParaTop(text);
  241.         while(1) {
  242.             TXCHAR ch = txReadChar(text);
  243.             if (ch != '\t' && ch != ' ') break;
  244.             if (txIsCurEof(text)) break;
  245.         }
  246.         txLeft(text);
  247.     txSetDisp(text);
  248. }
  249.  
  250. static void EMACSCMD kill_word(TX* text)
  251. {
  252.     txDeleteWord(text);
  253. }
  254.  
  255. static void EMACSCMD backward_word(TX* text)
  256. {
  257.     txLeftWordMi(text);
  258. }
  259.  
  260. static void EMACSCMD forward_word(TX* text)
  261. {
  262.     txRightWordMi(text);
  263. }
  264.  
  265. static void capitalize(TX* text,BOOL fWord,BOOL fTolower)
  266. {
  267.     if (txIsCurReturn(text)) {
  268.         //WZ3.90I 981102 改行でのcapitalizeを改良。
  269.         txRight(text);
  270.     } else {
  271.         txSetUndisp(text);
  272.         {
  273.             mchar buff[CCHTXSTR];
  274.             if (!text->fClip) {
  275.                 txSelect(text);
  276.                 if (fWord) {
  277.                     txJumpWordEndMi(text);
  278.                 } else {
  279.                     txRight(text);
  280.                 }
  281.             }
  282.             txGetWordEx(text,buff,cchof(buff));
  283.             if (fTolower) {
  284.                 strlwr(buff);
  285.             } else {
  286.                 strupr(buff);
  287.             }
  288.             txSelectDelete(text);
  289.             txInsert(text,buff);
  290.             txJumpWordEndMi(text);
  291.         }
  292.         txSetDisp(text);
  293.     }
  294. }
  295.  
  296. static void EMACSCMD capitalize_word(TX* text)
  297. {
  298.     capitalize(text,FALSE,FALSE);
  299. }
  300.  
  301. static void EMACSCMD downcase_word(TX* text)
  302. {
  303.     capitalize(text,TRUE,TRUE);
  304. }
  305.  
  306. static void EMACSCMD upcase_word(TX* text)
  307. {
  308.     capitalize(text,TRUE,FALSE);
  309. }
  310.  
  311. static void EMACSCMD beginning_of_buffer(TX* text)
  312. {
  313.     txMarkCur(text);
  314.     txJumpFileTop(text);
  315.     statprintf("Mark set");
  316. }
  317.  
  318. static void EMACSCMD end_of_buffer(TX* text)
  319. {
  320.     txMarkCur(text);
  321.     txJumpFileEnd(text);
  322.     statprintf("Mark set");
  323. }
  324.  
  325. static void EMACSCMD query_replase(TX* text)
  326. {
  327.     txIdmExec(text,IDM_UIREPLACEQUERY);
  328. }
  329.  
  330. static void EMACSCMD backward_paragraph(TX* text)
  331. {
  332.     txJumpParaTop(text);
  333. }
  334.  
  335. static void EMACSCMD forward_paragraph(TX* text)
  336. {
  337.     txJumpParaEnd(text);
  338. }
  339.  
  340. static void EMACSCMD beginning_of_defun(TX* text)
  341. {
  342.     txSearchEx(text,"^[{]",SEARCH_REWZ|SEARCH_PREV);
  343. }
  344.  
  345. static void EMACSCMD end_of_defun(TX* text)
  346. {
  347.     txSearchEx(text,"^[}]",SEARCH_REWZ|SEARCH_PREV);
  348. }
  349.  
  350. static void EMACSCMD backward_sexp(TX* text)
  351. {
  352.     txSetUndisp(text);
  353.         //WZ3.90I 981102 WZ4.0の正規表現に対応
  354.         txSearchEx(text,"\\x5D|\\x7D|\\x29",SEARCH_REWZ|SEARCH_PREV);    // ]})
  355.         txJumpBrace(text);
  356.     txSetDisp(text);
  357. }
  358.  
  359. static void EMACSCMD forward_sexp(TX* text)
  360. {
  361.     txSetUndisp(text);
  362.         //WZ3.90I 981102 WZ4.0の正規表現に対応
  363.         txSearchEx(text,"\\x5B|\\x7B|\\x28",SEARCH_REWZ|SEARCH_CUR);    // [{(
  364.         txJumpBrace(text);
  365.         txRight(text);
  366.     txSetDisp(text);
  367. }
  368.  
  369. static void EMACSCMD call_last_kbd_macro(TX* text)
  370. {
  371. #if 1    // ^x^eの動作が変だった。
  372.     PostMessage(text->hwndtext,WM_TXEMACS_TXCMD,IDM_KEYMACROPLAY,0);
  373. #else
  374.     txIdmExec(text,IDM_KEYMACROPLAY);
  375. #endif
  376. }
  377.  
  378. static void _start_kbd_macro(TX* text)
  379. {
  380.     if (sh->fMacroRec) txIdmExec(text,IDM_KEYMACRORECORD);    // 既に記録中の場合は抜ける。
  381.     txIdmExec(text,IDM_KEYMACRORECORD);
  382.     statprintf("Defining kbd macro...");
  383. }
  384. static void EMACSCMD start_kbd_macro(TX* text)
  385. {
  386.     PostMessage(text->hwndtext,WM_TXEMACS_TXCMD,IDM_KEYMACRORECORD,0);
  387. }
  388.  
  389. static void _end_kbd_macro(TX* text)
  390. {
  391.     if (sh->fMacroRec) {
  392.         txIdmExec(text,IDM_KEYMACRORECORD);
  393.         statprintf("Keyboard macro defined");
  394.     }
  395. }
  396. static void EMACSCMD end_kbd_macro(TX* text)
  397. {
  398.     PostMessage(text->hwndtext,WM_TXEMACS_TXCMD,IDM_KEYMACRORECORD,TRUE);
  399. }
  400.  
  401. static void EMACSCMD advertised_undo(TX* text)
  402. {
  403.     txUndo(text);
  404.     statprintf("Undo!");
  405. }
  406.  
  407. static void EMACSCMD kill_buffer(TX* text)
  408. {
  409.     txuiClose(text);
  410. }
  411.  
  412. static void EMACSCMD insert_file(TX* text)
  413. {
  414.     txuiInsertFile(text);
  415. }
  416.  
  417. static void EMACSCMD other_window(TX* text)
  418. {
  419.     txSwitchWindow(text);
  420. }
  421.  
  422. static void EMACSCMD mark_whole_buffer(TX* text)
  423. {
  424.     txSetUndisp(text);
  425.         txJumpFileEnd(text);
  426.         txMarkCur(text);
  427.         txJumpFileTop(text);
  428.     txSetDisp(text);
  429. }
  430.  
  431. static void EMACSCMD set_fill_column(TX* text)
  432. {
  433.     txIdmExec(text,IDM_UIFORMPROPERTY);
  434. }
  435.  
  436. static void EMACSCMD dired(TX* text)
  437. {
  438.     txIdmExec(text,IDM_FILER);
  439. }
  440.  
  441. static void EMACSCMD delete_other_windows(TX* text)
  442. {
  443.     txIdmExec(text,IDM_SWITCHSPLIT);    // とりあえず
  444. }
  445.  
  446. static void EMACSCMD split_window_vertically(TX* text)
  447. {
  448.     txIdmExec(text,IDM_SWITCHSPLIT);    // とりあえず
  449. }
  450.  
  451. static void EMACSCMD suspend_emacs(TX* text)
  452. {
  453. // DOS PROMPT
  454. #if !WINDOWSCE
  455.     if (_platform == WINDOWSNT) {
  456.         shellOpenW(L"cmd.exe");
  457.     } else {
  458.         shellOpenW(L"dosprmpt.pif");
  459.     }
  460. #endif
  461. }
  462.  
  463. static void EMACSCMD save_buffers_kill_emacs(TX* text)
  464. {
  465.     txuiCloseAllEvery(text);
  466. }
  467.  
  468. static void EMACSCMD toggle_read_only(TX* text)
  469. {
  470.     txIdmExec(text,IDM_SWITCHREADMODE);
  471. }
  472.  
  473. static void EMACSCMD save_buffer(TX* text)
  474. {
  475.     if (!text->fEdit) {
  476.         statprintf("(No changes need to be saved)");
  477.     } else {
  478.         if (txuiSave(text)) {
  479.             statprintf("Wrote %s",text->szfilename);
  480.         }
  481.     }
  482. }
  483.  
  484. static void EMACSCMD write_file(TX* text)
  485. {
  486.     txuiSaveTo(text);
  487. }
  488.  
  489. static void EMACSCMD exchange_point_and_mark(TX* text)
  490. {
  491.     txJumpMarkCur(text);
  492.     txSetLyCenter(text);
  493. }
  494.  
  495. static void EMACSCMD list_buffers(TX* text)
  496. {
  497.     txIdmExec(text,IDM_UIWINDOWLIST);
  498. }
  499.  
  500. static void EMACSCMD kill_line(TX* text)
  501. {
  502. // カーソル位置から行末までを削除します。
  503. // カーソル位置が改行なら、改行を削除します。
  504. // 削除した文字列をクリップボードにコピーします。
  505. // 連続実行するとクリップボードに追加します。
  506.     TX* textWork = NULL;
  507.     txSetUndisp(text);
  508.     {
  509. //information("%d %d",text->idmLast,_idm_kill_line);
  510.         if (text->idmLast == _idm_kill_line) {
  511.             // ^K連続実行でクリップボードに出力
  512.             textWork = textopen(NULL);
  513.             txIdmExec(textWork,IDM_PASTE);
  514.         }
  515.         txSelectEx(text,CLIP_CHAR);
  516.         if (txIsCurReturn(text)) {
  517.             txRight(text);
  518.         } else {
  519.             txJumpParaEnd(text);
  520.         }
  521.         if (textWork) {
  522.             txJumpFileEnd(textWork);
  523.             txInsertTextSelect(textWork,text);
  524.             txSelectDelete(text);
  525.             txSelectEx(textWork,CLIP_ALL);
  526.             txIdmExec(textWork,IDM_COPY);
  527.             textclose(textWork);
  528.         } else {
  529.             txIdmExec(text,IDM_CUT);
  530.         }
  531.     }
  532.     txSetDisp(text);
  533. }
  534.  
  535. static void EMACSCMD c_indent_command(TX* text)
  536. {
  537.     txIdmExec(text,IDM_TAB);
  538. }
  539.  
  540. static void EMACSCMD recenter(TX* text)
  541. {
  542. // カーソルを画面中央にセットし、画面表示をリフレッシュ
  543.     txSetUndisp(text);
  544.         txSetLyCenter(text);
  545.     txSetDisp(text);
  546. }
  547.  
  548. static void EMACSCMD quoted_insert(TX* text)
  549. {
  550. //    なにもしない
  551. }
  552.  
  553. static void EMACSCMD keyboard_quit(TX* text)
  554. {
  555. // インクリメンタルサーチ等の取り消し
  556.     isearch_quit(text);
  557.     if (isearchIsContinue(text)) {
  558.         txJumpAddress(text,text->emacswz->adrIsearch0);
  559.     }
  560.     statprintf("Quit");
  561. }
  562.  
  563. static void EMACSCMD transpose_chars(TX* text)
  564. {
  565. // カーソル位置と左の文字を入れ替え
  566.     if (txIsCurReturn(text)) return;
  567.     txSetUndisp(text);
  568.         txSelectQuit(text);
  569.         {
  570.             TXCHAR ch = txGetChar(text);
  571.             txDeleteChar(text);
  572.             txLeft(text);
  573.             txInsertChar(text,ch);
  574.             txRight(text);
  575.         }
  576.     txSetDisp(text);
  577. }
  578.  
  579. static void EMACSCMD toggle_ime_mode(TX* text)
  580. {
  581.     wndImeSetOpen(text->hwndtext,!wndImeGetOpen(text->hwndtext));
  582. }
  583.  
  584. static void EMACSCMD scroll_down(TX* text)
  585. {
  586.     txIdmExec(text,IDM_PAGEUP);
  587. }
  588.  
  589. static void EMACSCMD delete_backward_char(TX* text)
  590. {
  591.     txIdmExec(text,IDM_DELETEPREV);
  592. }
  593.  
  594. static void EMACSCMD set_mark_command(TX* text)
  595. {
  596.     statprintf("Mark set");
  597.     txMarkCur(text);
  598. }
  599.  
  600. static void EMACSCMD find_file(TX* text)
  601. {
  602.     txIdmExec(text,IDM_UIOPEN);
  603. }
  604.  
  605. //##wndproc
  606.  
  607. typedef struct {
  608.     mchar* szctrlx;
  609.     mchar* szesc;
  610.     mchar* szName;
  611.     void (*pfunc)(TX* text);
  612. } FUNCTION_TABLE;
  613.  
  614. static FUNCTION_TABLE _table[] = {
  615.     NULL,    NULL,    "isearch_backward",isearch_backward,
  616.     NULL,    NULL,    "isearch_forward",isearch_forward,
  617.     NULL,    "^s",    "isearch_forward_regexp",isearch_forward_regexp,
  618.     NULL,    NULL,    "kill_region",kill_region,
  619.     NULL,    "w",    "copy_region_as_kill",copy_region_as_kill,
  620.     NULL,    "q",    "fill_paragraph",fill_paragraph,
  621.     NULL,    "g",    "goto_line",goto_line,
  622.     NULL,    "t",    "transpose_words",transpose_words,
  623.     NULL,    "m",    "back_to_indentation",back_to_indentation,
  624.     NULL,    "d",    "kill_word",kill_word,
  625.     NULL,    "b",    "backward_word",backward_word,
  626.     NULL,    "f",    "forward_word",forward_word,
  627.     NULL,    "c",    "capitalize_word",capitalize_word,
  628.     NULL,    "l",    "downcase_word",downcase_word,
  629.     NULL,    "u",    "upcase_word",upcase_word,
  630.     NULL,    "<",    "beginning_of_buffer",beginning_of_buffer,
  631.     NULL,    ">",    "end_of_buffer",end_of_buffer,
  632.     NULL,    "%",    "query_replase",query_replase,
  633.     NULL,    "[",    "backward_paragraph",backward_paragraph,
  634.     NULL,    "]",    "forward_paragraph",forward_paragraph,
  635.     NULL,    "^a",    "beginning_of_defun",beginning_of_defun,
  636.     NULL,    "^e",    "end_of_defun",end_of_defun,
  637.     NULL,    "^b",    "backward_sexp",backward_sexp,
  638.     NULL,    "^f",    "forward_sexp",forward_sexp,
  639.     "e",    NULL,    "call_last_kbd_macro",call_last_kbd_macro,
  640.     "(",    NULL,    "start_kbd_macro",start_kbd_macro,
  641.     ")",    NULL,    "end_kbd_macro",end_kbd_macro,
  642.     "u",    NULL,    "advertised_undo",advertised_undo,
  643.     "k",    NULL,    "kill_buffer",kill_buffer,
  644.     "i",    NULL,    "insert_file",insert_file,
  645.     "o",    NULL,    "other_window",other_window,
  646.     "h",    NULL,    "mark_whole_buffer",mark_whole_buffer,
  647.     "f",    NULL,    "set_fill_column",set_fill_column,
  648.     "d",    NULL,    "dired",dired,
  649.     "1",    NULL,    "delete_other_windows",delete_other_windows,
  650.     "2",    NULL,    "split_window_vertically",split_window_vertically,
  651.     "^z",    NULL,    "suspend_emacs",suspend_emacs,
  652.     "^c",    NULL,    "save_buffers_kill_emacs",save_buffers_kill_emacs,
  653.     "^q",    NULL,    "toggle_read_only",toggle_read_only,
  654.     "^s",    NULL,    "save_buffer",save_buffer,
  655.     "^w",    NULL,    "write_file",write_file,
  656.     "^x",    NULL,    "exchange_point_and_mark",exchange_point_and_mark,
  657.     "^b",    NULL,    "list_buffers",list_buffers,
  658.     NULL,    NULL,    "kill_line",kill_line,
  659.     NULL,    NULL,    "c_indent_command",c_indent_command,
  660.     NULL,    NULL,    "recenter",recenter,
  661.     NULL,    NULL,    "quoted_insert",quoted_insert,
  662.     "^g",    "^g",    "keyboard_quit",keyboard_quit,
  663.     NULL,    NULL,    "transpose_chars",transpose_chars,
  664.     NULL,    NULL,    "toggle_ime_mode",toggle_ime_mode,
  665.     NULL,    "v",    "scroll_down",scroll_down,
  666.     NULL,    NULL,    "delete_backward_char",delete_backward_char,
  667.     NULL,    " ",    "set_mark_command",set_mark_command,
  668.     "^f",    NULL,    "find_file",find_file,
  669. };
  670. static int _nTable = sizeof(_table) / sizeof(FUNCTION_TABLE);
  671.  
  672. static int szemacscmdToIdm(mchar* szcmd)
  673. {
  674.     int n = _nTable;
  675.     FUNCTION_TABLE* p = _table;
  676.     for (;n--;p++) {
  677.         if (!stricmp(p->szName,szcmd)) {
  678.             return _idmFirst + (p - _table);
  679.         }
  680.     }
  681.     return 0;
  682. }
  683.  
  684. static FUNCTION_TABLE* idmToFunction(int idm)
  685. {
  686. //WZ3.90L 981125 new
  687.     if (_idmFirst <= idm && idm <= _idmLast) {
  688.         return _table + (idm - _idmFirst);
  689.     }
  690.     return NULL;
  691. }
  692.  
  693. #if !WINDOWSCE
  694. mchar* idmToSzEmacsFunction(int idm)
  695. {
  696. //WZ3.90L 981125 new
  697.     FUNCTION_TABLE* p = idmToFunction(idm);
  698.     if (p) return p->szName;
  699.     return NULL;
  700. }
  701.  
  702. static void OutputEmacs2Stroke(TX* textDst,mchar* sz)
  703. {
  704.     if (*sz == '^') {
  705.         txInsert(textDst,"Ctrl+");sz++;
  706.     }
  707.     if (*sz == ' ') {
  708.         txInsert(textDst,"Space");
  709.     } else {
  710.         txInsertChar(textDst,toupper(*sz));
  711.     }
  712. }
  713.  
  714. void txKeylistOutputEmacs2Stroke(TX* textDst)
  715. {
  716.     int n = _nTable;
  717.     FUNCTION_TABLE* p = _table;
  718.     for (;n--;p++) {
  719.         if (p->szctrlx) {
  720.             txInsert(textDst,"Ctrl+X-");
  721.             OutputEmacs2Stroke(textDst,p->szctrlx);
  722.             txfTagInsertBeam(textDst,20);
  723.             txInsert(textDst,p->szName);
  724.             txInsertReturn(textDst);
  725.         }
  726.         if (p->szesc) {
  727.             txInsert(textDst,"Esc-");
  728.             OutputEmacs2Stroke(textDst,p->szesc);
  729.             txfTagInsertBeam(textDst,20);
  730.             txInsert(textDst,p->szName);
  731.             txInsertReturn(textDst);
  732.         }
  733.     }
  734. }
  735. #endif    // !WINDOWSCE
  736.  
  737. static BOOL szkeyIsIncluded(mchar* sz,mchar* szkey)
  738. {
  739. // szにszkeyが含まれているか返す
  740.     if (sz) {
  741.         int lch = strlen(szkey);
  742.         while(*sz) {
  743.             if (!strnicmp(sz,szkey,lch)) return TRUE;
  744.             if (*sz == '^' && sz[1]) {
  745.                 sz += 2;
  746.             } else {
  747.                 sz++;
  748.             }
  749.         }
  750.     }
  751.     return FALSE;
  752. }
  753.  
  754. static HOOKRESULT CALLBACK wndprocTextHook(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  755. {
  756.     TX* text = hwndtextGetText(hwnd);
  757.     switch (message) {
  758.         case WM_TXEVENT: {
  759.             if (text->emacswz) {
  760.                 switch(wParam) {
  761.                     case TXEVENT_2STROKE: {
  762.                         if (text->emacswz->chPrefix) {
  763.                             int n = _nTable;
  764.                             int chPrefix = text->emacswz->chPrefix;
  765.                             FUNCTION_TABLE* p = _table;
  766.                             BOOL fFind = FALSE;
  767.                             mchar szkey[CCHWORD];
  768.                             //
  769.                             text->emacswz->chPrefix = 0;
  770. //                            txControlProcWmKey(text);    // Ctrl+X-Ctrl+Bで、Ctrl+B単独のIDM_LEFTも入ってしまう。
  771.                             txStatusbarPrintf(text,NULL);
  772. //information("%02X",lParam);
  773.                             {
  774.                                 mchar c = lParam;
  775.                                 if (c < 0x20) {
  776.                                     szkey[0] = '^';szkey[1] = c + 'a' - 1;szkey[2] = 0;
  777.                                 } else {
  778.                                     szkey[0] = tolower(c);szkey[1] = 0;
  779.                                 }
  780.                             }
  781.                             for (;n--;p++) {
  782.                                 if (chPrefix == VK_ESCAPE) {
  783.                                     if (szkeyIsIncluded(p->szesc,szkey)) {fFind = TRUE;break;}
  784.                                 } else {
  785.                                     if (szkeyIsIncluded(p->szctrlx,szkey)) {fFind = TRUE;break;}
  786.                                 }
  787.                             }
  788.                             if (fFind) {
  789.                                 (p->pfunc)(text);
  790.                             }
  791.                             txSetHookWndproctextResult(text,1);return HOOK_CAPTURE;
  792.                         }
  793.                         break;
  794.                     }
  795.                     case TXEVENT_IDMEXEC: {
  796.                         int idm = lParam;
  797. #if 1    //WZ3.90L 981125 
  798.                         if (text->emacswz->fIsearching && !isearchIsContinueIdm(idm)) {
  799.                             //WZ4.00Ab 990124 Emacswz:インクリメンタル検索中にカーソル移動などを実行するとインクリメンタル検索を中止するようにした。
  800.                             isearch_quit(text);
  801.                         }
  802.                         {
  803.                             FUNCTION_TABLE* p = idmToFunction(idm);
  804.                             if (p) {
  805.                                 (p->pfunc)(text);    // __TXC__では"p->pfunc(text)"という書き方には対応していない。
  806.                                 return HOOK_CAPTURE;
  807.                             }
  808.                         }
  809. #else
  810.                         if (_idmFirst <= idm && idm <= _idmLast) {
  811.                             FUNCTION_TABLE* p = _table + (idm - _idmFirst);
  812.                             (p->pfunc)(text);
  813.                             return HOOK_CAPTURE;
  814.                         }
  815. #endif
  816.                         if (idm == _idm_prefix_ctrlx) {
  817.                             text->emacswz->chPrefix = 'X';
  818.                             txKeySet2Stroke(text,_idm_prefix_ctrlx);
  819.                             txStatusbarPrintf(text,"C-x-");
  820.                             return HOOK_CAPTURE;
  821.                         }
  822.                         if (idm == _idm_prefix_escape) {
  823.                             text->emacswz->chPrefix = VK_ESCAPE;
  824.                             txKeySet2Stroke(text,_idm_prefix_escape);
  825.                             txStatusbarPrintf(text,"ESC-");
  826.                             return HOOK_CAPTURE;
  827.                         }
  828.                         break;
  829.                     }
  830.                     case TXEVENT_INPUT:
  831.                     case TXEVENT_INPUTIME: {
  832.                         mchar* sz = (LPVOID)lParam;
  833.                         if (text->emacswz->fIsearching) {
  834.                             sstrcat(text->emacswz->szIsearch,sz);
  835.                             text->emacswz->fIsearchWrapped = FALSE;
  836.                             txSetUndisp(text);
  837.                                 txJumpAddress(text,text->emacswz->adrIsearch);
  838.                                 isearch_next(text,SEARCH_CUR|text->emacswz->Isearchmode);
  839.                             txSetDisp(text);
  840.                             txSetHookWndproctextResult(text,1);return HOOK_CAPTURE;
  841.                         }
  842.                         break;
  843.                     }
  844.                     case TXEVENT_CLOSE: {
  845.                         if (text->emacswz) {
  846.                             free(text->emacswz);
  847.                             text->emacswz = NULL;
  848.                         }
  849.                         break;
  850.                     }
  851.                 }
  852.             }
  853.             break;
  854.         }
  855.         case WM_TXEMACS_TXCMD: {
  856.             if (wParam == IDM_KEYMACRORECORD) {
  857.                 if (lParam) {
  858.                     _end_kbd_macro(text);
  859.                 } else {
  860.                     _start_kbd_macro(text);
  861.                 }
  862.             } else {
  863.                 txIdmExec(text,wParam);
  864.             }
  865.             break;
  866.         }
  867.     }
  868.     return HOOK_CONTINUE;
  869. }
  870.  
  871. //##event
  872.  
  873. //static int _aaa = sizeof(_table);    // これがヘン
  874. //static int _bbb = sizeof(FUNCTION_TABLE);
  875.  
  876. void __on_txFrameNewEmacs(TX* text)
  877. {
  878. //information("%d %d %d %d %d",_nTable,sizeof(_table) ,sizeof(FUNCTION_TABLE),_aaa,_bbb);
  879.     if (text->modeEditor == ME_EMACS) {
  880.         #ifdef __TXC__
  881.         txSetHookWndproctextTxpcode(text,wndprocTextHook);
  882.         #else
  883.         if (stristrword(txcGetEventMacro(),"_emacswz")) {
  884.             // イベントマクロに指定されている場合は何もしない。for 乗っ取り。
  885.             return;
  886.         }
  887.         txAddHookWndproctext(text,wndprocTextHook);
  888.         #endif
  889.         // コマンドの登録。登録したコマンドはプロセス内で有効
  890.         if (!_idmFirst) {
  891.             // 全コマンド登録
  892.             {
  893.                 int n = _nTable;
  894.                 if (n) {
  895.                     _idmFirst = idmRegister();
  896.                     n--;
  897.                 }
  898.                 while(n--) idmRegister();
  899.                 _idmLast = _idmFirst + _nTable - 1;
  900.             }
  901.             // コマンドとは別に登録
  902.             _idm_prefix_ctrlx = idmRegister();
  903.             _idm_prefix_escape = idmRegister();
  904.         }
  905.         // キー登録
  906.         _idm_kill_line = szemacscmdToIdm("kill_line");
  907.         _idm_isearch_backward = szemacscmdToIdm("isearch_backward");
  908.         _idm_isearch_forward = szemacscmdToIdm("isearch_forward");
  909.         _idm_isearch_forward_regexp = szemacscmdToIdm("isearch_forward_regexp");
  910.         txKeySetWzcmd(text,"^W",szemacscmdToIdm("kill_region"));
  911.         txKeySetWzcmd(text,"^R",_idm_isearch_backward);
  912.         txKeySetWzcmd(text,"^S",_idm_isearch_forward);
  913.         txKeySetWzcmd(text,"^K",_idm_kill_line);
  914.         txKeySetWzcmd(text,"^I",szemacscmdToIdm("c_indent_command"));
  915.         txKeySetWzcmd(text,"^L",szemacscmdToIdm("recenter"));
  916.         txKeySetWzcmd(text,"^Q",szemacscmdToIdm("quoted_insert"));
  917.         txKeySetWzcmd(text,"^G",szemacscmdToIdm("keyboard_quit"));
  918.         txKeySetWzcmd(text,"^T",szemacscmdToIdm("transpose_chars"));
  919.         txKeySetWzcmd(text,"^\\",szemacscmdToIdm("toggle_ime_mode"));
  920.         txKeySetWzcmd(text,"+^{Space}",szemacscmdToIdm("toggle_ime_mode"));
  921.         txKeySetWzcmd(text,"^Z",szemacscmdToIdm("scroll_down"));
  922.         txKeySetWzcmd(text,"^H",szemacscmdToIdm("delete_backward_char"));
  923.         txKeySetWzcmd(text,"^{Space}",szemacscmdToIdm("set_mark_command"));
  924.         txKeySetWzcmd(text,"^X",_idm_prefix_ctrlx);
  925.         txKeySetWzcmd(text,"{Esc}",_idm_prefix_escape);
  926.         // コンテキスト
  927.         if (!text->emacswz) {
  928.             text->emacswz = zmalloc(sizeof(EMACSWZ_CONTEXT));
  929.         }
  930.     }
  931. }
  932.  
  933. #ifdef __TXC__
  934. void __on_txFrameNew(TX* text)
  935. {
  936.     __on_txFrameNewEmacs(text);
  937. }
  938. main
  939. {
  940. }
  941. #endif
  942.  
  943. #endif    // defined(__TXC__) || !WINDOWSCE
  944.