/**************************************************************************** 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); }