1 // TortoiseGit - a Windows shell extension for easy version control
3 // Copyright (c) 2003 by Andreas Kapust <info@akinstaller.de>; <http://www.codeproject.com/Articles/2607/AutoComplete-without-IAutoComplete>
4 // Copyright (C) 2009, 2012-2013, 2015-2016 - TortoiseGit
6 // Licensed under: The Code Project Open License (CPOL); <http://www.codeproject.com/info/cpol10.aspx>
8 // ACEdit.cpp: Implementierungsdatei
14 #include "StringUtils.h"
19 static char THIS_FILE
[] = __FILE__
;
25 /////////////////////////////////////////////////////////////////////////////
30 m_iMode
= _MODE_STANDARD_
;
41 /*********************************************************************/
48 /*********************************************************************/
50 BEGIN_MESSAGE_MAP(CACEdit
, CWnd
)
51 //{{AFX_MSG_MAP(CACEdit)
52 ON_CONTROL_REFLECT(EN_KILLFOCUS
, OnKillfocus
)
53 ON_CONTROL_REFLECT(CBN_KILLFOCUS
, OnKillfocus
)
55 ON_CONTROL_REFLECT(EN_CHANGE
, OnChange
)
56 ON_CONTROL_REFLECT(CBN_EDITCHANGE
, OnChange
)
57 ON_CONTROL_REFLECT(CBN_DROPDOWN
, OnCloseList
)
59 ON_MESSAGE(ENAC_UPDATE
,OnUpdateFromList
)
62 /*********************************************************************/
64 void CACEdit::SetMode(int iMode
)
73 ** NEW: _MODE_CURSOR_O_LIST_
75 if(iMode
== _MODE_CURSOR_O_LIST_
)
76 m_iMode
|= _MODE_STANDARD_
;
78 if(iMode
& _MODE_FILESYSTEM_
)
79 m_SeparationStr
= L
'\\';
82 if(iMode
& _MODE_FIND_ALL_
)
84 m_Liste
.m_lMode
|= _MODE_FIND_ALL_
;
88 /*********************************************************************/
92 CString szClassName
= AfxRegisterWndClass(CS_CLASSDC
|CS_SAVEBITS
|CS_HREDRAW
|CS_VREDRAW
,
93 0,(HBRUSH
) (COLOR_WINDOW
), 0);
97 VERIFY(m_Liste
.CreateEx(WS_EX_TOOLWINDOW
,
99 WS_THICKFRAME
| WS_CHILD
| WS_BORDER
|
100 WS_CLIPSIBLINGS
| WS_OVERLAPPED
,
101 CRect(rcWnd
.left
, rcWnd
.top
+20, rcWnd
.left
+ 200, rcWnd
.top
+200),
106 ::GetClassName(GetSafeHwnd(), CStrBuf(m_ClassName
, 32), 32);
108 if (m_ClassName
.Compare(L
"Edit") == 0)
112 if (m_ClassName
.Compare(L
"ComboBox") == 0)
114 m_iType
= _COMBOBOX_
;
116 m_pEdit
= (CEdit
*)GetWindow(GW_CHILD
);
118 ::GetClassName(m_pEdit
->GetSafeHwnd(), CStrBuf(m_ClassName
, 32), 32);
119 VERIFY(m_ClassName
.Compare(L
"Edit") == 0);
132 /*********************************************************************/
134 void CACEdit::AddSearchStrings(LPCTSTR Strings
[])
138 if(m_iType
== -1) {ASSERT(0); return;}
147 m_Liste
.AddSearchString(str
);
154 m_Liste
.SortSearchList();
157 /*********************************************************************/
159 void CACEdit::AddSearchString(LPCTSTR lpszString
)
161 if(m_iType
== -1) {ASSERT(0); return;}
163 m_Liste
.AddSearchString(lpszString
);
166 /*********************************************************************/
168 void CACEdit::RemoveSearchAll()
170 if(m_iType
== -1) {ASSERT(0); return;}
175 /*********************************************************************/
177 void CACEdit::OnKillfocus()
179 if(m_Liste
.GetSafeHwnd()) // fix Vers 1.1
180 m_Liste
.ShowWindow(false);
183 /*********************************************************************/
185 void CACEdit::OnKeyDown(UINT nChar
, UINT nRepCnt
, UINT nFlags
)
187 if(!HandleKey(nChar
,false))
188 CWnd::OnKeyDown(nChar
, nRepCnt
, nFlags
);
191 /*********************************************************************/
193 bool CACEdit::HandleKey(UINT nChar
, bool m_bFromChild
)
195 if (nChar
== VK_ESCAPE
||nChar
== VK_RETURN
)
197 m_Liste
.ShowWindow(false);
201 if (nChar
== VK_DOWN
|| nChar
== VK_UP
202 || nChar
== VK_PRIOR
|| nChar
== VK_NEXT
203 || nChar
== VK_HOME
|| nChar
== VK_END
)
207 ** NEW: _MODE_CURSOR_O_LIST_
209 if(!m_Liste
.IsWindowVisible() && (m_iMode
& _MODE_CURSOR_O_LIST_
))
211 GetWindowText(m_EditText
);
212 if(m_EditText
.IsEmpty())
219 if(m_Liste
.IsWindowVisible())
224 if(m_iMode
& _MODE_STANDARD_
225 || m_iMode
& _MODE_FILESYSTEM_
226 || m_iMode
& _MODE_FS_START_DIR_
)
231 m_EditText
= m_Liste
.GetNextString(nChar
);
233 m_EditText
= m_Liste
.GetString();
235 if(m_iMode
& _MODE_FILESYSTEM_
)
237 if (CStringUtils::EndsWith(m_EditText
, L
'\\'))
238 m_EditText
= m_EditText
.Mid(0,m_EditText
.GetLength()-1);
241 m_Liste
.SelectItem(-1);
242 SetWindowText(m_EditText
);
243 pos
= m_EditText
.GetLength();
245 if(m_iType
== _COMBOBOX_
)
247 m_pEdit
->SetSel(pos
,pos
,true);
248 m_pEdit
->SetModify(true);
251 if(m_iType
== _EDIT_
)
253 ((CEdit
*)this)->SetSel(pos
,pos
,true);
254 ((CEdit
*)this)->SetModify(true);
257 GetParent()->SendMessage(ENAC_UPDATE
, WM_KEYDOWN
, GetDlgCtrlID());
258 m_CursorMode
= false;
262 if(m_iMode
& _MODE_SEPARATION_
)
264 CString m_Text
,m_Left
,m_Right
;
265 int left
,right
,pos2
=0,len
;
269 GetWindowText(m_EditText
);
271 if(m_iType
== _EDIT_
)
272 pos2
= LOWORD(((CEdit
*)this)->CharFromPos(GetCaretPos()));
274 if(m_iType
== _COMBOBOX_
)
275 pos2
= m_pEdit
->CharFromPos(m_pEdit
->GetCaretPos());
277 left
= FindSepLeftPos(pos2
-1,true);
278 right
= FindSepRightPos(pos2
);
280 m_Text
= m_EditText
.Left(left
);
283 m_Text
+= m_Liste
.GetNextString(nChar
);
285 m_Text
+= m_Liste
.GetString();
287 m_Liste
.SelectItem(-1);
288 m_Text
+= m_EditText
.Mid(right
);
289 len
= m_Liste
.GetString().GetLength();
291 m_Text
+= this->m_SeparationStr
;
293 SetWindowText(m_Text
);
294 GetParent()->SendMessage(ENAC_UPDATE
, WM_KEYDOWN
, GetDlgCtrlID());
296 right
= FindSepLeftPos2(pos2
-1);
300 left
+=m_SeparationStr
.GetLength();
302 if(m_iType
== _EDIT_
)
304 ((CEdit
*)this)->SetModify(true);
305 ((CEdit
*)this)->SetSel(left
+len
,left
+len
,false);
308 if(m_iType
== _COMBOBOX_
)
310 m_pEdit
->SetModify(true);
311 m_pEdit
->SetSel(left
,left
+len
,true);
314 m_CursorMode
= false;
322 /*********************************************************************/
324 void CACEdit::OnChange()
332 GetWindowText(m_EditText
);
333 len
= m_EditText
.GetLength();
334 //----------------------------------------------
335 if(m_iMode
& _MODE_FILESYSTEM_
|| m_iMode
& _MODE_FS_START_DIR_
)
339 if(m_iType
== _EDIT_
)
340 pos
= LOWORD(((CEdit
*)this)->CharFromPos(GetCaretPos()));
342 if(m_iType
== _COMBOBOX_
)
343 pos
= m_pEdit
->CharFromPos(m_pEdit
->GetCaretPos());
345 if(m_iMode
& _MODE_FS_START_DIR_
)
348 m_Liste
.FindString(-1,m_EditText
);
350 m_Liste
.ShowWindow(false);
354 if(len
> 2 && pos
== len
)
356 if(_taccess(m_EditText
,0) == 0)
358 ReadDirectory(m_EditText
);
360 m_Liste
.FindString(-1,m_EditText
);
363 m_Liste
.ShowWindow(false);
367 //----------------------------------------------
368 if(m_iMode
& _MODE_SEPARATION_
)
372 if(m_iType
== _EDIT_
)
373 pos
= LOWORD(((CEdit
*)this)->CharFromPos(GetCaretPos()));
375 if(m_iType
== _COMBOBOX_
)
376 pos
= m_pEdit
->CharFromPos(m_pEdit
->GetCaretPos());
379 left
= FindSepLeftPos(pos
-1);
380 right
= FindSepRightPos(pos
);
381 m_Text
= m_EditText
.Mid(left
,right
-left
);
382 m_Liste
.FindString(-1,m_Text
);
385 //----------------------------------------------
386 if(m_iMode
& _MODE_STANDARD_
)
389 m_Liste
.FindString(-1,m_EditText
);
391 //----------------------------------------------
392 GetParent()->SendMessage(ENAC_UPDATE
, EN_UPDATE
, GetDlgCtrlID());
395 /*********************************************************************/
397 int CACEdit::FindSepLeftPos(int pos
,bool m_bIncludePrefix
)
399 int len
= m_EditText
.GetLength();
403 if(pos
>= len
&& len
!= 1)
406 for(i
= pos
; i
>= 0 ; i
--)
408 ch
= m_EditText
.GetAt(i
);
409 if(m_PrefixChar
== ch
)
410 return i
+ (m_bIncludePrefix
? 1 : 0);
411 if(m_SeparationStr
.Find(ch
) != -1)
418 /*********************************************************************/
420 int CACEdit::FindSepLeftPos2(int pos
)
422 int len
= m_EditText
.GetLength();
425 if(pos
>= len
&& len
!= 1)
431 for(int i
= pos
; i
>= 0 ; i
--)
433 ch
= m_EditText
.GetAt(i
);
434 if(m_PrefixChar
== ch
)
441 /*********************************************************************/
443 int CACEdit::FindSepRightPos(int pos
)
445 int len
= m_EditText
.GetLength();
449 for(i
= pos
; i
< len
; i
++)
451 ch
= m_EditText
.GetAt(i
);
452 if(m_SeparationStr
.Find(ch
) != -1)
459 /*********************************************************************/
460 LRESULT
CACEdit::OnUpdateFromList(WPARAM lParam
, LPARAM
/*wParam*/)
464 if(lParam
== WM_KEYDOWN
)
465 HandleKey(VK_DOWN
,true);
469 /*********************************************************************/
471 void CACEdit::OnCloseList()
473 m_Liste
.ShowWindow(false);
476 /*********************************************************************/
478 BOOL
CACEdit::PreTranslateMessage(MSG
* pMsg
)
480 if(pMsg
->message
== WM_KEYDOWN
)
482 if(m_Liste
.IsWindowVisible())
484 if(m_iType
== _COMBOBOX_
)
486 if(pMsg
->wParam
== VK_DOWN
|| pMsg
->wParam
== VK_UP
)
487 if (HandleKey((UINT
)pMsg
->wParam
, false))
491 if(pMsg
->wParam
== VK_ESCAPE
|| pMsg
->wParam
== VK_RETURN
)
492 if (HandleKey((UINT
)pMsg
->wParam
, false))
496 return CWnd::PreTranslateMessage(pMsg
);
499 /*********************************************************************/
501 void CACEdit::ReadDirectory(CString m_Dir
)
503 CFileFind FoundFiles
;
507 // Wenn mittem im Pfad,
508 // vorheriges Verzeichnis einlesen.
509 if (!CStringUtils::EndsWith(m_Dir
, L
'\\'))
511 _wsplitpath_s(m_Dir
, m_szDrive
, m_szDir
, m_szFname
, m_szExt
);
512 m_Dir
.Format(L
"%s%s",m_szDrive
, m_szDir
);
516 ch
= (TCHAR
)towupper(m_Dir
.GetAt(0));
519 CString m_Name
,m_File
,m_Dir1
= m_Dir
;
520 if (!CStringUtils::EndsWith(m_Dir
, L
'\\'))
523 if(m_LastDirectory
.CompareNoCase(m_Dir
) == 0 && m_Liste
.m_SearchList
.GetSize())
526 m_LastDirectory
= m_Dir
;
529 BOOL bContinue
= FoundFiles
.FindFile(m_Dir
);
533 while (bContinue
== TRUE
)
535 bContinue
= FoundFiles
.FindNextFile();
536 m_File
= FoundFiles
.GetFileName();
538 if(FoundFiles
.IsHidden() || FoundFiles
.IsSystem())
540 if(FoundFiles
.IsDirectory())
542 if(m_iMode
& _MODE_ONLY_FILES
)
544 if(FoundFiles
.IsDots())
547 if (!CStringUtils::EndsWith(m_File
, L
'\\'))
551 if(!FoundFiles
.IsDirectory())
552 if(m_iMode
& _MODE_ONLY_DIRS
)
555 if(m_iMode
& _MODE_FS_START_DIR_
)
562 if (!CStringUtils::EndsWith(m_Name
, L
'\\'))
568 AddSearchString(m_Name
);
574 /*********************************************************************/
576 void CACEdit::SetStartDirectory(LPCTSTR lpszString
)
578 if(m_iType
== -1) {ASSERT(0); return;}
580 if(m_iMode
& _MODE_FS_START_DIR_
)
581 ReadDirectory(lpszString
);
584 /*********************************************************************
587 *********************************************************************/
589 int CACEdit::AddString( LPCTSTR lpszString
)
591 if(m_iType
== _COMBOBOX_
)
593 return ((CComboBox
*)this)->AddString(lpszString
);
598 /*********************************************************************/
600 int CACEdit::SetDroppedWidth( UINT nWidth
)
602 if(m_iType
== _COMBOBOX_
)
604 return ((CComboBox
*)this)->SetDroppedWidth(nWidth
);
609 /*********************************************************************/
611 int CACEdit::FindString( int nStartAfter
, LPCTSTR lpszString
)
613 if(m_iType
== _COMBOBOX_
)
615 return ((CComboBox
*)this)->FindString(nStartAfter
,lpszString
);
620 /*********************************************************************/
622 int CACEdit::SelectString( int nStartAfter
, LPCTSTR lpszString
)
624 if(m_iType
== _COMBOBOX_
)
626 return ((CComboBox
*)this)->SelectString(nStartAfter
,lpszString
);
631 /*********************************************************************/
633 void CACEdit::ShowDropDown(BOOL bShowIt
)
635 if(m_iType
== _COMBOBOX_
)
637 ((CComboBox
*)this)->ShowDropDown(bShowIt
);
641 /*********************************************************************/
643 void CACEdit::ResetContent()
645 if(m_iType
== _COMBOBOX_
)
647 ((CComboBox
*)this)->ResetContent();
651 /*********************************************************************/
653 int CACEdit::GetCurSel()
655 if(m_iType
== _COMBOBOX_
)
657 return ((CComboBox
*)this)->GetCurSel();
662 /*********************************************************************/
664 int CACEdit::GetLBText( int nIndex
, LPTSTR lpszText
)
666 if(m_iType
== _COMBOBOX_
)
668 return ((CComboBox
*)this)->GetLBText(nIndex
,lpszText
);
673 /*********************************************************************/
675 void CACEdit::GetLBText( int nIndex
, CString
& rString
)
677 if(m_iType
== _COMBOBOX_
)
679 ((CComboBox
*)this)->GetLBText(nIndex
,rString
);
683 /*********************************************************************/