📄 chokanmgr.cpp
字号:
// $Id: CHokanMgr.cpp,v 1.20 2004/10/11 01:23:05 genta Exp $
/*! @file
@brief キーワード補完
@author Norio Nakatani
$Revision: 1.20 $
*/
/*
Copyright (C) 1998-2001, Norio Nakatani
Copyright (C) 2001, asa-o
This source code is designed for sakura editor.
Please contact the copyright holders to use this code for other purpose.
*/
#include "CHokanMgr.h"
#include "debug.h"
#include "CKeyBind.h"
#include "Keycode.h"
#include "CDicMgr.h"
#include "CEditView.h"
#include "mymessage.h"
#include "sakura_rc.h"
#include "etc_uty.h"
WNDPROC gm_wpHokanListProc;
LRESULT APIENTRY HokanList_SubclassProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
//#ifdef _DEBUG
// MYTRACE( "HokanList_SubclassProc() uMsg == %xh\n", uMsg );
//#endif
// Modified by KEITA for WIN64 2003.9.6
CDialog* pCDialog = ( CDialog* )::GetWindowLongPtr( ::GetParent( hwnd ), DWLP_USER );
CHokanMgr* pCHokanMgr = (CHokanMgr*)::GetWindowLongPtr( ::GetParent( hwnd ), DWLP_USER );
// WORD vkey;
// WORD nCaretPos;
// LPARAM hwndLB;
// int i;
MSG* pMsg;
int nVKey;
// LPARAM lKeyData;
switch( uMsg ){
case WM_KEYDOWN:
nVKey = (int) wParam; // virtual-key code
// lKeyData = lParam; // key data
// MYTRACE( "WM_KEYDOWN nVKey = %xh\n", nVKey );
/* キー操作を偽造しよう */
if (nVKey == VK_SPACE){ // Space
// novice 2004/10/10
/* Shift,Ctrl,Altキーが押されていたか */
int nIdx = getCtrlKeyState();
if (nIdx == _SHIFT){
// Shift + Spaceで↑を偽造
wParam = VK_UP;
}
else if (nIdx == 0) {
// Spaceのみで↓を偽造
wParam = VK_DOWN;
}
}
/* 補完実行キーなら補完する */
if( -1 != pCHokanMgr->KeyProc( wParam, lParam ) ){
/* キーストロークを親に転送 */
::EnableWindow( ::GetParent( ::GetParent( pCDialog->m_hwndParent ) ), TRUE );
// ::ShowWindow( pCDialog->m_hWnd, SW_HIDE );
// ::SetFocus( ::GetParent( ::GetParent( pCDialog->m_hwndParent ) ) );
return ::PostMessage( ::GetParent( ::GetParent( pCDialog->m_hwndParent ) ), uMsg, wParam, lParam );
}
break;
case WM_GETDLGCODE:
pMsg = (MSG*) lParam; // pointer to an MSG structure
if( NULL == pMsg ){
// MYTRACE( "WM_GETDLGCODE pMsg==NULL\n" );
return 0;
}
// MYTRACE( "WM_GETDLGCODE pMsg->message = %xh\n", pMsg->message );
return DLGC_WANTALLKEYS;/* すべてのキーストロークを私に下さい */ // Sept. 17, 2000 jepro 説明の「全て」を「すべて」に統一
}
return CallWindowProc( (WNDPROC)gm_wpHokanListProc, hwnd, uMsg, wParam, lParam);
}
CHokanMgr::CHokanMgr()
{
// m_hFont = NULL;
// m_hFontOld = NULL;
m_cmemCurWord.SetDataSz( "" );
m_pcmemKouho = NULL;
m_nKouhoNum = 0;;
m_nCurKouhoIdx = -1;
m_pszCurKouho = NULL;
// m_pcEditView = NULL;
m_bTimerFlag = TRUE;
// hm_wpHokanListProc = FALSE;
return;
}
CHokanMgr::~CHokanMgr()
{
if( NULL != m_pcmemKouho ){
delete m_pcmemKouho;
m_pcmemKouho = NULL;
}
m_nKouhoNum = 0;;
if( NULL != m_pszCurKouho ){
delete [] m_pszCurKouho;
m_pszCurKouho = NULL;
}
}
/* モードレスダイアログの表示 */
HWND CHokanMgr::DoModeless( HINSTANCE hInstance , HWND hwndParent, LPARAM lParam )
{
HWND hwndWork;
hwndWork = CDialog::DoModeless( hInstance, hwndParent, IDD_HOKAN, lParam, SW_HIDE );
OnSize( 0, 0 );
/* リストをフック */
// Modified by KEITA for WIN64 2003.9.6
::gm_wpHokanListProc = (WNDPROC) ::SetWindowLongPtr( ::GetDlgItem( m_hWnd, IDC_LIST_WORDS ), GWLP_WNDPROC, (LONG_PTR)HokanList_SubclassProc );
::ShowWindow( m_hWnd, SW_HIDE );
return hwndWork;
}
/* モードレス時:対象となるビューの変更 */
void CHokanMgr::ChangeView( LPARAM pcEditView )
{
m_lParam = pcEditView;
return;
}
void CHokanMgr::Hide( void )
{
CEditView* pcEditView;
::EnableWindow( ::GetParent( ::GetParent( m_hwndParent ) ), TRUE );
// ::DestroyWindow( hwnd );
::ShowWindow( m_hWnd, SW_HIDE );
m_nCurKouhoIdx = -1;
/* 入力フォーカスを受け取ったときの処理 */
pcEditView = (CEditView*)m_lParam;
pcEditView->OnSetFocus();
// m_nCurKouhoIdx = -1;
return;
}
/*! 初期化
pcmemHokanWord == NULLのとき、補完候補がひとつだったら、補完ウィンドウを表示しないで終了します。
Search()呼び出し元で確定処理を進めてください。
@date 2002.2.17 YAZAKI CShareDataのインスタンスは、CProcessにひとつあるのみ。
*/
int CHokanMgr::Search(
// HFONT hFont,
POINT* ppoWin,
int nWinHeight,
int nColmWidth,
const char* pszCurWord,
const char* pszHokanFile,
int bHokanLoHiCase, // 入力補完機能:英大文字小文字を同一視する 2001/06/19 asa-o
BOOL bHokanByFile, // 編集中データから候補を探す 2003.06.23 Moca
CMemory* pcmemHokanWord // 2001/06/19 asa-o
)
{
CEditView* pcEditView = (CEditView*)m_lParam;
/*
|| 補完キーワードの検索
||
|| ?見つかった候補をすべて返す(改行で区切って返す)
|| ?指定された候補の最大数を超えると処理を中断する
|| ?見つかった数を返す
||
*/
if( NULL != m_pcmemKouho ){
delete m_pcmemKouho;
m_pcmemKouho = NULL;
}
m_nKouhoNum = CDicMgr::HokanSearch(
pszCurWord,
// m_pShareData->m_Common.m_bHokanLoHiCase, /* 入力補完機能:英大文字小文字を同一視する */
bHokanLoHiCase, // 引数からに変更 2001/06/19 asa-o
&m_pcmemKouho,
0, //Max候補数
pszHokanFile
);
// 2003.05.16 Moca 追加 編集中データ内から候補を探す
if( bHokanByFile ){
m_nKouhoNum = pcEditView->HokanSearchByFile(
pszCurWord,
bHokanLoHiCase,
&m_pcmemKouho,
m_nKouhoNum,
1024 // 編集中データからなので数を制限しておく
);
}
if( 0 == m_nKouhoNum ){
m_nCurKouhoIdx = -1;
return 0;
}
// 2001/06/19 asa-o 候補が1つの場合補完ウィンドウは表示しない(逐次補完の場合は除く)
if( 1 == m_nKouhoNum ){
if(pcmemHokanWord != NULL){
m_nCurKouhoIdx = -1;
// 2004.05.14 Moca m_pcmemKouhoの末尾には改行コードがあり、それを削除してコピーするするように
pcmemHokanWord->SetData( m_pcmemKouho->GetPtr(), m_pcmemKouho->GetLength() - 1 );
return 1;
}
}
// LOGFONT lf;
// HDC hdc;
// WNDCLASS wc;
// ATOM atom;
int i;
/* 共有データ構造体のアドレスを返す */
m_pShareData = CShareData::getInstance()->GetShareData();
// m_hFont = hFont;
m_poWin.x = ppoWin->x;
m_poWin.y = ppoWin->y;
m_nWinHeight = nWinHeight;
m_nColmWidth = nColmWidth;
// m_cmemCurWord.SetData( pszCurWord, lstrlen( pszCurWord ) );
m_cmemCurWord.SetDataSz( pszCurWord );
m_nCurKouhoIdx = 0;
// SetCurKouhoStr();
// ::ShowWindow( m_hWnd, SW_SHOWNA );
HWND hwndList;
hwndList = ::GetDlgItem( m_hWnd, IDC_LIST_WORDS );
::SendMessage( hwndList, LB_RESETCONTENT, 0, 0 );
char* pszCR = "\n";
char* pszWork;
char* pszNext;
char* pszTest;
pszWork = m_pcmemKouho->GetPtr();
for( i = 0; i < m_nKouhoNum; ++i ){
pszNext = strstr( pszWork, pszCR );
if( NULL == pszNext ){
break;
}
pszTest = new char[pszNext - pszWork + 1];
memcpy( pszTest, pszWork, pszNext - pszWork );
pszTest[pszNext - pszWork] = '\0';
::SendMessage( hwndList, LB_ADDSTRING, 0, (LPARAM) (LPCTSTR) pszTest );
delete [] pszTest;
pszTest = NULL;
pszWork = pszNext + lstrlen( pszCR );
}
::SendMessage( hwndList, LB_SETCURSEL, 0, 0 );
//? この処理はやらないほうが見やすいかも?
//? /* リストの全アイテム数がリストに収まる時は、リストのサイズを小さくする */
//? int nItemHeight;
//? nItemHeight = ::SendMessage( hwndList, LB_GETITEMHEIGHT, 0, 0 );
//? if( ( m_nKouhoNum + 1 ) * nItemHeight < m_nHeight ){
//? m_nHeight = ( m_nKouhoNum + 1 ) * nItemHeight;
//? }else{
//? if( m_nHeight < 1000 ){
//? m_nHeight = 1000;
//? }
//? }
//? if( ( m_nKouhoNum + 1 ) * nItemHeight < m_nHeight ){
//? m_nHeight = ( m_nKouhoNum + 1 ) * nItemHeight;
//? }
//?
//@@ ::EnableWindow( ::GetParent( ::GetParent( m_hwndParent ) ), FALSE );
int nX;
int nY;
int nCX;
int nCY;
RECT rcDesktop;
// May 01, 2004 genta マルチモニタ対応
::GetMonitorWorkRect( m_hWnd, &rcDesktop );
nX = m_poWin.x - m_nColmWidth;
nY = m_poWin.y + m_nWinHeight + 4;
nCX = m_nWidth;
nCY = m_nHeight;
/* 下に入るなら */
if( nY + nCY < rcDesktop.bottom ){
/* 何もしない */
}else
/* 上に入るなら */
if( rcDesktop.top < m_poWin.y - m_nHeight - 4 ){
/* 上に出す */
nY = m_poWin.y - m_nHeight - 4;
}else
/* 上に出すか下に出すか(広いほうに出す) */
if( rcDesktop.bottom - nY > m_poWin.y ){
/* 下に出す */
// m_nHeight = rcDesktop.bottom - nY;
nCY = rcDesktop.bottom - nY;
}else{
/* 上に出す */
nY = rcDesktop.top;
nCY = m_poWin.y - 4 - rcDesktop.top;
}
// 2001/06/19 Start by asa-o: 表示位置補正
// 右に入る
if(nX + nCX < rcDesktop.right ){
// そのまま
}else
// 左に入る
if(rcDesktop.left < nX - nCX + 8){
// 左に表示
nX -= nCX - 8;
}else{
// サイズを調整して右に表示
nCX = max((int)(rcDesktop.right - nX) , 100); // 最低サイズを100くらいに
}
// 2001/06/19 End
// 2001/06/18 Start by asa-o: 補正後の位置?サイズを保存
m_poWin.x = nX;
m_poWin.y = nY;
m_nHeight = nCY;
m_nWidth = nCX;
// 2001/06/18 End
/* はみ出すなら小さくする */
// if( rcDesktop.bottom < nY + nCY ){
// /* 下にはみ出す */
// if( m_poWin.y - 4 - nCY < 0 ){
// /* 上にはみ出す */
// /* →高さだけ調節 */
// nCY = rcDesktop.bottom - nY - 4;
// }else{
//
// }
//
// }
::MoveWindow( m_hWnd, nX, nY, nCX, nCY, TRUE );
::ShowWindow( m_hWnd, SW_SHOW );
// ::ShowWindow( m_hWnd, SW_SHOWNA );
::SetFocus( m_hWnd );
// ::SetFocus( ::GetDlgItem( m_hWnd, IDC_LIST_WORDS ) );
// ::SetFocus( ::GetParent( ::GetParent( m_hwndParent ) ) );
// 2001/06/18 asa-o:
ShowTip(); // 補完ウィンドウで選択中の単語にキーワードヘルプを表示
// 2003.06.25 Moca 他のメソッドで使っていないので、とりあえず削除しておく
if( NULL != m_pcmemKouho ){
delete m_pcmemKouho;
m_pcmemKouho = NULL;
}
return m_nKouhoNum;
}
#if 0
///// 2003.06.25 未使用のようだ。Moca
void CHokanMgr::SetCurKouhoStr( void )
{
char* pszCR = "\n";
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -