📄 bookmarks.cpp
字号:
FILETIME tt;
tt.dwLowDateTime=tt.dwHighDateTime=0;
for (DWORD index=0;;++index) {
TCHAR name[1024];
DWORD namelen=sizeof(name)/sizeof(TCHAR);
TCHAR value[4096];
DWORD valuelen=sizeof(value);
DWORD type;
if (RegEnumValue(hKey,index,name,&namelen,NULL,&type,(LPBYTE)value,&valuelen)!=ERROR_SUCCESS)
break;
if (type!=REG_SZ)
continue;
int dummy;
TCHAR *cp=tmp.GetBuffer(valuelen);
FILETIME tm;
if (_stscanf(value,_T("%d,%d,%u,%u,%[^\001]"),&dummy,&dummy,&tm.dwLowDateTime,&tm.dwHighDateTime,cp)!=5) {
tmp.ReleaseBuffer(0);
continue;
}
tmp.ReleaseBuffer();
if (tm.dwHighDateTime>tt.dwHighDateTime ||
(tm.dwHighDateTime==tt.dwHighDateTime && tm.dwLowDateTime>tt.dwLowDateTime))
{
tt=tm;
filename=tmp;
}
}
RegCloseKey(hKey);
return filename;
}
struct Item {
TCHAR *name;
FILETIME time;
};
static int __cdecl itemcmp(const void *v1,const void *v2) {
const Item *i1=(const Item *)v1;
const Item *i2=(const Item *)v2;
if (i1->time.dwHighDateTime<i2->time.dwHighDateTime)
return 1;
if (i1->time.dwHighDateTime>i2->time.dwHighDateTime)
return -1;
if (i1->time.dwLowDateTime<i2->time.dwLowDateTime)
return 1;
if (i1->time.dwLowDateTime>i2->time.dwLowDateTime)
return -1;
return 0;
}
void Bookmarks::CleanupRegistry(int max_count) {
HKEY hKey=AfxGetApp()->GetSectionKey(_T("Bookmarks"));
if (!hKey)
return;
CArray<Item,Item&> ilist;
Item ii;
for (DWORD index=0;;++index) {
TCHAR name[1024];
DWORD namelen=sizeof(name)/sizeof(TCHAR);
TCHAR value[4096];
DWORD valuelen=sizeof(value);
DWORD type;
if (RegEnumValue(hKey,index,name,&namelen,NULL,&type,(LPBYTE)value,&valuelen)!=ERROR_SUCCESS)
break;
if (type!=REG_SZ)
continue;
int dummy;
if (_stscanf(value,_T("%d,%d,%u,%u,"),&dummy,&dummy,
&ii.time.dwLowDateTime,&ii.time.dwHighDateTime)!=4)
continue;
ii.name=_tcsdup(name);
if (ii.name)
ilist.Add(ii);
}
if (ilist.GetSize()>max_count) {
qsort(ilist.GetData(),ilist.GetSize(),sizeof(Item),itemcmp);
for (int kk=max_count;kk<ilist.GetSize();++kk) {
RegDeleteKey(hKey,ilist[kk].name);
RegDeleteValue(hKey,ilist[kk].name);
}
}
RegCloseKey(hKey);
for (int jj=0;jj<ilist.GetSize();++jj)
free(ilist[jj].name);
}
void Bookmarks::get_recent_files(CStringArray& fl,int num,FILETIME& toptime) {
HKEY hKey=AfxGetApp()->GetSectionKey(_T("Bookmarks"));
if (!hKey)
return;
CArray<Item,Item&> ilist;
Item ii;
CString tmp;
for (DWORD index=0;;++index) {
TCHAR name[1024];
DWORD namelen=sizeof(name)/sizeof(TCHAR);
TCHAR value[4096];
DWORD valuelen=sizeof(value);
DWORD type;
if (RegEnumValue(hKey,index,name,&namelen,NULL,&type,(LPBYTE)value,&valuelen)!=ERROR_SUCCESS)
break;
if (type!=REG_SZ)
continue;
int dummy;
TCHAR *cp=tmp.GetBuffer(valuelen);
if (_stscanf(value,_T("%d,%d,%u,%u,%[^\001]"),&dummy,&dummy,
&ii.time.dwLowDateTime,&ii.time.dwHighDateTime,cp)!=5)
{
tmp.ReleaseBuffer(0);
continue;
}
tmp.ReleaseBuffer();
ii.name=_tcsdup(tmp);
if (ii.name)
ilist.Add(ii);
}
qsort(ilist.GetData(),ilist.GetSize(),sizeof(Item),itemcmp);
for (int kk=0;kk<ilist.GetSize() && kk<num;++kk)
fl.Add(ilist[kk].name);
if (ilist.GetSize()>0)
toptime=ilist[0].time;
RegCloseKey(hKey);
for (int jj=0;jj<ilist.GetSize();++jj)
free(ilist[jj].name);
}
int Bookmarks::BFind(FilePos p,int type) {
int low=0,high=m_bmk.GetSize()-1;
while (low<=high) {
int mid=(low+high)>>1;
if (p<m_bmk[mid].ref)
high=mid-1;
else if (m_bmk[mid].ref<p)
low=mid+1;
else {
switch (type) {
case SPREVCH:
while (mid>0 && m_bmk[mid].flags&BMK)
--mid;
break;
case SNEXTICH:
while (mid<m_bmk.GetSize() && m_bmk[mid].ref==p && !(m_bmk[mid].flags&BMK))
++mid;
break;
case SNEXTCH:
while (mid<m_bmk.GetSize() && m_bmk[mid].flags&BMK)
++mid;
break;
case SPREVANY: case SNEXTANY:
break;
case SPREVBMK:
while (mid>0 && !(m_bmk[mid].flags&BMK))
--mid;
if (!(m_bmk[mid].flags&BMK))
return -1;
break;
}
return mid;
}
}
// no exact match, this is expected
switch (type) {
case SPREVBMK:
while (high>0 && !(m_bmk[high].flags&BMK))
--high;
if (high<0 || !(m_bmk[high].flags&BMK))
return -1;
break;
case SPREVCH:
while (high>0 && m_bmk[high].flags&BMK)
--high;
break;
case SNEXTICH:
return low;
case SNEXTCH:
while (low<m_bmk.GetSize() && m_bmk[low].flags&BMK)
++low;
case SNEXTANY:
return low;
case SPREVANY:
break;
}
return high<0 ? 0 : high;
}
int Bookmarks::UserBookmarks() {
int n=0;
for (int i=0;i<m_bmk.GetSize();++i)
if (m_bmk[i].flags&BMK)
++n;
return n;
}
void Bookmarks::NormalizeLevels() {
int minlevel=-1;
for (int ii=0;ii<m_bmk.GetSize();++ii) {
if (m_bmk[ii].flags&BMK)
continue;
if (minlevel<0 || minlevel>m_bmk[ii].level)
minlevel=m_bmk[ii].level;
}
m_topbmk=m_ubmk=0;
for (int jj=0;jj<m_bmk.GetSize();++jj) {
if (m_bmk[jj].flags&BMK) {
++m_topbmk;
++m_ubmk;
continue;
}
if ((m_bmk[jj].level-=minlevel)==0)
++m_topbmk;
}
}
bool Bookmarks::BookmarksInRange(FilePos start,FilePos end) {
if (!m_ubmk) // shortcut when there are no user bookmarks
return false;
// ok, have to do some searching
int ptr=BFind(start,SNEXTANY);
if (ptr>=m_bmk.GetSize())
return false;
while (m_bmk[ptr].ref<end) {
if (m_bmk[ptr].flags&BMK)
return true;
++ptr;
}
return false;
}
bool Bookmarks::BookmarkFind(FilePos& start,FilePos end) {
if (!m_ubmk) // shortcut when there are no user bookmarks
return false;
// ok, have to do some searching
int ptr=BFind(start,SNEXTANY);
while (ptr<m_bmk.GetSize() && m_bmk[ptr].ref<end) {
if (m_bmk[ptr].flags&BMK) {
start=m_bmk[ptr].ref;
return true;
}
++ptr;
}
return false;
}
static void utf8write(HANDLE hFile,const CString& str) {
Buffer<char> utf8(Unicode::ToUtf8(str));
DWORD nw;
// XXX no error checking
WriteFile(hFile,utf8,utf8.size(),&nw,NULL);
}
bool Bookmarks::ExportAllBookmarks(const CString& destfile) {
// open dest file
HANDLE hFile=::CreateFile(destfile,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
if (hFile==NULL)
return false;
// open registry entry
HKEY hBmk=AfxGetApp()->GetSectionKey(_T("Bookmarks"));
if (hBmk==NULL) {
::CloseHandle(hFile);
return false;
}
// write utf-8 BOM
DWORD nw;
::WriteFile(hFile,"\xef\xbb\xbf",3,&nw,NULL);
// enumerate files
for (int i=0;;++i) {
CString name;
DWORD namelen=1024;
TCHAR *namep=name.GetBuffer(namelen);
CString cls;
DWORD clslen=1024;
TCHAR *clsp=cls.GetBuffer(clslen);
FILETIME wtime;
DWORD type;
if (::RegEnumKeyEx(hBmk,i,namep,&namelen,NULL,clsp,&clslen,&wtime)!=ERROR_SUCCESS)
break;
name.ReleaseBuffer(namelen);
cls.ReleaseBuffer(clslen);
// we have a file name at this point
name=unescape(name);
// enumerate bookmarks
HKEY hKey;
if (::RegOpenKeyEx(hBmk,name,0,HR_REG_PERM,&hKey)==ERROR_SUCCESS) {
// get default settings
clslen=4096;
clsp=cls.GetBuffer(clslen);
clslen<<=1;
if (::RegQueryValueEx(hKey,NULL,NULL,&type,(LPBYTE)clsp,&clslen)==ERROR_SUCCESS && type==REG_SZ)
{
cls.ReleaseBuffer();
// write file header
CString tmp;
tmp.Format(_T("-%s,%s\r\n"),(const TCHAR *)cls,(const TCHAR *)escape3(name));
utf8write(hFile,tmp);
for (int j=0;;++j) {
name.Format(_T("%d"),j);
clslen=4096;
clsp=cls.GetBuffer(clslen);
clslen<<=1;
if (::RegQueryValueEx(hKey,name,NULL,&type,(LPBYTE)clsp,&clslen)!=ERROR_SUCCESS || type!=REG_SZ)
break;
cls.ReleaseBuffer();
tmp.Format(_T(" %s\r\n"),(const TCHAR *)escape3(cls));
utf8write(hFile,tmp);
}
}
::RegCloseKey(hKey);
}
}
// close file
::CloseHandle(hFile);
::RegCloseKey(hBmk);
return true;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -