MRU.cpp
上传用户:sbftbdw
上传日期:2007-01-03
资源大小:379k
文件大小:9k
源码类别:

远程控制编程

开发平台:

Visual C++

  1. //  Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
  2. //
  3. //  This file is part of the VNC system.
  4. //
  5. //  The VNC system is free software; you can redistribute it and/or modify
  6. //  it under the terms of the GNU General Public License as published by
  7. //  the Free Software Foundation; either version 2 of the License, or
  8. //  (at your option) any later version.
  9. //
  10. //  This program is distributed in the hope that it will be useful,
  11. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //  GNU General Public License for more details.
  14. //
  15. //  You should have received a copy of the GNU General Public License
  16. //  along with this program; if not, write to the Free Software
  17. //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  18. //  USA.
  19. //
  20. // If the source code for the VNC system is not available from the place 
  21. // whence you received this file, check http://www.orl.co.uk/vnc or contact
  22. // the authors on vnc@orl.co.uk for information on obtaining it.
  23. //
  24. // MRU maintains a list of 'Most Recently Used' strings in the registry
  25. // 
  26. #include "MRU.h"
  27. static const TCHAR * INDEX_VAL_NAME = _T("index");
  28. static const int MRU_MAX_ITEM_LENGTH = 256;
  29. MRU::MRU(LPTSTR keyname, unsigned int maxnum)
  30. {
  31. DWORD dispos;
  32.     // Create the registry key.  If unsuccessful all other methods will be no-ops.
  33.     if ( RegCreateKeyEx(HKEY_CURRENT_USER, keyname, 0, NULL, 
  34. REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &m_hRegKey, &dispos)  != ERROR_SUCCESS ) {
  35.         m_hRegKey = NULL;
  36.     }
  37.     m_index[0] = _T('');
  38.     m_maxnum = maxnum;
  39.     // Read the index entry
  40.     ReadIndex();
  41.     Tidy();
  42. }
  43. // Add the item specified at the front of the list
  44. // Move it there if not already.  If this makes the
  45. // list longer than the maximum, older ones are deleted.
  46. void MRU::AddItem(LPTSTR txt) 
  47. {
  48.     if (m_hRegKey == NULL) return;
  49.     // Read each value in index,
  50.     // noting which is the first unused id
  51.     TCHAR id = _T('');
  52.     TCHAR firstUnusedId = _T('A');
  53.     TCHAR itembuf[MRU_MAX_ITEM_LENGTH+1];
  54. // Find first unused letter.
  55. while (_tcschr(m_index, firstUnusedId) != NULL)
  56. firstUnusedId++;
  57.     for (int i = 0; i < (int) _tcslen(m_index); i++) {
  58.         
  59.         // Does this entry already contain the item we're adding
  60.         if (GetItem(i, itembuf, MRU_MAX_ITEM_LENGTH) != 0) {
  61.             
  62.             // If a value matches the txt specified, move it to the front.
  63.             if (_tcscmp(itembuf, txt) == 0) {
  64.                 id = m_index[i];
  65.                 for (int j = i; j > 0; j--)
  66.                     m_index[j] = m_index[j-1];
  67.                 m_index[0] = id;
  68.                 WriteIndex();
  69.                 // That's all we need to do.
  70.                 return;
  71.             }
  72.         }
  73.     }
  74.     // If we haven't found it, then we need to create a new entry and put it
  75.     // at the front of the index.
  76.     TCHAR valname[2];
  77.     valname[0] = firstUnusedId;
  78.     valname[1] = _T('');
  79.     RegSetValueEx(m_hRegKey, valname, NULL, REG_SZ, 
  80.         (CONST BYTE *) txt, (_tcslen(txt) + 1) * sizeof(TCHAR));
  81.     
  82.     // move all the current ids up one
  83.     for (int j = _tcslen(m_index); j >= 0; j--)
  84.         m_index[j] = m_index[j-1];
  85.     
  86.     // and insert this one at the front
  87.     m_index[0] = firstUnusedId;
  88.     WriteIndex();
  89.     // Tidy, to truncate index if too long.
  90.     Tidy();
  91. }
  92. // How many items are on the list?
  93. int MRU::NumItems()
  94. {
  95.     if (m_hRegKey == NULL) return 0;
  96.     // return the length of index
  97.     return _tcslen(m_index);
  98. }
  99. // Return them in order. 0 is the newest.
  100. // NumItems()-1 is the oldest.
  101. // Returns length, or 0 if unsuccessful.
  102. int MRU::GetItem(int index, LPTSTR buf, int buflen)
  103. {
  104.     if (m_hRegKey == NULL)      return 0;
  105.     if (index > NumItems() - 1) return 0;
  106.     TCHAR valname[2];
  107.     valname[0] = m_index[index];
  108.     valname[1] = _T('');
  109.     DWORD valtype;
  110.     DWORD dwbuflen = buflen;
  111.     if ( RegQueryValueEx( m_hRegKey,  valname, 
  112.             NULL, &valtype, 
  113.             (LPBYTE) buf, &dwbuflen) != ERROR_SUCCESS)
  114.           return 0;
  115.     if (valtype != REG_SZ)
  116.         return 0;  // should really be an assert
  117.     // May not be one byte per char, so we won't use dwbuflen
  118.     return _tcslen(buf);
  119. }
  120. // Remove the specified item if it exists.
  121. // Only one copy will be removed, but nothing should occur more than once.
  122. void MRU::RemoveItem(LPTSTR txt)
  123. {
  124.     if (m_hRegKey == NULL) return;
  125.     TCHAR itembuf[MRU_MAX_ITEM_LENGTH+1];
  126.     for (int i = 0; i < NumItems(); i++) {
  127.         GetItem(i, itembuf, MRU_MAX_ITEM_LENGTH);
  128.         if (_tcscmp(itembuf, txt) == 0) {
  129.             RemoveItem(i);
  130.             break;
  131.         }
  132.     }
  133. }
  134. // Remove the item with the given index.
  135. // If this is greater than NumItems()-1 it will be ignored.
  136. void MRU::RemoveItem(int index)
  137. {
  138.     if (m_hRegKey == NULL) return;
  139.     if (index > NumItems()-1) return;
  140.     TCHAR valname[2];
  141.     valname[0] = m_index[index];
  142.     valname[1] = _T('');
  143.     RegDeleteValue(m_hRegKey, valname);
  144.     for (unsigned int i = index; i <= _tcslen(m_index); i++)
  145.         m_index[i] = m_index[i+1];
  146.     
  147.     WriteIndex();
  148. }
  149. // Load the index string from the registry
  150. void MRU::ReadIndex()
  151. {
  152.     if (m_hRegKey == NULL) return;
  153.     // read the index
  154.     DWORD valtype;
  155.     DWORD dwindexlen = sizeof(m_index);
  156.     if (RegQueryValueEx( m_hRegKey, INDEX_VAL_NAME,
  157.         NULL, &valtype, (LPBYTE) m_index, &dwindexlen) == ERROR_SUCCESS) {
  158.     } else {
  159.         // If index entry doesn't exist, create it
  160.         WriteIndex();
  161.     }
  162. }
  163. // Save the index string to the registry
  164. void MRU::WriteIndex()
  165. {
  166.    if (m_hRegKey == NULL) return;
  167.    RegSetValueEx(m_hRegKey, INDEX_VAL_NAME, NULL, REG_SZ, 
  168.         (CONST BYTE *)m_index, (_tcslen(m_index) + 1) * sizeof(TCHAR));
  169. }
  170. // Tidy is called from time to time to preserve the integrity of the MRU
  171. // list.  It does three things:
  172. //  * Check the length and integrity of the index
  173. //  * Check that all other values in the registry key have an 
  174. //    entry in the index and delete them from registry if not.
  175. //  * Check that all entries in the index have a corresponding
  176. //    value in the registry key and delete them from index if not.
  177. void MRU::Tidy()
  178. {
  179.     if (m_hRegKey == NULL) return;
  180.     int i;    
  181. // First some checks on the index itself.
  182.     // Truncate the index.
  183.     m_index[m_maxnum] = _T('');
  184.     // Check that no entry occurs more than once.
  185. DWORD seenCharMask = 0;
  186. for (i = 0; m_index[i] != _T(''); i++) {
  187. DWORD mask = 1 << (m_index[i]-_T('A'));
  188. if (seenCharMask & mask) {
  189. // The current character has been used before.
  190. // Delete it and move everything up.
  191. for (int j = i; m_index[j] != _T(''); j++)
  192. m_index[j] = m_index[j+1];
  193. // Start next check at new current character
  194. i--;
  195. }
  196. seenCharMask |= mask;
  197. }
  198. // Then check that all entries in registry have entry in index.
  199.     TCHAR valname[256];
  200.     DWORD valtype;
  201.     DWORD valnamelen;
  202.     DWORD numValues;
  203.     RegQueryInfoKey ( m_hRegKey,  
  204.         NULL, NULL, 
  205.         NULL, NULL, 
  206.         NULL, NULL,  
  207.         &numValues,  
  208.         NULL, NULL,
  209.         NULL, NULL);
  210.     // We're being good here.  The documentation says we shouldn't
  211.     // modify a key while enumerating its values. So this array will
  212.     // hold the names of keys which should be deleted
  213.     TCHAR **dudValues = new TCHAR* [numValues];
  214.     for (i = 0; i < (int) numValues; i++)
  215.         dudValues[i] = NULL;
  216.     unsigned int numDudValues = 0;
  217.     i = 0;
  218.     while (1) {
  219.         valnamelen = 255;
  220.         
  221.         if (RegEnumValue(m_hRegKey, i, 
  222.                         valname, &valnamelen, NULL,
  223.                         &valtype, NULL, NULL) == ERROR_NO_MORE_ITEMS)
  224.             break;
  225.         i++;
  226.         
  227.         // ignore the index
  228.         if (_tcscmp(valname, INDEX_VAL_NAME) == 0)
  229.             continue;
  230.         // Record as invalid other non-single-char entries
  231.         if (_tcslen(valname) > 1) {
  232.             dudValues[numDudValues++] = _tcsdup(valname);
  233.             continue;
  234.         }
  235.         // Record as invalid if not in the index
  236.         if (_tcschr(m_index, valname[0]) == 0) {
  237.             dudValues[numDudValues++] = _tcsdup(valname);
  238.             continue;
  239.         }   
  240.     }
  241.     // Now delete the invalid ones
  242.     for (i = 0; i < (int) numDudValues; i++) {
  243.         RegDeleteValue(m_hRegKey, dudValues[i]);
  244.         free(dudValues[i]);
  245.     }
  246.     delete[] dudValues;
  247.     // Lastly, check that all entries in the index have a corresponding 
  248.     // entry in registry and delete them if not.
  249.     for (i = _tcslen(m_index)-1; i >= 0;  i--) {
  250.         TCHAR itembuf[MRU_MAX_ITEM_LENGTH+1];
  251.         if (GetItem(i, itembuf, MRU_MAX_ITEM_LENGTH) == 0) {
  252.             for (unsigned int j = i; j <= _tcslen(m_index)-1; j++)
  253.                 m_index[j] = m_index[j+1];
  254.         }
  255.     }
  256. // Save any changes to the index.
  257.     WriteIndex();
  258. }
  259. MRU::~MRU()
  260. {
  261.     if (m_hRegKey != NULL) {
  262.         Tidy();
  263.         RegCloseKey(m_hRegKey);
  264.         m_hRegKey = NULL;
  265.     }
  266. }