Update editorconfig
[TortoiseGit.git] / src / Utils / ACEdit.cpp
blobcb06eb5333489b0d136788e680a1281c7aae6255
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>
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 = 0;
35 m_szDrive[0] = 0;
36 m_szDir[0] = 0;
37 m_szFname[0] = 0;
38 m_szExt[0] = 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 = _T("\\");
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(), m_ClassName.GetBuffer(32), 32);
107 m_ClassName.ReleaseBuffer();
109 if (m_ClassName.Compare(_T("Edit")) == 0)
110 m_iType = _EDIT_;
111 else
113 if (m_ClassName.Compare(_T("ComboBox")) == 0)
115 m_iType = _COMBOBOX_;
117 m_pEdit = (CEdit*)GetWindow(GW_CHILD);
118 VERIFY(m_pEdit);
119 ::GetClassName(m_pEdit->GetSafeHwnd(), m_ClassName.GetBuffer(32), 32);
120 m_ClassName.ReleaseBuffer();
121 VERIFY(m_ClassName.Compare(_T("Edit")) == 0);
125 if(m_iType == -1)
127 ASSERT(0);
128 return;
131 m_Liste.Init(this);
134 /*********************************************************************/
136 void CACEdit::AddSearchStrings(LPCTSTR Strings[])
138 int i = 0;
139 LPCTSTR str;
140 if(m_iType == -1) {ASSERT(0); return;}
142 m_Liste.RemoveAll();
146 str = Strings[i];
147 if(str)
149 m_Liste.AddSearchString(str);
152 i++;
154 while(str);
156 m_Liste.SortSearchList();
159 /*********************************************************************/
161 void CACEdit::AddSearchString(LPCTSTR lpszString)
163 if(m_iType == -1) {ASSERT(0); return;}
165 m_Liste.AddSearchString(lpszString);
168 /*********************************************************************/
170 void CACEdit::RemoveSearchAll()
172 if(m_iType == -1) {ASSERT(0); return;}
174 m_Liste.RemoveAll();
177 /*********************************************************************/
179 void CACEdit::OnKillfocus()
181 if(m_Liste.GetSafeHwnd()) // fix Vers 1.1
182 m_Liste.ShowWindow(false);
185 /*********************************************************************/
187 void CACEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
189 if(!HandleKey(nChar,false))
190 CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
193 /*********************************************************************/
195 bool CACEdit::HandleKey(UINT nChar, bool m_bFromChild)
197 if (nChar == VK_ESCAPE ||nChar == VK_RETURN)
199 m_Liste.ShowWindow(false);
200 return true;
203 if (nChar == VK_DOWN || nChar == VK_UP
204 || nChar == VK_PRIOR || nChar == VK_NEXT
205 || nChar == VK_HOME || nChar == VK_END)
208 ** Vers. 1.1
209 ** NEW: _MODE_CURSOR_O_LIST_
211 if(!m_Liste.IsWindowVisible() && (m_iMode & _MODE_CURSOR_O_LIST_))
213 GetWindowText(m_EditText);
214 if(m_EditText.IsEmpty())
216 m_Liste.CopyList();
217 return true;
221 if(m_Liste.IsWindowVisible())
223 int pos;
226 if(m_iMode & _MODE_STANDARD_
227 || m_iMode & _MODE_FILESYSTEM_
228 || m_iMode & _MODE_FS_START_DIR_)
230 m_CursorMode = true;
232 if(!m_bFromChild)
233 m_EditText = m_Liste.GetNextString(nChar);
234 else
235 m_EditText = m_Liste.GetString();
237 if(m_iMode & _MODE_FILESYSTEM_)
239 if (m_EditText.Right(1) == _T('\\'))
240 m_EditText = m_EditText.Mid(0,m_EditText.GetLength()-1);
243 m_Liste.SelectItem(-1);
244 SetWindowText(m_EditText);
245 pos = m_EditText.GetLength();
247 if(m_iType == _COMBOBOX_)
249 m_pEdit->SetSel(pos,pos,true);
250 m_pEdit->SetModify(true);
253 if(m_iType == _EDIT_)
255 ((CEdit*)this)->SetSel(pos,pos,true);
256 ((CEdit*)this)->SetModify(true);
259 GetParent()->SendMessage(ENAC_UPDATE, WM_KEYDOWN, GetDlgCtrlID());
260 m_CursorMode = false;
261 return true;
264 if(m_iMode & _MODE_SEPARATION_)
266 CString m_Text,m_Left,m_Right;
267 int left,right,pos2=0,len;
269 m_CursorMode = true;
271 GetWindowText(m_EditText);
273 if(m_iType == _EDIT_)
274 pos2 = LOWORD(((CEdit*)this)->CharFromPos(GetCaretPos()));
276 if(m_iType == _COMBOBOX_)
277 pos2 = m_pEdit->CharFromPos(m_pEdit->GetCaretPos());
279 left = FindSepLeftPos(pos2-1,true);
280 right = FindSepRightPos(pos2);
282 m_Text = m_EditText.Left(left);
284 if(!m_bFromChild)
285 m_Text += m_Liste.GetNextString(nChar);
286 else
287 m_Text += m_Liste.GetString();
289 m_Liste.SelectItem(-1);
290 m_Text += m_EditText.Mid(right);
291 len = m_Liste.GetString().GetLength();
293 m_Text += this->m_SeparationStr;
295 SetWindowText(m_Text);
296 GetParent()->SendMessage(ENAC_UPDATE, WM_KEYDOWN, GetDlgCtrlID());
298 right = FindSepLeftPos2(pos2-1);
299 left -= right;
300 len += right;
302 left+=m_SeparationStr.GetLength();
304 if(m_iType == _EDIT_)
306 ((CEdit*)this)->SetModify(true);
307 ((CEdit*)this)->SetSel(left+len,left+len,false);
310 if(m_iType == _COMBOBOX_)
312 m_pEdit->SetModify(true);
313 m_pEdit->SetSel(left,left+len,true);
316 m_CursorMode = false;
317 return true;
321 return false;
324 /*********************************************************************/
326 void CACEdit::OnChange()
328 CString m_Text;
329 int pos=0,len;
331 if(m_iType == -1)
332 {ASSERT(0); return;}
334 GetWindowText(m_EditText);
335 len = m_EditText.GetLength();
336 //----------------------------------------------
337 if(m_iMode & _MODE_FILESYSTEM_ || m_iMode & _MODE_FS_START_DIR_)
339 if(!m_CursorMode)
341 if(m_iType == _EDIT_)
342 pos = LOWORD(((CEdit*)this)->CharFromPos(GetCaretPos()));
344 if(m_iType == _COMBOBOX_)
345 pos = m_pEdit->CharFromPos(m_pEdit->GetCaretPos());
347 if(m_iMode & _MODE_FS_START_DIR_)
349 if(len)
350 m_Liste.FindString(-1,m_EditText);
351 else
352 m_Liste.ShowWindow(false);
354 else
356 if(len > 2 && pos == len)
358 if(_taccess(m_EditText,0) == 0)
360 ReadDirectory(m_EditText);
362 m_Liste.FindString(-1,m_EditText);
364 else
365 m_Liste.ShowWindow(false);
367 } // m_CursorMode
369 //----------------------------------------------
370 if(m_iMode & _MODE_SEPARATION_)
372 if(!m_CursorMode)
374 if(m_iType == _EDIT_)
375 pos = LOWORD(((CEdit*)this)->CharFromPos(GetCaretPos()));
377 if(m_iType == _COMBOBOX_)
378 pos = m_pEdit->CharFromPos(m_pEdit->GetCaretPos());
380 int left,right;
381 left = FindSepLeftPos(pos-1);
382 right = FindSepRightPos(pos);
383 m_Text = m_EditText.Mid(left,right-left);
384 m_Liste.FindString(-1,m_Text);
387 //----------------------------------------------
388 if(m_iMode & _MODE_STANDARD_)
390 if(!m_CursorMode)
391 m_Liste.FindString(-1,m_EditText);
393 //----------------------------------------------
394 GetParent()->SendMessage(ENAC_UPDATE, EN_UPDATE, GetDlgCtrlID());
397 /*********************************************************************/
399 int CACEdit::FindSepLeftPos(int pos,bool m_bIncludePrefix)
401 int len = m_EditText.GetLength();
402 TCHAR ch;
403 int i;
405 if(pos >= len && len != 1)
406 pos = len -1;
408 for(i = pos; i >= 0 ; i--)
410 ch = m_EditText.GetAt(i);
411 if(m_PrefixChar == ch)
412 return i + (m_bIncludePrefix ? 1 : 0);
413 if(m_SeparationStr.Find(ch) != -1)
414 break;
417 return i + 1;
420 /*********************************************************************/
422 int CACEdit::FindSepLeftPos2(int pos)
424 int len = m_EditText.GetLength();
425 TCHAR ch;
427 if(pos >= len && len != 1)
428 pos = len -1;
430 if(len == 1)
431 return 0;
433 for(int i = pos; i >= 0 ; i--)
435 ch = m_EditText.GetAt(i);
436 if(m_PrefixChar == ch)
437 return 1;
440 return 0;
443 /*********************************************************************/
445 int CACEdit::FindSepRightPos(int pos)
447 int len = m_EditText.GetLength();
448 TCHAR ch;
449 int i;
451 for(i = pos; i < len ; i++)
453 ch = m_EditText.GetAt(i);
454 if(m_SeparationStr.Find(ch) != -1)
455 break;
458 return i;
461 /*********************************************************************/
462 LRESULT CACEdit::OnUpdateFromList(WPARAM lParam, LPARAM /*wParam*/)
464 UpdateData(true);
466 if(lParam == WM_KEYDOWN)
467 HandleKey(VK_DOWN,true);
468 return 0;
471 /*********************************************************************/
473 void CACEdit::OnCloseList()
475 m_Liste.ShowWindow(false);
478 /*********************************************************************/
480 BOOL CACEdit::PreTranslateMessage(MSG* pMsg)
482 if(pMsg->message == WM_KEYDOWN)
484 if(m_Liste.IsWindowVisible())
486 if(m_iType == _COMBOBOX_)
488 if(pMsg->wParam == VK_DOWN || pMsg->wParam == VK_UP)
489 if (HandleKey((UINT)pMsg->wParam, false))
490 return true;
493 if(pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN)
494 if (HandleKey((UINT)pMsg->wParam, false))
495 return true;
498 return CWnd::PreTranslateMessage(pMsg);
501 /*********************************************************************/
503 void CACEdit::ReadDirectory(CString m_Dir)
505 CFileFind FoundFiles;
506 TCHAR ch;
507 CWaitCursor hg;
509 // Wenn mittem im Pfad,
510 // vorheriges Verzeichnis einlesen.
511 if (m_Dir.Right(1) != _T('\\'))
513 _tsplitpath_s(m_Dir, m_szDrive, m_szDir, m_szFname, m_szExt);
514 m_Dir.Format(_T("%s%s"),m_szDrive, m_szDir);
517 //ist hübscher
518 ch = (TCHAR)towupper(m_Dir.GetAt(0));
519 m_Dir.SetAt(0,ch);
521 CString m_Name,m_File,m_Dir1 = m_Dir;
522 if (m_Dir.Right(1) != _T('\\'))
523 m_Dir += _T("\\");
525 if(m_LastDirectory.CompareNoCase(m_Dir) == 0 && m_Liste.m_SearchList.GetSize())
526 return;
528 m_LastDirectory = m_Dir;
529 m_Dir += _T("*.*");
531 BOOL bContinue = FoundFiles.FindFile(m_Dir);
532 if(bContinue)
533 RemoveSearchAll();
535 while (bContinue == TRUE)
537 bContinue = FoundFiles.FindNextFile();
538 m_File = FoundFiles.GetFileName();
540 if(FoundFiles.IsHidden() || FoundFiles.IsSystem())
541 continue;
542 if(FoundFiles.IsDirectory())
544 if(m_iMode & _MODE_ONLY_FILES)
545 continue;
546 if(FoundFiles.IsDots())
547 continue;
549 if (m_File.Right(1) != _T('\\'))
550 m_File += _T("\\");
553 if(!FoundFiles.IsDirectory())
554 if(m_iMode & _MODE_ONLY_DIRS)
555 continue;
557 if(m_iMode & _MODE_FS_START_DIR_)
559 m_Name = m_File;
561 else
563 m_Name = m_Dir1;
564 if (m_Name.Right(1) != _T('\\'))
565 m_Name += _T("\\");
567 m_Name += m_File;
570 AddSearchString(m_Name);
572 FoundFiles.Close();
573 return;
576 /*********************************************************************/
578 void CACEdit::SetStartDirectory(LPCTSTR lpszString)
580 if(m_iType == -1) {ASSERT(0); return;}
582 if(m_iMode & _MODE_FS_START_DIR_)
583 ReadDirectory(lpszString);
586 /*********************************************************************
587 ** CComboBox
588 ** NEW:V1.1
589 *********************************************************************/
591 int CACEdit::AddString( LPCTSTR lpszString )
593 if(m_iType == _COMBOBOX_)
595 return ((CComboBox *)this)->AddString(lpszString);
597 return CB_ERR;
600 /*********************************************************************/
602 int CACEdit::SetDroppedWidth( UINT nWidth )
604 if(m_iType == _COMBOBOX_)
606 return ((CComboBox *)this)->SetDroppedWidth(nWidth);
608 return CB_ERR;
611 /*********************************************************************/
613 int CACEdit::FindString( int nStartAfter, LPCTSTR lpszString )
615 if(m_iType == _COMBOBOX_)
617 return ((CComboBox *)this)->FindString(nStartAfter,lpszString);
619 return CB_ERR;
622 /*********************************************************************/
624 int CACEdit::SelectString( int nStartAfter, LPCTSTR lpszString )
626 if(m_iType == _COMBOBOX_)
628 return ((CComboBox *)this)->SelectString(nStartAfter,lpszString);
630 return CB_ERR;
633 /*********************************************************************/
635 void CACEdit::ShowDropDown(BOOL bShowIt)
637 if(m_iType == _COMBOBOX_)
639 ((CComboBox *)this)->ShowDropDown(bShowIt);
643 /*********************************************************************/
645 void CACEdit::ResetContent()
647 if(m_iType == _COMBOBOX_)
649 ((CComboBox *)this)->ResetContent();
653 /*********************************************************************/
655 int CACEdit::GetCurSel()
657 if(m_iType == _COMBOBOX_)
659 return ((CComboBox *)this)->GetCurSel();
661 return CB_ERR;
664 /*********************************************************************/
666 int CACEdit::GetLBText( int nIndex, LPTSTR lpszText )
668 if(m_iType == _COMBOBOX_)
670 return ((CComboBox *)this)->GetLBText(nIndex,lpszText);
672 return CB_ERR;
675 /*********************************************************************/
677 void CACEdit::GetLBText( int nIndex, CString& rString )
679 if(m_iType == _COMBOBOX_)
681 ((CComboBox *)this)->GetLBText(nIndex,rString);
685 /*********************************************************************/