home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 1999 February / VPR9902A.BIN / APUPDATE / VC / Tx300d / TX300D.LZH / EMACSWZ.C < prev    next >
C/C++ Source or Header  |  1997-05-09  |  14KB  |  758 lines

  1. // Emacs like keybind support TLL
  2. // programed by TY
  3. //2.99 970313 start
  4. // EMACS like keybind 実装にあたり、中村 学 (Nakamura Manabu)さんのEMACSWZと、
  5. // UK-TaniyamaさんのEMACSWZを参考にさせて頂きました。ありがとうございます。
  6.  
  7. //{###Emacsライクキーコマンド}
  8.  
  9. #include <windows.h>
  10. #include <windowsx.h>
  11.  
  12. #include "dialog.h"
  13. #include "edit.h"
  14.  
  15. #define chToCtrl(ch)    (ch-0x60)    // chは小文字のこと
  16.  
  17. static BOOL _fIsearching;
  18. static txstr _szIsearch;
  19. static txstr _szIsearch0;
  20. static BOOL _fIsearchWrapped;
  21. static WZCMD _wzcmdKillLine;//2.99D 970402 
  22. static WZCMD _wzcmdIsearchForward;
  23. static WZCMD _wzcmdIsearchBackward;
  24. static WZCMD _wzcmdIsearchRegexp;
  25. static IFILE _adrIsearch;
  26. static IFILE _adrIsearch0;
  27. static BOOL _fStatBasePrinting = FALSE;
  28. static BOOL _fIsearchLastFail;
  29. static SEARCHMODE _Isearchmode;
  30. static mchar _chPrefix = 0;
  31. static BOOL _fImeOpen = FALSE;//3.00A4 970509 
  32.  
  33. typedef struct {
  34.     mchar ch;
  35.     mchar *szCmd;
  36. } EMACSKEYITEM;
  37.  
  38. static EMACSKEYITEM _tKeyPrefixX[] = {
  39.     {chToCtrl('b'),    "list_buffers"},
  40.     {chToCtrl('c'),    "save_buffers_kill_emacs"},
  41.     {chToCtrl('f'),    "find_file"},
  42.     {chToCtrl('q'),    "toggle_read_only"},
  43.     {chToCtrl('s'),    "save_buffer"},
  44.     {chToCtrl('g'),    "keyboard_quit"},
  45.     {chToCtrl('x'),    "exchange_point_and_mark"},
  46.     {chToCtrl('w'),    "write_file"},
  47.     {chToCtrl('z'),    "suspend_emacs"},
  48.     {'1',            "delete_other_windows"},
  49.     {'2',            "split_window_vertically"},
  50.     {'b',            "list_buffers"},
  51.     {'d',            "dired"},
  52.     {'f',            "set_fill_column"},
  53.     {'h',            "mark_whole_buffer"},
  54.     {'o',            "other_window"},
  55.     {'k',            "kill_buffer"},
  56.     {'i',            "insert_file"},
  57.     {'u',            "advertised_undo"},
  58.     {'(',            "start_kbd_macro"},
  59.     {')',            "end_kbd_macro"},
  60.     {'e',            "call_last_kbd_macro"},
  61.     {0,                NULL}
  62. };
  63.  
  64. static EMACSKEYITEM _tKeyPrefixEsc[] = {
  65.     {chToCtrl('a'),    "beginning_of_defun"},
  66.     {chToCtrl('b'),    "backward_sexp"},
  67.     {chToCtrl('e'),    "end_of_defun"},
  68.     {chToCtrl('f'),    "forward_sexp"},
  69.     {chToCtrl('g'),    "keyboard_quit"},
  70.     {chToCtrl('s'),    "isearch_forward_regexp"},
  71.     {' ',            "set_mark_command"},
  72.     {'[',            "backward_paragraph"},
  73.     {']',            "forward_paragraph"},
  74.     {'%',            "query_replase"},
  75.     {'<',            "beginning_of_buffer"},
  76.     {'>',            "end_of_buffer"},
  77.     {'c',            "capitalize_word"},
  78.     {'v',            "scroll_down"},
  79.     {'f',            "forward_word"},
  80.     {'b',            "backward_word"},
  81.     {'g',            "goto_line"},
  82.     {'d',            "kill_word"},
  83.     {'l',            "downcase_word"},
  84.     {'m',            "back_to_indentation"},
  85.     {'t',            "transpose_words"},
  86.     {'u',            "upcase_word"},
  87.     {'q',            "fill_paragraph"},
  88.     {'w',            "copy_region_as_kill"},
  89. //    {'x',            "execute_extended_command"},////未完成
  90.     {0,                NULL}
  91. };
  92.  
  93. kill_region
  94. {
  95. //{#EMACS} ^W
  96.     txSetUndisp(text);
  97.     txJumpMarkCur(text);
  98.     txSelectEx(text,CLIP_CHAR);
  99.     txJumpMarkCur(text);
  100.     call("edit.txClipboardCut");
  101.     txSetDisp(text);
  102.     statprintf("Region cuted");
  103. }
  104.  
  105. copy_region_as_kill
  106. {
  107.     txSetUndisp(text);
  108.     txJumpMarkCur(text);
  109.     txSelectEx(text,CLIP_CHAR);
  110.     txJumpMarkCur(text);
  111.     call("edit.txClipboardCopy");
  112.     txSetDisp(text);
  113.     statprintf("Region copyed");
  114. }
  115.  
  116. fill_paragraph
  117. {
  118.     call("paraform.form");
  119. }
  120.  
  121. goto_line
  122. {
  123.     txuiJump(text);
  124. }
  125.  
  126. transpose_words
  127. {
  128.     txstr src;
  129.     txstr dst;
  130.     txSetUndisp(text);
  131.     //
  132.     txJumpWordTopMi(text);
  133.     txSelectEx(text,CLIP_CHAR);
  134.     txJumpWordEndMi(text);
  135.     TXCHAR ch = txGetChar(text);
  136.     if (ch == ' ') {
  137.         txJumpWordEndMi(text);
  138.     }
  139.     txGetWord(text,src);
  140.     txSelectDelete(text);
  141.     //
  142.     txSelectEx(text,CLIP_CHAR);
  143.     txLeftWordMi(text);
  144.     TXCHAR ch = txGetChar(text);
  145.     if (ch == ' ') {
  146.         txLeftWordMi(text);
  147.     }
  148.     txGetWord(text,dst);
  149.     txSelectDelete(text);
  150.     //
  151.     txInsert(text,src);
  152.     txInsert(text,dst);
  153.     //
  154.     txSetDisp(text);
  155. }
  156.  
  157. back_to_indentation
  158. {
  159.     txSetUndisp(text);
  160.     txJumpParaTop(text);
  161.     while(1) {
  162.         TXCHAR ch = txReadChar(text);
  163.         if (ch != '\t' && ch != ' ') break;
  164.         if (txIsCurEof(text)) break;
  165.     }
  166.     txLeft(text);
  167.     txSetDisp(text);
  168. }
  169.  
  170. kill_word
  171. {
  172.     txDeleteWord(text);
  173. }
  174.  
  175. backward_word
  176. {
  177.     txLeftWordMi(text);
  178. }
  179.  
  180. forward_word
  181. {
  182.     txRightWordMi(text);
  183. }
  184.  
  185. static void capitalize(BOOL fWord,BOOL fTolower)
  186. {
  187.     txstr buff;
  188.     txSetUndisp(text);
  189.     if (!text->fClip) {
  190.         txSelect(text);
  191.         if (fWord) {
  192.             txJumpWordEndMi(text);
  193.         } else {
  194.             txRight(text);
  195.         }
  196.     }
  197.     txGetWord(text,buff);
  198.     if (fTolower) {
  199.         strlwr(buff);
  200.     } else {
  201.         strupr(buff);
  202.     }
  203.     txSelectDelete(text);
  204.     txInsert(text,buff);
  205.     txJumpWordEndMi(text);
  206.     txSetDisp(text);
  207. }
  208.  
  209. capitalize_word
  210. {
  211.     capitalize(FALSE,FALSE);
  212. }
  213.  
  214. downcase_word
  215. {
  216.     capitalize(TRUE,TRUE);
  217. }
  218.  
  219. upcase_word
  220. {
  221.     capitalize(TRUE,FALSE);
  222. }
  223.  
  224. beginning_of_buffer
  225. {
  226.     txMarkCur(text);
  227.     txJumpFileTop(text);
  228.     statprintf("Mark set");
  229. }
  230.  
  231. end_of_buffer
  232. {
  233.     txMarkCur(text);
  234.     txJumpFileEnd(text);
  235.     statprintf("Mark set");
  236. }
  237.  
  238. query_replase
  239. {
  240.     txuiReplaceQuery(text);
  241. }
  242.  
  243. backward_paragraph
  244. {
  245.     txJumpParaTop(text);
  246. }
  247.  
  248. forward_paragraph
  249. {
  250.     txJumpParaEnd(text);
  251. }
  252.  
  253. beginning_of_defun
  254. {
  255.     txSearchEx(text,"^{",SEARCH_RE|SEARCH_PREV);
  256. }
  257.  
  258. end_of_defun
  259. {
  260.     txSearchEx(text,"^}",SEARCH_RE|SEARCH_PREV);
  261. }
  262.  
  263. backward_sexp
  264. {
  265.     txSetUndisp(text);
  266.     txSearchEx(text,"[])}]",SEARCH_RE|SEARCH_PREV);
  267.     txJumpBrace(text);
  268.     txSetDisp(text);
  269. }
  270.  
  271. forward_sexp
  272. {
  273.     txSetUndisp(text);
  274.     txSearchEx(text,"[[({]",SEARCH_RE|SEARCH_CUR);
  275.     txJumpBrace(text);
  276.     txRight(text);
  277.     txSetDisp(text);
  278. }
  279.  
  280.  
  281.  
  282.  
  283.  
  284. static BOOL IsLastOpIsearch(void)
  285. {
  286.     if (text->wzcmdLastOp == _wzcmdIsearchForward) return TRUE;
  287.     if (text->wzcmdLastOp == _wzcmdIsearchBackward) return TRUE;
  288.     if (text->wzcmdLastOp == _wzcmdIsearchRegexp) return TRUE;
  289.     return FALSE;
  290. }
  291.  
  292. static void statbaseprint(mchar* sz)
  293. {
  294.     _fStatBasePrinting = (sz && sz[0]);
  295.     SendMessage(text->hwndbase,WM_TXSB_SETUPTEXT,HSL_INFOBASE,(LPARAM)sz);
  296. }
  297.  
  298. //## search
  299.  
  300. static void isearch_statprint(BOOL find,SEARCHMODE searchmode)
  301. {
  302.     txstr sz;
  303.     if (!find) sz += "Failing ";
  304.     if (_fIsearchWrapped) sz += "Wrapped ";
  305.     if (searchmode & SEARCH_RE) sz += "Regexp ";
  306.     sz += "I-search";
  307.     if (searchmode & SEARCH_PREV) sz += " backward";
  308.     sz += ": ";
  309.     sz += _szIsearch;
  310.     statbaseprint(sz);
  311. }
  312.  
  313. static void isearch_next(SEARCHMODE searchmode)
  314. {
  315.     SEARCHMODE mode = SEARCH_FORWARD|SEARCH_NOSENSECASE|searchmode;
  316.     if (_szIsearch[0]) {
  317.         BOOL ret = FALSE;
  318.         IFILE adr = txGetAddress(text);
  319.         IFILE adrCurscreen = txGetAddressCurscreen(text);
  320.         int ly = text->ly;
  321.         txSetUndisp(text);
  322.         if (_fIsearchLastFail) {
  323.             _fIsearchLastFail = FALSE;
  324.             if (mode & SEARCH_PREV) {
  325.                 txJumpFileEnd(text);
  326.             } else {
  327.                 txJumpFileTop(text);
  328.             }
  329.             _fIsearchWrapped = TRUE;
  330.         }
  331.         ret = txSearchEx(text,_szIsearch,mode);
  332.         if (!ret) {
  333.             _fIsearchLastFail = TRUE;
  334.         }
  335.         if (ret) {
  336.             _adrIsearch = txGetAddress(text);
  337.             if ((mode & SEARCH_PREV) && !(mode & SEARCH_CUR)) {
  338.                 // 連続実行時でBackward時は実行しない
  339.             } else {
  340.                 txRightBytes(text,ret-1);
  341.             }
  342.             txSetLy(text,ly);
  343.         } else {
  344.             txJumpAddress(text,adr);
  345.             txSetLyCurscreen(text,adrCurscreen);
  346.         }
  347.         txSetDisp(text);
  348.         isearch_statprint(ret,mode);
  349.         _szIsearch0 = _szIsearch;
  350.     } else {
  351.         isearch_statprint(TRUE,searchmode);
  352.     }
  353. }
  354.  
  355. static void isearch(SEARCHMODE searchmode)
  356. {
  357.     if (IsLastOpIsearch()) {
  358.         // 連続実行
  359.         if (!_fIsearching) {
  360.             _fIsearching = TRUE;
  361.             text->fImeInputToWmChar++;
  362.         }
  363.         if (!_szIsearch[0]) _szIsearch = _szIsearch0;
  364.         isearch_next(searchmode|_Isearchmode);
  365.     } else {
  366.         if (!_fIsearching) {
  367.             _fIsearching = TRUE;
  368.             text->fImeInputToWmChar++;
  369.             _szIsearch = "";
  370.             _fIsearchWrapped = FALSE;
  371.             _adrIsearch0 = _adrIsearch = txGetAddress(text);
  372.             _fIsearchLastFail = FALSE;
  373.             _Isearchmode = searchmode & SEARCH_RE;
  374.         }
  375.         isearch_next(searchmode|SEARCH_CUR);
  376.     }
  377. }
  378.  
  379. isearch_backward
  380. {
  381. // インクリメンタルサーチ(上方向)
  382. //{#EMACS} ^R
  383.     isearch(SEARCH_PREV);
  384. }
  385.  
  386. isearch_forward
  387. {
  388. // インクリメンタルサーチ(下方向)
  389. //{#EMACS} ^S
  390.     isearch(0);
  391. }
  392.  
  393. isearch_forward_regexp
  394. {
  395.     isearch(SEARCH_RE);
  396. }
  397.  
  398. //## cmds
  399.  
  400. call_last_kbd_macro
  401. {
  402.     txKeymacroPlay(text);
  403. }
  404.  
  405. start_kbd_macro
  406. {
  407.     txKeymacroRecord(text);
  408.     statprintf("Defining kbd macro...");
  409. }
  410.  
  411. end_kbd_macro
  412. {
  413.     txKeymacroRecord(text);
  414.     statprintf("Keyboard macro defined");
  415. }
  416.  
  417. advertised_undo
  418. {
  419.     txUndo(text);
  420.     statprintf("Undo!");
  421. }
  422.  
  423. kill_buffer
  424. {
  425.     txuiClose(text);
  426. }
  427.  
  428. insert_file
  429. {
  430.     txuiInsertFile(text);
  431. }
  432.  
  433. other_window
  434. {
  435.     txSwitchWindow(text);
  436. }
  437.  
  438. mark_whole_buffer
  439. {
  440.     txSetUndisp(text);
  441.     txJumpFileEnd(text);
  442.     txMarkCur(text);
  443.     txJumpFileTop(text);
  444.     txSetDisp(text);
  445. }
  446.  
  447. set_fill_column
  448. {
  449.     call("paraform.config");
  450. }
  451.  
  452. dired
  453. {
  454.     call("filer.txe");
  455. }
  456.  
  457. delete_other_windows
  458. {
  459.     txSwitchSplit(text);    // とりあえず
  460. }
  461.  
  462. split_window_vertically
  463. {
  464.     txSwitchSplit(text);    // とりあえず
  465. }
  466.  
  467. suspend_emacs
  468. {
  469. // DOS PROMPT
  470.     if (_platform == WINDOWSNT) {
  471.         exec("cmd.exe");
  472.     } else {
  473.         exec("dosprmpt.pif");
  474.     }
  475. }
  476.  
  477. save_buffers_kill_emacs
  478. {
  479.     txuiCloseAllEvery(text);
  480. }
  481.  
  482. toggle_read_only
  483. {
  484.     call("disp.readmode");
  485. }
  486.  
  487. save_buffer
  488. {
  489.     if (!text->fEdit) {
  490.         statprintf("(No changes need to be saved)");
  491.     } else {
  492.         if (txuiSave(text))
  493.         statprintf("Wrote %s",text->szfilename);
  494.     }
  495. }
  496.  
  497. write_file
  498. {
  499.     txuiSaveTo(text);
  500. }
  501.  
  502. exchange_point_and_mark
  503. {
  504.     txJumpMarkCur(text);
  505.     txSetLyCenter(text);
  506. }
  507.  
  508. list_buffers
  509. {
  510.     txuiSwitchText(text);
  511. }
  512.  
  513. kill_line
  514. {
  515. // カーソル位置から行末までを削除します。
  516. // カーソル位置が改行なら、改行を削除します。
  517. // 削除した文字列をクリップボードにコピーします。
  518. // 連続実行するとクリップボードに追加します。
  519. //2.99 970313 new
  520. //{#EMACS} ^K
  521. #if 1///2.99D 970402 
  522.     TX* textWork = NULL;
  523.     txSetUndispSilent(text);
  524.     if (text->wzcmdLastOp == _wzcmdKillLine) {
  525.         //2.99D 970402 EMACS ^Kで連続実行でクリップボードに出力するようにした
  526.         textWork = textopen(NULL);
  527.         txClipboardPaste(textWork);
  528.     }
  529.     txSelectEx(text,CLIP_CHAR);
  530.     if (txIsCurReturn(text)) {
  531.         txRight(text);
  532.     } else {
  533.         txJumpParaEnd(text);
  534.     }
  535.     if (textWork) {
  536.         txPrivatePush(text);
  537.         txSelectDelete(text);
  538.         txJumpFileEnd(textWork);
  539.         txPrivatePaste(textWork);
  540.         txPrivateDeleteTop(textWork);
  541.         txSelectEx(textWork,CLIP_ALL);
  542.         txClipboardCopy(textWork);
  543.         textclose(textWork);
  544.     } else {
  545.         txClipboardCut(text);
  546.     }
  547.     txSetDispSilent(text);
  548. #else
  549.     if (txIsCurReturn(text)) {
  550.         txDeleteChar(text);
  551.     } else {
  552.         txDeleteParaEnd(text);
  553.     }
  554. #endif
  555. }
  556.  
  557. c_indent_command
  558. {
  559. //{#EMACS} ^I
  560.     call("edit.tab");
  561. }
  562.  
  563. recenter
  564. {
  565. // カーソルを画面中央にセットし、画面表示をリフレッシュ
  566. //{#EMACS} ^L
  567.     txSetUndisp(text);
  568.     txSetLyCenter(text);
  569.     txSetDisp(text);
  570. }
  571.  
  572. quoted_insert
  573. {
  574. //{#EMACS} ^Q
  575. //    なにもしない
  576. }
  577.  
  578. keyboard_quit
  579. {
  580. // インクリメンタルサーチ等の取り消し
  581. //{#EMACS} ^G
  582.     if (_fIsearching) {
  583.         _fIsearching = FALSE;
  584.         text->fImeInputToWmChar--;
  585.     }
  586.     if (IsLastOpIsearch()) {
  587.         txJumpAddress(text,_adrIsearch0);
  588.     }
  589.     statprintf("Quit");
  590. }
  591.  
  592. transpose_chars
  593. {
  594. // カーソル位置と左の文字を入れ替え
  595. //{#EMACS} ^T
  596.     if (txIsCurReturn(text)) return FALSE;
  597.     txSetUndispSilent(text);
  598.         txSelectQuit(text);
  599.         TXCHAR ch = txGetChar(text);
  600.         txDeleteChar(text);
  601.         txLeft(text);
  602.         txInsertChar(text,ch);
  603.         txRight(text);
  604.     txSetDispSilent(text);
  605. }
  606.  
  607. toggle_ime_mode
  608. {
  609. //{#EMACS} ^\ +^{Space}
  610.     if (imeGetOpen()) {
  611.         imeSetOpen(FALSE);
  612.     } else {
  613.         imeSetOpen(TRUE);
  614.     }
  615. }
  616.  
  617. scroll_down
  618. {
  619. //{#EMACS} ^Z
  620.     txPrevPageVz(text);
  621. }
  622.  
  623. delete_backward_char
  624. {
  625. //{#EMACS} ^H
  626.     call("edit.txkeyDeletePrev");
  627. }
  628.  
  629. set_mark_command
  630. {
  631. //{#EMACS} ^{Space}
  632.     statprintf("Mark set");
  633.     txMarkCur(text);
  634. }
  635.  
  636. find_file
  637. {
  638.     txuiOpen(text);
  639. }
  640.  
  641. //##
  642.  
  643. static void prefix_exec(int ch)
  644. {
  645.     statbaseprint(NULL);
  646.     //
  647.     ch = tolower(ch);
  648.     EMACSKEYITEM* item = NULL;
  649.     if (_chPrefix == chToCtrl('x')) {
  650.         item = _tKeyPrefixX;
  651.     } else if (_chPrefix == 0x1B) {
  652.         item = _tKeyPrefixEsc;
  653.     }
  654.     if (item) {
  655.         for (;item->ch;item++) {
  656.             if (ch == item->ch) {
  657.                 statprintf(item->szCmd);
  658.                 call("\m." + item->szCmd);
  659.                 if (!stricmp(item->szCmd,"isearch_forward_regexp")) {
  660.                     text->wzcmdLastOp = _wzcmdIsearchRegexp;
  661.                 }
  662.                 break;
  663.             }
  664.         }
  665.     }
  666.     //
  667.     _chPrefix = 0;
  668.     imeSetOpen(_fImeOpen);//3.00A4 970509 
  669. }
  670.  
  671. static void prefix_set(int ch)
  672. {
  673.     _chPrefix = ch;
  674.     //3.00A4 970509 EMACS.KEY : Esc,^Xの2ストローク目の入力で、IMEをOFFにするようにした
  675.     _fImeOpen = imeGetOpen();
  676.     imeSetOpen(FALSE);
  677.  
  678. }
  679.  
  680. prefix_ctrlx
  681. {
  682. //{#EMACS} ^X
  683.     statbaseprint("C-x-");
  684.     prefix_set(chToCtrl('x'));
  685. }
  686.  
  687. prefix_esc
  688. {
  689. //{#EMACS} {Esc}
  690.     statbaseprint("ESC-");
  691.     prefix_set(0x1B);
  692. }
  693.  
  694. //##
  695.  
  696. HOOKRESULT __wndproctext(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
  697. {
  698.     TX* text = textTarget;
  699.     switch(message) {
  700.         case WM_KEYDOWN: {
  701.             if (_fIsearching) {
  702.                 if (GetKeyState(VK_CONTROL) < 0) {
  703.                     _fIsearching = FALSE;
  704.                     text->fImeInputToWmChar--;
  705.                 }
  706.             } else if (!_chPrefix) {
  707.                 if (!IsLastOpIsearch()) {
  708.                     if (_fStatBasePrinting) statbaseprint(NULL);
  709.                 }
  710.             }
  711.             break;
  712.         }
  713.         case WM_KILLFOCUS: {
  714.             if (_fIsearching) {
  715.                 _fIsearching = FALSE;
  716.                 text->fImeInputToWmChar--;
  717.             }
  718.             break;
  719.         }
  720.         case WM_CHAR: {
  721.             if (text->fKeyD) {
  722.                 break;
  723.             }
  724.             if (_chPrefix) {
  725.                 prefix_exec(wParam);
  726.                 return TRUE;
  727.             } else if (_fIsearching) {
  728.                 if (wParam >= ' ') {
  729.                     _szIsearch += chartostr(wParam);
  730.                     _fIsearchWrapped = FALSE;
  731.                     txSetUndisp(text);
  732.                     txJumpAddress(text,_adrIsearch);
  733.                     isearch_next(SEARCH_CUR|_Isearchmode);
  734.                     txSetDisp(text);
  735.                     return TRUE;
  736.                 }
  737.             }
  738.             break;
  739.         }
  740.     }
  741.     return FALSE;
  742. }
  743.  
  744. __new
  745. {
  746.     _wzcmdKillLine = wzcmdRegister("\m.kill_line");
  747.     _wzcmdIsearchForward = wzcmdRegister("\m.isearch_forward");
  748.     _wzcmdIsearchBackward = wzcmdRegister("\m.isearch_backward");
  749.     _wzcmdIsearchRegexp = wzcmdRegister("\m.isearch_forward_regexp");
  750.     macroHookWndText();
  751. }
  752.  
  753. __delete
  754. {
  755.     macroHookWndTextFree();
  756. }
  757.  
  758.