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 (std::nothrow
) 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()
132 delete[] m_pszContext
;
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
)))
164 delete[] m_pszContext
;
176 delete[] m_pszCurrentKey
;
177 m_pszCurrentKey
= NULL
;
180 size_t s
= _tcslen(pszContext
);
181 m_pszContext
= new (std::nothrow
) TCHAR
[s
+1];
184 _tcscpy(m_pszContext
,pszContext
);
186 s
= _tcslen(pszBegin
);
187 m_pszBegin
= new (std::nothrow
) TCHAR
[s
+1];
190 delete[] m_pszContext
;
194 _tcscpy(m_pszBegin
,pszBegin
);
196 s
= _tcslen(pszCurrentKey
);
197 m_pszCurrentKey
= new (std::nothrow
) TCHAR
[s
+1];
198 if (!m_pszCurrentKey
)
200 delete[] m_pszContext
;
206 _tcscpy(m_pszCurrentKey
,pszCurrentKey
);
215 BOOL
CCompletionList::Add(const TCHAR
*pszText
, BOOL blnIsKey
)
217 if (_tcsnicmp(pszText
,m_pszBegin
,_tcslen(m_pszBegin
)) != 0)
219 CCompletionMatch
*pNode
= new (std::nothrow
) CCompletionMatch
;
222 if (!pNode
->Init(pszText
))
225 ASSERT(pNode
->m_pszText
);
226 ASSERT(pNode
->m_pNext
== NULL
);
228 // add new node to tail
229 pNode
->m_blnIsKey
= blnIsKey
;
232 pNode
->m_pPrev
= m_pTail
;
233 ASSERT(m_pTail
->m_pNext
== NULL
);
234 m_pTail
->m_pNext
= pNode
;
239 ASSERT(m_pHead
== NULL
);
240 m_pHead
= m_pTail
= pNode
;
245 m_pLastSearched
= NULL
;
250 const TCHAR
* CCompletionList::Get(unsigned __int64 nIndex
, BOOL
& rblnIsKey
)
252 ASSERT(nIndex
< m_nCount
);
253 BOOL blnForward
= FALSE
;
254 CCompletionMatch
*pNode
= NULL
;
256 unsigned __int64 nRelativeIndex
= 0;
260 pNode
= m_pLastSearched
;
261 blnForward
= nIndex
> m_nLastSearched
;
262 nRelativeIndex
= blnForward
?(nIndex
-m_nLastSearched
):(m_nLastSearched
-nIndex
);
263 if ((nRelativeIndex
> nIndex
)||(nRelativeIndex
> m_nCount
-nIndex
-1))
264 pNode
= NULL
; // seraching from tail or from head is more effective
267 if (!pNode
&& (nIndex
<= m_nCount
/2))
268 { // search from head
271 nRelativeIndex
= nIndex
;
275 { // search from tail
278 nRelativeIndex
= m_nCount
-nIndex
-1;
283 if (nRelativeIndex
== 0)
285 m_nLastSearched
= nIndex
;
286 m_pLastSearched
= pNode
;
287 rblnIsKey
= pNode
->m_blnIsKey
;
288 if (!pNode
->m_pszText
)
290 return pNode
->m_pszText
;
295 pNode
= blnForward
?(pNode
->m_pNext
):(pNode
->m_pPrev
);
302 unsigned __int64
CCompletionList::GetCount()
307 const TCHAR
* CCompletionList::GetContext()
312 const TCHAR
* CCompletionList::GetBegin()
317 void CCompletionList::DeleteList()
319 CCompletionMatch
*pNode
;
323 m_pHead
= m_pHead
->m_pNext
;
327 ASSERT(m_pHead
== NULL
);
331 // --- end of CCompletionList implementation ---
333 BOOL
FillCompletion(const TCHAR
*pszKey
)
335 g_Completion
.DeleteList();
338 TCHAR
*pszSubkeyName
= NULL
;
339 DWORD dwMaxSubkeyNameLength
;
340 TCHAR
*pszValueName
= NULL
;
341 DWORD dwMaxValueNameSize
;
343 if (!Tree
.GetKey(pszKey
?pszKey
:_T("."),KEY_ENUMERATE_SUB_KEYS
|KEY_QUERY_VALUE
,Key
))
346 BOOL blnCompletionOnKeys
= TRUE
;
347 BOOL blnCompletionOnValues
= TRUE
;
349 /* if ((_tcsnicmp(pchContext,DIR_CMD,DIR_CMD_LENGTH) == 0)||
350 (_tcsnicmp(pchContext,CD_CMD,CD_CMD_LENGTH) == 0)||
351 (_tcsnicmp(pchContext,OWNER_CMD,OWNER_CMD_LENGTH) == 0)||
352 (_tcsnicmp(pchContext,DACL_CMD,DACL_CMD_LENGTH) == 0)||
353 (_tcsnicmp(pchContext,SACL_CMD,SACL_CMD_LENGTH) == 0))
355 blnCompletionOnValues = FALSE;
357 // else if (_tcsnicmp(pchContext,VALUE_CMD,VALUE_CMD_LENGTH) == 0)
359 // blnCompletionOnKeys = FALSE;
362 size_t nKeyNameSize
= 0;
365 nKeyNameSize
= _tcslen(pszKey
);
366 if (_tcscmp(pszKey
,_T("\\")))
370 if (blnCompletionOnKeys
)
372 nError
= Key
.GetSubkeyNameMaxLength(dwMaxSubkeyNameLength
);
373 if (nError
!= ERROR_SUCCESS
)
376 pszSubkeyName
= new (std::nothrow
) TCHAR
[nKeyNameSize
+dwMaxSubkeyNameLength
+1];
381 _stprintf(pszSubkeyName
,_tcscmp(pszKey
,_T("\\"))?_T("%s\\"):_T("%s"),pszKey
);
383 Key
.InitSubkeyEnumeration(pszSubkeyName
+nKeyNameSize
,dwMaxSubkeyNameLength
);
384 while ((nError
= Key
.GetNextSubkeyName()) == ERROR_SUCCESS
)
385 if (!g_Completion
.Add(pszSubkeyName
,TRUE
))
390 if ((nError
!= ERROR_SUCCESS
)&&(nError
!= ERROR_NO_MORE_ITEMS
))
397 if (blnCompletionOnValues
)
399 nError
= Key
.GetMaxValueNameLength(dwMaxValueNameSize
);
400 if (nError
!= ERROR_SUCCESS
)
406 pszValueName
= new (std::nothrow
) TCHAR
[nKeyNameSize
+dwMaxValueNameSize
+1];
411 _stprintf(pszValueName
,_tcscmp(pszKey
,_T("\\"))?_T("%s\\"):_T("%s"),pszKey
);
413 Key
.InitValueEnumeration(pszValueName
+nKeyNameSize
,dwMaxValueNameSize
,NULL
,0,NULL
);
414 while((nError
= Key
.GetNextValue()) == ERROR_SUCCESS
)
415 if (!g_Completion
.Add(pszValueName
,FALSE
))
420 if ((nError
!= ERROR_SUCCESS
)&&(nError
!= ERROR_NO_MORE_ITEMS
))
428 delete[] pszValueName
;
430 delete[] pszSubkeyName
;
434 delete[] pszValueName
;
436 delete[] pszSubkeyName
;
440 const TCHAR
* CompletionCallback(unsigned __int64
& rnIndex
,
441 const BOOL
*pblnForward
,
442 const TCHAR
*pszContext
,
443 const TCHAR
*pszBegin
)
445 static TCHAR pszBuffer
[COMPLETION_BUFFER_SIZE
];
447 // Find first non-white space in context
448 while(*pszContext
&& _istspace(*pszContext
))
451 BOOL blnNewCompletion
= TRUE
;
452 if (!g_Completion
.IsNewCompletion(pszContext
,pszBegin
,blnNewCompletion
))
458 if (blnNewCompletion
)
460 _tcsncpy(pszBuffer
,pszBegin
,COMPLETION_BUFFER_SIZE
-1);
461 pszBuffer
[COMPLETION_BUFFER_SIZE
-1] = 0;
462 TCHAR
*pszSeparator
= pszBuffer
; // set it to aby non null value
463 if (_tcscmp(pszBuffer
,_T("\\")))
465 pszSeparator
= _tcsrchr(pszBuffer
,_T('\\'));
470 if (!FillCompletion(pszSeparator
?pszBuffer
:NULL
))
474 unsigned __int64 nTotalItems
= g_Completion
.GetCount();
475 if (nTotalItems
== 0)
478 if (rnIndex
>= nTotalItems
)
479 rnIndex
= nTotalItems
-1;
486 if (rnIndex
>= nTotalItems
)
488 if (g_blnCompletionCycle
)
498 else if (g_blnCompletionCycle
)
499 rnIndex
= nTotalItems
-1;
502 BOOL blnIsKey
= FALSE
;
503 const TCHAR
*pszName
= g_Completion
.Get(rnIndex
,blnIsKey
);
507 _sntprintf(pszBuffer
,COMPLETION_BUFFER_SIZE
-1,_T("%s%s"),pszName
,(blnIsKey
?_T("\\"):_T("")));
508 pszBuffer
[COMPLETION_BUFFER_SIZE
-1] = 0;
512 void InvalidateCompletion()
514 g_Completion
.Invalidate();