home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 1998 September
/
VPR9809B.ISO
/
APUPDATE
/
VC
/
Tx300d
/
TX300D.LZH
/
EMACSWZ.C
< prev
next >
Wrap
C/C++ Source or Header
|
1997-05-09
|
14KB
|
758 lines
// Emacs like keybind support TLL
// programed by TY
//2.99 970313 start
// EMACS like keybind 実装にあたり、中村 学 (Nakamura Manabu)さんのEMACSWZと、
// UK-TaniyamaさんのEMACSWZを参考にさせて頂きました。ありがとうございます。
//{###Emacsライクキーコマンド}
#include <windows.h>
#include <windowsx.h>
#include "dialog.h"
#include "edit.h"
#define chToCtrl(ch) (ch-0x60) // chは小文字のこと
static BOOL _fIsearching;
static txstr _szIsearch;
static txstr _szIsearch0;
static BOOL _fIsearchWrapped;
static WZCMD _wzcmdKillLine;//2.99D 970402
static WZCMD _wzcmdIsearchForward;
static WZCMD _wzcmdIsearchBackward;
static WZCMD _wzcmdIsearchRegexp;
static IFILE _adrIsearch;
static IFILE _adrIsearch0;
static BOOL _fStatBasePrinting = FALSE;
static BOOL _fIsearchLastFail;
static SEARCHMODE _Isearchmode;
static mchar _chPrefix = 0;
static BOOL _fImeOpen = FALSE;//3.00A4 970509
typedef struct {
mchar ch;
mchar *szCmd;
} EMACSKEYITEM;
static EMACSKEYITEM _tKeyPrefixX[] = {
{chToCtrl('b'), "list_buffers"},
{chToCtrl('c'), "save_buffers_kill_emacs"},
{chToCtrl('f'), "find_file"},
{chToCtrl('q'), "toggle_read_only"},
{chToCtrl('s'), "save_buffer"},
{chToCtrl('g'), "keyboard_quit"},
{chToCtrl('x'), "exchange_point_and_mark"},
{chToCtrl('w'), "write_file"},
{chToCtrl('z'), "suspend_emacs"},
{'1', "delete_other_windows"},
{'2', "split_window_vertically"},
{'b', "list_buffers"},
{'d', "dired"},
{'f', "set_fill_column"},
{'h', "mark_whole_buffer"},
{'o', "other_window"},
{'k', "kill_buffer"},
{'i', "insert_file"},
{'u', "advertised_undo"},
{'(', "start_kbd_macro"},
{')', "end_kbd_macro"},
{'e', "call_last_kbd_macro"},
{0, NULL}
};
static EMACSKEYITEM _tKeyPrefixEsc[] = {
{chToCtrl('a'), "beginning_of_defun"},
{chToCtrl('b'), "backward_sexp"},
{chToCtrl('e'), "end_of_defun"},
{chToCtrl('f'), "forward_sexp"},
{chToCtrl('g'), "keyboard_quit"},
{chToCtrl('s'), "isearch_forward_regexp"},
{' ', "set_mark_command"},
{'[', "backward_paragraph"},
{']', "forward_paragraph"},
{'%', "query_replase"},
{'<', "beginning_of_buffer"},
{'>', "end_of_buffer"},
{'c', "capitalize_word"},
{'v', "scroll_down"},
{'f', "forward_word"},
{'b', "backward_word"},
{'g', "goto_line"},
{'d', "kill_word"},
{'l', "downcase_word"},
{'m', "back_to_indentation"},
{'t', "transpose_words"},
{'u', "upcase_word"},
{'q', "fill_paragraph"},
{'w', "copy_region_as_kill"},
// {'x', "execute_extended_command"},////未完成
{0, NULL}
};
kill_region
{
//{#EMACS} ^W
txSetUndisp(text);
txJumpMarkCur(text);
txSelectEx(text,CLIP_CHAR);
txJumpMarkCur(text);
call("edit.txClipboardCut");
txSetDisp(text);
statprintf("Region cuted");
}
copy_region_as_kill
{
txSetUndisp(text);
txJumpMarkCur(text);
txSelectEx(text,CLIP_CHAR);
txJumpMarkCur(text);
call("edit.txClipboardCopy");
txSetDisp(text);
statprintf("Region copyed");
}
fill_paragraph
{
call("paraform.form");
}
goto_line
{
txuiJump(text);
}
transpose_words
{
txstr src;
txstr dst;
txSetUndisp(text);
//
txJumpWordTopMi(text);
txSelectEx(text,CLIP_CHAR);
txJumpWordEndMi(text);
TXCHAR ch = txGetChar(text);
if (ch == ' ') {
txJumpWordEndMi(text);
}
txGetWord(text,src);
txSelectDelete(text);
//
txSelectEx(text,CLIP_CHAR);
txLeftWordMi(text);
TXCHAR ch = txGetChar(text);
if (ch == ' ') {
txLeftWordMi(text);
}
txGetWord(text,dst);
txSelectDelete(text);
//
txInsert(text,src);
txInsert(text,dst);
//
txSetDisp(text);
}
back_to_indentation
{
txSetUndisp(text);
txJumpParaTop(text);
while(1) {
TXCHAR ch = txReadChar(text);
if (ch != '\t' && ch != ' ') break;
if (txIsCurEof(text)) break;
}
txLeft(text);
txSetDisp(text);
}
kill_word
{
txDeleteWord(text);
}
backward_word
{
txLeftWordMi(text);
}
forward_word
{
txRightWordMi(text);
}
static void capitalize(BOOL fWord,BOOL fTolower)
{
txstr buff;
txSetUndisp(text);
if (!text->fClip) {
txSelect(text);
if (fWord) {
txJumpWordEndMi(text);
} else {
txRight(text);
}
}
txGetWord(text,buff);
if (fTolower) {
strlwr(buff);
} else {
strupr(buff);
}
txSelectDelete(text);
txInsert(text,buff);
txJumpWordEndMi(text);
txSetDisp(text);
}
capitalize_word
{
capitalize(FALSE,FALSE);
}
downcase_word
{
capitalize(TRUE,TRUE);
}
upcase_word
{
capitalize(TRUE,FALSE);
}
beginning_of_buffer
{
txMarkCur(text);
txJumpFileTop(text);
statprintf("Mark set");
}
end_of_buffer
{
txMarkCur(text);
txJumpFileEnd(text);
statprintf("Mark set");
}
query_replase
{
txuiReplaceQuery(text);
}
backward_paragraph
{
txJumpParaTop(text);
}
forward_paragraph
{
txJumpParaEnd(text);
}
beginning_of_defun
{
txSearchEx(text,"^{",SEARCH_RE|SEARCH_PREV);
}
end_of_defun
{
txSearchEx(text,"^}",SEARCH_RE|SEARCH_PREV);
}
backward_sexp
{
txSetUndisp(text);
txSearchEx(text,"[])}]",SEARCH_RE|SEARCH_PREV);
txJumpBrace(text);
txSetDisp(text);
}
forward_sexp
{
txSetUndisp(text);
txSearchEx(text,"[[({]",SEARCH_RE|SEARCH_CUR);
txJumpBrace(text);
txRight(text);
txSetDisp(text);
}
static BOOL IsLastOpIsearch(void)
{
if (text->wzcmdLastOp == _wzcmdIsearchForward) return TRUE;
if (text->wzcmdLastOp == _wzcmdIsearchBackward) return TRUE;
if (text->wzcmdLastOp == _wzcmdIsearchRegexp) return TRUE;
return FALSE;
}
static void statbaseprint(mchar* sz)
{
_fStatBasePrinting = (sz && sz[0]);
SendMessage(text->hwndbase,WM_TXSB_SETUPTEXT,HSL_INFOBASE,(LPARAM)sz);
}
//## search
static void isearch_statprint(BOOL find,SEARCHMODE searchmode)
{
txstr sz;
if (!find) sz += "Failing ";
if (_fIsearchWrapped) sz += "Wrapped ";
if (searchmode & SEARCH_RE) sz += "Regexp ";
sz += "I-search";
if (searchmode & SEARCH_PREV) sz += " backward";
sz += ": ";
sz += _szIsearch;
statbaseprint(sz);
}
static void isearch_next(SEARCHMODE searchmode)
{
SEARCHMODE mode = SEARCH_FORWARD|SEARCH_NOSENSECASE|searchmode;
if (_szIsearch[0]) {
BOOL ret = FALSE;
IFILE adr = txGetAddress(text);
IFILE adrCurscreen = txGetAddressCurscreen(text);
int ly = text->ly;
txSetUndisp(text);
if (_fIsearchLastFail) {
_fIsearchLastFail = FALSE;
if (mode & SEARCH_PREV) {
txJumpFileEnd(text);
} else {
txJumpFileTop(text);
}
_fIsearchWrapped = TRUE;
}
ret = txSearchEx(text,_szIsearch,mode);
if (!ret) {
_fIsearchLastFail = TRUE;
}
if (ret) {
_adrIsearch = txGetAddress(text);
if ((mode & SEARCH_PREV) && !(mode & SEARCH_CUR)) {
// 連続実行時でBackward時は実行しない
} else {
txRightBytes(text,ret-1);
}
txSetLy(text,ly);
} else {
txJumpAddress(text,adr);
txSetLyCurscreen(text,adrCurscreen);
}
txSetDisp(text);
isearch_statprint(ret,mode);
_szIsearch0 = _szIsearch;
} else {
isearch_statprint(TRUE,searchmode);
}
}
static void isearch(SEARCHMODE searchmode)
{
if (IsLastOpIsearch()) {
// 連続実行
if (!_fIsearching) {
_fIsearching = TRUE;
text->fImeInputToWmChar++;
}
if (!_szIsearch[0]) _szIsearch = _szIsearch0;
isearch_next(searchmode|_Isearchmode);
} else {
if (!_fIsearching) {
_fIsearching = TRUE;
text->fImeInputToWmChar++;
_szIsearch = "";
_fIsearchWrapped = FALSE;
_adrIsearch0 = _adrIsearch = txGetAddress(text);
_fIsearchLastFail = FALSE;
_Isearchmode = searchmode & SEARCH_RE;
}
isearch_next(searchmode|SEARCH_CUR);
}
}
isearch_backward
{
// インクリメンタルサーチ(上方向)
//{#EMACS} ^R
isearch(SEARCH_PREV);
}
isearch_forward
{
// インクリメンタルサーチ(下方向)
//{#EMACS} ^S
isearch(0);
}
isearch_forward_regexp
{
isearch(SEARCH_RE);
}
//## cmds
call_last_kbd_macro
{
txKeymacroPlay(text);
}
start_kbd_macro
{
txKeymacroRecord(text);
statprintf("Defining kbd macro...");
}
end_kbd_macro
{
txKeymacroRecord(text);
statprintf("Keyboard macro defined");
}
advertised_undo
{
txUndo(text);
statprintf("Undo!");
}
kill_buffer
{
txuiClose(text);
}
insert_file
{
txuiInsertFile(text);
}
other_window
{
txSwitchWindow(text);
}
mark_whole_buffer
{
txSetUndisp(text);
txJumpFileEnd(text);
txMarkCur(text);
txJumpFileTop(text);
txSetDisp(text);
}
set_fill_column
{
call("paraform.config");
}
dired
{
call("filer.txe");
}
delete_other_windows
{
txSwitchSplit(text); // とりあえず
}
split_window_vertically
{
txSwitchSplit(text); // とりあえず
}
suspend_emacs
{
// DOS PROMPT
if (_platform == WINDOWSNT) {
exec("cmd.exe");
} else {
exec("dosprmpt.pif");
}
}
save_buffers_kill_emacs
{
txuiCloseAllEvery(text);
}
toggle_read_only
{
call("disp.readmode");
}
save_buffer
{
if (!text->fEdit) {
statprintf("(No changes need to be saved)");
} else {
if (txuiSave(text))
statprintf("Wrote %s",text->szfilename);
}
}
write_file
{
txuiSaveTo(text);
}
exchange_point_and_mark
{
txJumpMarkCur(text);
txSetLyCenter(text);
}
list_buffers
{
txuiSwitchText(text);
}
kill_line
{
// カーソル位置から行末までを削除します。
// カーソル位置が改行なら、改行を削除します。
// 削除した文字列をクリップボードにコピーします。
// 連続実行するとクリップボードに追加します。
//2.99 970313 new
//{#EMACS} ^K
#if 1///2.99D 970402
TX* textWork = NULL;
txSetUndispSilent(text);
if (text->wzcmdLastOp == _wzcmdKillLine) {
//2.99D 970402 EMACS ^Kで連続実行でクリップボードに出力するようにした
textWork = textopen(NULL);
txClipboardPaste(textWork);
}
txSelectEx(text,CLIP_CHAR);
if (txIsCurReturn(text)) {
txRight(text);
} else {
txJumpParaEnd(text);
}
if (textWork) {
txPrivatePush(text);
txSelectDelete(text);
txJumpFileEnd(textWork);
txPrivatePaste(textWork);
txPrivateDeleteTop(textWork);
txSelectEx(textWork,CLIP_ALL);
txClipboardCopy(textWork);
textclose(textWork);
} else {
txClipboardCut(text);
}
txSetDispSilent(text);
#else
if (txIsCurReturn(text)) {
txDeleteChar(text);
} else {
txDeleteParaEnd(text);
}
#endif
}
c_indent_command
{
//{#EMACS} ^I
call("edit.tab");
}
recenter
{
// カーソルを画面中央にセットし、画面表示をリフレッシュ
//{#EMACS} ^L
txSetUndisp(text);
txSetLyCenter(text);
txSetDisp(text);
}
quoted_insert
{
//{#EMACS} ^Q
// なにもしない
}
keyboard_quit
{
// インクリメンタルサーチ等の取り消し
//{#EMACS} ^G
if (_fIsearching) {
_fIsearching = FALSE;
text->fImeInputToWmChar--;
}
if (IsLastOpIsearch()) {
txJumpAddress(text,_adrIsearch0);
}
statprintf("Quit");
}
transpose_chars
{
// カーソル位置と左の文字を入れ替え
//{#EMACS} ^T
if (txIsCurReturn(text)) return FALSE;
txSetUndispSilent(text);
txSelectQuit(text);
TXCHAR ch = txGetChar(text);
txDeleteChar(text);
txLeft(text);
txInsertChar(text,ch);
txRight(text);
txSetDispSilent(text);
}
toggle_ime_mode
{
//{#EMACS} ^\ +^{Space}
if (imeGetOpen()) {
imeSetOpen(FALSE);
} else {
imeSetOpen(TRUE);
}
}
scroll_down
{
//{#EMACS} ^Z
txPrevPageVz(text);
}
delete_backward_char
{
//{#EMACS} ^H
call("edit.txkeyDeletePrev");
}
set_mark_command
{
//{#EMACS} ^{Space}
statprintf("Mark set");
txMarkCur(text);
}
find_file
{
txuiOpen(text);
}
//##
static void prefix_exec(int ch)
{
statbaseprint(NULL);
//
ch = tolower(ch);
EMACSKEYITEM* item = NULL;
if (_chPrefix == chToCtrl('x')) {
item = _tKeyPrefixX;
} else if (_chPrefix == 0x1B) {
item = _tKeyPrefixEsc;
}
if (item) {
for (;item->ch;item++) {
if (ch == item->ch) {
statprintf(item->szCmd);
call("\m." + item->szCmd);
if (!stricmp(item->szCmd,"isearch_forward_regexp")) {
text->wzcmdLastOp = _wzcmdIsearchRegexp;
}
break;
}
}
}
//
_chPrefix = 0;
imeSetOpen(_fImeOpen);//3.00A4 970509
}
static void prefix_set(int ch)
{
_chPrefix = ch;
//3.00A4 970509 EMACS.KEY : Esc,^Xの2ストローク目の入力で、IMEをOFFにするようにした
_fImeOpen = imeGetOpen();
imeSetOpen(FALSE);
}
prefix_ctrlx
{
//{#EMACS} ^X
statbaseprint("C-x-");
prefix_set(chToCtrl('x'));
}
prefix_esc
{
//{#EMACS} {Esc}
statbaseprint("ESC-");
prefix_set(0x1B);
}
//##
HOOKRESULT __wndproctext(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{
TX* text = textTarget;
switch(message) {
case WM_KEYDOWN: {
if (_fIsearching) {
if (GetKeyState(VK_CONTROL) < 0) {
_fIsearching = FALSE;
text->fImeInputToWmChar--;
}
} else if (!_chPrefix) {
if (!IsLastOpIsearch()) {
if (_fStatBasePrinting) statbaseprint(NULL);
}
}
break;
}
case WM_KILLFOCUS: {
if (_fIsearching) {
_fIsearching = FALSE;
text->fImeInputToWmChar--;
}
break;
}
case WM_CHAR: {
if (text->fKeyD) {
break;
}
if (_chPrefix) {
prefix_exec(wParam);
return TRUE;
} else if (_fIsearching) {
if (wParam >= ' ') {
_szIsearch += chartostr(wParam);
_fIsearchWrapped = FALSE;
txSetUndisp(text);
txJumpAddress(text,_adrIsearch);
isearch_next(SEARCH_CUR|_Isearchmode);
txSetDisp(text);
return TRUE;
}
}
break;
}
}
return FALSE;
}
__new
{
_wzcmdKillLine = wzcmdRegister("\m.kill_line");
_wzcmdIsearchForward = wzcmdRegister("\m.isearch_forward");
_wzcmdIsearchBackward = wzcmdRegister("\m.isearch_backward");
_wzcmdIsearchRegexp = wzcmdRegister("\m.isearch_forward_regexp");
macroHookWndText();
}
__delete
{
macroHookWndTextFree();
}