2020-09-30 17:12:29 +02:00

2567 lines
95 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/****************************************************************************
CACHE.C
$Log: S:\products\msprods\oiwh\display\cache.c_v $
*
* Rev 1.104 24 Apr 1996 14:38:34 BEG06016
* Added horizontal differencing.
*
* Rev 1.104 24 Apr 1996 14:27:40 BEG06016
* Added horizontal differencing.
*
* Rev 1.103 19 Apr 1996 09:02:26 BEG06016
* Added CheckError2 for error handling.
*
* Rev 1.102 18 Apr 1996 13:47:04 BEG06016
* Added CheckError2 for error handling.
*
* Rev 1.101 15 Apr 1996 15:54:00 BEG06016
* Fixed reading of 16 bit annotations.
*
* Rev 1.100 15 Apr 1996 09:50:12 BEG06016
* Fixed reading of 16 bit annotations.
*
* Rev 1.99 12 Apr 1996 09:38:56 BEG06016
* Ficed the initialization of some variables.
*
* Rev 1.98 12 Apr 1996 08:47:18 BEG06016
* Ficed the initialization of some variables.
*
* Rev 1.97 12 Apr 1996 08:18:14 BEG06016
* Ficed the initialization of some variables.
*
* Rev 1.96 11 Apr 1996 15:12:52 BEG06016
* Optimized named block access some.
*
* Rev 1.95 27 Feb 1996 11:08:42 BEG06016
* Misc fixes.
*
* Rev 1.94 10 Jan 1996 16:09:26 RC
* Fixed dib size calculation in ReadAnnotations
*
* Rev 1.93 10 Jan 1996 15:18:04 BLJ
* Fixed some error handling.
*
* Rev 1.92 05 Jan 1996 14:07:52 RC
* Propagated previous change
*
* Rev 1.91 05 Jan 1996 11:03:50 BLJ
* Fixed some error handling.
*
* Rev 1.90 04 Jan 1996 17:43:40 RC
* Changed cache line upper bound from -1 to 0xfffffff to account for uints
* changing to ints
*
* Rev 1.89 02 Jan 1996 09:58:14 BLJ
* Changed alot of UINTs to ints.
* Changed IMG structure to include the image data.
* Changed lp prefix to p.
****************************************************************************/
#include "privdisp.h"
#define CACHE_PAGE 0
/****************************************************************************
FUNCTION: IMGCacheFile
PURPOSE: Send cacheing request to BACKCAP
INPUT: pCacheFileParms - The cache parameters given by the caller.
****************************************************************************/
int WINAPI IMGCacheFile(LP_CACHE_FILE_PARMS pCacheFileParms){
int nStatus;
PANO_IMAGE pAnoImage;
Start();
CheckError2(IntSeqfileInit())
// Prevent Multiprocessing in this code.
CheckError2(LockMutex())
if (!pCacheFileParms){
nStatus = Error(DISPLAY_NULLPOINTERINVALID);
goto Exit;
}
if (!pCacheFileParms->file_name){
nStatus = Error(DISPLAY_INVALIDFILENAME);
goto Exit;
}
CheckError2(CacheFileAno(pCacheFileParms->hWnd, pCacheFileParms->file_name,
pCacheFileParms->wPage_number, &pAnoImage))
Exit:
// Allow Multiprocessing again.
UnlockMutex();
End();
return(nStatus);
}
//
/*****************************************************************************
FUNCTION: IMGCacheDiscard
PURPOSE: Discard files from the cache
INPUT: hWnd - callers window handle
option
CACHE_DISCARD_SYSOLD - discard oldest image regardless of window
CACHE_DISCARD_WINOLD - discard oldest image belonging to this window
CACHE_DISCARD_WINALL - discard all images belonging to this window
*****************************************************************************/
int WINAPI IMGCacheDiscard(HWND hWnd, UINT option){
int nStatus;
int nLoop;
PANO_IMAGE pAnoImage;
Start();
CheckError2(IntSeqfileInit())
// Prevent Multiprocessing in this code.
CheckError2(LockMutex())
switch (option){
case CACHE_DISCARD_WINOLD:
case CACHE_DISCARD_SYSOLD:
// Find the oldest file in the cache.
pAnoImage = 0;
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (!pSubSegMemory->ppCachedImage[nLoop]){
break;
}
if (!pSubSegMemory->ppCachedAnoImage[nLoop]->nLockCount
&& pSubSegMemory->ppCachedAnoImage[nLoop]->nAge > pAnoImage->nAge){
pAnoImage = pSubSegMemory->ppCachedAnoImage[nLoop];
}
}
// Delete the oldest file in the cache.
if (pAnoImage){
CheckError2(CacheClearAno(&pAnoImage))
}
break;
case CACHE_DISCARD_WINALL:
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (pSubSegMemory->ppCachedAnoImage[nLoop]){
pAnoImage = pSubSegMemory->ppCachedAnoImage[nLoop];
if (!pAnoImage->nLockCount){
CheckError2(CacheClearAno(&pAnoImage))
}
}
}
break;
default:
nStatus = Error(DISPLAY_INVALID_OPTIONS);
}
Exit:
// Allow Multiprocessing again.
UnlockMutex();
End();
return(nStatus);
}
//
/****************************************************************************
Function: IMGCacheDiscardFileCgbw
Description: Discard a given file from the cache for a given window.
Although this API is not documented, it is public.
Inputs: hWnd - handle of window for which the file is cached.
pFileName - file name string.
nPage - The page number to cache.
****************************************************************************/
int WINAPI IMGCacheDiscardFileCgbw(HWND hWnd, PSTR pFileName, int nPage){
int nStatus;
int nLoop;
BOOL bFileFound = FALSE;
PANO_IMAGE pAnoImage;
PIMAGE pImage;
Start();
CheckError2(IntSeqfileInit())
// Prevent Multiprocessing in this code.
CheckError2(LockMutex())
if (!pFileName){
nStatus = Error(DISPLAY_INVALIDFILENAME);
goto Exit;
}
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (pAnoImage = pSubSegMemory->ppCachedAnoImage[nLoop]){
if (pImage = pAnoImage->pBaseImage){
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)){
if (nPage == -1 || pImage->nFilePageNum == nPage){
bFileFound = TRUE;
if (!pAnoImage->nLockCount){
CheckError2(CacheClearAno(&pAnoImage))
}else{
nStatus = Error2(DISPLAY_CACHEFILEINUSE);
goto Exit;
}
if (nPage < -1){
break;
}
}
}
}
}
}
}
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (pImage = pSubSegMemory->ppCachedImage[nLoop]){
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)){
if (nPage == -1 || pImage->nFilePageNum == nPage){
bFileFound = TRUE;
if (!pImage->nLockCount){
CheckError2(CacheClear(&pImage))
}else{
nStatus = Error2(DISPLAY_CACHEFILEINUSE);
goto Exit;
}
if (nPage < -1){
break;
}
}
}
}
}
}
if (!bFileFound){
nStatus = Error2(DISPLAY_CACHENOTFOUND);
goto Exit;
}
Exit:
// Allow Multiprocessing again.
UnlockMutex();
End();
return(nStatus);
}
//
/*****************************************************************************
FUNCTION: IMGCacheFilesInCache
PURPOSE: Returns a list of files that are in the cache.
INPUTS: hWnd - This is the window handle whose cache entries are
being checked.
pFiles - The caller allocated array where the information will
be stored.
pNumberOfFiles
- At entry this is the maximum number of entries
the array can hold.
- At return this is the exact number of entries being
returned.
*****************************************************************************/
int WINAPI IMGCacheFilesInCache(HWND hWnd, LPCACHE_FILES_IN_CACHE_STRUCT pFiles,
UINT *puNumberOfFiles){
int nStatus = 0;
int nLoop;
int nNumberOfFiles = 0;
PANO_IMAGE pAnoImage;
PIMAGE pImage;
Start();
CheckError2(IntSeqfileInit())
// Prevent Multiprocessing in this code.
CheckError2(LockMutex())
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (pAnoImage = pSubSegMemory->ppCachedAnoImage[nLoop]){
if (pImage = pAnoImage->pBaseImage){
if (pImage->szFileName){
if (nNumberOfFiles >= (int) *puNumberOfFiles){
break;
}
strcpy(pFiles->File[nLoop].szFilename, pImage->szFileName);
pFiles->File[nLoop].uPageNumber = pImage->nFilePageNum;
nNumberOfFiles++;
}
}
}
}
*puNumberOfFiles = nNumberOfFiles;
Exit:
// Allow Multiprocessing again.
UnlockMutex();
End();
return(nStatus);
}
//
/****************************************************************************
FUNCTION: ValidateCache
PURPOSE: Makes sure all data has been read from cache.
INPUT: hWnd - Handle to window where image is to be displayed.
HANDLE - Handle to image structure.
*****************************************************************************/
int WINAPI ValidateCache(HWND hWnd, PANO_IMAGE pAnoImage){
int nStatus;
CheckError2(ValidateCacheLines(hWnd, pAnoImage, 0xffffff))
Exit:
return(nStatus);
}
//
/****************************************************************************
FUNCTION: ValidateCacheLines
PURPOSE: Makes sure the specified lines of data have been read from cache.
INPUT: hWnd - Handle to window where image is to be displayed.
HANDLE - Handle to image structure.
*****************************************************************************/
int WINAPI ValidateCacheLines(HWND hWnd, PANO_IMAGE pAnoImage, int nValidationLine){
int nStatus = 0;
PIMAGE pBaseImage;
PIMAGE pFormImage;
PIMG pBasePlusFormImg = 0;
PBYTE pDestLine;
PBYTE pSourceLine;
int nWidthInBytes;
RECT rSrceImageRect;
RECT rDestMergeRect;
LRECT lrSourceRect;
LRECT lrDestRect;
int nAdjHScale;
int nAdjVScale;
int nMarkIndex;
PMARK pMark=0;
PAN_NEW_ROTATE_STRUCT pAnRotation = 0;
PSTR pFileName;
char FileName[256];
PAN_NAME_STRUCT pAnName;
int nEarlyBPFValidLines; // keeps track of how many base image lines
// are valid coming into validate cache
pBaseImage = pAnoImage->pBaseImage;
if (!pBaseImage->pImg){
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
goto Exit;
}
if (!pBaseImage->bFileRotationDone){
nValidationLine = 0xffffff;
}
nValidationLine = min(pBaseImage->nHeight, nValidationLine);
nEarlyBPFValidLines = pAnoImage->nBPFValidLines;
if (!pAnoImage->bAnnotationsAlreadyRead && pBaseImage->bAnnotationsPresent){
CheckError2(ReadAnnotationsFromFile(hWnd, pAnoImage,
&pAnoImage->Annotations.ppMarks,
&pAnoImage->Annotations.nMarks))
}
// Read the base image.
if (pBaseImage->bUsingCache && !pBaseImage->bCacheValid
&& pBaseImage->nLinesRead < nValidationLine){
CheckError2(CacheRead(hWnd, pBaseImage, nValidationLine - pBaseImage->nLinesRead))
}
// check to see if there is a form mark
for (nMarkIndex = 0; nMarkIndex < pAnoImage->Annotations.nMarks; nMarkIndex++){
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
if ((int) pMark->Attributes.uType == OIOP_AN_FORM){
break;
}
}
// if the form has been thrown away or doesnt exist, get it
if (pMark && ((int) pMark->Attributes.uType == OIOP_AN_FORM) && (!pAnoImage->pFormImage)){
pAnName = 0;
CheckError2(GetAMarkNamedBlock(pMark, szOiFilNam, (PPSTR) &pAnName))
if (pAnName == 0){
nStatus = Error (DISPLAY_DATACORRUPTED);
goto Exit;
}
pFileName = FileName;
GetFileName (pFileName, (PSTR) pAnName->name);
pAnRotation = 0;
CheckError2( GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation))
if (pAnRotation == 0){
nStatus = Error (DISPLAY_DATACORRUPTED);
goto Exit;
}
CheckError2( CacheFile(hWnd, pFileName, 1, &pAnoImage->pFormImage))
pAnRotation->nHRes = pBaseImage->nHRes;
pAnRotation->nVRes = pBaseImage->nVRes;
pAnoImage->pFormImage->nLockCount++;
pAnoImage->pFormMark = pMark;
pAnoImage->nBPFValidLines = 0;
pAnoImage->pBasePlusFormImg = 0;
pAnoImage->pDisplayFormImage = 0;
}
if ((!(pFormImage = pAnoImage->pFormImage)) || (pMark && !pMark->Attributes.bVisible)){
pAnoImage->pBasePlusFormImg = pBaseImage->pImg;
pAnoImage->nBPFValidLines = pBaseImage->nLinesRead;
}else{
// Read the form image.
if (pFormImage->bUsingCache && !pFormImage->bCacheValid
&& pFormImage->nLinesRead < nValidationLine){
CheckError2( CacheRead(hWnd, pFormImage, pFormImage->nHeight))
}
// Generate the BasePlusForm image.
pMark = pAnoImage->Annotations.ppMarks[0];
if (!pAnoImage->nBPFValidLines){
CheckError2( AllocateMemory(sizeof(IMG), (PPSTR) &pAnoImage->pBasePlusFormImg, ZERO_INIT))
CheckError2( CreateAnyImgBuf(&pAnoImage->pBasePlusFormImg, pBaseImage->nWidth,
pBaseImage->nHeight, pBaseImage->pImg->nType))
}
pBasePlusFormImg = pAnoImage->pBasePlusFormImg;
// Copy the base image to BasePlusForm.
switch (pBaseImage->pImg->nType){
case ITYPE_BI_LEVEL:
nWidthInBytes = (pBaseImage->nWidth + 7) / 8;
break;
case ITYPE_GRAY4:
case ITYPE_PAL4:
nWidthInBytes = (pBaseImage->nWidth + 1) / 2;
break;
case ITYPE_GRAY7:
case ITYPE_GRAY8:
case ITYPE_COMPAL8:
case ITYPE_CUSPAL8:
nWidthInBytes = pBaseImage->nWidth;
break;
case ITYPE_RGB24:
case ITYPE_BGR24:
nWidthInBytes = pBaseImage->nWidth * 3;
break;
default:
break;
}
if (pAnoImage->nBPFValidLines < nValidationLine){
pSourceLine = &pBaseImage->pImg->bImageData[0]
+ (pAnoImage->nBPFValidLines * pBaseImage->pImg->nBytesPerLine);
pDestLine = &pBasePlusFormImg->bImageData[0]
+ (pAnoImage->nBPFValidLines * pBasePlusFormImg->nBytesPerLine);
memcpy(pDestLine, pSourceLine,
nWidthInBytes * (nValidationLine - pAnoImage->nBPFValidLines));
pAnoImage->nBPFValidLines = nValidationLine;
}
pAnRotation = 0;
CheckError2(GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation))
if (pAnRotation == 0){
nStatus = Error (DISPLAY_DATACORRUPTED);
goto Exit;
}
// adjust the resolution of the form image to the base image
// Only do this if any scaling is necessary
if (!pAnoImage->pDisplayFormImage){
CheckError2( AllocateMemory(sizeof(IMAGE),
(PPSTR) &pAnoImage->pDisplayFormImage, ZERO_INIT))
SetLRect (lrSourceRect, 0, 0, pAnoImage->pFormImage->nWidth,
pAnoImage->pFormImage->nHeight);
nAdjHScale = ((pAnRotation->scale * pBaseImage->nHRes)/ pFormImage->nHRes);
nAdjVScale = ((pAnRotation->scale * pBaseImage->nVRes)/ pFormImage->nVRes);
CopyRect (lrDestRect, lrSourceRect);
ConvertRect2(&lrDestRect, CONV_FULLSIZE_TO_SCALED, nAdjHScale, nAdjVScale, 0, 0);
CheckError2( CreateAnyImgBuf(&pAnoImage->pDisplayFormImage->pImg,
(lrDestRect.right - lrDestRect.left),
(lrDestRect.bottom - lrDestRect.top), ITYPE_BI_LEVEL))
CheckError2( ScaleBits(pAnoImage->pFormImage->pImg,
pAnoImage->pDisplayFormImage->pImg, OI_SCALE_ALG_BW_KEEP_BLACK,
nAdjHScale, nAdjVScale, lrSourceRect, lrDestRect, NULL))
pAnoImage->pDisplayFormImage->nHeight = pAnoImage->pDisplayFormImage->pImg->nHeight;
pAnoImage->pDisplayFormImage->nWidth = pAnoImage->pDisplayFormImage->pImg->nWidth;
CheckError2( RotateImage (pMark, pAnoImage->pDisplayFormImage,
pAnRotation->rotation))
}
// Merge form image into BasePlusForm.
CopyRectLtoR(rSrceImageRect, pAnoImage->pFormMark->Attributes.lrBounds);
SetRect(&rDestMergeRect,
max(0, rSrceImageRect.left),
max(0, rSrceImageRect.top),
min((int) pBaseImage->nWidth, rSrceImageRect.right),
min((int)min(nValidationLine, pBaseImage->nHeight),
rSrceImageRect.bottom));
//do the merge only if needed
if ((rDestMergeRect.left < rDestMergeRect.right
&& rDestMergeRect.top < rDestMergeRect.bottom) &&
(rSrceImageRect.top <= (int)nValidationLine) &&
(rSrceImageRect.bottom >= (int)nEarlyBPFValidLines)){
CheckError2( MergeImgs(pAnoImage->pDisplayFormImage->pImg, pBasePlusFormImg,
rDestMergeRect, rSrceImageRect))
}
}
Exit:
return(nStatus);
}
//
/****************************************************************************
FUNCTION: MakeCacheAnoImage
PURPOSE: Add an Ano Image to the cache.
****************************************************************************/
int WINAPI MakeCacheAnoImage(PANO_IMAGE *ppAnoImage){
int nStatus = 0;
PANO_IMAGE pAnoImage = 0;
int nLoop;
// If there is no room for the new entry then increase the number of file entries possible.
if (!pSubSegMemory->nMaxAnoCachedEntries || pSubSegMemory->ppCachedAnoImage[pSubSegMemory->nMaxAnoCachedEntries - 1]){
CheckError2( ReAllocateMemory(sizeof(PANO_IMAGE) * (pSubSegMemory->nMaxAnoCachedEntries + 1),
(PPSTR) &pSubSegMemory->ppCachedAnoImage, ZERO_INIT))
pSubSegMemory->nMaxAnoCachedEntries++;
}
CheckError2( AllocateMemory(sizeof(ANO_IMAGE), (PPSTR) &pAnoImage, ZERO_INIT))
// Allocate the default mark.
CheckError2( AllocateMemory(sizeof(MARK), (PPSTR) &pAnoImage->Annotations.pDefMark, ZERO_INIT))
// Save it in the cache.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (!pSubSegMemory->ppCachedAnoImage[nLoop]){
pSubSegMemory->ppCachedAnoImage[nLoop] = pAnoImage;
break;
}
}
Exit:
if (nStatus && pAnoImage){
if (pAnoImage->Annotations.pDefMark){
FreeMemory((PPSTR) &pAnoImage->Annotations.pDefMark);
}
FreeMemory((PPSTR) &pAnoImage);
}
*ppAnoImage = pAnoImage;
return(nStatus);
}
//
/****************************************************************************
FUNCTION: CacheFileAno
PURPOSE: Add a file to the cache.
****************************************************************************/
int WINAPI CacheFileAno(HWND hWnd, PSTR pFileName, int nPage, PANO_IMAGE *ppAnoImage){
int nStatus = 0;
PIMAGE pImage;
PANO_IMAGE pAnoImage = 0;
int nLoop;
//int nOldestIndex;
// Age all files in the cache.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (!pSubSegMemory->ppCachedAnoImage[nLoop]){
break;
}
pSubSegMemory->ppCachedAnoImage[nLoop]->nAge = min(32000, pSubSegMemory->ppCachedAnoImage[nLoop]->nAge +1);
}
// If this file is already in the cache, then return the pointer to it.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (!(pAnoImage = pSubSegMemory->ppCachedAnoImage[nLoop])){
break;
}
if (pImage = pAnoImage->pBaseImage){
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)
&& pImage->nFilePageNum == nPage){
goto Exit;
}
}
}
}
CheckError2( CacheFile(hWnd, pFileName, nPage, &pImage))
CheckError2( MakeCacheAnoImage(&pAnoImage))
pImage->nLockCount++;
pAnoImage->pBaseImage = pImage;
Exit:
*ppAnoImage = pAnoImage;
return(nStatus);
}
//
/****************************************************************************
FUNCTION: MakeCacheImage
PURPOSE: Add an Image to the cache.
****************************************************************************/
int WINAPI MakeCacheImage(HWND hWnd, FIO_INFORMATION FioInfo, FIO_INFO_CGBW FioInfoCgbw,
PIMAGE *ppImage){
int nStatus = 0;
PIMAGE pImage = 0;
int nLoop;
int nOldestIndex;
int nOldestAge;
long lSizeOfThisImage;
PSTR pTemp;
int nSize;
// Free np room in the cache.
lSizeOfThisImage = ((( FioInfo.vertical_pixels * FioInfo.bits_per_sample
* FioInfo.samples_per_pix) + 7) / 8) * FioInfo.horizontal_pixels;
lCurrentCacheSize += lSizeOfThisImage;
if (!lMaxCacheSize){
LoadString((HANDLE) hInst, ID_MAX_CACHE_SIZE, Buff2, 80);
nSize = 20;
if (nStatus = OiGetStringfromReg(szIniSectionOi, Buff2, "6000000", Buff1, &nSize)){
Error(nStatus);
}
lMaxCacheSize = 0;
pTemp = Buff1;
while(pTemp[0]){
lMaxCacheSize *= 10;
lMaxCacheSize += pTemp[0] - '0';
pTemp++;
}
if (!lMaxCacheSize){
lMaxCacheSize = 1; // Prevent this code from being executed again.
}
}
while(lCurrentCacheSize >= lMaxCacheSize){
// Delete the oldest ano file from the cache.
if (pSubSegMemory->ppCachedImage){
nOldestIndex = 0;
nOldestAge = 0;
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (!pSubSegMemory->ppCachedImage[nLoop]){
break;
}
if (!pSubSegMemory->ppCachedImage[nLoop]->nLockCount &&
pSubSegMemory->ppCachedImage[nLoop]->nAge > nOldestAge){
nOldestIndex = nLoop;
nOldestAge = pSubSegMemory->ppCachedImage[nLoop]->nAge;
}
}
if (pSubSegMemory->ppCachedImage[nOldestIndex]){
if (!pSubSegMemory->ppCachedImage[nOldestIndex]->nLockCount){
CacheClear(&pSubSegMemory->ppCachedImage[nOldestIndex]);
continue;
}
}
}
// Delete the oldest ano file from the cache.
if (pSubSegMemory->ppCachedAnoImage){
nOldestIndex = 0;
nOldestAge = 0;
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (!pSubSegMemory->ppCachedAnoImage[nLoop]){
break;
}
if (!pSubSegMemory->ppCachedAnoImage[nLoop]->nLockCount &&
pSubSegMemory->ppCachedAnoImage[nLoop]->nAge > nOldestAge){
nOldestIndex = nLoop;
nOldestAge = pSubSegMemory->ppCachedAnoImage[nLoop]->nAge;
}
}
if (pSubSegMemory->ppCachedAnoImage[nOldestIndex]){
if (!pSubSegMemory->ppCachedAnoImage[nOldestIndex]->nLockCount){
CacheClearAno(&pSubSegMemory->ppCachedAnoImage[nOldestIndex]);
continue;
}
}
}
// No more to discard.
break;
}
// If there is no room for the new entry then increase the number of file entries possible.
if (!pSubSegMemory->nMaxCachedEntries || pSubSegMemory->ppCachedImage[pSubSegMemory->nMaxCachedEntries - 1]){
CheckError2( ReAllocateMemory(sizeof(PIMAGE) * (pSubSegMemory->nMaxCachedEntries + 1),
(PPSTR) &pSubSegMemory->ppCachedImage, ZERO_INIT))
pSubSegMemory->nMaxCachedEntries++;
}
CheckError2(OpenViaHandleCgbw(&pImage, 0, &FioInfo, &FioInfoCgbw))
// Save it in the cache.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (!pSubSegMemory->ppCachedImage[nLoop]){
pSubSegMemory->ppCachedImage[nLoop] = pImage;
break;
}
}
if (FioInfoCgbw.fio_flags & FIO_ANNO_DATA){
pImage->bAnnotationsPresent = TRUE;
}
Exit:
*ppImage = pImage;
return(nStatus);
}
//
/****************************************************************************
FUNCTION: CacheFile
PURPOSE: Add a file to the cache.
****************************************************************************/
int WINAPI CacheFile(HWND hWnd, PSTR pFileName, int nPage, PIMAGE *ppImage){
int nStatus = 0;
PIMAGE pImage = 0;
int nLoop;
FIO_INFORMATION FioInfo;
FIO_INFO_CGBW FioInfoCgbw;
RGBQUAD PaletteTable[256];
BOOL bCloseFileOnError = FALSE;
HANDLE hFileProp;
FIO_INFO_MISC FioInfoMisc;
PIMG pImg = 0;
int nTemp;
// Age all files in the cache.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (!pSubSegMemory->ppCachedImage[nLoop]){
break;
}
pSubSegMemory->ppCachedImage[nLoop]->nAge = min(32000, pSubSegMemory->ppCachedImage[nLoop]->nAge +1);
}
// If this file is already in the cache, then return the pointer to it.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (!pSubSegMemory->ppCachedImage[nLoop]){
break;
}
if (pSubSegMemory->ppCachedImage[nLoop]->szFileName){
if (!_stricmp(pSubSegMemory->ppCachedImage[nLoop]->szFileName, pFileName)
&& pSubSegMemory->ppCachedImage[nLoop]->nFilePageNum == nPage){
pImage = pSubSegMemory->ppCachedImage[nLoop];
goto Exit;
}
}
}
// Open the new file.
memset(&FioInfo, 0, sizeof(FIO_INFORMATION));
memset(&FioInfoCgbw, 0, sizeof(FIO_INFO_CGBW));
FioInfo.filename = pFileName;
FioInfo.page_number = nPage;
FioInfoCgbw.fio_flags = FIO_IMAGE_DATA | FIO_ANNO_DATA | FIO_HITIFF_DATA;
CheckError( IMGFileOpenForRead(&hFileProp, hWnd,
&FioInfo, &FioInfoCgbw, &FioInfoMisc, ALIGN_BYTE))
bCloseFileOnError = TRUE;
FioInfo.filename = 0; // This is NULL to avoid reopening the file.
FioInfo.page_number = nPage;
FioInfoCgbw.lppalette_table = PaletteTable;
CheckError( IMGFileGetInfo(hFileProp, hWnd, &FioInfo, &FioInfoCgbw, &FioInfoMisc))
FioInfo.filename = pFileName;
CheckError2( MakeCacheImage(hWnd, FioInfo, FioInfoCgbw, &pImage))
pImage->hWnd = hWnd;
pImage->nCompressionType = FioInfoCgbw.compress_type;
pImage->nFileType = FioInfo.file_type;
pImage->nMaxStripSize = FioInfoCgbw.max_strip_size;
pImage->bUsingCache = TRUE;
pImage->hFileProp = hFileProp;
pImage->nStripIndex = 1;
pImage->nLinesPerStrip = FioInfo.rows_strip;
// Setup last view info.
pImage->bFileScaleValid = FioInfoMisc.bLastInfoValid;
if (FioInfoMisc.bLastInfoValid){
if (FioInfo.horizontal_dpi >= FioInfo.vertical_dpi){
pImage->nFileScale = max(20, min(65535, FioInfoMisc.LastInfo.ScaleX * 10));
}else{
pImage->nFileScale = max(20, min(65535, FioInfoMisc.LastInfo.ScaleY * 10));
}
pImage->nFileScaleFlags = FioInfoMisc.LastInfo.Flags;
pImage->nFileRotation = FioInfoMisc.LastInfo.Rotation;
if (!(FioInfoMisc.LastInfo.Flags & FIO_LASTINFO_INVERT)){
// This is being commented out by request of Rita.
// Not setting this bit will cause all subsequent displays to be slowwer.
// pImage->bArchive |= ARCHIVE_PASTED_INTO_IMAGE;
}
}
while(pImage->nFileRotation < 0){
pImage->nFileRotation += 360;
}
while(pImage->nFileRotation >= 360){
pImage->nFileRotation -= 360;
}
if (!pImage->nFileRotation){
pImage->bFileRotationDone = TRUE;
}
pImage->nCompFlags = 0;
if (FioInfo.compression_type & FIO_HORZ_PREDICTOR){
pImage->nCompFlags |= COMPRESS_HORZ_PREDICTOR;
}
if (FioInfo.compression_type & FIO_PREFIXED_EOL){
pImage->nCompFlags |= COMPRESS_BEGINNING_EOLS;
}else if (FioInfo.compression_type & FIO_EOL){
pImage->nCompFlags |= COMPRESS_ENDING_EOLS;
}
// A001, B001 = Byte align lines.
// B901, BB01 = not byte aligned.
if (((FioInfo.compression_type & 0x0fff) == 0x001)){
pImage->nCompFlags |= COMPRESS_BYTE_ALIGN_LINES;
}
if ((FioInfo.compression_type & FIO_COMPRESSED_LTR)){
pImage->nCompFlags |= COMPRESS_COMPRESSED_IS_LTR;
}
if ((FioInfo.compression_type & FIO_EXPAND_LTR)){
pImage->nCompFlags |= COMPRESS_EXPANDED_IS_LTR;
}
if ((FioInfo.compression_type & FIO_NEGATE)){
pImage->nCompFlags |= COMPRESS_NEGATE_BITS;
}
if (((FioInfoCgbw.compress_type == FIO_1D) || (FioInfoCgbw.compress_type == FIO_2D))){
pImage->nCompFlags &= ~COMPRESS_NEGATE_BITS;
}
if ((FioInfoCgbw.compress_type == FIO_PACKED)){
pImage->nCompFlags ^= COMPRESS_EXPANDED_IS_LTR;
}
// Start the background cache timer.
if (pImage->nFileType == FIO_AWD){
CheckError2( CacheRead(hWnd, pImage, 0xffffff))
if (!pImage->bFileRotationDone){
// bFileRotationDone must be set to TRUE before orientation to avoid endless recursion.
pImage->bFileRotationDone = TRUE;
if (pImage->nFileRotation == 90){
CheckError2( CreateAnyImgBuf(&pImg, pImage->nHeight, pImage->nWidth, pImage->pImg->nType))
CheckError2( RotateRight90(pImage->pImg, pImg, pImage->nWidth, pImage->nHeight))
FreeImgBuf(&pImage->pImg);
MoveImage(&pImg, &pImage->pImg);
nTemp = pImage->nHRes;
pImage->nHRes = pImage->nVRes;
pImage->nVRes = nTemp;
nTemp = pImage->nHeight;
pImage->nHeight = pImage->nWidth;
pImage->nWidth = nTemp;
}else if (pImage->nFileRotation == 180){
CheckError2( Flip(pImage->pImg, pImage->nWidth, pImage->nHeight))
}else if (pImage->nFileRotation == 270){
CheckError2( CreateAnyImgBuf(&pImg, pImage->nHeight, pImage->nWidth, pImage->pImg->nType))
CheckError2( RotateRight270(pImage->pImg, pImg, pImage->nWidth, pImage->nHeight))
CheckError2( FreeImgBuf(&pImage->pImg))
MoveImage(&pImg, &pImage->pImg);
nTemp = pImage->nHRes;
pImage->nHRes = pImage->nVRes;
pImage->nVRes = nTemp;
nTemp = pImage->nHeight;
pImage->nHeight = pImage->nWidth;
pImage->nWidth = nTemp;
}else{
nStatus = Error(DISPLAY_INVALIDORIENTATION);
pImage->bFileRotationDone = FALSE;
goto Exit;
}
}
}else{
CacheStartTimer(hWnd);
}
Exit:
FreeImgBuf(&pImg);
if (nStatus && bCloseFileOnError){
// This takes hWnd, not pImage->hWnd, on purpose to work in error conditions
IMGFileClose(hFileProp, hWnd);
if (pImage){
pImage->hFileProp = 0;
}
}
*ppImage = pImage;
return(nStatus);
}
//
/*****************************************************************************
FUNCTION: CacheReadOld
PURPOSE: Reads a number of lines from the cache.
*****************************************************************************/
int WINAPI CacheReadOld(HWND hWnd, PIMAGE pImage, int nLinesToRead){
int nStatus = 0;
int nLines;
DWORD dwLines;
DWORD dwLine;
PSTR pAddress;
int nLineWidth;
int nBufferSize;
FIO_INFORMATION FioInfo;
FIO_INFO_CGBW FioInfoCgbw;
if (!pImage->pImg){
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
goto Exit;
}
if (nLinesToRead + pImage->nLinesRead + 10 >= pImage->nHeight){
nLinesToRead = pImage->nHeight - pImage->nLinesRead;
}
if (!pImage->hFileProp){
memset(&FioInfo, 0, sizeof(FIO_INFORMATION));
memset(&FioInfoCgbw, 0, sizeof(FIO_INFO_CGBW));
FioInfo.filename = pImage->szFileName;
FioInfo.page_number = pImage->nFilePageNum;
CheckError( IMGFileOpenForRead(&pImage->hFileProp, hWnd,
&FioInfo, &FioInfoCgbw, NULL, ALIGN_BYTE))
pImage->hWnd = hWnd;
}
switch (pImage->pImg->nType){
case ITYPE_BI_LEVEL:
nLineWidth = (pImage->nWidth + 7) / 8;
break;
case ITYPE_GRAY4:
case ITYPE_PAL4:
nLineWidth = (pImage->nWidth + 1) / 2;
break;
case ITYPE_GRAY8:
case ITYPE_PAL8:
case ITYPE_COMPAL8:
case ITYPE_CUSPAL8:
nLineWidth = pImage->nWidth;
break;
case ITYPE_RGB24:
case ITYPE_BGR24:
default:
nLineWidth = pImage->nWidth * 3;
break;
}
while (nLinesToRead){
pAddress = &pImage->pImg->bImageData[0]
+ (pImage->nLinesRead * pImage->pImg->nBytesPerLine);
nLines = max(1, min(pImage->nHeight - pImage->nLinesRead, (32767 / nLineWidth)));
nBufferSize = nLines * nLineWidth;
dwLine = pImage->nLinesRead;
dwLines = nLines;
if (nStatus = IMGFileReadData(pImage->hFileProp, pImage->hWnd, &dwLine, &dwLines,
pAddress, FIO_IMAGE_DATA)){
// The check for "lpImage->nLinesRead < pImage->nHeight - 1" below
// is caused by the fact that some of the tiff files gotten from
// elsewhere (from VS WIIS) actually have 1 less line than specified.
if (nStatus != FIO_EOF){
nStatus = Error(nStatus);
goto Exit;
}else{
// if (nStatus == FIO_EOF && pImage->nLinesRead >= pImage->nHeight - 1){
nStatus = 0;
// This is for AWD files where we dont know the exact height of each page beforehand.
pImage->nLinesRead = dwLine;
lCurrentCacheSize -= (pImage->nHeight - pImage->nLinesRead) * nLineWidth;
pImage->nHeight = pImage->nLinesRead;
pImage->pImg->nHeight = pImage->nHeight;
goto Exit;
}
}
nLines = (int)dwLines;
pImage->nLinesRead = dwLine;
if (((int)nLinesToRead) >= 0){
nLinesToRead -= min((int) nLinesToRead, nLines);
}else{
nLinesToRead -= nLines;
}
}
Exit:
if (pImage->nLinesRead >= pImage->nHeight){
pImage->nLinesRead = pImage->nHeight;
pImage->bCacheValid = TRUE;
}
if (nStatus || pImage->bCacheValid){
IMGFileClose(pImage->hFileProp, pImage->hWnd);
pImage->hFileProp = 0;
pImage->hWnd = 0;
}
return nStatus;
}
//
int PASCAL IMGFileReadRawm (HWND window_handle, int strip_index,
PINT this_many_bytes, PSTR buffer_address,
long *bytes_remain, HANDLE hprop);
/*****************************************************************************
FUNCTION: CacheReadNew
PURPOSE: Reads a number of lines from the cache.
*****************************************************************************/
int WINAPI CacheReadNew(HWND hWnd, PIMAGE pImage, int nLinesToRead){
int nStatus = 0;
int nLines;
PSTR pAddress;
int nLineWidth;
int nBufferSize;
FIO_INFORMATION FioInfo;
FIO_INFO_CGBW FioInfoCgbw;
PBYTE pCompressedBuffer = 0;
long lSize;
long lRemaining;
int nCompressedBufferSize;
if (!pImage->pImg){
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
goto Exit;
}
if (nLinesToRead + pImage->nLinesRead + 10 >= pImage->nHeight){
nLinesToRead = pImage->nHeight - pImage->nLinesRead;
}
if (!pImage->hFileProp){
memset(&FioInfo, 0, sizeof(FIO_INFORMATION));
memset(&FioInfoCgbw, 0, sizeof(FIO_INFO_CGBW));
FioInfo.filename = pImage->szFileName;
FioInfo.page_number = pImage->nFilePageNum;
CheckError( IMGFileOpenForRead(&pImage->hFileProp, hWnd,
&FioInfo, &FioInfoCgbw, NULL, ALIGN_BYTE))
pImage->hWnd = hWnd;
}
switch (pImage->pImg->nType){
case ITYPE_BI_LEVEL:
nLineWidth = (pImage->nWidth + 7) / 8;
break;
case ITYPE_GRAY4:
case ITYPE_PAL4:
nLineWidth = (pImage->nWidth + 1) / 2;
break;
case ITYPE_GRAY8:
case ITYPE_PAL8:
case ITYPE_COMPAL8:
case ITYPE_CUSPAL8:
nLineWidth = pImage->nWidth;
break;
case ITYPE_RGB24:
case ITYPE_BGR24:
default:
nLineWidth = pImage->nWidth * 3;
break;
}
nCompressedBufferSize = pImage->nMaxStripSize + 4;
CheckError2( AllocateMemory(nCompressedBufferSize, &pCompressedBuffer, NO_INIT))
if (pImage->nLinesRead == 0){
pImage->nStripIndex = 1;
}
while (nLinesToRead){
pAddress = &pImage->pImg->bImageData[0] + (pImage->nLinesRead * pImage->pImg->nBytesPerLine);
nLines = max(1, min(pImage->nHeight - pImage->nLinesRead, (32767 / nLineWidth)));
nBufferSize = nLines * nLineWidth;
lSize = nCompressedBufferSize;
if (nStatus = IMGFileReadRawm(pImage->hWnd, pImage->nStripIndex,
&lSize, pCompressedBuffer, &lRemaining, pImage->hFileProp)){
// The check for "lpImage->nLinesRead < pImage->nHeight - 1" below
// is caused by the fact that some of the tiff files gotten from
// elsewhere (from VS WIIS) actually have 1 less line than specified.
if (nStatus != FIO_EOF || pImage->nLinesRead < pImage->nHeight - 1){
nStatus = Error(nStatus);
goto Exit;
}else{
// if (nStatus == FIO_EOF && pImage->nLinesRead >= pImage->nHeight - 1){
nStatus = 0;
pImage->nLinesRead = pImage->nHeight;
goto Exit;
}
}
if (lRemaining){
nStatus = Error(DISPLAY_DATACORRUPTED);
goto Exit;
}
CheckError2( DecompressImage(pImage->nWidth, pImage->pImg->nBytesPerLine,
min( pImage->nLinesPerStrip, pImage->nHeight - pImage->nLinesRead),
pAddress, pImage->pImg->nType, pCompressedBuffer, lSize,
pImage->nCompressionType & FIO_TYPES_MASK, pImage->nCompFlags))
pImage->nStripIndex++;
pImage->nLinesRead += pImage->nLinesPerStrip;
nLinesToRead -= min((int) nLinesToRead, pImage->nLinesPerStrip);
}
Exit:
if (pCompressedBuffer){
FreeMemory(&pCompressedBuffer);
}
if (pImage->nLinesRead >= pImage->nHeight){
pImage->nLinesRead = pImage->nHeight;
pImage->bCacheValid = TRUE;
}
if (nStatus || pImage->bCacheValid){
IMGFileClose(pImage->hFileProp, pImage->hWnd);
pImage->hFileProp = 0;
pImage->hWnd = 0;
}
return nStatus;
}
//
/*****************************************************************************
FUNCTION: CacheRead
PURPOSE: Reads a number of lines from the cache.
*****************************************************************************/
int WINAPI CacheRead(HWND hWnd, PIMAGE pImage, int nLinesToRead){
int nStatus = 0;
FIO_INFORMATION FioInfo;
FIO_INFO_CGBW FioInfoCgbw;
BOOL bRead = FALSE;
if (pImage->bCacheValid){
goto Exit; // This is not an error.
}
if (!pImage->hFileProp){
memset(&FioInfo, 0, sizeof(FIO_INFORMATION));
memset(&FioInfoCgbw, 0, sizeof(FIO_INFO_CGBW));
FioInfo.filename = pImage->szFileName;
FioInfo.page_number = pImage->nFilePageNum;
CheckError( IMGFileOpenForRead(&pImage->hFileProp, hWnd,
&FioInfo, &FioInfoCgbw, NULL, ALIGN_BYTE))
pImage->hWnd = hWnd;
}
if (pImage->nFileType == FIO_TIF){
switch (pImage->nCompressionType){
case FIO_0D:
case FIO_1D:
case FIO_2D:
case FIO_PACKED:
case FIO_LZW:
CheckError2( CacheReadNew(hWnd, pImage, nLinesToRead))
bRead = TRUE;
break;
case FIO_GLZW:
case FIO_TJPEG:
default:
break;
}
}
if (!bRead){
CheckError2( CacheReadOld(hWnd, pImage, nLinesToRead))
}
Exit:
return nStatus;
}
//
/*****************************************************************************
FUNCTION: CacheClearAno
PURPOSE: Discard annotated files from the cache.
*****************************************************************************/
int WINAPI CacheClearAno(PANO_IMAGE *ppAnoImage){
int nStatus = 0;
int nLoop;
PANO_IMAGE pAnoImage;
PIMAGE pImage;
PMARK pMark;
int nMarkIndex;
pAnoImage = *ppAnoImage;
if (pAnoImage->nLockCount){
nStatus = Error(DISPLAY_CACHEFILEINUSE);
goto Exit;
}
if (pImage = pAnoImage->pBaseImage){
pImage->nLockCount = max(0, pImage->nLockCount -1);
if (!pImage->nLockCount && (!pImage->bUsingCache || pImage->bArchive
|| (pImage->szFileName[0] == '\0'))){
// If not nsing the cache or the image has been modified
// and not saved yet, then throw it away.
CheckError2( CacheClear(&pImage))
pAnoImage->pBaseImage = 0;
}
}
// DON'T free the FormImage or the DisplayFormImage.
// Freeing the mark will free the form image.
// Delete all annotations.
for (nMarkIndex = 0; nMarkIndex < pAnoImage->Annotations.nMarks; nMarkIndex++){
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
pMark->Attributes.dwPermissions = ACL_ALL;
}
CheckError2( DeleteAnnotations(pAnoImage))
// Free the default mark.
pMark = pAnoImage->Annotations.pDefMark;
CheckError2( DeleteMarkNamedBlocks(pMark))
CheckError2( FreeMemory((PPSTR) &pMark))
pAnoImage->Annotations.pDefMark = NULL;
// Find the entry in the cache.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (pSubSegMemory->ppCachedAnoImage[nLoop] == pAnoImage){
FreeMemory((PPSTR) &pSubSegMemory->ppCachedAnoImage[nLoop]);
// Compress the cache.
for (nLoop += 1; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (!pSubSegMemory->ppCachedAnoImage[nLoop]){
break;
}
pSubSegMemory->ppCachedAnoImage[nLoop - 1] = pSubSegMemory->ppCachedAnoImage[nLoop];
pSubSegMemory->ppCachedAnoImage[nLoop] = 0;
}
}
}
Exit:
return nStatus;
}
//
/*****************************************************************************
FUNCTION: CacheClear
PURPOSE: Discard files from the cache
*****************************************************************************/
int WINAPI CacheClear(PIMAGE *ppImage){
int nStatus = 0;
int nLoop;
PIMAGE pImage = *ppImage;
long lSizeOfThisImage;
if (!pImage->pImg){
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
goto Exit;
}
if (pImage->nLockCount){
nStatus = Error(DISPLAY_CACHEFILEINUSE);
goto Exit;
}
switch (pImage->pImg->nType){
case ITYPE_BI_LEVEL: lSizeOfThisImage = 1; break;
case ITYPE_GRAY4: lSizeOfThisImage = 4; break;
case ITYPE_GRAY8: lSizeOfThisImage = 8; break;
case ITYPE_PAL4: lSizeOfThisImage = 4; break;
case ITYPE_CUSPAL8: lSizeOfThisImage = 8; break;
case ITYPE_COMPAL8: lSizeOfThisImage = 8; break;
case ITYPE_RGB24: lSizeOfThisImage = 24; break;
case ITYPE_BGR24: lSizeOfThisImage = 24; break;
default:
nStatus = Error(DISPLAY_INTERNALDATAERROR);
goto Exit;
}
lSizeOfThisImage = ((lSizeOfThisImage * pImage->nWidth) + 7) / 8;
lSizeOfThisImage *= pImage->nHeight;
lCurrentCacheSize -= lSizeOfThisImage;
if (pImage->hFileProp){
IMGFileClose(pImage->hFileProp, pImage->hWnd);
pImage->hFileProp = 0;
pImage->hWnd = 0;
}
FreeImgBuf(&pImage->pImg);
if (pImage->hCusPal){
DeleteObject(pImage->hCusPal);
}
// Find the entry in the cache.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (pSubSegMemory->ppCachedImage[nLoop] == pImage){
FreeMemory((PPSTR) &pSubSegMemory->ppCachedImage[nLoop]);
// Compress the cache.
for (nLoop++; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (!pSubSegMemory->ppCachedImage[nLoop]){
break;
}
pSubSegMemory->ppCachedImage[nLoop - 1] = pSubSegMemory->ppCachedImage[nLoop];
pSubSegMemory->ppCachedImage[nLoop] = 0;
}
}
}
Exit:
return nStatus;
}
//
/*****************************************************************************
FUNCTION: CacheStartTimer
PURPOSE: Causes the cache to be activated for processing in the background.
*****************************************************************************/
int WINAPI CacheStartTimer(HWND hWnd){
int nStatus = 0;
TIMERPROC pfnTimer;
if (!bTimerRunning){
hTimerWnd = hWnd;
pfnTimer = (TIMERPROC) GetProcAddress(hInst, "CacheTimerProc");
if (SetTimer(hTimerWnd, CACHE_TIMER_ID, CACHE_TIMER_CYCLE, pfnTimer)){
bTimerRunning = TRUE;
}else{
nStatus = Error(DISPLAY_DATACORRUPTED);
goto Exit;
}
}
Exit:
return nStatus;
}
//
/*****************************************************************************
FUNCTION: CacheStopTimer
PURPOSE: Stops the cache from being activated.
*****************************************************************************/
int WINAPI CacheStopTimer(HWND hWnd){
int nStatus = 0;
if (bTimerRunning){
KillTimer(hTimerWnd, CACHE_TIMER_ID);
bTimerRunning = FALSE;
}
return(nStatus);
}
//
/*****************************************************************************
FUNCTION: CacheTimerProc
PURPOSE: Discard files from the cache
*****************************************************************************/
int WINAPI CacheTimerProc(HWND hWnd, int Msg, int nTimerId, DWORD dwCurrentTime){
int nStatus = 0;
PIMAGE pImage;
int nLoop;
// Prevent Multiprocessing in this code.
CheckError2( LockMutex())
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (!pSubSegMemory->ppCachedAnoImage[nLoop]){
break;
}
if (pSubSegMemory->ppCachedAnoImage[nLoop]->pBaseImage->bAnnotationsPresent
&& !pSubSegMemory->ppCachedAnoImage[nLoop]->bAnnotationsAlreadyRead){
ReadAnnotationsFromFile(hWnd, pSubSegMemory->ppCachedAnoImage[nLoop],
&pSubSegMemory->ppCachedAnoImage[nLoop]->Annotations.ppMarks,
&pSubSegMemory->ppCachedAnoImage[nLoop]->Annotations.nMarks);
goto Exit;
}
}
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (pImage = pSubSegMemory->ppCachedImage[nLoop]){
if (!pImage->bCacheValid && pImage->bUsingCache){
CheckError2( CacheRead(hWnd, pImage, 1))
goto Exit;
}
if (pImage->bCacheValid && pImage->hFileProp){
if (nStatus || pImage->bCacheValid){
IMGFileClose(pImage->hFileProp, pImage->hWnd);
pImage->hFileProp = 0;
}
}
}
}
// If we get here, it means that there are currently no images needing cache.
CacheStopTimer(hWnd);
Exit:
// Allow Multiprocessing again.
UnlockMutex();
if (nStatus){
CacheStopTimer(hWnd);
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: BlockedAnoReadChar
PURPOSE: Reads a char.
****************************************************************************/
char WINAPI BlockedAnoReadChar(HWND hWnd, PANO_IMAGE pAnoImage, PINT pnStatus){
int nStatus = 0;
char cTemp;
nStatus = BlockedAnoRead(hWnd, pAnoImage, 1, (PSTR) &cTemp);
if (!*pnStatus){
*pnStatus = nStatus;
}
return(cTemp);
}
//
/****************************************************************************
FUNCTION: BlockedAnoReadShort
PURPOSE: Reads a short.
****************************************************************************/
short WINAPI BlockedAnoReadShort(HWND hWnd, PANO_IMAGE pAnoImage, PINT pnStatus){
int nStatus = 0;
short shTemp;
nStatus = BlockedAnoRead(hWnd, pAnoImage, 2, (PSTR) &shTemp);
if (!*pnStatus){
*pnStatus = nStatus;
}
return(shTemp);
}
//
/****************************************************************************
FUNCTION: BlockedAnoReadLong
PURPOSE: Reads a long.
****************************************************************************/
long WINAPI BlockedAnoReadLong(HWND hWnd, PANO_IMAGE pAnoImage, PINT pnStatus){
int nStatus = 0;
long lTemp;
nStatus = BlockedAnoRead(hWnd, pAnoImage, 4, (PSTR) &lTemp);
if (!*pnStatus){
*pnStatus = nStatus;
}
return(lTemp);
}
//
/****************************************************************************
FUNCTION: BlockedAnoReadStr
PURPOSE: Reads a string.
****************************************************************************/
void WINAPI BlockedAnoReadStr(HWND hWnd, PANO_IMAGE pAnoImage, PINT pnStatus, int nSize, PSTR pBuffer){
int nStatus = 0;
nStatus = BlockedAnoRead(hWnd, pAnoImage, nSize, pBuffer);
if (!*pnStatus){
*pnStatus = nStatus;
}
return;
}
//
/****************************************************************************
FUNCTION: ReadMarkAttributes16
PURPOSE: Reads mark attributes structure.
****************************************************************************/
int WINAPI ReadMarkAttributes16(HWND hWnd, PANO_IMAGE pAnoImage, PMARK pMark){
int nStatus = 0;
(int) pMark->Attributes.uType = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lrBounds.left = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lrBounds.top = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lrBounds.right = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lrBounds.bottom = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.rgbColor1.rgbBlue = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.rgbColor1.rgbGreen = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.rgbColor1.rgbRed = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.rgbColor1.rgbReserved = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.rgbColor2.rgbBlue = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.rgbColor2.rgbGreen = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.rgbColor2.rgbRed = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.rgbColor2.rgbReserved = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.bHighlighting = (BOOL) BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pMark->Attributes.bTransparent = (BOOL) BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
(int) pMark->Attributes.uLineSize = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pMark->Attributes.uStartingPoint = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pMark->Attributes.uEndPoint = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lfFont.lfHeight = (int) BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lfFont.lfWidth = (int) BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lfFont.lfEscapement = (int) BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lfFont.lfOrientation = (int) BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lfFont.lfWeight = (int) BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lfFont.lfItalic = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lfFont.lfUnderline = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lfFont.lfStrikeOut = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lfFont.lfCharSet = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lfFont.lfOutPrecision = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lfFont.lfClipPrecision = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lfFont.lfQuality = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lfFont.lfPitchAndFamily = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
BlockedAnoReadStr(hWnd, pAnoImage, &nStatus, 32, (PSTR) &pMark->Attributes.lfFont.lfFaceName[0]);
pMark->Attributes.bMinimizable = (BOOL) BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pMark->Attributes.Time = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.bVisible = (BOOL) BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pMark->Attributes.dwPermissions = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lReserved[0] = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lReserved[1] = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lReserved[2] = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lReserved[3] = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lReserved[4] = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lReserved[5] = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lReserved[6] = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lReserved[7] = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lReserved[8] = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pMark->Attributes.lReserved[9] = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
return(nStatus);
}
//
/****************************************************************************
FUNCTION: ReadAnnotationsFromFile
PURPOSE: Reads all annotations from a file.
****************************************************************************/
int WINAPI ReadAnnotationsFromFile(HWND hWnd, PANO_IMAGE pAnoImage,
PMARK **pppMarks, int *pnMarks){
int nStatus = 0;
FIO_INFO_CGBW FioInfoCgbw;
FIO_INFORMATION FioInfo;
PIMAGE pImage;
PSTR pTemp;
PMARK pMark=0;
BOOL bFileOpenedHere = FALSE;
pAnoImage->lAnoStart = 0;
pImage = pAnoImage->pBaseImage;
if (!pImage->szFileName[0]){
goto Exit;
}
if (!pImage->hFileProp){
memset(&FioInfoCgbw, 0, sizeof(FIO_INFO_CGBW));
memset(&FioInfo, 0, sizeof(FIO_INFORMATION));
FioInfo.filename = pImage->szFileName;
FioInfo.page_number = pImage->nFilePageNum;
FioInfoCgbw.fio_flags = FIO_IMAGE_DATA | FIO_ANNO_DATA | FIO_HITIFF_DATA;
CheckError( IMGFileOpenForRead(&pImage->hFileProp, hWnd,
&FioInfo, &FioInfoCgbw, NULL, ALIGN_BYTE))
pImage->hWnd = hWnd;
bFileOpenedHere = TRUE;
}
CheckError2( ReadAnnotations(pImage->hWnd, pAnoImage, pppMarks, pnMarks))
Exit:
// add the default mark stuff
if (!nStatus){
// add default group and index
pMark = pAnoImage->Annotations.pDefMark;
pTemp = 0;
GetAMarkNamedBlock(pMark, szOiGroup, (PPSTR) &pTemp);
if (!pTemp){
LoadString(hInst, ID_UNTITLED, Buff1, 16);
AddAMarkNamedBlock(pMark, szOiGroup, (PPSTR) &pTemp, lstrlen(Buff1) + 1);
memcpy(pTemp, Buff1, lstrlen(Buff1) + 1);
}
// Update file with index# info.
pTemp = 0;
GetAMarkNamedBlock(pMark, szOiIndex, (PPSTR) &pTemp);
if (!pTemp){
AddAMarkNamedBlock(pMark, szOiIndex, (PPSTR) &pTemp, 10);
strcpy(pTemp, "0");
}
}
if (bFileOpenedHere){
IMGFileClose(pImage->hFileProp, pImage->hWnd);
pImage->hFileProp = 0;
pImage->hWnd = 0;
}
pAnoImage->bAnnotationsAlreadyRead = TRUE;
return(nStatus);
}
//
/****************************************************************************
FUNCTION: ReadAnnotations
PURPOSE: Reads all annotations.
****************************************************************************/
int WINAPI ReadAnnotations(HWND hWnd, PANO_IMAGE pAnoImage,
PMARK **pppMarks, int *pnMarks){
int nStatus = 0;
int nNamedBlockIndex;
PMARK pDefMark;
int nIndex;
PMARK pMark = 0;
long lTemp[2];
int nIntSize = 2;
PSTR pTemp = 0;
BOOL bDone;
BOOL bThrowItAway;
BOOL bDontRead;
PAN_NEW_ROTATE_STRUCT pAnRotation = NULL;
int nMarkIndex;
PAN_POINTS pPoints;
LPLRECT plrRect;
int nIDs;
LPOI_ACL_BLOCK pAclBlock;
BITMAPINFOHEADER *pDib;
RGBQUAD *pRGBQuad;
int nMaxPoints;
int nPoints;
int nLoop;
NAMED_BLOCK NamedBlock;
PSTR pBlock;
LPOIAN_TEXTPRIVDATA pTextPrivData = NULL;
pAnoImage->lAnoStart = 0;
if (nStatus = BlockedAnoRead(hWnd, pAnoImage, 4, (PSTR) &lTemp)){
if (nStatus == DISPLAY_EOF){ // Ignor Real EOFs.
nStatus = 0;
}
goto Exit;
}
if (lTemp[0] == 1){ // 32 bit Intel.
bDontRead = FALSE;
while(1){
if (!bDontRead){
if (nStatus = BlockedAnoRead(hWnd, pAnoImage, 8, (PSTR) lTemp)){
if (nStatus != DISPLAY_EOF){ // Ignor Real EOFs.
Error(nStatus);
goto Exit;
}
nStatus = 0;
break;
}
}
bDontRead = FALSE;
switch (lTemp[0]){
case SAVE_ANO_DEFAULT_MARK_NAMED_BLOCK:
pMark = pAnoImage->Annotations.pDefMark;
CheckError( BlockedAnoRead(hWnd, pAnoImage, 8, &NamedBlock.szName[0]))
CheckError( BlockedAnoRead(hWnd, pAnoImage, 4, (PSTR) &NamedBlock.lSize))
bThrowItAway = FALSE;
if (!memcmp(NamedBlock.szName, szOiAnoDat, 8)){
if (pMark->pOiAnoDat){
bThrowItAway = TRUE;
}
}else if (!memcmp(NamedBlock.szName, szOiGroup, 8)){
if (pMark->pOiGroup){
bThrowItAway = TRUE;
}
}else if (!memcmp(NamedBlock.szName, szOiSelect, 8)){
if (pMark->pOiSelect){
bThrowItAway = TRUE;
}
}else if (!memcmp(NamedBlock.szName, szOiIndex, 8)){
if (pMark->pOiIndex){
bThrowItAway = TRUE;
}
}else{
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
if (!memcmp(pMark->ppNamedBlock[nNamedBlockIndex]->szName, NamedBlock.szName, 8)){
bThrowItAway = TRUE;
break;
}
}
}
if (bThrowItAway){
// Duplicate name. Read it and throw it away.
CheckError2( ReAllocateMemory(NamedBlock.lSize, &pTemp, ZERO_INIT))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, NamedBlock.lSize, pTemp))
CheckError2( FreeMemory(&pTemp))
}else{
pBlock = 0;
CheckError2( AddAMarkNamedBlock(pMark, NamedBlock.szName, &pBlock, NamedBlock.lSize))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, NamedBlock.lSize, pBlock))
}
break;
case SAVE_ANO_MARK_ATTRIBUTES:
CheckError2( ReAllocateMemory(sizeof(PMARK) * (*pnMarks + 2), (PPSTR) &(*pppMarks), ZERO_INIT))
CheckError2( AllocateMemory(sizeof(MARK), (PPSTR) &((*pppMarks)[*pnMarks]), ZERO_INIT))
pMark = (*pppMarks)[*pnMarks];
CheckError2( BlockedAnoRead(hWnd, pAnoImage, lTemp[1], (PSTR) &pMark->Attributes))
(*pnMarks)++;
break;
case SAVE_ANO_MARK_NAMED_BLOCK:
if (!pMark){
nStatus = Error(DISPLAY_BAD_ANO_DATA);
goto Exit;
}
CheckError2( BlockedAnoRead(hWnd, pAnoImage, 8, &NamedBlock.szName[0]))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, 4, (PSTR) &NamedBlock.lSize))
bThrowItAway = FALSE;
if (!memcmp(NamedBlock.szName, szOiAnoDat, 8)){
if (pMark->pOiAnoDat){
bThrowItAway = TRUE;
}
}else if (!memcmp(NamedBlock.szName, szOiGroup, 8)){
if (pMark->pOiGroup){
bThrowItAway = TRUE;
}
}else if (!memcmp(NamedBlock.szName, szOiSelect, 8)){
if (pMark->pOiSelect){
bThrowItAway = TRUE;
}
}else if (!memcmp(NamedBlock.szName, szOiIndex, 8)){
if (pMark->pOiIndex){
bThrowItAway = TRUE;
}
}else{
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
if (!memcmp(pMark->ppNamedBlock[nNamedBlockIndex]->szName, NamedBlock.szName, 8)){
bThrowItAway = TRUE;
break;
}
}
}
if (bThrowItAway){
// Duplicate name. Read it and throw it away.
CheckError2( ReAllocateMemory(NamedBlock.lSize, &pTemp, ZERO_INIT))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, NamedBlock.lSize, pTemp))
CheckError2( FreeMemory(&pTemp))
}else{
pBlock = 0;
CheckError2( AddAMarkNamedBlock(pMark, NamedBlock.szName, &pBlock, NamedBlock.lSize))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, NamedBlock.lSize, pBlock))
}
break;
default:
nStatus = Error(DISPLAY_BAD_ANO_DATA);
goto Exit;
}
}
}else if (lTemp[0] == 0){ // 16 bit Intel.
bDontRead = FALSE;
while(!nStatus){
if (!bDontRead){
if (nStatus = BlockedAnoRead(hWnd, pAnoImage, 8, (PSTR) lTemp)){
if (nStatus != DISPLAY_EOF){ // Ignor Real EOFs.
Error(nStatus);
goto Exit;
}
nStatus = 0;
break;
}
}
bDontRead = FALSE;
switch (lTemp[0]){
case SAVE_ANO_DEFAULT_MARK_NAMED_BLOCK:
pMark = pAnoImage->Annotations.pDefMark;
CheckError2( AllocateMemory(lTemp[1], &pTemp, NO_INIT))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, lTemp[1], pTemp))
lTemp[1] = ((PNAMED_BLOCK) pTemp)->lSize;
bThrowItAway = FALSE;
if (!memcmp(((PNAMED_BLOCK) pTemp)->szName, szOiAnoDat, 8)){
if (pMark->pOiAnoDat){
bThrowItAway = TRUE;
}else{
CheckError2( ReAllocateMemory(lTemp[1], &pTemp, NO_INIT))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, lTemp[1], pTemp))
pMark->pOiAnoDat = pTemp;
pMark->nOiAnoDatSize = lTemp[1];
pTemp = 0;
}
}else if (!memcmp(((PNAMED_BLOCK) pTemp)->szName, szOiGroup, 8)){
if (pMark->pOiGroup){
bThrowItAway = TRUE;
}else{
CheckError2( ReAllocateMemory(lTemp[1], &pTemp, NO_INIT))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, lTemp[1], pTemp))
pMark->pOiGroup = pTemp;
pMark->nOiGroupSize = lTemp[1];
pTemp = 0;
}
}else if (!memcmp(((PNAMED_BLOCK) pTemp)->szName, szOiSelect, 8)){
if (pMark->pOiSelect){
bThrowItAway = TRUE;
}else{
CheckError2( ReAllocateMemory(lTemp[1], &pTemp, NO_INIT))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, lTemp[1], pTemp))
pMark->pOiSelect = pTemp;
pMark->nOiSelectSize = lTemp[1];
pTemp = 0;
}
}else if (!memcmp(((PNAMED_BLOCK) pTemp)->szName, szOiIndex, 8)){
if (pMark->pOiIndex){
bThrowItAway = TRUE;
}else{
CheckError2( ReAllocateMemory(lTemp[1], &pTemp, NO_INIT))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, lTemp[1], pTemp))
pMark->pOiIndex = pTemp;
pMark->nOiIndexSize = lTemp[1];
pTemp = 0;
}
}else{
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
if (!memcmp(pMark->ppNamedBlock[nNamedBlockIndex]->szName, ((PNAMED_BLOCK) pTemp)->szName, 8)){
bThrowItAway = TRUE;
break;
}
}
if (bThrowItAway){
break;
}
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK) * (pMark->nNamedBlocks + 1),
(PPSTR) &pMark->ppNamedBlock, ZERO_INIT))
pMark->ppNamedBlock[nNamedBlockIndex] = (PNAMED_BLOCK) pTemp;
pMark->nNamedBlocks++;
CheckError2( AllocateMemory(lTemp[1], &pTemp, NO_INIT))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, lTemp[1], pTemp))
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock = pTemp;
pTemp = 0;
}
if (bThrowItAway){
// Duplicate name. Read it and throw it away.
CheckError2( ReAllocateMemory(lTemp[1], &pTemp, ZERO_INIT))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, lTemp[1], pTemp))
CheckError2( FreeMemory(&pTemp))
}
pMark = 0;
break;
case SAVE_ANO_MARK_ATTRIBUTES:
if (lTemp[1] != 138){
nStatus = Error(DISPLAY_BAD_ANO_DATA);
goto Exit;
}
CheckError2( ReAllocateMemory(sizeof(PMARK) * (*pnMarks + 2),
(PPSTR) &(*pppMarks), ZERO_INIT))
CheckError2( AllocateMemory(sizeof(MARK),
(PPSTR) &((*pppMarks)[*pnMarks]), ZERO_INIT))
pMark = (*pppMarks)[*pnMarks];
(*pnMarks)++;
CheckError2( ReadMarkAttributes16(hWnd, pAnoImage, pMark))
break;
case SAVE_ANO_MARK_NAMED_BLOCK:
if (!pMark){
nStatus = Error(DISPLAY_BAD_ANO_DATA);
goto Exit;
}
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK), &pTemp, NO_INIT))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, lTemp[1], pTemp))
lTemp[1] = ((PNAMED_BLOCK) pTemp)->lSize;
bThrowItAway = FALSE;
if (!memcmp(((PNAMED_BLOCK) pTemp)->szName, szOiAnoDat, 8)){
if (pMark->pOiAnoDat){
bThrowItAway = TRUE;
}
}else if (!memcmp(((PNAMED_BLOCK) pTemp)->szName, szOiGroup, 8)){
if (pMark->pOiGroup){
bThrowItAway = TRUE;
}
}else if (!memcmp(((PNAMED_BLOCK) pTemp)->szName, szOiSelect, 8)){
if (pMark->pOiSelect){
bThrowItAway = TRUE;
}
}else if (!memcmp(((PNAMED_BLOCK) pTemp)->szName, szOiIndex, 8)){
if (pMark->pOiIndex){
bThrowItAway = TRUE;
}
}else{
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
if (!memcmp(pMark->ppNamedBlock[nNamedBlockIndex]->szName, ((PNAMED_BLOCK) pTemp)->szName, 8)){
bThrowItAway = TRUE;
break;
}
}
}
if (bThrowItAway){
// Duplicate name. Read it and throw it away.
CheckError2( ReAllocateMemory(lTemp[1], &pTemp, ZERO_INIT))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, lTemp[1], pTemp))
CheckError2( FreeMemory(&pTemp))
}else{
bDone = FALSE;
if (!memcmp(((PNAMED_BLOCK) pTemp)->szName, szOiAnoDat, 8)){
switch ((int) pMark->Attributes.uType){
case OIOP_AN_LINE:
case OIOP_AN_FREEHAND:
// AN_POINTS.
nMaxPoints = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
nPoints = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pPoints = 0;
CheckError2( AddAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pPoints,
sizeof(AN_POINTS) + (sizeof(POINT) * nMaxPoints)))
pPoints->nMaxPoints = nMaxPoints;
pPoints->nPoints = nPoints;
for (nLoop = 0; nLoop < nMaxPoints + 1; nLoop++){
pPoints->ptPoint[nLoop].x = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pPoints->ptPoint[nLoop].y = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
}
bDone = TRUE;
break;
case OIOP_AN_IMAGE:
case OIOP_AN_IMAGE_BY_REFERENCE:
case OIOP_AN_FORM:
pAnRotation = 0;
CheckError2( AddAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation,
sizeof(AN_NEW_ROTATE_STRUCT)))
if (lTemp[1] == 12){
// pre 3.7.2 image rotation data blocks
pAnRotation->rotation = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->scale = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nHRes = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nVRes = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nOrigHRes = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nOrigVRes = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->bFormMark = FALSE;
pAnRotation->bClipboardOp = FALSE;
}else if (lTemp[1] == 28){
// 3.7.2 image rotation data blocks
pAnRotation->rotation = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->scale = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nHRes = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nVRes = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nOrigHRes = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nOrigVRes = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->bFormMark = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->bClipboardOp = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nReserved[0] = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nReserved[1] = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nReserved[2] = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nReserved[3] = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nReserved[4] = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAnRotation->nReserved[5] = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
}else{
nStatus = Error(DISPLAY_BAD_ANO_DATA);
goto Exit;
}
bDone = TRUE;
break;
default:
break;
}
}else if (!memcmp(((PNAMED_BLOCK) pTemp)->szName, szOiAnTextData, 8)){
switch ((int) pMark->Attributes.uType){
case OIOP_AN_TEXT:
case OIOP_AN_TEXT_FROM_A_FILE:
case OIOP_AN_TEXT_STAMP:
case OIOP_AN_ATTACH_A_NOTE:
pTextPrivData = 0;
CheckError2( AddAMarkNamedBlock(pMark, szOiAnTextData, (PPSTR) &pTextPrivData,
sizeof(OIAN_TEXTPRIVDATA)))
pTextPrivData->nCurrentOrientation = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pTextPrivData->uCurrentScale = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pTextPrivData->uCreationScale = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pTextPrivData->uAnoTextLength = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
CheckError2( ReAllocateAMarkNamedBlock(pMark, szOiAnTextData, (PPSTR) &pTextPrivData,
sizeof(OIAN_TEXTPRIVDATA) + pTextPrivData->uAnoTextLength))
BlockedAnoReadStr(hWnd, pAnoImage, &nStatus,
pTextPrivData->uAnoTextLength, (PSTR) &pTextPrivData->szAnoText[0]);
bDone = TRUE;
break;
default:
break;
}
}else if (!memcmp(((PNAMED_BLOCK) pTemp)->szName, szOiCurPt, 8)){
// LRECT
plrRect = 0;
CheckError2( AddAMarkNamedBlock(pMark, szOiCurPt, (PPSTR) &plrRect, sizeof(LRECT)))
plrRect->left = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
plrRect->top = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
plrRect->right = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
plrRect->bottom = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
bDone = TRUE;
}else if (!memcmp(((PNAMED_BLOCK) pTemp)->szName, szOiACL, 8)){
// OI_ACL_BLOCK
nIDs = BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pAclBlock = 0;
CheckError2( AddAMarkNamedBlock(pMark, szOiACL, (PPSTR) &pAclBlock,
sizeof(OI_ACL_BLOCK) + (sizeof(OI_ACL_STRUCT) * nIDs)))
pAclBlock->uIDs = nIDs;
for (nLoop = 0; nLoop < nIDs; nLoop++){
CheckError2( BlockedAnoRead(hWnd, pAnoImage, 8, pAclBlock->ACL[nLoop].ID))
pAclBlock->ACL[nLoop].dwPermissions
= BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
}
bDone = TRUE;
}else if (!memcmp(((PNAMED_BLOCK) pTemp)->szName, szOiDIB, 8)){
// BITMAPINFOHEADER
pDib = 0;
CheckError2( AddAMarkNamedBlock(pMark, szOiDIB, (PPSTR) &pDib, sizeof(BITMAPINFOHEADER)))
pDib->biSize = (DWORD) BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pDib->biSize = sizeof(BITMAPINFOHEADER);
(int) pDib->biWidth = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
(int) pDib->biHeight = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pDib->biPlanes = (WORD) BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pDib->biBitCount = (WORD) BlockedAnoReadShort(hWnd, pAnoImage, &nStatus);
pDib->biCompression = (DWORD) BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pDib->biSizeImage = (DWORD) BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pDib->biXPelsPerMeter = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pDib->biYPelsPerMeter = BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pDib->biClrUsed = (DWORD) BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
pDib->biClrImportant = (DWORD) BlockedAnoReadLong(hWnd, pAnoImage, &nStatus);
CheckError2( ReAllocateAMarkNamedBlock(pMark, szOiDIB, (PPSTR) &pDib,
sizeof(BITMAPINFOHEADER) + (sizeof(RGBQUAD) * pDib->biClrUsed)
+ (((((int) pDib->biWidth * pDib->biBitCount) + 31) & -32) >> 3) * (int) pDib->biHeight))
pRGBQuad = (RGBQUAD *) ((PSTR) pDib + sizeof(BITMAPINFOHEADER));
for (nLoop = 0; nLoop < (int) pDib->biClrUsed; nLoop++){
pRGBQuad->rgbBlue = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pRGBQuad->rgbGreen = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pRGBQuad->rgbRed = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pRGBQuad->rgbReserved = BlockedAnoReadChar(hWnd, pAnoImage, &nStatus);
pRGBQuad++;
}
pTemp = ((PSTR) pDib) + sizeof(BITMAPINFOHEADER)
+ (sizeof(RGBQUAD) * pDib->biClrUsed);
CheckError2( BlockedAnoRead(hWnd, pAnoImage,
(((((int) pDib->biWidth * pDib->biBitCount) + 31) & -32) >> 3) * (int) pDib->biHeight,
(PSTR) pTemp))
bDone = TRUE;
}
}
if (!bDone){
// Name not a known structure, assume it is a string.
memcpy(NamedBlock.szName, ((PNAMED_BLOCK) pTemp)->szName, 8);
CheckError2( FreeMemory(&pTemp))
CheckError2( AddAMarkNamedBlock(pMark, NamedBlock.szName,
(PPSTR) &pTemp, lTemp[1]))
CheckError2( BlockedAnoRead(hWnd, pAnoImage, lTemp[1], pTemp))
}
// if it is an oiop_activate mark, then delete it
// they were saved by mistake in 3.7.2
if ((int) pMark->Attributes.uType == OIOP_ACTIVATE){
CheckError2( DeleteMark(pAnoImage, (*pnMarks) - 1))
}
break;
default:
nStatus = Error(DISPLAY_BAD_ANO_DATA);
goto Exit;
}
}
}
if (nStatus){
goto Exit;
}
// Update file with index# info.
pDefMark = pAnoImage->Annotations.pDefMark;
if (!pDefMark->pOiIndex){
nIndex = 0;
for (nMarkIndex = 0; nMarkIndex < *pnMarks; nMarkIndex++){
pMark = (*pppMarks)[nMarkIndex];
pTemp = 0;
CheckError2( AddAMarkNamedBlock(pMark, szOiIndex, (PPSTR) &pTemp, 10))
_itoa(nIndex, Buff1, 10);
strcpy(pTemp, Buff1);
nIndex++;
}
pTemp = 0;
CheckError2( AddAMarkNamedBlock(pDefMark, szOiIndex, (PPSTR) &pTemp, 10))
_itoa(nIndex, Buff1, 10);
strcpy(pTemp, Buff1);
}
Exit:
return(nStatus);
}
/****************************************************************************
FUNCTION: IMGCacheUpdate
PURPOSE: Prepares for filing to make changes to a file.
****************************************************************************/
int WINAPI IMGCacheUpdate(HWND hWnd, PSTR pFileName, int nPage, int nUpdateType){
int nStatus = 0;
PANO_IMAGE pAnoImage;
PIMAGE pImage;
int nLoop;
Start();
CheckError2( IntSeqfileInit())
// Read all data for all locked pages of this file.
// Look for the file in the AnoImage Table.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (!(pAnoImage = pSubSegMemory->ppCachedAnoImage[nLoop])){
break;
}
if (pImage = pAnoImage->pBaseImage){
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)){
if (pAnoImage->nLockCount){
CheckError2( ValidateCacheLines(hWnd, pAnoImage, 0xffffff))
}
}
}
}
}
// Look for the file in the Image Table.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (!(pImage = pSubSegMemory->ppCachedImage[nLoop])){
break;
}
if (pSubSegMemory->ppCachedImage[nLoop]->szFileName){
if (!_stricmp(pSubSegMemory->ppCachedImage[nLoop]->szFileName, pFileName)){
if (pImage->nLockCount && !pImage->bCacheValid){
CheckError2( CacheRead(hWnd, pSubSegMemory->ppCachedImage[nLoop],
pSubSegMemory->ppCachedImage[nLoop]->nHeight - pSubSegMemory->ppCachedImage[nLoop]->nLinesRead))
}
}
}
}
// Delete all nnlocked images, or finish reading them, or just continue - as needed.
switch (nUpdateType){
case CACHE_UPDATE_OVERWRITE_FILE:
case CACHE_UPDATE_DELETE_FILE:
case CACHE_UPDATE_ROTATE_ALL:
// Delete all nnlocked pages of this file.
// Look for the file in the AnoImage Table.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (!(pAnoImage = pSubSegMemory->ppCachedAnoImage[nLoop])){
break;
}
if (pImage = pAnoImage->pBaseImage){
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)){
if (!pAnoImage->nLockCount){
CheckError2( CacheClearAno(&pAnoImage))
nLoop--;
}
}
}
}
}
// Look for the file in the Image Table.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (!(pImage = pSubSegMemory->ppCachedImage[nLoop])){
break;
}
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)){
if (!pImage->nLockCount){
CheckError2( CacheClear(&pImage))
nLoop--;
}
}
}
}
break;
case CACHE_UPDATE_DELETE_PAGE:
case CACHE_UPDATE_APPEND:
case CACHE_UPDATE_INSERT_BEFORE:
case CACHE_UPDATE_CLOSE_FILE:
// Read all data for all pages of this file.
// Look for the file in the AnoImage Table.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (!(pAnoImage = pSubSegMemory->ppCachedAnoImage[nLoop])){
break;
}
if (pImage = pAnoImage->pBaseImage){
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)){
if (nUpdateType == CACHE_UPDATE_DELETE_PAGE
&& pImage->nFilePageNum == nPage){
CheckError2( CacheClearAno(&pAnoImage))
nLoop--;
}else{
CheckError2( ValidateCacheLines(hWnd, pAnoImage, 0xffffff))
}
}
}
}
}
// Look for the file in the Image Table.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (!(pImage = pSubSegMemory->ppCachedImage[nLoop])){
break;
}
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)){
if (nUpdateType == CACHE_UPDATE_DELETE_PAGE
&& pImage->nFilePageNum == nPage){
CheckError2( CacheClear(&pImage))
nLoop--;
}else{
if (!pImage->bCacheValid){
CheckError2( CacheRead(hWnd, pImage,
pImage->nHeight - pImage->nLinesRead))
}
}
}
}
}
break;
case CACHE_UPDATE_OVERWRITE_PAGE:
// Read all data for this page of this file.
// Look for the file in the AnoImage Table.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxAnoCachedEntries; nLoop++){
if (!(pAnoImage = pSubSegMemory->ppCachedAnoImage[nLoop])){
break;
}
if (pImage = pAnoImage->pBaseImage){
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)){
if (pImage->nFilePageNum == nPage){
if (!pAnoImage->nLockCount){
CheckError2( CacheClearAno(&pAnoImage))
nLoop--;
}else{
CheckError2( ValidateCacheLines(hWnd, pAnoImage, 0xffffff))
}
}
}
}
}
}
// Look for the file in the Image Table.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (!(pImage = pSubSegMemory->ppCachedImage[nLoop])){
break;
}
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)){
if (pImage->nFilePageNum == nPage){
if (!pImage->bCacheValid){
CheckError2( CacheRead(hWnd, pImage, pImage->nHeight - pImage->nLinesRead))
}
}
}
}
}
break;
default:
break;
}
// Do all page number modifying stuff here. (Also some error checking.)
switch (nUpdateType){
case CACHE_UPDATE_DELETE_PAGE:
// If this page is in the cache then fail.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (!(pImage = pSubSegMemory->ppCachedImage[nLoop])){
break;
}
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)){
if (pImage->nFilePageNum == nPage){
nStatus = Error(DISPLAY_CACHEFILEINUSE);
goto Exit;
}
}
}
}
// We have to decrement the page numbers that are greater than this one in the cache.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (!(pImage = pSubSegMemory->ppCachedImage[nLoop])){
break;
}
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)){
if (pImage->nFilePageNum > nPage){
pImage->nFilePageNum--;
}
pImage->nFileTotalPages--;
}
}
}
break;
case CACHE_UPDATE_INSERT_BEFORE:
// We have to increment the page numbers that are equal to and greater than this one in the cache.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (!(pImage = pSubSegMemory->ppCachedImage[nLoop])){
break;
}
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)){
if (pImage->nFilePageNum >= nPage){
pImage->nFilePageNum++;
}
pImage->nFileTotalPages++;
}
}
}
break;
case CACHE_UPDATE_APPEND:
// We have to increment the number of pages in the cache.
for (nLoop = 0; nLoop < pSubSegMemory->nMaxCachedEntries; nLoop++){
if (!(pImage = pSubSegMemory->ppCachedImage[nLoop])){
break;
}
if (pImage->szFileName){
if (!_stricmp(pImage->szFileName, pFileName)){
pImage->nFileTotalPages++;
}
}
}
break;
case CACHE_UPDATE_OVERWRITE_PAGE:
case CACHE_UPDATE_OVERWRITE_FILE:
case CACHE_UPDATE_DELETE_FILE:
case CACHE_UPDATE_ROTATE_ALL:
case CACHE_UPDATE_CLOSE_FILE:
default:
break;
}
Exit:
End();
return(nStatus);
}
/****************************************************************************
FUNCTION: OiRotateAllPages
PURPOSE: Marks all pages in a file for rotation.
****************************************************************************/
int WINAPI OiRotateAllPages(HWND hWnd, PSTR pFileName, int nRotation, int nFlags){
int nStatus = 0;
FIO_INFO_MISC MiscInfo;
Start();
CheckError2( IntSeqfileInit())
memset(&MiscInfo, 0, sizeof(FIO_INFO_MISC));
MiscInfo.LastInfo.BandSize = 0;
MiscInfo.LastInfo.Rotation = nRotation;
MiscInfo.LastInfo.ScaleX = 0;
MiscInfo.LastInfo.ScaleY = 0;
MiscInfo.LastInfo.Flags = FIO_LASTINFO_ROTATE_ALL;
MiscInfo.bLastInfoValid = TRUE;
CheckError( IMGFilePutInfo(hWnd, pFileName, 0, &MiscInfo))
Exit:
End();
return(nStatus);
}