Disable unsupported commands
[TortoiseGit.git] / src / Utils / ACEdit.cpp
blob2f5d79cd3dec6bd60295b01560da6497ffcfe66c
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
9 //
11 #include "stdafx.h"
12 #include "ACEdit.h"
13 #include <io.h>
14 #include "StringUtils.h"
16 #ifdef _DEBUG
17 #define new DEBUG_NEW
18 #undef THIS_FILE
19 static char THIS_FILE[] = __FILE__;
20 #endif
22 #define _EDIT_ 1
23 #define _COMBOBOX_ 2
25 /////////////////////////////////////////////////////////////////////////////
26 // CACEdit
28 CACEdit::CACEdit()
30 m_iMode = _MODE_STANDARD_;
31 m_iType = -1;
32 m_pEdit = nullptr;
33 m_CursorMode = false;
34 m_PrefixChar = L'\0';
35 m_szDrive[0] = L'\0';
36 m_szDir[0] = L'\0';
37 m_szFname[0] = L'\0';
38 m_szExt[0] = L'\0';
41 /*********************************************************************/
43 CACEdit::~CACEdit()
45 DestroyWindow();
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)
54 ON_WM_KEYDOWN()
55 ON_CONTROL_REFLECT(EN_CHANGE, OnChange)
56 ON_CONTROL_REFLECT(CBN_EDITCHANGE, OnChange)
57 ON_CONTROL_REFLECT(CBN_DROPDOWN, OnCloseList)
58 //}}AFX_MSG_MAP
59 ON_MESSAGE(ENAC_UPDATE,OnUpdateFromList)
60 END_MESSAGE_MAP()
62 /*********************************************************************/
64 void CACEdit::SetMode(int iMode)
66 if(m_iType == -1)
67 Init();
69 m_iMode = iMode;
72 ** Vers. 1.1
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'\\';
81 // Vers. 1.2
82 if(iMode & _MODE_FIND_ALL_)
84 m_Liste.m_lMode |= _MODE_FIND_ALL_;
88 /*********************************************************************/
90 void CACEdit::Init()
92 CString szClassName = AfxRegisterWndClass(CS_CLASSDC|CS_SAVEBITS|CS_HREDRAW|CS_VREDRAW,
93 0,(HBRUSH) (COLOR_WINDOW), 0);
94 CRect rcWnd,rcWnd1;
95 GetWindowRect(rcWnd);
97 VERIFY(m_Liste.CreateEx(WS_EX_TOOLWINDOW,
98 szClassName, nullptr,
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),
102 GetDesktopWindow(),
103 0x3E8, nullptr));
105 CString m_ClassName;
106 ::GetClassName(GetSafeHwnd(), CStrBuf(m_ClassName, 32), 32);
108 if (m_ClassName.Compare(L"Edit") == 0)
109 m_iType = _EDIT_;
110 else
112 if (m_ClassName.Compare(L"ComboBox") == 0)
114 m_iType = _COMBOBOX_;
116 m_pEdit = (CEdit*)GetWindow(GW_CHILD);
117 VERIFY(m_pEdit);
118 ::GetClassName(m_pEdit->GetSafeHwnd(), CStrBuf(m_ClassName, 32), 32);
119 VERIFY(m_ClassName.Compare(L"Edit") == 0);
123 if(m_iType == -1)
125 ASSERT(0);
126 return;
129 m_Liste.Init(this);
132 /*********************************************************************/
134 void CACEdit::AddSearchStrings(LPCTSTR Strings[])
136 int i = 0;
137 LPCTSTR str;
138 if(m_iType == -1) {ASSERT(0); return;}
140 m_Liste.RemoveAll();
144 str = Strings[i];
145 if(str)
147 m_Liste.AddSearchString(str);
150 i++;
152 while(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;}
172 m_Liste.RemoveAll();
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);
198 return true;
201 if (nChar == VK_DOWN || nChar == VK_UP
202 || nChar == VK_PRIOR || nChar == VK_NEXT
203 || nChar == VK_HOME || nChar == VK_END)
206 ** Vers. 1.1
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())
214 m_Liste.CopyList();
215 return true;
219 if(m_Liste.IsWindowVisible())
221 int pos;
224 if(m_iMode & _MODE_STANDARD_
225 || m_iMode & _MODE_FILESYSTEM_
226 || m_iMode & _MODE_FS_START_DIR_)
228 m_CursorMode = true;
230 if(!m_bFromChild)
231 m_EditText = m_Liste.GetNextString(nChar);
232 else
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;
259 return true;
262 if(m_iMode & _MODE_SEPARATION_)
264 CString m_Text,m_Left,m_Right;
265 int left,right,pos2=0,len;
267 m_CursorMode = true;
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);
282 if(!m_bFromChild)
283 m_Text += m_Liste.GetNextString(nChar);
284 else
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);
297 left -= right;
298 len += right;
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;
315 return true;
319 return false;
322 /*********************************************************************/
324 void CACEdit::OnChange()
326 CString m_Text;
327 int pos=0,len;
329 if(m_iType == -1)
330 {ASSERT(0); return;}
332 GetWindowText(m_EditText);
333 len = m_EditText.GetLength();
334 //----------------------------------------------
335 if(m_iMode & _MODE_FILESYSTEM_ || m_iMode & _MODE_FS_START_DIR_)
337 if(!m_CursorMode)
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_)
347 if(len)
348 m_Liste.FindString(-1,m_EditText);
349 else
350 m_Liste.ShowWindow(false);
352 else
354 if(len > 2 && pos == len)
356 if(_taccess(m_EditText,0) == 0)
358 ReadDirectory(m_EditText);
360 m_Liste.FindString(-1,m_EditText);
362 else
363 m_Liste.ShowWindow(false);
365 } // m_CursorMode
367 //----------------------------------------------
368 if(m_iMode & _MODE_SEPARATION_)
370 if(!m_CursorMode)
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());
378 int left,right;
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_)
388 if(!m_CursorMode)
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();
400 TCHAR ch;
401 int i;
403 if(pos >= len && len != 1)
404 pos = 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)
412 break;
415 return i + 1;
418 /*********************************************************************/
420 int CACEdit::FindSepLeftPos2(int pos)
422 int len = m_EditText.GetLength();
423 TCHAR ch;
425 if(pos >= len && len != 1)
426 pos = len -1;
428 if(len == 1)
429 return 0;
431 for(int i = pos; i >= 0 ; i--)
433 ch = m_EditText.GetAt(i);
434 if(m_PrefixChar == ch)
435 return 1;
438 return 0;
441 /*********************************************************************/
443 int CACEdit::FindSepRightPos(int pos)
445 int len = m_EditText.GetLength();
446 TCHAR ch;
447 int i;
449 for(i = pos; i < len ; i++)
451 ch = m_EditText.GetAt(i);
452 if(m_SeparationStr.Find(ch) != -1)
453 break;
456 return i;
459 /*********************************************************************/
460 LRESULT CACEdit::OnUpdateFromList(WPARAM lParam, LPARAM /*wParam*/)
462 UpdateData(true);
464 if(lParam == WM_KEYDOWN)
465 HandleKey(VK_DOWN,true);
466 return 0;
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))
488 return true;
491 if(pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN)
492 if (HandleKey((UINT)pMsg->wParam, false))
493 return true;
496 return CWnd::PreTranslateMessage(pMsg);
499 /*********************************************************************/
501 void CACEdit::ReadDirectory(CString m_Dir)
503 CFileFind FoundFiles;
504 TCHAR ch;
505 CWaitCursor hg;
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);
515 //ist hübscher
516 ch = (TCHAR)towupper(m_Dir.GetAt(0));
517 m_Dir.SetAt(0,ch);
519 CString m_Name,m_File,m_Dir1 = m_Dir;
520 if (!CStringUtils::EndsWith(m_Dir, L'\\'))
521 m_Dir += L'\\';
523 if(m_LastDirectory.CompareNoCase(m_Dir) == 0 && m_Liste.m_SearchList.GetSize())
524 return;
526 m_LastDirectory = m_Dir;
527 m_Dir += L"*.*";
529 BOOL bContinue = FoundFiles.FindFile(m_Dir);
530 if(bContinue)
531 RemoveSearchAll();
533 while (bContinue == TRUE)
535 bContinue = FoundFiles.FindNextFile();
536 m_File = FoundFiles.GetFileName();
538 if(FoundFiles.IsHidden() || FoundFiles.IsSystem())
539 continue;
540 if(FoundFiles.IsDirectory())
542 if(m_iMode & _MODE_ONLY_FILES)
543 continue;
544 if(FoundFiles.IsDots())
545 continue;
547 if (!CStringUtils::EndsWith(m_File, L'\\'))
548 m_File += L'\\';
551 if(!FoundFiles.IsDirectory())
552 if(m_iMode & _MODE_ONLY_DIRS)
553 continue;
555 if(m_iMode & _MODE_FS_START_DIR_)
557 m_Name = m_File;
559 else
561 m_Name = m_Dir1;
562 if (!CStringUtils::EndsWith(m_Name, L'\\'))
563 m_Name += L'\\';
565 m_Name += m_File;
568 AddSearchString(m_Name);
570 FoundFiles.Close();
571 return;
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 /*********************************************************************
585 ** CComboBox
586 ** NEW:V1.1
587 *********************************************************************/
589 int CACEdit::AddString( LPCTSTR lpszString )
591 if(m_iType == _COMBOBOX_)
593 return ((CComboBox *)this)->AddString(lpszString);
595 return CB_ERR;
598 /*********************************************************************/
600 int CACEdit::SetDroppedWidth( UINT nWidth )
602 if(m_iType == _COMBOBOX_)
604 return ((CComboBox *)this)->SetDroppedWidth(nWidth);
606 return CB_ERR;
609 /*********************************************************************/
611 int CACEdit::FindString( int nStartAfter, LPCTSTR lpszString )
613 if(m_iType == _COMBOBOX_)
615 return ((CComboBox *)this)->FindString(nStartAfter,lpszString);
617 return CB_ERR;
620 /*********************************************************************/
622 int CACEdit::SelectString( int nStartAfter, LPCTSTR lpszString )
624 if(m_iType == _COMBOBOX_)
626 return ((CComboBox *)this)->SelectString(nStartAfter,lpszString);
628 return CB_ERR;
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();
659 return CB_ERR;
662 /*********************************************************************/
664 int CACEdit::GetLBText( int nIndex, LPTSTR lpszText )
666 if(m_iType == _COMBOBOX_)
668 return ((CComboBox *)this)->GetLBText(nIndex,lpszText);
670 return CB_ERR;
673 /*********************************************************************/
675 void CACEdit::GetLBText( int nIndex, CString& rString )
677 if(m_iType == _COMBOBOX_)
679 ((CComboBox *)this)->GetLBText(nIndex,rString);
683 /*********************************************************************/