Use secure CRT functions
[TortoiseGit.git] / src / Utils / ACEdit.cpp
blob6e484746b6aac73810f9cd1082c9d5e0cf707146
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 - 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 = NULL;
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,NULL,
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, NULL));
105 CString m_ClassName;
106 ::GetClassName(GetSafeHwnd(), m_ClassName.GetBuffer(32), 32);
107 m_ClassName.ReleaseBuffer();
109 if (m_ClassName.Compare(_T("Edit")) == 0)
111 m_iType = _EDIT_;
113 else
115 if (m_ClassName.Compare(_T("ComboBox")) == 0)
117 m_iType = _COMBOBOX_;
119 m_pEdit = (CEdit*)GetWindow(GW_CHILD);
120 VERIFY(m_pEdit);
121 ::GetClassName(m_pEdit->GetSafeHwnd(), m_ClassName.GetBuffer(32), 32);
122 m_ClassName.ReleaseBuffer();
123 VERIFY(m_ClassName.Compare(_T("Edit")) == 0);
127 if(m_iType == -1)
129 ASSERT(0);
130 return;
133 m_Liste.Init(this);
136 /*********************************************************************/
138 void CACEdit::AddSearchStrings(LPCTSTR Strings[])
140 int i = 0;
141 LPCTSTR str;
142 if(m_iType == -1) {ASSERT(0); return;}
144 m_Liste.RemoveAll();
148 str = Strings[i];
149 if(str)
151 m_Liste.AddSearchString(str);
154 i++;
156 while(str);
158 m_Liste.SortSearchList();
161 /*********************************************************************/
163 void CACEdit::AddSearchString(LPCTSTR lpszString)
165 if(m_iType == -1) {ASSERT(0); return;}
167 m_Liste.AddSearchString(lpszString);
170 /*********************************************************************/
172 void CACEdit::RemoveSearchAll()
174 if(m_iType == -1) {ASSERT(0); return;}
176 m_Liste.RemoveAll();
179 /*********************************************************************/
181 void CACEdit::OnKillfocus()
183 if(m_Liste.GetSafeHwnd()) // fix Vers 1.1
184 m_Liste.ShowWindow(false);
187 /*********************************************************************/
189 void CACEdit::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
191 if(!HandleKey(nChar,false))
192 CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
195 /*********************************************************************/
197 bool CACEdit::HandleKey(UINT nChar, bool m_bFromChild)
199 if (nChar == VK_ESCAPE ||nChar == VK_RETURN)
201 m_Liste.ShowWindow(false);
202 return true;
205 if (nChar == VK_DOWN || nChar == VK_UP
206 || nChar == VK_PRIOR || nChar == VK_NEXT
207 || nChar == VK_HOME || nChar == VK_END)
210 ** Vers. 1.1
211 ** NEW: _MODE_CURSOR_O_LIST_
213 if(!m_Liste.IsWindowVisible() && (m_iMode & _MODE_CURSOR_O_LIST_))
215 GetWindowText(m_EditText);
216 if(m_EditText.IsEmpty())
218 m_Liste.CopyList();
219 return true;
223 if(m_Liste.IsWindowVisible())
225 int pos;
228 if(m_iMode & _MODE_STANDARD_
229 || m_iMode & _MODE_FILESYSTEM_
230 || m_iMode & _MODE_FS_START_DIR_)
232 m_CursorMode = true;
234 if(!m_bFromChild)
235 m_EditText = m_Liste.GetNextString(nChar);
236 else
237 m_EditText = m_Liste.GetString();
239 if(m_iMode & _MODE_FILESYSTEM_)
241 if (m_EditText.Right(1) == _T('\\'))
242 m_EditText = m_EditText.Mid(0,m_EditText.GetLength()-1);
245 m_Liste.SelectItem(-1);
246 SetWindowText(m_EditText);
247 pos = m_EditText.GetLength();
249 if(m_iType == _COMBOBOX_)
251 m_pEdit->SetSel(pos,pos,true);
252 m_pEdit->SetModify(true);
255 if(m_iType == _EDIT_)
257 ((CEdit*)this)->SetSel(pos,pos,true);
258 ((CEdit*)this)->SetModify(true);
261 GetParent()->SendMessage(ENAC_UPDATE, WM_KEYDOWN, GetDlgCtrlID());
262 m_CursorMode = false;
263 return true;
266 if(m_iMode & _MODE_SEPARATION_)
268 CString m_Text,m_Left,m_Right;
269 int left,right,pos=0,len;
271 m_CursorMode = true;
273 GetWindowText(m_EditText);
275 if(m_iType == _EDIT_)
276 pos = LOWORD(((CEdit*)this)->CharFromPos(GetCaretPos()));
278 if(m_iType == _COMBOBOX_)
279 pos = m_pEdit->CharFromPos(m_pEdit->GetCaretPos());
281 left = FindSepLeftPos(pos-1,true);
282 right = FindSepRightPos(pos);
284 m_Text = m_EditText.Left(left);
286 if(!m_bFromChild)
287 m_Text += m_Liste.GetNextString(nChar);
288 else
289 m_Text += m_Liste.GetString();
291 m_Liste.SelectItem(-1);
292 m_Text += m_EditText.Mid(right);
293 len = m_Liste.GetString().GetLength();
295 m_Text += this->m_SeparationStr;
297 SetWindowText(m_Text);
298 GetParent()->SendMessage(ENAC_UPDATE, WM_KEYDOWN, GetDlgCtrlID());
300 right = FindSepLeftPos2(pos-1);
301 left -= right;
302 len += right;
304 left+=m_SeparationStr.GetLength();
306 if(m_iType == _EDIT_)
308 ((CEdit*)this)->SetModify(true);
309 ((CEdit*)this)->SetSel(left+len,left+len,false);
312 if(m_iType == _COMBOBOX_)
314 m_pEdit->SetModify(true);
315 m_pEdit->SetSel(left,left+len,true);
318 m_CursorMode = false;
319 return true;
323 return false;
326 /*********************************************************************/
328 void CACEdit::OnChange()
330 CString m_Text;
331 int pos=0,len;
333 if(m_iType == -1)
334 {ASSERT(0); return;}
336 GetWindowText(m_EditText);
337 len = m_EditText.GetLength();
338 //----------------------------------------------
339 if(m_iMode & _MODE_FILESYSTEM_ || m_iMode & _MODE_FS_START_DIR_)
341 if(!m_CursorMode)
343 if(m_iType == _EDIT_)
344 pos = LOWORD(((CEdit*)this)->CharFromPos(GetCaretPos()));
346 if(m_iType == _COMBOBOX_)
347 pos = m_pEdit->CharFromPos(m_pEdit->GetCaretPos());
349 if(m_iMode & _MODE_FS_START_DIR_)
351 if(len)
352 m_Liste.FindString(-1,m_EditText);
353 else
354 m_Liste.ShowWindow(false);
356 else
358 if(len > 2 && pos == len)
360 if(_taccess(m_EditText,0) == 0)
362 ReadDirectory(m_EditText);
364 m_Liste.FindString(-1,m_EditText);
366 else
367 m_Liste.ShowWindow(false);
369 } // m_CursorMode
371 //----------------------------------------------
372 if(m_iMode & _MODE_SEPARATION_)
374 if(!m_CursorMode)
376 if(m_iType == _EDIT_)
377 pos = LOWORD(((CEdit*)this)->CharFromPos(GetCaretPos()));
379 if(m_iType == _COMBOBOX_)
380 pos = m_pEdit->CharFromPos(m_pEdit->GetCaretPos());
382 int left,right;
383 left = FindSepLeftPos(pos-1);
384 right = FindSepRightPos(pos);
385 m_Text = m_EditText.Mid(left,right-left);
386 m_Liste.FindString(-1,m_Text);
389 //----------------------------------------------
390 if(m_iMode & _MODE_STANDARD_)
392 if(!m_CursorMode)
393 m_Liste.FindString(-1,m_EditText);
395 //----------------------------------------------
396 GetParent()->SendMessage(ENAC_UPDATE, EN_UPDATE, GetDlgCtrlID());
399 /*********************************************************************/
401 int CACEdit::FindSepLeftPos(int pos,bool m_bIncludePrefix)
403 int len = m_EditText.GetLength();
404 TCHAR ch;
405 int i;
407 if(pos >= len && len != 1)
408 pos = len -1;
410 for(i = pos; i >= 0 ; i--)
412 ch = m_EditText.GetAt(i);
413 if(m_PrefixChar == ch)
414 return i + (m_bIncludePrefix ? 1 : 0);
415 if(m_SeparationStr.Find(ch) != -1)
416 break;
419 return i + 1;
422 /*********************************************************************/
424 int CACEdit::FindSepLeftPos2(int pos)
426 int len = m_EditText.GetLength();
427 TCHAR ch;
429 if(pos >= len && len != 1)
430 pos = len -1;
432 if(len == 1)
433 return 0;
435 for(int i = pos; i >= 0 ; i--)
437 ch = m_EditText.GetAt(i);
438 if(m_PrefixChar == ch)
439 return 1;
442 return 0;
445 /*********************************************************************/
447 int CACEdit::FindSepRightPos(int pos)
449 int len = m_EditText.GetLength();
450 TCHAR ch;
451 int i;
453 for(i = pos; i < len ; i++)
455 ch = m_EditText.GetAt(i);
456 if(m_SeparationStr.Find(ch) != -1)
457 break;
460 return i;
463 /*********************************************************************/
464 LRESULT CACEdit::OnUpdateFromList(WPARAM lParam, LPARAM /*wParam*/)
466 UpdateData(true);
468 if(lParam == WM_KEYDOWN)
470 HandleKey(VK_DOWN,true);
472 return 0;
475 /*********************************************************************/
477 void CACEdit::OnCloseList()
479 m_Liste.ShowWindow(false);
482 /*********************************************************************/
484 BOOL CACEdit::PreTranslateMessage(MSG* pMsg)
486 if(pMsg->message == WM_KEYDOWN)
488 if(m_Liste.IsWindowVisible())
490 if(m_iType == _COMBOBOX_)
492 if(pMsg->wParam == VK_DOWN || pMsg->wParam == VK_UP)
493 if (HandleKey((UINT)pMsg->wParam, false))
494 return true;
497 if(pMsg->wParam == VK_ESCAPE || pMsg->wParam == VK_RETURN)
498 if (HandleKey((UINT)pMsg->wParam, false))
499 return true;
502 return CWnd::PreTranslateMessage(pMsg);
505 /*********************************************************************/
507 void CACEdit::ReadDirectory(CString m_Dir)
509 CFileFind FoundFiles;
510 TCHAR ch;
511 CWaitCursor hg;
513 // Wenn mittem im Pfad,
514 // vorheriges Verzeichnis einlesen.
515 if (m_Dir.Right(1) != _T('\\'))
517 _tsplitpath_s(m_Dir, m_szDrive, m_szDir, m_szFname, m_szExt);
518 m_Dir.Format(_T("%s%s"),m_szDrive, m_szDir);
521 //ist hübscher
522 ch = (TCHAR)towupper(m_Dir.GetAt(0));
523 m_Dir.SetAt(0,ch);
525 CString m_Name,m_File,m_Dir1 = m_Dir;
526 if (m_Dir.Right(1) != _T('\\'))
527 m_Dir += _T("\\");
529 if(m_LastDirectory.CompareNoCase(m_Dir) == 0 && m_Liste.m_SearchList.GetSize())
530 return;
532 m_LastDirectory = m_Dir;
533 m_Dir += _T("*.*");
535 BOOL bContinue = FoundFiles.FindFile(m_Dir);
536 if(bContinue)
537 RemoveSearchAll();
539 while (bContinue == TRUE)
541 bContinue = FoundFiles.FindNextFile();
542 m_File = FoundFiles.GetFileName();
544 if(FoundFiles.IsHidden() || FoundFiles.IsSystem())
545 continue;
546 if(FoundFiles.IsDirectory())
548 if(m_iMode & _MODE_ONLY_FILES)
549 continue;
550 if(FoundFiles.IsDots())
551 continue;
553 if (m_File.Right(1) != _T('\\'))
554 m_File += _T("\\");
557 if(!FoundFiles.IsDirectory())
558 if(m_iMode & _MODE_ONLY_DIRS)
559 continue;
561 if(m_iMode & _MODE_FS_START_DIR_)
563 m_Name = m_File;
565 else
567 m_Name = m_Dir1;
568 if (m_Name.Right(1) != _T('\\'))
569 m_Name += _T("\\");
571 m_Name += m_File;
574 AddSearchString(m_Name);
576 FoundFiles.Close();
577 return;
581 /*********************************************************************/
583 void CACEdit::SetStartDirectory(LPCTSTR lpszString)
585 if(m_iType == -1) {ASSERT(0); return;}
587 if(m_iMode & _MODE_FS_START_DIR_)
588 ReadDirectory(lpszString);
591 /*********************************************************************
592 ** CComboBox
593 ** NEW:V1.1
594 *********************************************************************/
596 int CACEdit::AddString( LPCTSTR lpszString )
598 if(m_iType == _COMBOBOX_)
600 return ((CComboBox *)this)->AddString(lpszString);
602 return CB_ERR;
605 /*********************************************************************/
607 int CACEdit::SetDroppedWidth( UINT nWidth )
609 if(m_iType == _COMBOBOX_)
611 return ((CComboBox *)this)->SetDroppedWidth(nWidth);
613 return CB_ERR;
616 /*********************************************************************/
618 int CACEdit::FindString( int nStartAfter, LPCTSTR lpszString )
620 if(m_iType == _COMBOBOX_)
622 return ((CComboBox *)this)->FindString(nStartAfter,lpszString);
624 return CB_ERR;
627 /*********************************************************************/
629 int CACEdit::SelectString( int nStartAfter, LPCTSTR lpszString )
631 if(m_iType == _COMBOBOX_)
633 return ((CComboBox *)this)->SelectString(nStartAfter,lpszString);
635 return CB_ERR;
638 /*********************************************************************/
640 void CACEdit::ShowDropDown(BOOL bShowIt)
642 if(m_iType == _COMBOBOX_)
644 ((CComboBox *)this)->ShowDropDown(bShowIt);
648 /*********************************************************************/
650 void CACEdit::ResetContent()
652 if(m_iType == _COMBOBOX_)
654 ((CComboBox *)this)->ResetContent();
658 /*********************************************************************/
660 int CACEdit::GetCurSel()
662 if(m_iType == _COMBOBOX_)
664 return ((CComboBox *)this)->GetCurSel();
666 return CB_ERR;
669 /*********************************************************************/
671 int CACEdit::GetLBText( int nIndex, LPTSTR lpszText )
673 if(m_iType == _COMBOBOX_)
675 return ((CComboBox *)this)->GetLBText(nIndex,lpszText);
677 return CB_ERR;
680 /*********************************************************************/
682 void CACEdit::GetLBText( int nIndex, CString& rString )
684 if(m_iType == _COMBOBOX_)
686 ((CComboBox *)this)->GetLBText(nIndex,rString);
690 /*********************************************************************/