ReactOS 0.4.16-dev-338-g34e76ad
Completion.cpp
Go to the documentation of this file.
1/*
2 * regexpl - Console Registry Explorer
3 *
4 * Copyright (C) 2000-2005 Nedko Arnaudov <nedko@users.sourceforge.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; see the file COPYING. If not, write to
18 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
22// Completion.cpp : Defines the completion related functions.
23#include "ph.h"
24#include "RegistryKey.h"
25#include "RegistryTree.h"
26
27#define COMPLETION_BUFFER_SIZE 4096
28
29extern CRegistryTree Tree;
30
32
34{
35public:
37 {
40 };
41
42 BOOL Init(const TCHAR *pszText)
43 {
44 // find the offset to "unique" part
45 const TCHAR *pszUnique = _tcsrchr(pszText,_T('\\'));
46 pszUnique = pszUnique?(pszUnique+1):pszText;
47 BOOL b = _tcschr(pszUnique,_T(' ')) != NULL; // has it spaces in it ???
48 size_t s = _tcslen(pszText);
49
50 if (m_pszText)
51 delete[] m_pszText;
52
53 m_pszText = new (std::nothrow) TCHAR [s+(b?3:1)]; // if we have spaces in unique part, we need 2 addtional chars for "
54
55 if (!m_pszText)
56 return FALSE;
57
58 ASSERT(pszText <= pszUnique);
59 s = pszUnique - pszText; // calculate offset of the unique part
60 if (s)
61 _tcsncpy(m_pszText,pszText,s);
62
63 if (b)
64 m_pszText[s++] = _T('\"');
65
66 _tcscpy(m_pszText+s,pszUnique);
67
68 if (b)
69 _tcscat(m_pszText,_T("\""));
70
71 return TRUE;
72 }
73
75 {
76 if (m_pszText)
77 delete[] m_pszText;
78 }
79
80private:
85 friend class CCompletionList;
86};
87
89{
90public:
93
94 BOOL IsNewCompletion(const TCHAR *pszContext, const TCHAR *pszBegin, BOOL& rblnNew);
95 BOOL Add(const TCHAR *pszText, BOOL blnIsKey);
96 const TCHAR *Get(unsigned __int64 nIndex, BOOL& rblnIsKey);
97 unsigned __int64 GetCount();
98 const TCHAR * GetContext();
99 const TCHAR * GetBegin();
100 void DeleteList();
101 void Invalidate();
102
103private:
104 CCompletionMatch *m_pHead; // head of completions linked list
105 CCompletionMatch *m_pTail; // tail of completions linked list
107 unsigned int m_nLastSearched;
113
114// --- begin of CCompletionList implementation ---
116{
117 m_pHead = NULL;
118 m_pTail = NULL;
119 m_nCount = 0;
124}
125
127{
128 DeleteList();
129
130 if (m_pszContext)
131 delete[] m_pszContext;
132
133 if (m_pszBegin)
134 delete[] m_pszBegin;
135
136 if (m_pszCurrentKey)
137 delete[] m_pszCurrentKey;
138}
139
141{
142 if (m_pszCurrentKey)
143 {
144 delete[] m_pszCurrentKey;
146 }
147}
148
149BOOL CCompletionList::IsNewCompletion(const TCHAR *pszContext, const TCHAR *pszBegin, BOOL& rblnNew)
150{
151 const TCHAR *pszCurrentKey = Tree.GetCurrentPath();
152 if (!m_pszContext ||
153 !m_pszBegin ||
155 (_tcscmp(m_pszContext,pszContext) != 0) ||
156 (_tcscmp(m_pszBegin,pszBegin) != 0) ||
157 (_tcscmp(m_pszCurrentKey,pszCurrentKey)))
158 { // new completion
159 DeleteList();
160 rblnNew = TRUE;
161 if (m_pszContext)
162 {
163 delete[] m_pszContext;
165 }
166
167 if (m_pszBegin)
168 {
169 delete[] m_pszBegin;
171 }
172
173 if (m_pszCurrentKey)
174 {
175 delete[] m_pszCurrentKey;
177 }
178
179 size_t s = _tcslen(pszContext);
180 m_pszContext = new (std::nothrow) TCHAR[s+1];
181 if (!m_pszContext)
182 return FALSE;
183 _tcscpy(m_pszContext,pszContext);
184
185 s = _tcslen(pszBegin);
186 m_pszBegin = new (std::nothrow) TCHAR[s+1];
187 if (!m_pszBegin)
188 {
189 delete[] m_pszContext;
191 return FALSE;
192 }
193 _tcscpy(m_pszBegin,pszBegin);
194
195 s = _tcslen(pszCurrentKey);
196 m_pszCurrentKey = new (std::nothrow) TCHAR[s+1];
197 if (!m_pszCurrentKey)
198 {
199 delete[] m_pszContext;
200 delete[] m_pszBegin;
203 return FALSE;
204 }
205 _tcscpy(m_pszCurrentKey,pszCurrentKey);
206
207 return TRUE;
208 }
209
210 rblnNew = FALSE;
211 return TRUE;
212}
213
214BOOL CCompletionList::Add(const TCHAR *pszText, BOOL blnIsKey)
215{
216 if (_tcsnicmp(pszText,m_pszBegin,_tcslen(m_pszBegin)) != 0)
217 return TRUE;
218 CCompletionMatch *pNode = new (std::nothrow) CCompletionMatch;
219 if (!pNode)
220 return FALSE;
221 if (!pNode->Init(pszText))
222 return FALSE;
223
224 ASSERT(pNode->m_pszText);
225 ASSERT(pNode->m_pNext == NULL);
226
227 // add new node to tail
228 pNode->m_blnIsKey = blnIsKey;
229 if (m_pTail)
230 {
231 pNode->m_pPrev = m_pTail;
233 m_pTail->m_pNext = pNode;
234 m_pTail = pNode;
235 }
236 else
237 {
238 ASSERT(m_pHead == NULL);
239 m_pHead = m_pTail = pNode;
240 }
241
242 m_nCount++;
243
245
246 return TRUE;
247}
248
249const TCHAR * CCompletionList::Get(unsigned __int64 nIndex, BOOL& rblnIsKey)
250{
251 ASSERT(nIndex < m_nCount);
252 BOOL blnForward = FALSE;
253 CCompletionMatch *pNode = NULL;
254
255 unsigned __int64 nRelativeIndex = 0;
256
257 if (m_pLastSearched)
258 {
259 pNode = m_pLastSearched;
260 blnForward = nIndex > m_nLastSearched;
261 nRelativeIndex = blnForward?(nIndex-m_nLastSearched):(m_nLastSearched-nIndex);
262 if ((nRelativeIndex > nIndex)||(nRelativeIndex > m_nCount-nIndex-1))
263 pNode = NULL; // seraching from tail or from head is more effective
264 }
265
266 if (!pNode && (nIndex <= m_nCount/2))
267 { // search from head
268 pNode = m_pHead;
269 blnForward = TRUE;
270 nRelativeIndex = nIndex;
271 }
272
273 if (!pNode)
274 { // search from tail
275 pNode = m_pTail;
276 blnForward = FALSE;
277 nRelativeIndex = m_nCount-nIndex-1;
278 }
279
280 while(pNode)
281 {
282 if (nRelativeIndex == 0)
283 {
284 m_nLastSearched = nIndex;
285 m_pLastSearched = pNode;
286 rblnIsKey = pNode->m_blnIsKey;
287 if (!pNode->m_pszText)
288 ASSERT(FALSE);
289 return pNode->m_pszText;
290 }
291
292 nRelativeIndex--;
293
294 pNode = blnForward?(pNode->m_pNext):(pNode->m_pPrev);
295 }
296
297 ASSERT(FALSE);
298 return NULL;
299}
300
302{
303 return m_nCount;
304}
305
307{
308 return m_pszContext;
309}
310
312{
313 return m_pszBegin;
314}
315
317{
318 CCompletionMatch *pNode;
319 while(m_pHead)
320 {
321 pNode = m_pHead;
323 delete pNode;
324 }
325 m_pTail = NULL;
326 ASSERT(m_pHead == NULL);
327 m_nCount = 0;
328}
329
330// --- end of CCompletionList implementation ---
331
333{
335 LONG nError;
337 TCHAR *pszSubkeyName = NULL;
338 DWORD dwMaxSubkeyNameLength;
339 TCHAR *pszValueName = NULL;
340 DWORD dwMaxValueNameSize;
341
342 if (!Tree.GetKey(pszKey?pszKey:_T("."),KEY_ENUMERATE_SUB_KEYS|KEY_QUERY_VALUE,Key))
343 return FALSE;
344
345 BOOL blnCompletionOnKeys = TRUE;
346 BOOL blnCompletionOnValues = TRUE;
347
348/* if ((_tcsnicmp(pchContext,DIR_CMD,DIR_CMD_LENGTH) == 0)||
349 (_tcsnicmp(pchContext,CD_CMD,CD_CMD_LENGTH) == 0)||
350 (_tcsnicmp(pchContext,OWNER_CMD,OWNER_CMD_LENGTH) == 0)||
351 (_tcsnicmp(pchContext,DACL_CMD,DACL_CMD_LENGTH) == 0)||
352 (_tcsnicmp(pchContext,SACL_CMD,SACL_CMD_LENGTH) == 0))
353 {
354 blnCompletionOnValues = FALSE;
355 }*/
356// else if (_tcsnicmp(pchContext,VALUE_CMD,VALUE_CMD_LENGTH) == 0)
357// {
358// blnCompletionOnKeys = FALSE;
359// }
360
361 size_t nKeyNameSize = 0;
362 if (pszKey)
363 {
364 nKeyNameSize = _tcslen(pszKey);
365 if (_tcscmp(pszKey,_T("\\")))
366 nKeyNameSize++;
367 }
368
369 if (blnCompletionOnKeys)
370 {
371 nError = Key.GetSubkeyNameMaxLength(dwMaxSubkeyNameLength);
372 if (nError != ERROR_SUCCESS)
373 return FALSE;
374
375 pszSubkeyName = new (std::nothrow) TCHAR[nKeyNameSize+dwMaxSubkeyNameLength+1];
376 if (!pszSubkeyName)
377 goto Abort;
378
379 if (pszKey)
380 _stprintf(pszSubkeyName,_tcscmp(pszKey,_T("\\"))?_T("%s\\"):_T("%s"),pszKey);
381
382 Key.InitSubkeyEnumeration(pszSubkeyName+nKeyNameSize,dwMaxSubkeyNameLength);
383 while ((nError = Key.GetNextSubkeyName()) == ERROR_SUCCESS)
384 if (!g_Completion.Add(pszSubkeyName,TRUE))
385 {
386 ASSERT(FALSE);
387 goto Abort;
388 }
389 if ((nError != ERROR_SUCCESS)&&(nError != ERROR_NO_MORE_ITEMS))
390 {
391 ASSERT(FALSE);
392 goto Abort;
393 }
394 }
395
396 if (blnCompletionOnValues)
397 {
398 nError = Key.GetMaxValueNameLength(dwMaxValueNameSize);
399 if (nError != ERROR_SUCCESS)
400 {
401 ASSERT(FALSE);
402 goto Abort;
403 }
404
405 pszValueName = new (std::nothrow) TCHAR[nKeyNameSize+dwMaxValueNameSize+1];
406 if (!pszValueName)
407 goto Abort;
408
409 if (pszKey)
410 _stprintf(pszValueName,_tcscmp(pszKey,_T("\\"))?_T("%s\\"):_T("%s"),pszKey);
411
412 Key.InitValueEnumeration(pszValueName+nKeyNameSize,dwMaxValueNameSize,NULL,0,NULL);
413 while((nError = Key.GetNextValue()) == ERROR_SUCCESS)
414 if (!g_Completion.Add(pszValueName,FALSE))
415 {
416 ASSERT(FALSE);
417 goto Abort;
418 }
419 if ((nError != ERROR_SUCCESS)&&(nError != ERROR_NO_MORE_ITEMS))
420 {
421 ASSERT(FALSE);
422 goto Abort;
423 }
424 }
425
426 if (pszValueName)
427 delete[] pszValueName;
428 if (pszSubkeyName)
429 delete[] pszSubkeyName;
430 return TRUE;
431Abort:
432 if (pszValueName)
433 delete[] pszValueName;
434 if (pszSubkeyName)
435 delete[] pszSubkeyName;
436 return FALSE;
437}
438
439const TCHAR * CompletionCallback(unsigned __int64 & rnIndex,
440 const BOOL *pblnForward,
441 const TCHAR *pszContext,
442 const TCHAR *pszBegin)
443{
444 static TCHAR pszBuffer[COMPLETION_BUFFER_SIZE];
445
446 // Find first non-white space in context
447 while(*pszContext && _istspace(*pszContext))
448 pszContext++;
449
450 BOOL blnNewCompletion = TRUE;
451 if (!g_Completion.IsNewCompletion(pszContext,pszBegin,blnNewCompletion))
452 {
453 ASSERT(FALSE);
454 return NULL;
455 }
456
457 if (blnNewCompletion)
458 {
459 _tcsncpy(pszBuffer,pszBegin,COMPLETION_BUFFER_SIZE-1);
460 pszBuffer[COMPLETION_BUFFER_SIZE-1] = 0;
461 TCHAR *pszSeparator = pszBuffer; // set it to aby non null value
462 if (_tcscmp(pszBuffer,_T("\\")))
463 {
464 pszSeparator = _tcsrchr(pszBuffer,_T('\\'));
465 if (pszSeparator)
466 *pszSeparator = 0;
467 }
468
469 if (!FillCompletion(pszSeparator?pszBuffer:NULL))
470 return NULL;
471 }
472
473 unsigned __int64 nTotalItems = g_Completion.GetCount();
474 if (nTotalItems == 0)
475 return NULL;
476
477 if (rnIndex >= nTotalItems)
478 rnIndex = nTotalItems-1;
479
480 if (pblnForward)
481 {
482 if (*pblnForward)
483 {
484 rnIndex++;
485 if (rnIndex >= nTotalItems)
486 {
488 rnIndex = 0;
489 else
490 rnIndex--;
491 }
492 }
493 else
494 {
495 if (rnIndex)
496 rnIndex--;
497 else if (g_blnCompletionCycle)
498 rnIndex = nTotalItems-1;
499 }
500 }
501 BOOL blnIsKey = FALSE;
502 const TCHAR *pszName = g_Completion.Get(rnIndex,blnIsKey);
503
504 ASSERT(pszName);
505
506 _sntprintf(pszBuffer,COMPLETION_BUFFER_SIZE-1,_T("%s%s"),pszName,(blnIsKey?_T("\\"):_T("")));
507 pszBuffer[COMPLETION_BUFFER_SIZE-1] = 0;
508 return pszBuffer;
509}
510
512{
514}
BOOL FillCompletion(const TCHAR *pszKey)
Definition: Completion.cpp:332
void InvalidateCompletion()
Definition: Completion.cpp:511
const TCHAR * CompletionCallback(unsigned __int64 &rnIndex, const BOOL *pblnForward, const TCHAR *pszContext, const TCHAR *pszBegin)
Definition: Completion.cpp:439
BOOL g_blnCompletionCycle
Definition: Completion.cpp:31
class CCompletionList g_Completion
CRegistryTree Tree
#define COMPLETION_BUFFER_SIZE
Definition: Completion.cpp:27
#define __int64
Definition: basetyps.h:16
BOOL Add(const TCHAR *pszText, BOOL blnIsKey)
Definition: Completion.cpp:214
BOOL IsNewCompletion(const TCHAR *pszContext, const TCHAR *pszBegin, BOOL &rblnNew)
Definition: Completion.cpp:149
const TCHAR * GetBegin()
Definition: Completion.cpp:311
unsigned int m_nLastSearched
Definition: Completion.cpp:107
const TCHAR * Get(unsigned __int64 nIndex, BOOL &rblnIsKey)
Definition: Completion.cpp:249
CCompletionMatch * m_pLastSearched
Definition: Completion.cpp:106
TCHAR * m_pszCurrentKey
Definition: Completion.cpp:110
unsigned __int64 GetCount()
Definition: Completion.cpp:301
TCHAR * m_pszContext
Definition: Completion.cpp:108
unsigned __int64 m_nCount
Definition: Completion.cpp:111
CCompletionMatch * m_pHead
Definition: Completion.cpp:104
CCompletionMatch * m_pTail
Definition: Completion.cpp:105
const TCHAR * GetContext()
Definition: Completion.cpp:306
TCHAR * m_pszBegin
Definition: Completion.cpp:109
CCompletionMatch * m_pNext
Definition: Completion.cpp:83
CCompletionMatch * m_pPrev
Definition: Completion.cpp:84
BOOL Init(const TCHAR *pszText)
Definition: Completion.cpp:42
BOOL GetKey(const TCHAR *pchRelativePath, REGSAM DesiredAccess, CRegistryKey &rKey)
const TCHAR * GetCurrentPath() const
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:105
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLdouble s
Definition: gl.h:2039
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define _istspace
Definition: tchar.h:1504
#define _tcscmp
Definition: tchar.h:1424
#define _tcscat
Definition: tchar.h:622
#define _tcscpy
Definition: tchar.h:623
#define _tcsncpy
Definition: tchar.h:1410
#define _tcschr
Definition: tchar.h:1406
#define ASSERT(a)
Definition: mode.c:44
#define _stprintf
Definition: utility.h:124
#define _tcsrchr
Definition: utility.h:116
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019
long LONG
Definition: pedump.c:60
#define _T(x)
Definition: vfdio.h:22
char TCHAR
Definition: xmlstorage.h:189
#define _tcsnicmp
Definition: xmlstorage.h:207
#define _sntprintf
Definition: xmlstorage.h:201
#define _tcslen
Definition: xmlstorage.h:198