1022 lines
20 KiB
C
1022 lines
20 KiB
C
|
/*++
|
||
|
* File name:
|
||
|
* bmpdb.c
|
||
|
* Contents:
|
||
|
* Bitmap database manager
|
||
|
* Almost all functions ARE NOT thread safe
|
||
|
*
|
||
|
* Copyright (C) 1998-1999 Microsoft Corp.
|
||
|
--*/
|
||
|
#include <windows.h>
|
||
|
#include <io.h>
|
||
|
#include <fcntl.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/stat.h>
|
||
|
#include <string.h>
|
||
|
#include <stdio.h>
|
||
|
#include <malloc.h>
|
||
|
|
||
|
#include "bmpdb.h"
|
||
|
|
||
|
#define DB_NAME "bmpcache.db" // Database name
|
||
|
#define TEMPDB_NAME "bmpcache.tmp" // Temp file, used to recopy the database
|
||
|
|
||
|
// Global data
|
||
|
int g_hDB = 0; // Handle to the opened database
|
||
|
int g_hTempDB; // Temp handle
|
||
|
BOOL g_bNeedToPack; // True if some entrys are deleted
|
||
|
|
||
|
/*
|
||
|
* Internal functions definition
|
||
|
--*/
|
||
|
void _PackDB(void);
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* OpenDB
|
||
|
* Description:
|
||
|
* Opens and initializes the database
|
||
|
* Arguments:
|
||
|
* bWrite - TRUE if the caller wants to write in the database
|
||
|
* Return value:
|
||
|
* TRUE on success
|
||
|
* Called by:
|
||
|
* InitCache
|
||
|
--*/
|
||
|
BOOL OpenDB(BOOL bWrite)
|
||
|
{
|
||
|
int hFile, rv = TRUE;
|
||
|
int oflag;
|
||
|
|
||
|
if (g_hDB)
|
||
|
// Already initialized
|
||
|
goto exitpt;
|
||
|
|
||
|
oflag = (bWrite)?_O_RDWR|_O_CREAT:_O_RDONLY;
|
||
|
|
||
|
hFile = _open(DB_NAME, oflag|_O_BINARY, _S_IREAD|_S_IWRITE);
|
||
|
|
||
|
if (hFile == -1)
|
||
|
rv = FALSE;
|
||
|
else
|
||
|
g_hDB = hFile;
|
||
|
|
||
|
g_bNeedToPack = FALSE;
|
||
|
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* CloseDB
|
||
|
* Description:
|
||
|
* Closes the database deletes entry if necessary
|
||
|
* Called by:
|
||
|
* DeleteCache
|
||
|
--*/
|
||
|
VOID CloseDB(VOID)
|
||
|
{
|
||
|
if (!g_hDB)
|
||
|
goto exitpt;
|
||
|
|
||
|
if (g_bNeedToPack)
|
||
|
_PackDB();
|
||
|
else
|
||
|
_close(g_hDB);
|
||
|
|
||
|
g_hDB = 0;
|
||
|
exitpt:
|
||
|
;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* ReadGroup (Thread dependent)
|
||
|
* Description:
|
||
|
* Read the structure which represents
|
||
|
* a bitmap group with the same IDs
|
||
|
* Arguments:
|
||
|
* nOffset - offset in the DB file
|
||
|
* pGroup - pointer to the result
|
||
|
* Return value:
|
||
|
* TRUE on success
|
||
|
* Called by:
|
||
|
* internaly
|
||
|
--*/
|
||
|
BOOL ReadGroup(FOFFSET nOffset, PGROUPENTRY pGroup)
|
||
|
{
|
||
|
int rv = FALSE;
|
||
|
|
||
|
if (!g_hDB)
|
||
|
goto exitpt;
|
||
|
|
||
|
if (_lseek(g_hDB, nOffset, SEEK_SET) != nOffset)
|
||
|
goto exitpt;
|
||
|
|
||
|
if (_read(g_hDB, pGroup, sizeof(*pGroup)) != sizeof(*pGroup))
|
||
|
goto exitpt;
|
||
|
|
||
|
rv = TRUE;
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* WriteGroup (Thread dep)
|
||
|
* Description:
|
||
|
* Writes GROUPENTRY in the DB file
|
||
|
* Arguments:
|
||
|
* nOffset - where to store
|
||
|
* pGroup - what to store
|
||
|
* Return value:
|
||
|
* TRUE on success
|
||
|
* Called by:
|
||
|
* internaly
|
||
|
--*/
|
||
|
BOOL WriteGroup(FOFFSET nOffset, PGROUPENTRY pGroup)
|
||
|
{
|
||
|
BOOL rv = FALSE;
|
||
|
|
||
|
if (!g_hDB || !pGroup)
|
||
|
goto exitpt;
|
||
|
|
||
|
if (_lseek(g_hDB, nOffset, SEEK_SET) != nOffset)
|
||
|
goto exitpt;
|
||
|
|
||
|
if (_write(g_hDB, pGroup, sizeof(*pGroup)) != sizeof(*pGroup))
|
||
|
goto exitpt;
|
||
|
|
||
|
rv = TRUE;
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* EnumerateGroups (thread dep)
|
||
|
* Description:
|
||
|
* Enumerates all groups from the DB
|
||
|
* Arguments:
|
||
|
* pfnEnumGrpProc - Callback function
|
||
|
* pParam - Parameter passed to the callback
|
||
|
* Called by:
|
||
|
* internaly
|
||
|
--*/
|
||
|
VOID EnumerateGroups(PFNENUMGROUPS pfnEnumGrpProc, PVOID pParam)
|
||
|
{
|
||
|
GROUPENTRY Group;
|
||
|
BOOL bRun;
|
||
|
FOFFSET nOffs = 0;
|
||
|
|
||
|
bRun = ReadGroup(nOffs, &Group);
|
||
|
|
||
|
while(bRun) {
|
||
|
if (!Group.bDeleted)
|
||
|
bRun = pfnEnumGrpProc(nOffs, &Group, pParam) &&
|
||
|
(Group.FOffsNext != 0);
|
||
|
if (bRun)
|
||
|
{
|
||
|
nOffs = Group.FOffsNext;
|
||
|
if (nOffs)
|
||
|
bRun = ReadGroup(nOffs, &Group);
|
||
|
else
|
||
|
bRun = FALSE;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* ReadBitmapHeader (Thread dep)
|
||
|
* Description:
|
||
|
* Read only the header of the bitmap
|
||
|
* Arguments:
|
||
|
* nOffset - where in the file
|
||
|
* pBitmap - returned structure
|
||
|
* Return value:
|
||
|
* TRUE on success
|
||
|
* Called by:
|
||
|
* Internaly
|
||
|
--*/
|
||
|
BOOL ReadBitmapHeader(FOFFSET nOffset, PBMPENTRY pBitmap)
|
||
|
{
|
||
|
BOOL rv = FALSE;
|
||
|
|
||
|
if (!g_hDB || !pBitmap)
|
||
|
goto exitpt;
|
||
|
|
||
|
if (_lseek(g_hDB, nOffset, SEEK_SET) != nOffset)
|
||
|
goto exitpt;
|
||
|
|
||
|
if (_read(g_hDB, pBitmap, sizeof(*pBitmap)) != sizeof(*pBitmap))
|
||
|
goto exitpt;
|
||
|
|
||
|
rv = TRUE;
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* WriteBitmapHeader (Thread dep)
|
||
|
* Description:
|
||
|
* Writes only the bitmap header
|
||
|
* Arguments:
|
||
|
* nOffset - where to store
|
||
|
* pBitmap - what to store
|
||
|
* Return value:
|
||
|
* TRUE on success
|
||
|
* Called by:
|
||
|
* internaly
|
||
|
--*/
|
||
|
BOOL WriteBitmapHeader(FOFFSET nOffset, PBMPENTRY pBitmap)
|
||
|
{
|
||
|
BOOL rv = FALSE;
|
||
|
|
||
|
if (!g_hDB || !pBitmap)
|
||
|
goto exitpt;
|
||
|
|
||
|
if (_lseek(g_hDB, nOffset, SEEK_SET) != nOffset)
|
||
|
goto exitpt;
|
||
|
|
||
|
if (_write(g_hDB, pBitmap, sizeof(*pBitmap)) != sizeof(*pBitmap))
|
||
|
goto exitpt;
|
||
|
|
||
|
rv = TRUE;
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* ReadBitmap (Thread dependent)
|
||
|
* Description:
|
||
|
* Read the whole bitmap and allocates memory for it
|
||
|
* Arguments:
|
||
|
* nOffset - from where
|
||
|
* Return value:
|
||
|
* Pointer to the result, NULL on error
|
||
|
* Called by:
|
||
|
* internaly
|
||
|
--*/
|
||
|
PBMPENTRY ReadBitmap(FOFFSET nOffset)
|
||
|
{
|
||
|
PBMPENTRY rv = NULL;
|
||
|
|
||
|
if (!g_hDB)
|
||
|
goto exitpt;
|
||
|
|
||
|
rv = malloc(sizeof(*rv));
|
||
|
if (rv)
|
||
|
{
|
||
|
rv->pData = NULL;
|
||
|
|
||
|
if (!ReadBitmapHeader(nOffset, rv))
|
||
|
goto exitpt1;
|
||
|
|
||
|
rv->pData = malloc(rv->nDataSize);
|
||
|
if (rv->pData &&
|
||
|
_read(g_hDB, rv->pData, rv->nDataSize) != (long)rv->nDataSize)
|
||
|
{
|
||
|
goto exitpt1;
|
||
|
}
|
||
|
}
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
exitpt1:
|
||
|
if (rv)
|
||
|
{
|
||
|
if (rv->pData)
|
||
|
free(rv->pData);
|
||
|
free(rv);
|
||
|
}
|
||
|
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* FreeBitmap
|
||
|
* Description:
|
||
|
* Frees the resources allocated in ReadBitmap
|
||
|
* Arguments:
|
||
|
* pBmp - The bitmap
|
||
|
* Called by:
|
||
|
* internaly
|
||
|
--*/
|
||
|
VOID FreeBitmap(PBMPENTRY pBmp)
|
||
|
{
|
||
|
if (pBmp)
|
||
|
{
|
||
|
if (pBmp->pData)
|
||
|
free(pBmp->pData);
|
||
|
free(pBmp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* EnumerateBitmaps
|
||
|
* Description:
|
||
|
* Enumaretes all bitmaps within a group
|
||
|
* Arguments:
|
||
|
* nOffset - Location
|
||
|
* pfnEnumProc - Callback
|
||
|
* pParam - callback parameter
|
||
|
* Called by:
|
||
|
* internaly
|
||
|
--*/
|
||
|
VOID EnumerateBitmaps(FOFFSET nOffset, PFNENUMBITMAPS pfnEnumProc, PVOID pParam)
|
||
|
{
|
||
|
PBMPENTRY pBmp;
|
||
|
BOOL bRun = TRUE;
|
||
|
|
||
|
while(bRun && nOffset && (pBmp = ReadBitmap(nOffset)))
|
||
|
{
|
||
|
if (!pBmp->bDeleted)
|
||
|
bRun = pfnEnumProc(nOffset, pBmp, pParam);
|
||
|
|
||
|
nOffset = pBmp->FOffsNext;
|
||
|
FreeBitmap(pBmp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* FindGroup
|
||
|
* Description:
|
||
|
* Retrieves a group by ID
|
||
|
* Arguments:
|
||
|
* szWText - the ID
|
||
|
* Return value:
|
||
|
* Group location, -1 on error
|
||
|
--*/
|
||
|
FOFFSET FindGroup(LPWSTR szWText)
|
||
|
{
|
||
|
GROUPENTRY Group;
|
||
|
BOOL bRun;
|
||
|
FOFFSET rv = 0;
|
||
|
|
||
|
bRun = ReadGroup(0, &Group);
|
||
|
|
||
|
while(bRun)
|
||
|
{
|
||
|
if (!Group.bDeleted && !wcscmp(Group.WText, szWText))
|
||
|
break;
|
||
|
|
||
|
if (!Group.FOffsNext)
|
||
|
bRun = FALSE;
|
||
|
else
|
||
|
{
|
||
|
rv = Group.FOffsNext;
|
||
|
bRun = ReadGroup(Group.FOffsNext, &Group);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (!bRun)
|
||
|
rv = -1;
|
||
|
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* FindBitmap
|
||
|
* Description:
|
||
|
* Finds a bitmap by ID and comment
|
||
|
* Arguments:
|
||
|
* szWText - ID
|
||
|
* szComment - the comment
|
||
|
* Return value:
|
||
|
* The location of the bitmap, -1 on error
|
||
|
--*/
|
||
|
FOFFSET FindBitmap(LPWSTR szWText, char *szComment)
|
||
|
{
|
||
|
FOFFSET nGrpOffs, nBmpOffs;
|
||
|
GROUPENTRY group;
|
||
|
BMPENTRY Bitmap;
|
||
|
FOFFSET rv = -1;
|
||
|
BOOL bRun;
|
||
|
|
||
|
if ((nGrpOffs = FindGroup(szWText)) == -1)
|
||
|
goto exitpt;
|
||
|
|
||
|
if (!ReadGroup(nGrpOffs, &group))
|
||
|
goto exitpt;
|
||
|
|
||
|
nBmpOffs = group.FOffsBmp;
|
||
|
|
||
|
bRun = TRUE;
|
||
|
while(bRun)
|
||
|
{
|
||
|
bRun = ReadBitmapHeader(nBmpOffs, &Bitmap);
|
||
|
|
||
|
if (bRun)
|
||
|
{
|
||
|
if (!Bitmap.bDeleted && !strcmp(Bitmap.szComment, szComment))
|
||
|
break;
|
||
|
|
||
|
nBmpOffs = Bitmap.FOffsNext;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (bRun)
|
||
|
rv = nBmpOffs;
|
||
|
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* CheckSum
|
||
|
* Description:
|
||
|
* Calculates a check sum for block of memory
|
||
|
* Helps for bitmaps comapring
|
||
|
* Arguments:
|
||
|
* pData - pointer to the block
|
||
|
* nLen - block size
|
||
|
* Return value:
|
||
|
* the checksum
|
||
|
* Called by:
|
||
|
* AddBitMap, Glyph2String
|
||
|
--*/
|
||
|
UINT
|
||
|
CheckSum(PVOID pData, UINT nLen)
|
||
|
{
|
||
|
UINT nChkSum = 0;
|
||
|
BYTE *pbBlock = (BYTE *)pData;
|
||
|
|
||
|
for(;nLen; nLen--, pbBlock++)
|
||
|
nChkSum += (*pbBlock);
|
||
|
|
||
|
return nChkSum;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* AddBitmap (Thread dependent)
|
||
|
* Description:
|
||
|
* Adds a BitMap to the DB
|
||
|
* Arguments:
|
||
|
* pBitmap - the bitmap
|
||
|
* szWText - ID
|
||
|
* Return value:
|
||
|
* TRUE on success
|
||
|
* Called by:
|
||
|
* glyphspy.c
|
||
|
--*/
|
||
|
BOOL AddBitMap(PBMPENTRY pBitmap, LPCWSTR szWText)
|
||
|
{
|
||
|
BMPENTRY bmp;
|
||
|
GROUPENTRY group;
|
||
|
INT strl;
|
||
|
BOOL rv = FALSE;
|
||
|
FOFFSET lGroupOffs, lBmpOffs;
|
||
|
GROUPENTRY grpTemp;
|
||
|
BMPENTRY bmpTemp;
|
||
|
FOFFSET nOffs;
|
||
|
PVOID pData;
|
||
|
|
||
|
if (!g_hDB || !pBitmap || !pBitmap->pData || !wcslen(szWText))
|
||
|
goto exitpt;
|
||
|
|
||
|
memset(&group, 0, sizeof(group));
|
||
|
memset(&bmp, 0, sizeof(bmp));
|
||
|
|
||
|
bmp.nDataSize = pBitmap->nDataSize;
|
||
|
bmp.bmiSize = pBitmap->bmiSize;
|
||
|
bmp.bmpSize = pBitmap->bmpSize;
|
||
|
bmp.xSize = pBitmap->xSize;
|
||
|
bmp.ySize = pBitmap->ySize;
|
||
|
bmp.nChkSum = CheckSum(pBitmap->pData, pBitmap->nDataSize);
|
||
|
|
||
|
strcpy(bmp.szComment, pBitmap->szComment);
|
||
|
|
||
|
strl = wcslen(szWText);
|
||
|
if (strl > (sizeof(group.WText) - 1)/sizeof(WCHAR))
|
||
|
strl = (sizeof(group.WText) - 1)/sizeof(WCHAR);
|
||
|
wcsncpy(group.WText, szWText, strl);
|
||
|
group.WText[strl] = 0;
|
||
|
|
||
|
// Create group
|
||
|
if ((lGroupOffs = FindGroup(group.WText)) == -1)
|
||
|
{
|
||
|
// A new group will be created
|
||
|
lGroupOffs = _lseek(g_hDB, 0, SEEK_END);
|
||
|
group.FOffsMe = lGroupOffs;
|
||
|
if (_write(g_hDB, &group, sizeof(group)) != sizeof(group))
|
||
|
{
|
||
|
goto exitpt;
|
||
|
}
|
||
|
// Add this group to the list
|
||
|
if (lGroupOffs)
|
||
|
{
|
||
|
nOffs = 0;
|
||
|
|
||
|
while(ReadGroup(nOffs, &grpTemp) && grpTemp.FOffsNext)
|
||
|
nOffs = grpTemp.FOffsNext;
|
||
|
|
||
|
grpTemp.FOffsNext = lGroupOffs;
|
||
|
if (!WriteGroup(nOffs, &grpTemp))
|
||
|
goto exitpt;
|
||
|
}
|
||
|
} else {
|
||
|
if (ReadGroup(lGroupOffs, &group) == -1)
|
||
|
goto exitpt;
|
||
|
}
|
||
|
|
||
|
// Write the bitmap itself
|
||
|
lBmpOffs = _lseek(g_hDB, 0, SEEK_END);
|
||
|
bmp.FOffsMe = lBmpOffs;
|
||
|
if (_write(g_hDB, &bmp, sizeof(bmp)) != sizeof(bmp))
|
||
|
{
|
||
|
goto exitpt;
|
||
|
}
|
||
|
if (_write(g_hDB, pBitmap->pData, pBitmap->nDataSize) !=
|
||
|
(long)pBitmap->nDataSize)
|
||
|
{
|
||
|
goto exitpt;
|
||
|
}
|
||
|
|
||
|
// Add the bitmap to the list
|
||
|
if (group.FOffsBmp)
|
||
|
{
|
||
|
nOffs = group.FOffsBmp;
|
||
|
|
||
|
// Find end of the list and add
|
||
|
while(ReadBitmapHeader(nOffs, &bmpTemp) && bmpTemp.FOffsNext)
|
||
|
nOffs = bmpTemp.FOffsNext;
|
||
|
|
||
|
bmpTemp.FOffsNext = lBmpOffs;
|
||
|
if (!WriteBitmapHeader(nOffs, &bmpTemp))
|
||
|
goto exitpt;
|
||
|
} else {
|
||
|
// No list add to group pointer
|
||
|
group.FOffsBmp = lBmpOffs;
|
||
|
|
||
|
if (!WriteGroup(lGroupOffs, &group))
|
||
|
goto exitpt;
|
||
|
}
|
||
|
|
||
|
rv = TRUE;
|
||
|
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Ascii version of AddBitMap
|
||
|
--*/
|
||
|
BOOL AddBitMapA(PBMPENTRY pBitmap, LPCSTR szAText)
|
||
|
{
|
||
|
WCHAR szWText[MAX_STRING_LENGTH];
|
||
|
BOOL rv = FALSE;
|
||
|
INT ccAText = strlen(szAText);
|
||
|
|
||
|
if (!strlen(szAText) ||
|
||
|
!MultiByteToWideChar(
|
||
|
CP_ACP,
|
||
|
MB_ERR_INVALID_CHARS,
|
||
|
szAText,
|
||
|
-1,
|
||
|
szWText,
|
||
|
MAX_STRING_LENGTH - 1))
|
||
|
goto exitpt;
|
||
|
|
||
|
rv = AddBitMap(pBitmap, szWText);
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* DeleteBitmapByPointer (Thread dep)
|
||
|
* Description:
|
||
|
* Deletes a bitmap identified by pointer
|
||
|
* Arguments:
|
||
|
* nBmpOffset - the pointer
|
||
|
* Return value:
|
||
|
* TRUE on success
|
||
|
* Called by:
|
||
|
* glyphspy.c
|
||
|
--*/
|
||
|
BOOL DeleteBitmapByPointer(FOFFSET nBmpOffs)
|
||
|
{
|
||
|
BMPENTRY Bitmap;
|
||
|
BOOL rv = FALSE;
|
||
|
|
||
|
if (!g_hDB || !nBmpOffs)
|
||
|
goto exitpt;
|
||
|
|
||
|
if (!ReadBitmapHeader(nBmpOffs, &Bitmap))
|
||
|
goto exitpt;
|
||
|
|
||
|
if (Bitmap.bDeleted)
|
||
|
goto exitpt;
|
||
|
|
||
|
Bitmap.bDeleted = TRUE;
|
||
|
|
||
|
if (!WriteBitmapHeader(nBmpOffs, &Bitmap))
|
||
|
goto exitpt;
|
||
|
|
||
|
g_bNeedToPack = TRUE;
|
||
|
rv = TRUE;
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* DeleteGroupByPointer (Thread dep)
|
||
|
* Description:
|
||
|
* Deletes group with the same ID by pointer
|
||
|
* Arguments:
|
||
|
* nGrpOffs - the pointer
|
||
|
* Return value:
|
||
|
* TRUE on success
|
||
|
* Called by:
|
||
|
* glyphspy.c
|
||
|
--*/
|
||
|
BOOL DeleteGroupByPointer(FOFFSET nGrpOffs)
|
||
|
{
|
||
|
GROUPENTRY Group;
|
||
|
BOOL rv = FALSE;
|
||
|
|
||
|
if (!g_hDB)
|
||
|
goto exitpt;
|
||
|
|
||
|
if (!ReadGroup(nGrpOffs, &Group))
|
||
|
goto exitpt;
|
||
|
|
||
|
if (Group.bDeleted)
|
||
|
goto exitpt;
|
||
|
|
||
|
Group.bDeleted = TRUE;
|
||
|
|
||
|
if (!WriteGroup(nGrpOffs, &Group))
|
||
|
goto exitpt;
|
||
|
|
||
|
g_bNeedToPack = TRUE;
|
||
|
rv = TRUE;
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* DeleteBitmap (Thread dep)
|
||
|
* Description:
|
||
|
* Deletes a bitmap identified by ID and comment
|
||
|
* Arguments:
|
||
|
* szWText - the ID
|
||
|
* szComment - the comment
|
||
|
* Return value:
|
||
|
* TRUE on success
|
||
|
--*/
|
||
|
BOOL DeleteBitmap(LPWSTR szWText, char *szComment)
|
||
|
{
|
||
|
FOFFSET nBmpOffs;
|
||
|
BOOL rv = FALSE;
|
||
|
BMPENTRY Bitmap;
|
||
|
|
||
|
if (!g_hDB)
|
||
|
goto exitpt;
|
||
|
|
||
|
nBmpOffs = FindBitmap(szWText, szComment);
|
||
|
|
||
|
if (nBmpOffs == -1)
|
||
|
goto exitpt;
|
||
|
|
||
|
if (!ReadBitmapHeader(nBmpOffs, &Bitmap))
|
||
|
goto exitpt;
|
||
|
|
||
|
if (Bitmap.bDeleted)
|
||
|
goto exitpt;
|
||
|
|
||
|
Bitmap.bDeleted = TRUE;
|
||
|
|
||
|
if (!WriteBitmapHeader(nBmpOffs, &Bitmap))
|
||
|
goto exitpt;
|
||
|
|
||
|
g_bNeedToPack = TRUE;
|
||
|
rv = TRUE;
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* _PackDB (Thread dep)
|
||
|
* Description:
|
||
|
* Copies the all database in new file removing
|
||
|
* the deleted entrys
|
||
|
* If it fails leaves the old file
|
||
|
* Called by:
|
||
|
* CloseDB
|
||
|
--*/
|
||
|
void _PackDB(void)
|
||
|
{
|
||
|
GROUPENTRY group;
|
||
|
FOFFSET lGrpOffs = 0;
|
||
|
FOFFSET lBmpOffs;
|
||
|
|
||
|
if (!g_bNeedToPack)
|
||
|
goto exitpt;
|
||
|
|
||
|
g_hTempDB = _open(TEMPDB_NAME,
|
||
|
_O_RDWR|_O_TRUNC|_O_CREAT|_O_BINARY,
|
||
|
_S_IREAD|_S_IWRITE);
|
||
|
if (g_hTempDB == -1)
|
||
|
goto exitpt;
|
||
|
|
||
|
do {
|
||
|
if (!ReadGroup(lGrpOffs, &group))
|
||
|
goto exitpt;
|
||
|
|
||
|
if (!group.bDeleted)
|
||
|
{
|
||
|
lBmpOffs = group.FOffsBmp;
|
||
|
|
||
|
while(lBmpOffs)
|
||
|
{
|
||
|
BMPENTRY Bitmap;
|
||
|
|
||
|
if (!ReadBitmapHeader(lBmpOffs, &Bitmap))
|
||
|
goto exitpt;
|
||
|
|
||
|
if (!Bitmap.bDeleted)
|
||
|
{
|
||
|
PBMPENTRY pBmp = ReadBitmap(lBmpOffs);
|
||
|
|
||
|
if (pBmp)
|
||
|
{
|
||
|
int hSwap;
|
||
|
|
||
|
hSwap = g_hDB;
|
||
|
g_hDB = g_hTempDB;
|
||
|
g_hTempDB = hSwap;
|
||
|
|
||
|
AddBitMap(pBmp,
|
||
|
group.WText);
|
||
|
|
||
|
hSwap = g_hDB;
|
||
|
g_hDB = g_hTempDB;
|
||
|
g_hTempDB = hSwap;
|
||
|
|
||
|
FreeBitmap(pBmp);
|
||
|
}
|
||
|
}
|
||
|
lBmpOffs = Bitmap.FOffsNext;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
lGrpOffs = group.FOffsNext;
|
||
|
} while (lGrpOffs);
|
||
|
|
||
|
_close(g_hTempDB);
|
||
|
_close(g_hDB);
|
||
|
remove(DB_NAME);
|
||
|
rename(TEMPDB_NAME, DB_NAME);
|
||
|
|
||
|
exitpt:
|
||
|
;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* _CollectGroups (Thread dep)
|
||
|
* Description:
|
||
|
* Callback function wich collects all groups
|
||
|
* from the database in linked list
|
||
|
* Arguments:
|
||
|
* nOffs - pointer to group record in the database
|
||
|
* pGroup - ghe group
|
||
|
* ppList - the list
|
||
|
* Return value:
|
||
|
* TRUE on success
|
||
|
* Called by:
|
||
|
* GetGroupList thru EnumerateGroups
|
||
|
--*/
|
||
|
BOOL _cdecl _CollectGroups(FOFFSET nOffs,
|
||
|
PGROUPENTRY pGroup,
|
||
|
PGROUPENTRY *ppList)
|
||
|
{
|
||
|
BOOL rv = FALSE;
|
||
|
PGROUPENTRY pNewGrp, pIter, pPrev;
|
||
|
|
||
|
if (!pGroup)
|
||
|
goto exitpt;
|
||
|
|
||
|
pNewGrp = malloc(sizeof(*pNewGrp));
|
||
|
|
||
|
if (!pNewGrp)
|
||
|
goto exitpt;
|
||
|
|
||
|
memcpy(pNewGrp, pGroup, sizeof(*pNewGrp));
|
||
|
|
||
|
// Add to the end of the queue
|
||
|
pNewGrp->pNext = NULL;
|
||
|
pPrev = NULL;
|
||
|
pIter = *ppList;
|
||
|
while(pIter)
|
||
|
{
|
||
|
pPrev = pIter;
|
||
|
pIter = pIter->pNext;
|
||
|
}
|
||
|
if (pPrev)
|
||
|
pPrev->pNext = pNewGrp;
|
||
|
else
|
||
|
(*ppList) = pNewGrp;
|
||
|
|
||
|
rv = TRUE;
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* GetGroupList
|
||
|
* Description:
|
||
|
* Gets all groups from the database
|
||
|
* Return value:
|
||
|
* linked list
|
||
|
* Called by:
|
||
|
* InitCache, glyphspy.c
|
||
|
--*/
|
||
|
PGROUPENTRY GetGroupList(VOID)
|
||
|
{
|
||
|
PGROUPENTRY pList = NULL;
|
||
|
|
||
|
EnumerateGroups(_CollectGroups, &pList);
|
||
|
|
||
|
return pList;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* FreeGroupList
|
||
|
* Description:
|
||
|
* Frees the list allocated in GetGroupList
|
||
|
* Arguments:
|
||
|
* pList - the list
|
||
|
* Called by:
|
||
|
* DeleteCache, glyphspy.c
|
||
|
--*/
|
||
|
VOID FreeGroupList(PGROUPENTRY pList)
|
||
|
{
|
||
|
PGROUPENTRY pTmp, pIter = pList;
|
||
|
|
||
|
while(pIter)
|
||
|
{
|
||
|
pTmp = pIter;
|
||
|
pIter = pIter->pNext;
|
||
|
free(pTmp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* _CollectBitmaps (thread dep)
|
||
|
* Description:
|
||
|
* collects bitmaps in linked list
|
||
|
* Arguments:
|
||
|
* nOffs - pointer in the file
|
||
|
* pBitmap - the bitmap
|
||
|
* ppList - the list
|
||
|
* Return value:
|
||
|
* TRUE on success
|
||
|
* Called by:
|
||
|
* GetBitmapList thru EnumerateBitmaps
|
||
|
--*/
|
||
|
BOOL _cdecl _CollectBitmaps(FOFFSET nOffs,PBMPENTRY pBitmap, PBMPENTRY *ppList)
|
||
|
{
|
||
|
BOOL rv = FALSE;
|
||
|
PBMPENTRY pNewBmp, pIter, pPrev;
|
||
|
|
||
|
if (!pBitmap)
|
||
|
goto exitpt;
|
||
|
|
||
|
pNewBmp = malloc(sizeof(*pNewBmp));
|
||
|
if (!pNewBmp)
|
||
|
goto exitpt;
|
||
|
|
||
|
memcpy(pNewBmp, pBitmap, sizeof(*pNewBmp));
|
||
|
|
||
|
if (pNewBmp->nDataSize)
|
||
|
{
|
||
|
pNewBmp->pData = malloc(pNewBmp->nDataSize);
|
||
|
if (!pNewBmp->pData)
|
||
|
goto exitpt1;
|
||
|
|
||
|
memcpy(pNewBmp->pData, pBitmap->pData, pNewBmp->nDataSize);
|
||
|
} else
|
||
|
pNewBmp->pData = NULL;
|
||
|
|
||
|
// Add to the end of the queue
|
||
|
pNewBmp->pNext = NULL;
|
||
|
pPrev = NULL;
|
||
|
pIter = *ppList;
|
||
|
while(pIter)
|
||
|
{
|
||
|
pPrev = pIter;
|
||
|
pIter = pIter->pNext;
|
||
|
}
|
||
|
if (pPrev)
|
||
|
pPrev->pNext = pNewBmp;
|
||
|
else
|
||
|
(*ppList) = pNewBmp;
|
||
|
|
||
|
rv = TRUE;
|
||
|
exitpt:
|
||
|
return rv;
|
||
|
|
||
|
exitpt1:
|
||
|
free(pNewBmp);
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* GetBitmapList (thread dep)
|
||
|
* Description:
|
||
|
* Gets all bitmaps within a group
|
||
|
* Return value:
|
||
|
* linked list
|
||
|
* Called by:
|
||
|
* Glyph2String, BitmapCacheLookup, glyphspy.c
|
||
|
--*/
|
||
|
PBMPENTRY GetBitmapList(HDC hDC, FOFFSET nOffs)
|
||
|
{
|
||
|
PBMPENTRY pList = NULL;
|
||
|
PBMPENTRY pIter;
|
||
|
|
||
|
EnumerateBitmaps(nOffs, _CollectBitmaps, &pList);
|
||
|
|
||
|
pIter = pList;
|
||
|
while(pIter)
|
||
|
{
|
||
|
// Create bitmaps if needed
|
||
|
if (hDC)
|
||
|
{
|
||
|
if (!pIter->bmiSize)
|
||
|
pIter->hBitmap =
|
||
|
CreateBitmap(pIter->xSize,
|
||
|
pIter->ySize,
|
||
|
1, 1,
|
||
|
pIter->pData);
|
||
|
else {
|
||
|
pIter->hBitmap =
|
||
|
CreateDIBitmap(hDC,
|
||
|
(BITMAPINFOHEADER *)
|
||
|
pIter->pData,
|
||
|
CBM_INIT,
|
||
|
((BYTE *)(pIter->pData)) + pIter->bmiSize,
|
||
|
(BITMAPINFO *)
|
||
|
pIter->pData,
|
||
|
DIB_PAL_COLORS);
|
||
|
|
||
|
DeleteDC(hDC);
|
||
|
}
|
||
|
} else
|
||
|
pIter->hBitmap = NULL;
|
||
|
|
||
|
pIter = pIter->pNext;
|
||
|
}
|
||
|
|
||
|
return pList;
|
||
|
}
|
||
|
|
||
|
/*++
|
||
|
* Function:
|
||
|
* FreeBitmapList
|
||
|
* Description:
|
||
|
* Deletes resources allocated by GetBitmapList
|
||
|
* Arguments:
|
||
|
* pList - the list
|
||
|
* Called by:
|
||
|
* DeleteCache, glyphspy.c
|
||
|
--*/
|
||
|
VOID FreeBitmapList(PBMPENTRY pList)
|
||
|
{
|
||
|
PBMPENTRY pTmp, pIter = pList;
|
||
|
|
||
|
while(pIter)
|
||
|
{
|
||
|
pTmp = pIter;
|
||
|
pIter = pIter->pNext;
|
||
|
|
||
|
if (pTmp->hBitmap)
|
||
|
DeleteObject(pTmp->hBitmap);
|
||
|
|
||
|
if ( pTmp->pData )
|
||
|
free( pTmp->pData );
|
||
|
|
||
|
free(pTmp);
|
||
|
}
|
||
|
}
|