ReactOS  0.4.14-dev-614-gbfd8a84
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 
29 extern CRegistryTree Tree;
30 
32 
34 {
35 public:
37  {
38  m_pNext = m_pPrev = NULL;
39  m_pszText = NULL;
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 
80 private:
85  friend class CCompletionList;
86 };
87 
89 {
90 public:
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 
103 private:
104  CCompletionMatch *m_pHead; // head of completions linked list
105  CCompletionMatch *m_pTail; // tail of completions linked list
107  unsigned int m_nLastSearched;
111  unsigned __int64 m_nCount;
112 } g_Completion;
113 
114 // --- begin of CCompletionList implementation ---
116 {
117  m_pHead = NULL;
118  m_pTail = NULL;
119  m_nCount = 0;
121  m_pszContext = NULL;
122  m_pszBegin = NULL;
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 
149 BOOL CCompletionList::IsNewCompletion(const TCHAR *pszContext, const TCHAR *pszBegin, BOOL& rblnNew)
150 {
151  const TCHAR *pszCurrentKey = Tree.GetCurrentPath();
152  if (!m_pszContext ||
153  !m_pszBegin ||
154  !m_pszCurrentKey ||
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;
164  m_pszContext = NULL;
165  }
166 
167  if (m_pszBegin)
168  {
169  delete[] m_pszBegin;
170  m_pszBegin = NULL;
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;
190  m_pszContext = NULL;
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;
201  m_pszContext = NULL;
202  m_pszBegin = NULL;
203  return FALSE;
204  }
205  _tcscpy(m_pszCurrentKey,pszCurrentKey);
206 
207  return TRUE;
208  }
209 
210  rblnNew = FALSE;
211  return TRUE;
212 }
213 
214 BOOL 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;
232  ASSERT(m_pTail->m_pNext == NULL);
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 
249 const 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 
332 BOOL FillCompletion(const TCHAR *pszKey)
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;
431 Abort:
432  if (pszValueName)
433  delete[] pszValueName;
434  if (pszSubkeyName)
435  delete[] pszSubkeyName;
436  return FALSE;
437 }
438 
439 const 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 }
#define TRUE
Definition: types.h:120
CCompletionMatch * m_pNext
Definition: Completion.cpp:83
IN PLARGE_INTEGER IN PLARGE_INTEGER PEPROCESS ULONG Key
Definition: fatprocs.h:2697
BOOL Init(const TCHAR *pszText)
Definition: Completion.cpp:42
#define ERROR_SUCCESS
Definition: deptool.c:10
const TCHAR * GetBegin()
Definition: Completion.cpp:311
#define ERROR_NO_MORE_ITEMS
Definition: compat.h:95
int _tcscmp(const _TCHAR *s1, const _TCHAR *s2)
Definition: tcscmp.h:8
const TCHAR * GetCurrentPath() const
const TCHAR * Get(unsigned __int64 nIndex, BOOL &rblnIsKey)
Definition: Completion.cpp:249
TCHAR * m_pszContext
Definition: Completion.cpp:108
_TCHAR * _tcsncpy(_TCHAR *dst, const _TCHAR *src, size_t n)
Definition: tcsncpy.h:9
_TCHAR * _tcscpy(_TCHAR *to, const _TCHAR *from)
Definition: tcscpy.h:8
BOOL IsNewCompletion(const TCHAR *pszContext, const TCHAR *pszBegin, BOOL &rblnNew)
Definition: Completion.cpp:149
BOOL g_blnCompletionCycle
Definition: Completion.cpp:31
#define COMPLETION_BUFFER_SIZE
Definition: Completion.cpp:27
BOOL FillCompletion(const TCHAR *pszKey)
Definition: Completion.cpp:332
unsigned int BOOL
Definition: ntddk_ex.h:94
BOOL GetKey(const TCHAR *pchRelativePath, REGSAM DesiredAccess, CRegistryKey &rKey)
long LONG
Definition: pedump.c:60
#define _tcsnicmp
Definition: xmlstorage.h:207
const TCHAR * GetContext()
Definition: Completion.cpp:306
size_t __cdecl _tcslen(const _TCHAR *str)
Definition: tcslen.h:9
smooth NULL
Definition: ftsmooth.c:416
class CCompletionList g_Completion
TCHAR * m_pszCurrentKey
Definition: Completion.cpp:110
_TCHAR * _tcschr(const _TCHAR *s, _XINT c)
Definition: tcschr.h:4
char TCHAR
Definition: xmlstorage.h:189
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
#define _T(x)
Definition: vfdio.h:22
TCHAR * m_pszBegin
Definition: Completion.cpp:109
unsigned __int64 m_nCount
Definition: Completion.cpp:111
CCompletionMatch * m_pPrev
Definition: Completion.cpp:84
unsigned long DWORD
Definition: ntddk_ex.h:95
unsigned __int64 GetCount()
Definition: Completion.cpp:301
CRegistryTree Tree
CCompletionMatch * m_pHead
Definition: Completion.cpp:104
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
CCompletionMatch * m_pLastSearched
Definition: Completion.cpp:106
BOOL Add(const TCHAR *pszText, BOOL blnIsKey)
Definition: Completion.cpp:214
CCompletionMatch * m_pTail
Definition: Completion.cpp:105
#define _sntprintf
Definition: xmlstorage.h:201
GLdouble s
Definition: gl.h:2039
#define _stprintf
Definition: utility.h:124
#define KEY_QUERY_VALUE
Definition: nt_native.h:1016
unsigned int m_nLastSearched
Definition: Completion.cpp:107
_TCHAR * _tcscat(_TCHAR *s, const _TCHAR *append)
Definition: tcscat.h:8
_TCHAR * _tcsrchr(const _TCHAR *s, _XINT c)
Definition: tcsrchr.h:4
#define _istspace
Definition: tchar.h:1504
const TCHAR * CompletionCallback(unsigned __int64 &rnIndex, const BOOL *pblnForward, const TCHAR *pszContext, const TCHAR *pszBegin)
Definition: Completion.cpp:439
void InvalidateCompletion()
Definition: Completion.cpp:511
#define __int64
Definition: basetyps.h:16
#define KEY_ENUMERATE_SUB_KEYS
Definition: nt_native.h:1019