3 * regexpl - Console Registry Explorer
5 * Copyright (C) 2000-2005 Nedko Arnaudov <nedko@users.sourceforge.net>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
23 // Completion.cpp : Defines the completion related functions.
25 #include "RegistryKey.h"
26 #include "RegistryTree.h"
28 #define COMPLETION_BUFFER_SIZE 4096
30 extern CRegistryTree Tree
;
32 BOOL g_blnCompletionCycle
= TRUE
;
34 class CCompletionMatch
39 m_pNext
= m_pPrev
= NULL
;
43 BOOL
Init(const TCHAR
*pszText
)
45 // find the offset to "unique" part
46 const TCHAR
*pszUnique
= _tcsrchr(pszText
,_T('\\'));
47 pszUnique
= pszUnique
?(pszUnique
+1):pszText
;
48 BOOL b
= _tcschr(pszUnique
,_T(' ')) != NULL
; // has it spaces in it ???
49 size_t s
= _tcslen(pszText
);
54 m_pszText
= new TCHAR
[s
+(b
?3:1)]; // if we have spaces in unique part, we need 2 addtional chars for "
59 ASSERT(pszText
<= pszUnique
);
60 s
= pszUnique
- pszText
; // calculate offset of the unique part
62 _tcsncpy(m_pszText
,pszText
,s
);
65 m_pszText
[s
++] = _T('\"');
67 _tcscpy(m_pszText
+s
,pszUnique
);
70 _tcscat(m_pszText
,_T("\""));
84 CCompletionMatch
*m_pNext
;
85 CCompletionMatch
*m_pPrev
;
86 friend class CCompletionList
;
95 BOOL
IsNewCompletion(const TCHAR
*pszContext
, const TCHAR
*pszBegin
, BOOL
& rblnNew
);
96 BOOL
Add(const TCHAR
*pszText
, BOOL blnIsKey
);
97 const TCHAR
*Get(unsigned __int64 nIndex
, BOOL
& rblnIsKey
);
98 unsigned __int64
GetCount();
99 const TCHAR
* GetContext();
100 const TCHAR
* GetBegin();
105 CCompletionMatch
*m_pHead
; // head of completions linked list
106 CCompletionMatch
*m_pTail
; // tail of completions linked list
107 CCompletionMatch
*m_pLastSearched
;
108 unsigned int m_nLastSearched
;
111 TCHAR
*m_pszCurrentKey
;
112 unsigned __int64 m_nCount
;
115 // --- begin of CCompletionList implementation ---
116 CCompletionList::CCompletionList()
121 m_pLastSearched
= NULL
;
124 m_pszCurrentKey
= NULL
;
127 CCompletionList::~CCompletionList()
138 delete m_pszCurrentKey
;
141 void CCompletionList::Invalidate()
145 delete m_pszCurrentKey
;
146 m_pszCurrentKey
= NULL
;
150 BOOL
CCompletionList::IsNewCompletion(const TCHAR
*pszContext
, const TCHAR
*pszBegin
, BOOL
& rblnNew
)
152 const TCHAR
*pszCurrentKey
= Tree
.GetCurrentPath();
156 (_tcscmp(m_pszContext
,pszContext
) != 0) ||
157 (_tcscmp(m_pszBegin
,pszBegin
) != 0) ||
158 (_tcscmp(m_pszCurrentKey
,pszCurrentKey
)))
176 delete m_pszCurrentKey
;
177 m_pszCurrentKey
= NULL
;
180 size_t s
= _tcslen(pszContext
);
181 m_pszContext
= new TCHAR
[s
+1];
184 _tcscpy(m_pszContext
,pszContext
);
186 s
= _tcslen(pszBegin
);
187 m_pszBegin
= new TCHAR
[s
+1];
190 _tcscpy(m_pszBegin
,pszBegin
);
192 s
= _tcslen(pszCurrentKey
);
193 m_pszCurrentKey
= new TCHAR
[s
+1];
194 if (!m_pszCurrentKey
)
196 _tcscpy(m_pszCurrentKey
,pszCurrentKey
);
205 BOOL
CCompletionList::Add(const TCHAR
*pszText
, BOOL blnIsKey
)
207 if (_tcsnicmp(pszText
,m_pszBegin
,_tcslen(m_pszBegin
)) != 0)
209 CCompletionMatch
*pNode
= new CCompletionMatch
;
212 if (!pNode
->Init(pszText
))
215 ASSERT(pNode
->m_pszText
);
216 ASSERT(pNode
->m_pNext
== NULL
);
218 // add new node to tail
219 pNode
->m_blnIsKey
= blnIsKey
;
222 pNode
->m_pPrev
= m_pTail
;
223 ASSERT(m_pTail
->m_pNext
== NULL
);
224 m_pTail
->m_pNext
= pNode
;
229 ASSERT(m_pHead
== NULL
);
230 m_pHead
= m_pTail
= pNode
;
235 m_pLastSearched
= NULL
;
240 const TCHAR
* CCompletionList::Get(unsigned __int64 nIndex
, BOOL
& rblnIsKey
)
242 ASSERT(nIndex
< m_nCount
);
243 BOOL blnForward
= FALSE
;
244 CCompletionMatch
*pNode
= NULL
;
246 unsigned __int64 nRelativeIndex
= 0;
250 pNode
= m_pLastSearched
;
251 blnForward
= nIndex
> m_nLastSearched
;
252 nRelativeIndex
= blnForward
?(nIndex
-m_nLastSearched
):(m_nLastSearched
-nIndex
);
253 if ((nRelativeIndex
> nIndex
)||(nRelativeIndex
> m_nCount
-nIndex
-1))
254 pNode
= NULL
; // seraching from tail or from head is more effective
257 if (!pNode
&& (nIndex
<= m_nCount
/2))
258 { // search from head
261 nRelativeIndex
= nIndex
;
265 { // search from tail
268 nRelativeIndex
= m_nCount
-nIndex
-1;
273 if (nRelativeIndex
== 0)
275 m_nLastSearched
= nIndex
;
276 m_pLastSearched
= pNode
;
277 rblnIsKey
= pNode
->m_blnIsKey
;
278 if (!pNode
->m_pszText
)
280 return pNode
->m_pszText
;
285 pNode
= blnForward
?(pNode
->m_pNext
):(pNode
->m_pPrev
);
292 unsigned __int64
CCompletionList::GetCount()
297 const TCHAR
* CCompletionList::GetContext()
302 const TCHAR
* CCompletionList::GetBegin()
307 void CCompletionList::DeleteList()
309 CCompletionMatch
*pNode
;
313 m_pHead
= m_pHead
->m_pNext
;
317 ASSERT(m_pHead
== NULL
);
321 // --- end of CCompletionList implementation ---
323 BOOL
FillCompletion(const TCHAR
*pszKey
)
325 g_Completion
.DeleteList();
328 TCHAR
*pszSubkeyName
= NULL
;
329 DWORD dwMaxSubkeyNameLength
;
330 TCHAR
*pszValueName
= NULL
;
331 DWORD dwMaxValueNameSize
;
333 if (!Tree
.GetKey(pszKey
?pszKey
:_T("."),KEY_ENUMERATE_SUB_KEYS
|KEY_QUERY_VALUE
,Key
))
336 BOOL blnCompletionOnKeys
= TRUE
;
337 BOOL blnCompletionOnValues
= TRUE
;
339 /* if ((_tcsnicmp(pchContext,DIR_CMD,DIR_CMD_LENGTH) == 0)||
340 (_tcsnicmp(pchContext,CD_CMD,CD_CMD_LENGTH) == 0)||
341 (_tcsnicmp(pchContext,OWNER_CMD,OWNER_CMD_LENGTH) == 0)||
342 (_tcsnicmp(pchContext,DACL_CMD,DACL_CMD_LENGTH) == 0)||
343 (_tcsnicmp(pchContext,SACL_CMD,SACL_CMD_LENGTH) == 0))
345 blnCompletionOnValues = FALSE;
347 // else if (_tcsnicmp(pchContext,VALUE_CMD,VALUE_CMD_LENGTH) == 0)
349 // blnCompletionOnKeys = FALSE;
352 size_t nKeyNameSize
= 0;
355 nKeyNameSize
= _tcslen(pszKey
);
356 if (_tcscmp(pszKey
,_T("\\")))
360 if (blnCompletionOnKeys
)
362 nError
= Key
.GetSubkeyNameMaxLength(dwMaxSubkeyNameLength
);
363 if (nError
!= ERROR_SUCCESS
)
366 pszSubkeyName
= new TCHAR
[nKeyNameSize
+dwMaxSubkeyNameLength
+1];
371 _stprintf(pszSubkeyName
,_tcscmp(pszKey
,_T("\\"))?_T("%s\\"):_T("%s"),pszKey
);
373 Key
.InitSubkeyEnumeration(pszSubkeyName
+nKeyNameSize
,dwMaxSubkeyNameLength
);
374 while ((nError
= Key
.GetNextSubkeyName()) == ERROR_SUCCESS
)
375 if (!g_Completion
.Add(pszSubkeyName
,TRUE
))
380 if ((nError
!= ERROR_SUCCESS
)&&(nError
!= ERROR_NO_MORE_ITEMS
))
387 if (blnCompletionOnValues
)
389 nError
= Key
.GetMaxValueNameLength(dwMaxValueNameSize
);
390 if (nError
!= ERROR_SUCCESS
)
396 pszValueName
= new TCHAR
[nKeyNameSize
+dwMaxValueNameSize
+1];
401 _stprintf(pszValueName
,_tcscmp(pszKey
,_T("\\"))?_T("%s\\"):_T("%s"),pszKey
);
403 Key
.InitValueEnumeration(pszValueName
+nKeyNameSize
,dwMaxValueNameSize
,NULL
,0,NULL
);
404 while((nError
= Key
.GetNextValue()) == ERROR_SUCCESS
)
405 if (!g_Completion
.Add(pszValueName
,FALSE
))
410 if ((nError
!= ERROR_SUCCESS
)&&(nError
!= ERROR_NO_MORE_ITEMS
))
420 delete pszSubkeyName
;
426 delete pszSubkeyName
;
430 const TCHAR
* CompletionCallback(unsigned __int64
& rnIndex
,
431 const BOOL
*pblnForward
,
432 const TCHAR
*pszContext
,
433 const TCHAR
*pszBegin
)
435 static TCHAR pszBuffer
[COMPLETION_BUFFER_SIZE
];
437 // Find first non-white space in context
438 while(*pszContext
&& _istspace(*pszContext
))
441 BOOL blnNewCompletion
= TRUE
;
442 if (!g_Completion
.IsNewCompletion(pszContext
,pszBegin
,blnNewCompletion
))
448 if (blnNewCompletion
)
450 _tcsncpy(pszBuffer
,pszBegin
,COMPLETION_BUFFER_SIZE
-1);
451 pszBuffer
[COMPLETION_BUFFER_SIZE
-1] = 0;
452 TCHAR
*pszSeparator
= pszBuffer
; // set it to aby non null value
453 if (_tcscmp(pszBuffer
,_T("\\")))
455 pszSeparator
= _tcsrchr(pszBuffer
,_T('\\'));
460 if (!FillCompletion(pszSeparator
?pszBuffer
:NULL
))
464 unsigned __int64 nTotalItems
= g_Completion
.GetCount();
465 if (nTotalItems
== 0)
468 if (rnIndex
>= nTotalItems
)
469 rnIndex
= nTotalItems
-1;
476 if (rnIndex
>= nTotalItems
)
478 if (g_blnCompletionCycle
)
488 else if (g_blnCompletionCycle
)
489 rnIndex
= nTotalItems
-1;
492 BOOL blnIsKey
= FALSE
;
493 const TCHAR
*pszName
= g_Completion
.Get(rnIndex
,blnIsKey
);
497 _sntprintf(pszBuffer
,COMPLETION_BUFFER_SIZE
-1,_T("%s%s"),pszName
,(blnIsKey
?_T("\\"):_T("")));
498 pszBuffer
[COMPLETION_BUFFER_SIZE
-1] = 0;
502 void InvalidateCompletion()
504 g_Completion
.Invalidate();