Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2811 lines
110 KiB

/****************************************************************************
COPY.C
$Log: S:\products\wangview\oiwh\display\copy.c_v $
*
* Rev 1.48 22 Apr 1996 06:48:46 BEG06016
* Cleaned up error checking.
*
* Rev 1.47 11 Apr 1996 15:13:14 BEG06016
* Optimized named block access some.
*
* Rev 1.46 05 Mar 1996 07:44:30 BEG06016
* Added color and gamma correction.
* Fixed access violations when freeing pattern brush bitmaps.
* This is not complete but will allow unlocking of most files.
*
* Rev 1.45 09 Jan 1996 14:06:56 BLJ
* Fixed rendering.
*
* Rev 1.44 04 Jan 1996 14:29:06 BLJ
* Fixed a memory manager bug.
*
* Rev 1.43 02 Jan 1996 09:58:22 BLJ
* Changed alot of UINTs to ints.
* Changed IMG structure to include the image data.
* Changed lp prefix to p.
*
* Rev 1.42 22 Dec 1995 11:12:20 BLJ
* Added a parameter for zero init'ing to some memory manager calls.
*
* Rev 1.41 15 Nov 1995 13:51:50 BLJ
* Fixed 5266 scrolling image data left.
*
* Rev 1.40 10 Nov 1995 10:51:16 BLJ
* Fixed runtime part of 5142 - IMGClearImage nows work properly.
*
* Rev 1.39 09 Nov 1995 13:53:42 BLJ
* Fixed 5262 - RGB24 Image gets corrupted when scrolled left followed by right.
*
* Rev 1.38 13 Oct 1995 12:27:28 RAR
* Use StretchDIBits() instead of Rectangle() for non-highlighted filled
* rectangles (only when printing). Work around for printer drivers (HPLJ4
* drivers) that ignore SetROP2() drawing mode.
*
* Rev 1.37 12 Oct 1995 13:48:48 RC
* Passed in scalealg to convresbm rather than calculating it
*
* Rev 1.36 09 Oct 1995 13:53:24 BLJ
* Moved the paste information from pWindow to pAnoImage.
*
****************************************************************************/
#include "privdisp.h"
int WINAPI PaletteSize (VOID * pv);
int WINAPI DibNumColors (VOID * pv);
/*****************************************************************************
FUNCTION: IMGClipboardCgbw
PURPOSE: The function handles all operations involving the clipboard.
INPUT: hWnd - Identifies the image window.
nClipAction - A constant indicating the type of clipboard
operation to perform.
pParm - A pointer to the clipboard parameters.
nFlags - Flags indicating how or what to get the information.
*****************************************************************************/
int WINAPI IMGClipboardCgbw(HWND hWnd, int nClipAction, void *pParm, int nFlags){
int nStatus = 0;
PWINDOW pWindow;
PANO_IMAGE pAnoImage;
PIMAGE pImage;
PMARK pMark;
int nMarkIndex;
HANDLE hPalette = 0;
HANDLE hBitmap = 0;
int nScaledWidth;
int nScaledHeight;
CLIP_COPY_STRUCT ClipCopy;
//LRECT lrRect;
LRECT PasteRect;
int nHScale;
int nVScale;
HANDLE hDib = 0;
PBITMAPINFOHEADER pDib = 0;
BOOL fDeletePasteDib = FALSE;
long lHScale;
long lVScale;
BOOL bClipBoardOpen = FALSE;
PSTR pBlock;
CheckError2( Init(hWnd, &pWindow, &pAnoImage, TRUE, TRUE));
// Check for operation in progress.
if (pAnoImage->Annotations.ppMarks){
pMark = pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks];
if (pMark){
OiOpEndOperation(hWnd);
pMark = pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks];
if (pMark){
OiOpEndOperation(hWnd);
}
}
}
pImage = pAnoImage->pBaseImage;
if (pParm == NULL){
nStatus = Error(DISPLAY_NULLPOINTERINVALID);
goto Exit;
}
CheckError2( ValidateCache(hWnd, pAnoImage));
if (!OpenClipboard(hWnd)){
nStatus = Error(DISPLAY_CANTOPENCLIPBOARD);
goto Exit;
}
bClipBoardOpen = TRUE;
// Delete OiError named blocks.
for (nMarkIndex = 0; nMarkIndex < pAnoImage->Annotations.nMarks; nMarkIndex++){
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
CheckError2( DeleteAMarkNamedBlock(pMark, szOiError));
}
switch (nClipAction){
case CLIP_COPY:
ClipCopy = *((PCLIP_COPY_STRUCT) pParm);
ClipCopy.nScale = SD_FULLSIZE;
ClipCopy.bUseCurrentScale = FALSE;
CheckError2( ClipboardCopy(hWnd, pWindow, pAnoImage, pImage, &ClipCopy, nFlags));
break;
case CLIP_CUT:
ClipCopy = *((PCLIP_COPY_STRUCT) pParm);
ClipCopy.nScale = SD_FULLSIZE;
ClipCopy.bUseCurrentScale = FALSE;
if (ClipCopy.lRect.right == 0){
GetSelectBox(pAnoImage, &ClipCopy.lRect);
}else{
if ((ClipCopy.lRect.right - ClipCopy.lRect.left) > 0
|| (ClipCopy.lRect.bottom - ClipCopy.lRect.top) > 0){
if (nFlags & PARM_SCALED){
ConvertRect(pWindow, &ClipCopy.lRect, CONV_SCALED_TO_FULLSIZE);
}else if (!(nFlags & PARM_FULLSIZE)){ // Default to window.
ConvertRect(pWindow, &ClipCopy.lRect, CONV_WINDOW_TO_FULLSIZE);
}
}
}
nFlags = (nFlags & ~(PARM_WINDOW | PARM_SCALED)) | PARM_FULLSIZE;
// Check permissions for delete privileges.
for (nMarkIndex = 0; nMarkIndex < pAnoImage->Annotations.nMarks; nMarkIndex++){
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
if (pMark->bSelected){
if (!(pMark->Attributes.dwPermissions & ACL_DELETE_MARK)){
pBlock = 0;
CheckError2( AddAMarkNamedBlock(pMark, szOiError, &pBlock, 1L));
nStatus = Error(DISPLAY_RESTRICTED_ACCESS);
goto Exit;
}
}
}
CheckError2( ClipboardCopy(hWnd, pWindow, pAnoImage, pImage, &ClipCopy, nFlags));
// ClipboardCopy will convert ClipCopy.lRect to FULLSIZE.
CheckError2( ClearImage(pWindow, pImage, &ClipCopy.lRect));
// Delete selected marks.
for (nMarkIndex = pAnoImage->Annotations.nMarks - 1; nMarkIndex >= 0; nMarkIndex--){
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
if (pMark->bSelected){
if ((int) pMark->Attributes.uType == OIOP_AN_FORM){
CheckError2( InvalidateAllDisplayRects(pWindow, pImage, NULL, TRUE));
}
CheckError2( DeleteMark(pAnoImage, nMarkIndex));
}
}
break;
case CLIP_PASTE:
CopyRect(PasteRect, *((LPLRECT) pParm));
if ((PasteRect.right - PasteRect.left) <= 0
|| (PasteRect.bottom - PasteRect.top) <= 0){
GetSelectBox(pAnoImage, &PasteRect);
}else{
if ((PasteRect.right - PasteRect.left) <= 0
|| (PasteRect.bottom - PasteRect.top) <= 0){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
if (nFlags & PARM_SCALED){
ConvertRect(pWindow, &PasteRect, CONV_SCALED_TO_FULLSIZE);
}else if (!(nFlags & PARM_FULLSIZE)){ // Default to window.
ConvertRect(pWindow, &PasteRect, CONV_WINDOW_TO_FULLSIZE);
}
}
if ((PasteRect.right - PasteRect.left) <= 0
|| (PasteRect.bottom - PasteRect.top) <= 0
|| PasteRect.right > pImage->nWidth
|| PasteRect.bottom > pImage->nHeight){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
// Get clipboard data.
hBitmap = GetClipboardData(CF_BITMAP);
hDib = GetClipboardData(CF_DIB);
// Don't check for errors for this call!
// No handle simply means no palette.
hPalette = GetClipboardData(CF_PALETTE);
if (!hBitmap && !hDib){
nStatus = Error(DISPLAY_NO_CLIPBOARD);
goto Exit;
}else if (hBitmap && !hDib){
CheckError2( DibFromBitmap (hBitmap, hPalette, &pDib));
fDeletePasteDib = TRUE;
}else if (hDib && hPalette){
CheckError2( CorrectDibPalette(hPalette, pDib));
}
if (!(pDib = (VOID *) GlobalLock(hDib))){
nStatus = Error(DISPLAY_CANTLOCK);
goto Exit;
}
// Do this in long math to avoid overflow.
nScaledWidth = (PasteRect.right - PasteRect.left);
nScaledHeight = (PasteRect.bottom - PasteRect.top);
lHScale = ((nScaledWidth * 1000) / (int) pDib->biWidth);
lVScale = ((nScaledHeight * 1000) / (int) pDib->biHeight);
while (((int) pDib->biWidth * lHScale / 1000) < nScaledWidth){
lHScale++;
}
while (((int) pDib->biHeight * lVScale / 1000) < nScaledHeight){
lVScale++;
}
if ((lHScale > 65535) || (lVScale > 65535) || (lHScale < 20) || (lVScale < 20)){
// Scale too big.
nStatus = Error(DISPLAY_INVALIDSCALE);
goto Exit;
}
nHScale = (lHScale);
nVScale = (lVScale);
CheckError2( RenderDibToImage(&pAnoImage->pBaseImage->pImg,
pDib, nHScale, nVScale, PasteRect));
pImage->bArchive |= ARCHIVE_PASTED_INTO_IMAGE;
if (pAnoImage->pBasePlusFormImg != pImage->pImg){
CheckError2( FreeImgBuf(&pAnoImage->pBasePlusFormImg));
CheckError2( FreeMemory((PPSTR) &pAnoImage->pBasePlusFormImg));
}
pAnoImage->nBPFValidLines = 0;
CheckError2( InvalidateAllDisplayRects(pWindow, pImage, &PasteRect, TRUE));
break;
default:
nStatus = Error(DISPLAY_INVALID_OPTIONS); // nClipAction is invalid.
goto Exit;
}
// SetLRect(lrRect, 0, 0, 0, 0);
// if (nStatus = IMGSetParmsCgbw(hWnd, PARM_SELECTION_BOX, &lrRect, PARM_FULLSIZE)){
// goto Exit;
// }
if (!(nFlags & PARM_DONT_REPAINT)){
CheckError2( IMGRepaintDisplay(hWnd, NULL));
}
Exit:
if (bClipBoardOpen){
CloseClipboard();
}
if (hDib){
GlobalUnlock(hDib);
}
if (nClipAction != CLIP_PASTE){ // Can't free handles that aren't mine.
if (hBitmap){
DeleteObject(hBitmap);
}
}
// Can't free handles that aren't mine.
if (nClipAction != CLIP_PASTE || fDeletePasteDib){
if (hDib){
GlobalFree(hDib);
}
}
DeInit(TRUE, TRUE);
return(nStatus);
}
//
/*****************************************************************************
FUNCTION: ClipboardCopy
PURPOSE: The function handles copy operations involving the clipboard.
INPUT: hWnd - Identifies the image window.
pParm - A pointer to the clipboard parameters.
nFlags - Flags indicating how or what to get the information.
*****************************************************************************/
int WINAPI ClipboardCopy(HWND hWnd, PWINDOW pWindow, PANO_IMAGE pAnoImage,
PIMAGE pImage, PCLIP_COPY_STRUCT pClipCopy, int nFlags){
int nStatus = 0;
PMARK pMark;
MARK Mark;
MARK NewMarks[4];
PMARK pNewMarks;
PMARK pMark2;
int nMarkIndex;
int nMarkIndex2;
int nMarkIndex3;
int nHScale;
int nVScale;
HANDLE hDib = 0;
PBITMAPINFOHEADER pDib = 0;
LRECT lCopyRect;
PSTR pBlock;
LRECT lrCopyBounds;
HGLOBAL hGlobal;
long lTemp;
int nNamedBlockIndex;
int nMarks = 0;
LRECT lrRect;
PAN_NEW_ROTATE_STRUCT pAnRotation =0;
// Get and validate parameters.
if (pClipCopy->lRect.right == 0){
GetSelectBox(pAnoImage, &lCopyRect);
}else{
if ((pClipCopy->lRect.right - pClipCopy->lRect.left) > 0
|| (pClipCopy->lRect.bottom - pClipCopy->lRect.top) > 0){
CopyRect(lCopyRect, pClipCopy->lRect);
if (nFlags & PARM_SCALED){
ConvertRect(pWindow, &lCopyRect, CONV_SCALED_TO_FULLSIZE);
}else if (!(nFlags & PARM_FULLSIZE)){ // Default to window.
ConvertRect(pWindow, &lCopyRect, CONV_WINDOW_TO_FULLSIZE);
}
}
}
if (lCopyRect.right > pImage->nWidth
|| lCopyRect.bottom > pImage->nHeight){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
#ifdef old
if (pClipCopy->bUseCurrentScale){
nHScale = pWindow->nScale;
}else{
nHScale = pClipCopy->nScale;
}
if (nHScale < 20){
switch (nHScale){
case SD_EIGHTXSIZE: nHScale = SCALE_DENOMINATOR * 8; break;
case SD_FOURXSIZE: nHScale = SCALE_DENOMINATOR * 4; break;
case SD_TWOXSIZE: nHScale = SCALE_DENOMINATOR * 2; break;
case SD_FULLSIZE: nHScale = SCALE_DENOMINATOR * 1; break;
case SD_HALFSIZE: nHScale = SCALE_DENOMINATOR / 2; break;
case SD_QUARTERSIZE: nHScale = SCALE_DENOMINATOR / 4; break;
case SD_EIGHTHSIZE: nHScale = SCALE_DENOMINATOR / 8; break;
case SD_SIXTEENTHSIZE: nHScale = SCALE_DENOMINATOR /16; break;
default:
nStatus = Error(DISPLAY_INVALIDSCALE);
goto Exit;
}
}
if (nHScale == 1000){
nVScale = nHScale;
}else{
CheckError2( TranslateScale(nHScale, pImage->nHRes, pImage->nVRes, &nHScale, &nVScale));
}
#endif
nHScale = 1000;
nVScale = 1000;
// Partial select all marks.
CheckError2( CheckSelection(pAnoImage, ACL_MUST_INCLUDE_IN_COPY));
// Find the bounding rect of the copy operation.
CopyRect(lrCopyBounds, lCopyRect);
if (lrCopyBounds.left == lrCopyBounds.right || lrCopyBounds.top == lrCopyBounds.bottom){
SetLRect(lrCopyBounds, pImage->nWidth + 10, pImage->nHeight + 10, 0, 0);
}
for (nMarkIndex = 0; nMarkIndex < pAnoImage->Annotations.nMarks; nMarkIndex++){
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
if (pMark->bSelected || pMark->bTempSelected){
if (!(pMark->Attributes.dwPermissions & ACL_COPY_MARK)){
pBlock = 0;
CheckError2( AddAMarkNamedBlock(pMark, szOiError, &pBlock, 1L));
nStatus = Error(DISPLAY_RESTRICTED_ACCESS);
goto Exit;
}
if (((int) pMark->Attributes.uType == OIOP_AN_LINE) ||
((int) pMark->Attributes.uType == OIOP_AN_FREEHAND) ||
((int) pMark->Attributes.uType == OIOP_AN_HOLLOW_RECT)){
lrCopyBounds.left = lmin(lrCopyBounds.left, pMark->Attributes.lrBounds.left -
(((int) pMark->Attributes.uLineSize + 1)/2));
lrCopyBounds.top = lmin(lrCopyBounds.top, pMark->Attributes.lrBounds.top -
(((int) pMark->Attributes.uLineSize + 1)/2));
lrCopyBounds.right = lmax(lrCopyBounds.right, pMark->Attributes.lrBounds.right +
(((int) pMark->Attributes.uLineSize + 1)/2));
lrCopyBounds.bottom = lmax(lrCopyBounds.bottom, pMark->Attributes.lrBounds.bottom +
(((int) pMark->Attributes.uLineSize + 1)/2));
}else{
lrCopyBounds.left = lmin(lrCopyBounds.left, pMark->Attributes.lrBounds.left);
lrCopyBounds.top = lmin(lrCopyBounds.top, pMark->Attributes.lrBounds.top);
lrCopyBounds.right = lmax(lrCopyBounds.right, pMark->Attributes.lrBounds.right);
lrCopyBounds.bottom = lmax(lrCopyBounds.bottom, pMark->Attributes.lrBounds.bottom);
}
}
}
pAnoImage->bAnoBlockUseMemOnly = TRUE;
pAnoImage->hpAnoBlock = 0;
pAnoImage->lAnoBlockIndex = 0;
pAnoImage->lAnoBlockCount = 0;
// Reserve space for length.
CheckError2( BlockedAnoWrite(hWnd, pAnoImage, 4, (PSTR) &pAnoImage->lAnoBlockCount));
CheckError2( BlockedAnoWrite(hWnd, pAnoImage, 4, (PSTR) &pAnoImage->pBaseImage->nHRes));
CheckError2( BlockedAnoWrite(hWnd, pAnoImage, 4, (PSTR) &pAnoImage->pBaseImage->nVRes));
// Set for 32 bit Intel format.
lTemp = 1;
CheckError2( BlockedAnoWrite(hWnd, pAnoImage, 4, (PSTR) &lTemp));
// Copy the image if there is a selection box on the image
if ((lCopyRect.right - lCopyRect.left) > 0
|| (lCopyRect.bottom - lCopyRect.top) > 0){
CheckError2( MakeDibFromImage(pImage, lCopyRect, &pDib, nHScale, nVScale));
pMark = &Mark;
memset(pMark, 0, sizeof(MARK));
CheckError2( MakeMarkFromDib(pDib, &pMark, pImage->nHRes, pImage->nVRes));
CheckError2( FreeMemory((PPSTR) &pDib));
SetLRect(pMark->Attributes.lrBounds,
lCopyRect.left - lrCopyBounds.left,
lCopyRect.top - lrCopyBounds.top,
lCopyRect.right - lrCopyBounds.left,
lCopyRect.bottom - lrCopyBounds.top);
pBlock = 0;
CheckError2( AddAMarkNamedBlock(pMark, szOiBaseIm, &pBlock, 1L));
CheckError2( SaveMark(hWnd, pAnoImage, pMark, nHScale, nVScale, OI_SCALE_ALG_NORMAL));
// delete the dib mark
// Free the named block info.
CheckError2( DeleteMarkNamedBlocks(pMark));
}
// Copy all selected annotation marks.
for (nMarkIndex = 0; nMarkIndex < (int) pAnoImage->Annotations.nMarks; nMarkIndex++){
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
// if it is a form type then change to image type
if ((int) pMark->Attributes.uType == OIOP_AN_FORM){
CheckError2( GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation));
(int) pMark->Attributes.uType = OIOP_AN_IMAGE;
pMark->Attributes.bTransparent = TRUE;
pAnRotation->bFormMark = TRUE;
pAnRotation->bClipboardOp = TRUE;
}
if (pMark->bSelected || pMark->bTempSelected){
if (!pMark->bSelected && pMark->bTempSelected){
pNewMarks = NewMarks;
for (nMarkIndex2 = 0; nMarkIndex2 < 4; nMarkIndex2++){
memset(&NewMarks[nMarkIndex2], 0, sizeof(MARK));
}
GetSelectBox (pAnoImage, &lrRect);
if (lrRect.left < pMark->Attributes.lrBounds.right
&& lrRect.right > pMark->Attributes.lrBounds.left
&& lrRect.top < pMark->Attributes.lrBounds.bottom
&& lrRect.bottom > pMark->Attributes.lrBounds.top){
CheckError2( CreatePartialMark(hWnd, pNewMarks, pMark, lrRect, &nMarks));
for (nMarkIndex2 = 0; nMarkIndex2 < nMarks; nMarkIndex2++){
CheckError2( SaveMark(hWnd, pAnoImage, &NewMarks[nMarkIndex2],
nHScale, nVScale, OI_SCALE_ALG_NORMAL));
if (NewMarks[nMarkIndex2].ppNamedBlock){
for (nNamedBlockIndex = 0; nNamedBlockIndex < NewMarks[nMarkIndex2].nNamedBlocks; nNamedBlockIndex++){
CheckError2( FreeMemory(&NewMarks[nMarkIndex2].ppNamedBlock[nNamedBlockIndex]->pBlock));
CheckError2( FreeMemory((PPSTR) &NewMarks[nMarkIndex2].ppNamedBlock[nNamedBlockIndex]));
}
CheckError2( FreeMemory((PPSTR) &NewMarks[nMarkIndex2].ppNamedBlock));
}
}
continue;
}
// for must include mark, check to see if there are any
// selected marks below it, if so create partial mark from
// the must include mark
for (nMarkIndex2 = nMarkIndex; nMarkIndex2 >= 0; nMarkIndex2--){
pMark2 = pAnoImage->Annotations.ppMarks[nMarkIndex2];
if (pMark2->bSelected){
if (pMark2->Attributes.lrBounds.left < pMark->Attributes.lrBounds.right
&& pMark2->Attributes.lrBounds.right > pMark->Attributes.lrBounds.left
&& pMark2->Attributes.lrBounds.top < pMark->Attributes.lrBounds.bottom
&& pMark2->Attributes.lrBounds.bottom > pMark->Attributes.lrBounds.top){
CheckError2( CreatePartialMark(hWnd, pNewMarks,
pMark, pMark2->Attributes.lrBounds, &nMarks));
for (nMarkIndex3 = 0; nMarkIndex3 < nMarks; nMarkIndex3++){
CheckError2( SaveMark(hWnd, pAnoImage, &NewMarks[nMarkIndex3],
nHScale, nVScale, OI_SCALE_ALG_NORMAL));
if (NewMarks[nMarkIndex3].ppNamedBlock){
for (nNamedBlockIndex = 0; nNamedBlockIndex
< NewMarks[nMarkIndex3].nNamedBlocks; nNamedBlockIndex++){
CheckError2( FreeMemory(&NewMarks[nMarkIndex3].ppNamedBlock[nNamedBlockIndex]->pBlock));
CheckError2( FreeMemory((PPSTR) &NewMarks[nMarkIndex3].ppNamedBlock[nNamedBlockIndex]));
}
CheckError2( FreeMemory((PPSTR) &NewMarks[nMarkIndex3].ppNamedBlock));
}
}
break;
}
}
}
}else{
SetLRect(pMark->Attributes.lrBounds,
pMark->Attributes.lrBounds.left - lrCopyBounds.left,
pMark->Attributes.lrBounds.top - lrCopyBounds.top,
pMark->Attributes.lrBounds.right - lrCopyBounds.left,
pMark->Attributes.lrBounds.bottom - lrCopyBounds.top);
CheckError2( SaveMark(hWnd, pAnoImage, pMark, nHScale, nVScale, OI_SCALE_ALG_NORMAL));
SetLRect(pMark->Attributes.lrBounds,
pMark->Attributes.lrBounds.left + lrCopyBounds.left,
pMark->Attributes.lrBounds.top + lrCopyBounds.top,
pMark->Attributes.lrBounds.right + lrCopyBounds.left,
pMark->Attributes.lrBounds.bottom + lrCopyBounds.top);
}
}
// change form mark back from image type, now that save is done
if ((int) pMark->Attributes.uType == OIOP_AN_IMAGE){
CheckError2( GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation));
if (pAnRotation->bFormMark){
(int) pMark->Attributes.uType = OIOP_AN_FORM;
pMark->Attributes.bTransparent = FALSE;
pAnRotation->bFormMark = FALSE;
pAnRotation->bClipboardOp = FALSE;
}
}
}
// Set length to correct value.
*((long *) pAnoImage->hpAnoBlock) = pAnoImage->lAnoBlockIndex;
*((long *) (pAnoImage->hpAnoBlock + 4)) = pAnoImage->pBaseImage->nHRes;
*((long *) (pAnoImage->hpAnoBlock + 8)) = pAnoImage->pBaseImage->nVRes;
// Move the data to the clipboard.
EmptyClipboard();
if (pAnoImage->pWangAnnotatedImageFormat){
CheckError2( FreeMemory(&pAnoImage->pWangAnnotatedImageFormat));
}
pAnoImage->pWangAnnotatedImageFormat = pAnoImage->hpAnoBlock;
pAnoImage->hpAnoBlock = 0;
pAnoImage->lAnoBlockIndex = 0;
pAnoImage->lAnoBlockCount = 0;
SetClipboardData(nWangAnnotatedImageFormat, NULL);
SetClipboardData(CF_DIB, NULL);
bRenderDib = TRUE;
bRenderWangAnnotatedIFormat = TRUE;
// This must remain GlobalAlloc.
if (!(hGlobal = GlobalAlloc(GHND | GMEM_DDESHARE, 1))){
nStatus = Error(DISPLAY_CANTALLOC);
goto Exit;
}
SetClipboardData(nWangAnnotationFormat, hGlobal);
bRenderWangAnnotations = TRUE;
Exit:
if (pAnoImage->hpAnoBlock){
FreeMemory(&pAnoImage->pWangAnnotatedImageFormat);
pAnoImage->hpAnoBlock = 0;
pAnoImage->lAnoBlockIndex = 0;
pAnoImage->lAnoBlockCount = 0;
}
pAnoImage->bAnoBlockUseMemOnly = FALSE;
if (hDib){
GlobalFree(hDib);
}
return(nStatus);
}
//
/*****************************************************************************
FUNCTION: StartPasteAnnotatedImage
PURPOSE: Pastes an annotated image from the clipboard.
*****************************************************************************/
int WINAPI StartPasteAnnotatedImage(HWND hWnd, PWINDOW pWindow, PANO_IMAGE pAnoImage,
PIMAGE pImage, LRECT lrRectPoint, int nFlags){
int nStatus = 0;
PMARK pMark;
PMARK pPasteMark;
int nMarkIndex;
LRECT lrPasteRect;
int nStartingMark;
int nEndingMark;
long lHOffset;
long lVOffset;
HPSTR hpClipData = 0;
HGLOBAL hClipData = 0;
int nResHScale = 0;
int nResVScale = 0;
// Get clipboard data.
// Calculate bounds of new marks.
// Deselect all.
for (nMarkIndex = 0; nMarkIndex < pAnoImage->Annotations.nMarks; nMarkIndex++){
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
pMark->bSelected = FALSE;
pMark->bTempSelected = FALSE;
}
// Save paste mark.
pPasteMark = pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks];
pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks] = 0;
// Copy marks being pasted into ppMarks.
if (!OpenClipboard(hWnd)){
nStatus = Error(DISPLAY_CANTOPENCLIPBOARD);
goto Exit;
}
if (!(hClipData = GetClipboardData(nWangAnnotatedImageFormat))){
CloseClipboard();
nStatus = Error(DISPLAY_NO_CLIPBOARD);
goto Exit;
}
CloseClipboard();
if (!(hpClipData = GlobalLock(hClipData))){
nStatus = Error(DISPLAY_CANTLOCK);
goto Exit;
}
// get the resolution adjustment stuff now
nResHScale = *((long *) (hpClipData + 4)); // (clipboard's) pBaseImage->nHRes.
nResHScale = (1000 * pImage->nHRes) / nResHScale;
nResVScale = *((long *) (hpClipData + 8)); // (clipboard's) pBaseImage->nVRes.
nResVScale = (1000 * pImage->nVRes) / nResVScale;
if (!nResHScale){
nResHScale = 1000;
}
if (!nResVScale){
nResVScale = (1000 * pImage->nHRes) / pImage->nVRes;
}
nStartingMark = pAnoImage->Annotations.nMarks;
pAnoImage->bAnoBlockUseMemOnly = TRUE;
pAnoImage->lAnoBlockCount = *((PLONG) hpClipData) - 12;
pAnoImage->hpAnoBlock = hpClipData;
pAnoImage->lAnoBlockIndex = 12;
CheckError2( ReadAnnotations(hWnd, pAnoImage,
&pAnoImage->Annotations.ppMarks, &pAnoImage->Annotations.nMarks));
nEndingMark = pAnoImage->Annotations.nMarks;
// Restore paste mark.
pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks] = pPasteMark;
// Delete the "Base Image" flag (named block) if pasting as an annotation.
if (pAnoImage->nPasteFormat == nWangAnnotationFormat){
for (nMarkIndex = nStartingMark; nMarkIndex < nEndingMark; nMarkIndex++){
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
CheckError2( DeleteAMarkNamedBlock(pMark, szOiBaseIm));
}
}
// Set paste mark's bounds.
SetLRect(lrPasteRect, 0, 0, 0, 0);
for (nMarkIndex = nStartingMark; nMarkIndex < nEndingMark; nMarkIndex++){
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
pMark->Attributes.dwPermissions = ACL_ALL;
pMark->bSelected = TRUE;
if (((int) pMark->Attributes.uType != OIOP_AN_IMAGE) &&
((int) pMark->Attributes.uType != OIOP_AN_IMAGE_BY_REFERENCE) &&
((int) pMark->Attributes.uType != OIOP_AN_FORM)){
CheckError2( ScaleAnnotation(hWnd, pMark, nResHScale, nResVScale, OI_SCALE_ALG_NORMAL));
}
lrPasteRect.right = lmax(lrPasteRect.right, pMark->Attributes.lrBounds.right);
lrPasteRect.bottom = lmax(lrPasteRect.bottom, pMark->Attributes.lrBounds.bottom);
}
// Place the data and adjust PasteRect offsets to keep pasted data on the image.
if ((nFlags & OIAN_UPPER_LEFT)){
lHOffset = lmin( pImage->nWidth - 5, lrRectPoint.right);
lVOffset = lmin( pImage->nHeight - 5, lrRectPoint.bottom);
}else{
lHOffset = lmin( pImage->nWidth - 5, lrRectPoint.right - lrPasteRect.right / 2);
lVOffset = lmin( pImage->nHeight - 5, lrRectPoint.bottom - lrPasteRect.bottom / 2);
}
lHOffset = lmax(lHOffset, -(lrPasteRect.right - 5));
lVOffset = lmax(lVOffset, -(lrPasteRect.bottom - 5));
// Adjust all mark's bounds including paste mark's bounds.
for (nMarkIndex = nStartingMark; nMarkIndex < nEndingMark; nMarkIndex++){
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
pMark->Attributes.lrBounds.left = pMark->Attributes.lrBounds.left + lHOffset;
pMark->Attributes.lrBounds.top = pMark->Attributes.lrBounds.top + lVOffset;
pMark->Attributes.lrBounds.right = pMark->Attributes.lrBounds.right + lHOffset;
pMark->Attributes.lrBounds.bottom = pMark->Attributes.lrBounds.bottom + lVOffset;
}
Exit:
if (hpClipData){
GlobalUnlock(hClipData);
}
pAnoImage->bAnoBlockUseMemOnly = 0;
pAnoImage->lAnoBlockCount = 0;
pAnoImage->hpAnoBlock = 0;
pAnoImage->lAnoBlockIndex = 0;
return(nStatus);
}
//
/*****************************************************************************
FUNCTION: StartPasteImage
PURPOSE: Pastes an image from the clipboard.
*****************************************************************************/
int WINAPI StartPasteImage(HWND hWnd, PWINDOW pWindow, PANO_IMAGE pAnoImage,
PIMAGE pImage, LRECT lrRectPoint, int nFlags){
int nStatus = 0;
PMARK pMark = 0;
PMARK pPasteMark;
int nMarkIndex;
LRECT lrPasteRect;
long lHOffset;
long lVOffset;
HGLOBAL hDib = 0;
HPSTR hpDib = 0;
PBITMAPINFOHEADER pDib = 0;
PSTR pBlock;
// Get clipboard data.
// Calculate bounds of new marks.
// Deselect all.
for (nMarkIndex = 0; nMarkIndex < pAnoImage->Annotations.nMarks; nMarkIndex++){
pMark = pAnoImage->Annotations.ppMarks[nMarkIndex];
pMark->bSelected = FALSE;
pMark->bTempSelected = FALSE;
}
// Copy Dib being pasted into ppMarks.
if (!OpenClipboard(hWnd)){
nStatus = Error(DISPLAY_CANTOPENCLIPBOARD);
goto Exit;
}
if (!(hDib = GetClipboardData(CF_DIB))){
nStatus = Error(DISPLAY_NO_CLIPBOARD);
CloseClipboard();
goto Exit;
}
CloseClipboard();
if (!(hpDib = GlobalLock(hDib))){
nStatus = Error(DISPLAY_CANTLOCK);
goto Exit;
}
pDib = (PBITMAPINFOHEADER) hpDib;
CheckError2( ReAllocateMemory(sizeof(PMARK) * (pAnoImage->Annotations.nMarks + 2),
(PPSTR) &pAnoImage->Annotations.ppMarks, ZERO_INIT));
CheckError2(AllocateMemory(sizeof(MARK), (PPSTR) &pMark, ZERO_INIT) );
// Save mark.
pPasteMark = pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks];
pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks] = pMark;
pAnoImage->Annotations.nMarks++;
pAnoImage->Annotations.ppMarks[pAnoImage->Annotations.nMarks] = pPasteMark;
CheckError2( MakeMarkFromDib(pDib, &pMark, pImage->nHRes, pImage->nVRes));
SetLRect(pMark->Attributes.lrBounds, 0, 0, (int) pDib->biWidth, (int) pDib->biHeight);
// Tag mark so it is burnt into the base image.
CheckError2( AllocateMemory(1L, &pBlock, NO_INIT));
pBlock = 0;
CheckError2( AddAMarkNamedBlock(pMark, szOiBaseIm, &pBlock, 1L));
// Set paste mark's bounds.
SetLRect(lrPasteRect, 0, 0, (int) pDib->biWidth, (int) pDib->biHeight);
pMark->Attributes.dwPermissions = ACL_ALL;
pMark->bSelected = TRUE;
// Place the data and adjust PasteRect offsets to keep pasted data on the image.
if ((nFlags & OIAN_UPPER_LEFT)){
lHOffset = lmin( pImage->nWidth - 5, lrRectPoint.right);
lVOffset = lmin( pImage->nHeight - 5, lrRectPoint.bottom);
}else{
lHOffset = lmin( pImage->nWidth - 5, lrRectPoint.right - lrPasteRect.right / 2);
lVOffset = lmin( pImage->nHeight - 5, lrRectPoint.bottom - lrPasteRect.bottom / 2);
}
lHOffset = lmax(lHOffset, -(lrPasteRect.right - 5));
lVOffset = lmax(lVOffset, -(lrPasteRect.bottom - 5));
// Adjust all mark's bounds.
pMark->Attributes.lrBounds.left = pMark->Attributes.lrBounds.left + lHOffset;
pMark->Attributes.lrBounds.top = pMark->Attributes.lrBounds.top + lVOffset;
pMark->Attributes.lrBounds.right = pMark->Attributes.lrBounds.right + lHOffset;
pMark->Attributes.lrBounds.bottom = pMark->Attributes.lrBounds.bottom + lVOffset;
Exit:
if (hpDib){
GlobalUnlock(hDib);
}
return(nStatus);
}
//
/*****************************************************************************
FUNCTION: MakeDibFromImage
PURPOSE: This will make a DIB from the specified portion of the image.
*****************************************************************************/
int WINAPI MakeDibFromImage(PIMAGE pImage, LRECT lRect, PBITMAPINFOHEADER *ppDib,
int nHScale, int nVScale){
int nStatus = 0;
PIMG pImg = 0;
RECT Rect;
PBITMAPINFOHEADER pDib = 0;
// Copy the image.
CopyRectLtoR(Rect, lRect);
if (nHScale == 1000){
CheckError2( IPtoDIB(pImage, pImage->pImg, &pDib, Rect));
}else{
CheckError2( ScaleImage(pImage->pImg, &pImg, nHScale, nVScale, Rect, 0,
pImage->PaletteTable, pImage->nPaletteEntries));
SetRect(&Rect, 0, 0, pImg->nWidth, pImg->nHeight);
CheckError2( IPtoDIB(pImage, pImg, &pDib, Rect));
}
Exit:
if (nStatus){
FreeMemory((PPSTR) &pDib);
}
FreeImgBuf(&pImg);
*ppDib = pDib;
return(nStatus);
}
//
/****************************************************************************
FUNCTION: DibFromBitmap()
PURPOSE: Will create a global memory block in DIB format that
represents the Device-dependent bitmap (DDB) passed in.
RETURNS: A handle to the DIB
****************************************************************************/
int WINAPI DibFromBitmap (HBITMAP hbm, HPALETTE hpal, PBITMAPINFOHEADER *ppDib){
int nStatus = 0;
BITMAP bm;
PBITMAPINFOHEADER pDib;
HDC hMemDC;
if (hpal == NULL){
hpal = GetStockObject(DEFAULT_PALETTE);
}
GetObject(hbm, sizeof(BITMAP), (PSTR)&bm);
CheckError2( AllocateMemory(sizeof(BITMAPINFOHEADER) + 1024, (PPSTR) &pDib, ZERO_INIT));
pDib->biSize = sizeof(BITMAPINFOHEADER);
(int) pDib->biWidth = bm.bmWidth;
(int) pDib->biHeight = bm.bmHeight;
pDib->biPlanes = 1;
pDib->biBitCount = bm.bmPlanes * bm.bmBitsPixel;
pDib->biCompression = BI_RGB;
pDib->biSizeImage = 0;
pDib->biXPelsPerMeter = 0;
pDib->biYPelsPerMeter = 0;
pDib->biClrUsed = 0;
pDib->biClrImportant = 0;
hMemDC = CreateCompatibleDC(NULL);
hpal = SelectPalette(hMemDC, hpal, FALSE);
RealizePalette(hMemDC);
// Call GetDIBits with a NULL pBits param, so it will calculate the
// biSizeImage field for us.
GetDIBits(hMemDC, hbm, 0, (int) pDib->biHeight, NULL, (PBITMAPINFO) pDib, DIB_RGB_COLORS);
// If the driver did not fill in the biSizeImage field, make one up.
if (pDib->biSizeImage == 0){
pDib->biSizeImage = (((((DWORD)bm.bmWidth * pDib->biBitCount) + 31 ) / 32) * 4)
* bm.bmHeight;
}
// Realloc the buffer big enough to hold all the bits.
CheckError2( ReAllocateMemory(pDib->biSize + PaletteSize(pDib) + pDib->biSizeImage,
(PPSTR) &pDib, NO_INIT));
CheckError2( CorrectDibPaletteHdc(hpal, pDib, hMemDC));
// Call GetDIBits with a NON-NULL pBits param, and actualy get the
// bits this time.
if (!GetDIBits(hMemDC, hbm, 0, (int) pDib->biHeight,
(PSTR) pDib + pDib->biSize + PaletteSize(pDib),
(PBITMAPINFO) pDib, DIB_RGB_COLORS)){
nStatus = Error(DISPLAY_GETBITMAPBITSFAILED);
goto Exit;
}
// This routine is called twice because GetDIBits erases the palette data.
CheckError2( CorrectDibPaletteHdc(hpal, pDib, hMemDC));
*ppDib = pDib;
Exit:
if (nStatus){
if (pDib){
FreeMemory((PPSTR) &pDib);
*ppDib = NULL;
}
}
SelectPalette(hMemDC, hpal, FALSE);
DeleteDC(hMemDC);
return(nStatus);
}
//
/****************************************************************************
FUNCTION: PaletteSize(VOID * pv)
PURPOSE: Calculates the palette size in bytes. If the info. block
is of the BITMAPCOREHEADER type, the number of colors is
multiplied by 3 to give the palette size, otherwise the
number of colors is multiplied by 4.
RETURNS: Palette size in number of bytes.
****************************************************************************/
int WINAPI PaletteSize (VOID * pv){
PBITMAPINFOHEADER pDib;
int NumColors;
pDib = (PBITMAPINFOHEADER)pv;
NumColors = DibNumColors(pDib);
if (pDib->biSize == sizeof(BITMAPCOREHEADER)){
return NumColors * sizeof(RGBTRIPLE);
}else{
return NumColors * sizeof(RGBQUAD);
}
}
//
/****************************************************************************
FUNCTION: DibNumColors
PURPOSE: Determines the number of colors in the DIB by looking at
the BitCount filed in the info block.
RETURNS: The number of colors in the DIB.
****************************************************************************/
int WINAPI DibNumColors (VOID * pv){
int bits;
PBITMAPINFOHEADER pDib;
PBITMAPCOREHEADER pbc;
pDib = ((PBITMAPINFOHEADER)pv);
pbc = ((PBITMAPCOREHEADER)pv);
/* With the BITMAPINFO format headers, the size of the palette
* is in biClrUsed, whereas in the BITMAPCORE - style headers, it
* is dependent on the bits per pixel (= 2 raised to the power of
* bits/pixel).
*/
if (pDib->biSize != sizeof(BITMAPCOREHEADER)){
if (pDib->biClrUsed != 0)
return pDib->biClrUsed;
bits = pDib->biBitCount;
}else{
bits = pbc->bcBitCount;
}
switch (bits){
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
/* A 24 bitcount DIB has no color table */
return 0;
}
}
//
/****************************************************************************
FUNCTION: IPtoDIB()
PURPOSE: Will create a global memory block in DIB format that
represents the IPpack image passed in.
****************************************************************************/
int WINAPI IPtoDIB(PIMAGE pImage, PIMG pImgSrce, PBITMAPINFOHEADER *ppDib, RECT rRect){
int nStatus = 0;
int nWidth=0;
int nWidthBytes;
int nHeight;
int nBitsPerPixel;
int nNumPaletteEntries;
int nLine;
PBYTE pAddress;
PBITMAPINFOHEADER pDib;
char *hpDib = 0;
int nLoop;
int nLeftShiftAmount;
int nRightShiftAmount;
int nStartingByte;
if (!pImgSrce){
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
goto Exit;
}
nWidth = (rRect.right - rRect.left);
nHeight = (rRect.bottom - rRect.top);
switch (pImgSrce->nType){
case ITYPE_BI_LEVEL:
nBitsPerPixel = 1;
nNumPaletteEntries = 2;
break;
case ITYPE_PAL4:
case ITYPE_GRAY4:
nBitsPerPixel = 4;
nNumPaletteEntries = 16;
break;
case ITYPE_GRAY7:
nBitsPerPixel = 8;
nNumPaletteEntries = 128;
break;
case ITYPE_PAL8:
case ITYPE_CUSPAL8:
case ITYPE_GRAY8:
nBitsPerPixel = 8;
nNumPaletteEntries = 256;
break;
case ITYPE_COMPAL8:
nBitsPerPixel = 8;
nNumPaletteEntries = NUMBER_OF_PALETTES;
break;
case ITYPE_RGB24:
case ITYPE_BGR24:
nBitsPerPixel = 24;
nNumPaletteEntries = 0;
break;
default:
nStatus = Error(DISPLAY_DATACORRUPTED);
goto Exit;
}
nStartingByte = (nBitsPerPixel * rRect.left) >> 3;
nWidthBytes = (((nWidth * nBitsPerPixel) + 31) / 32) * 4;
CheckError2( AllocateMemory(sizeof(BITMAPINFOHEADER)
+ (nNumPaletteEntries * 4) + ((ulong)nWidthBytes * nHeight),
(PPSTR) ppDib, ZERO_INIT));
pDib = *ppDib;
hpDib = (char *) pDib;
hpDib += sizeof(BITMAPINFOHEADER) + (nNumPaletteEntries * 4);
pDib->biSize = sizeof(BITMAPINFOHEADER);
(int) pDib->biWidth = nWidth;
(int) pDib->biHeight = nHeight;
pDib->biPlanes = 1;
pDib->biBitCount = nBitsPerPixel;
pDib->biCompression = BI_RGB;
pDib->biSizeImage = (ulong)nWidthBytes * nHeight;
pDib->biXPelsPerMeter = 0;
pDib->biYPelsPerMeter = 0;
pDib->biClrUsed = nNumPaletteEntries;
pDib->biClrImportant = nNumPaletteEntries;
switch (pImgSrce->nType){
case ITYPE_BI_LEVEL:
memset((PSTR) pDib + sizeof(BITMAPINFOHEADER), 0, 8);
memset((PSTR) pDib + sizeof(BITMAPINFOHEADER) + 4, 0xff, 3);
break;
case ITYPE_PAL4:
case ITYPE_PAL8:
case ITYPE_CUSPAL8:
memcpy((PSTR) pDib + sizeof(BITMAPINFOHEADER),
(PSTR)&pImage->PaletteTable, (pDib->biClrUsed * 4));
break;
case ITYPE_GRAY4:
memcpy((PSTR) pDib + sizeof(BITMAPINFOHEADER),
(PSTR)&Gray4PaletteTable, (pDib->biClrUsed * 4));
break;
case ITYPE_GRAY7:
memcpy((PSTR) pDib + sizeof(BITMAPINFOHEADER),
(PSTR)&Gray7PaletteTable, (pDib->biClrUsed * 4));
break;
case ITYPE_GRAY8:
memcpy((PSTR) pDib + sizeof(BITMAPINFOHEADER),
(PSTR)&Gray8PaletteTable, (pDib->biClrUsed * 4));
break;
case ITYPE_COMPAL8:
memcpy((PSTR) pDib + sizeof(BITMAPINFOHEADER),
(PSTR)&CommonPaletteTable, (pDib->biClrUsed * 4));
break;
case ITYPE_RGB24:
case ITYPE_BGR24:
break;
}
for (nLine = rRect.top; nLine < rRect.bottom; nLine++){
pAddress = &pImgSrce->bImageData[0] + (nLine * pImgSrce->nBytesPerLine);
pAddress += nStartingByte;
hpDib = ((char *) pDib) + sizeof(BITMAPINFOHEADER) + (nNumPaletteEntries * 4)
+ (((nHeight - (nLine - rRect.top)) - 1) * nWidthBytes);
switch (nBitsPerPixel){
case 1:
if (!(nLeftShiftAmount = rRect.left & 7)){
memcpy(hpDib, pAddress, (nWidth + 7) / 8);
}else{
nRightShiftAmount = 8 - nLeftShiftAmount;
for (nLoop = nWidth / 8; nLoop; nLoop--, hpDib++, pAddress++){
*hpDib = (*pAddress << nLeftShiftAmount)
| (*(pAddress + 1) >> nRightShiftAmount);
}
if ((nWidth & 7)){
*hpDib = *pAddress << nLeftShiftAmount;
}
if ((nWidth & 7) >= nRightShiftAmount){
*hpDib |= *(pAddress + 1) >> nRightShiftAmount;
}
}
break;
case 4:
if (rRect.left & 1){
for (nLoop = nWidth / 2; nLoop; nLoop--, hpDib++, pAddress++){
*hpDib = (*pAddress << 4) | ((*(pAddress + 1) >> 4) & 0x000f);
}
if (nWidth & 1){
*hpDib = *pAddress << 4;
}
}else{
memcpy(hpDib, pAddress, (nWidth + 1) / 2);
}
break;
case 8:
case 24:
if (pImgSrce->nType == ITYPE_RGB24){
// Convert RGB24 to BGR24.
for (nLoop = 0; nLoop < nWidth; nLoop++, pAddress += 3){
*hpDib++ = *(pAddress + 2);
*hpDib++ = *(pAddress + 1);
*hpDib++ = *(pAddress + 0);
}
}else{
memcpy(hpDib, pAddress, nWidth * nBitsPerPixel / 8);
}
break;
default:
nStatus = Error(DISPLAY_DATACORRUPTED);
goto Exit;
}
}
Exit:
return(nStatus);
}
//
/****************************************************************************
FUNCTION: DibToIpNoPal()
PURPOSE: Will create an IPpack image for a non-palettized Dib.
****************************************************************************/
int WINAPI DibToIpNoPal(PPIMG ppImg, PBITMAPINFOHEADER pDib){
int nStatus = 0;
int nWidth=0;
int nWidthBytes;
int nWidthBytesIP;
int nLine;
int nLines;
PSTR pAddress;
char *hpDib;
int nPixel;
PIMG pImg;
int nImageType;
hpDib = (char *) pDib;
// if the biClrUsed field is 0 and it is not a 24 bit image, then set the palette entries
// (biClrUsed) field manually
if (pDib->biClrUsed == 0){
if (pDib->biBitCount == 1){
pDib->biClrUsed = 2;
}
if (pDib->biBitCount == 4){
pDib->biClrUsed = 16;
}
if (pDib->biBitCount == 8){
pDib->biClrUsed = 256;
}
}
if (!(nImageType = CheckPalette((LP_FIO_RGBQUAD)
(hpDib + sizeof(BITMAPINFOHEADER)), pDib->biClrUsed))){
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
goto Exit;
}
nWidthBytesIP = ((((int) pDib->biWidth * pDib->biBitCount)
+ 7) / 8);
nWidthBytes = (((ulong)nWidthBytesIP + 3) & -4);
CheckError2( CreateAnyImgBuf(ppImg, (int) pDib->biWidth, (int) pDib->biHeight, nImageType));
pImg = *ppImg;
nLines = (int) pDib->biHeight;
for (nLine = 0; nLine < nLines; nLine++){
pAddress = &pImg->bImageData[0] + (nLine * pImg->nBytesPerLine);
if (nImageType == ITYPE_RGB24){
for (nPixel = 0; nPixel < nWidth; nPixel++){
*(pAddress + (nPixel * 3)) =
*(hpDib + sizeof(BITMAPINFOHEADER)
+ (pDib->biClrUsed * 4)
+ (((nLines - nLine) - 1) * nWidthBytes)
+ (nPixel * 3) + 2);
*(pAddress + (nPixel * 3) + 1) =
*(hpDib + sizeof(BITMAPINFOHEADER)
+ (pDib->biClrUsed * 4)
+ (((nLines - nLine) - 1) * nWidthBytes)
+ (nPixel * 3) + 1);
*(pAddress + (nPixel * 3) + 2) =
*(hpDib + sizeof(BITMAPINFOHEADER)
+ (pDib->biClrUsed * 4)
+ (((nLines - nLine) - 1) * nWidthBytes)
+ (nPixel * 3));
}
}else{
memcpy(pAddress, hpDib + sizeof(BITMAPINFOHEADER)
+ (pDib->biClrUsed * 4) + (((nLines - nLine) - 1)
* nWidthBytes), nWidthBytesIP);
}
}
Exit:
return(nStatus);
}
//
/****************************************************************************
FUNCTION: BWIpToBitmap
PURPOSE: Will create a Bitmap from an IPpack image.
****************************************************************************/
int WINAPI BWIpToBitmap (PIMG pImgSrce, PHANDLE phBitmap){
int nStatus = 0;
BITMAP Bitmap;
HANDLE hBitmapData = 0;
char *pBitmapData;
PSTR pAddress;
int nLine;
int nLines;
int nWidthBytes;
if (!(*phBitmap = CreateBitmap( pImgSrce->nWidth,
pImgSrce->nHeight, 1, 1, NULL))){
nStatus = Error(DISPLAY_CANTALLOC);
goto Exit;
}
if (!GetObject(*phBitmap, sizeof(BITMAP), (PSTR) &Bitmap)){
nStatus = Error(DISPLAY_CANTLOCK);
goto Exit;
}
nLines = pImgSrce->nHeight;
nWidthBytes = Bitmap.bmWidthBytes;
if (!(hBitmapData = GlobalAlloc(GMEM_MOVEABLE, nLines * nWidthBytes))){
nStatus = Error(DISPLAY_CANTALLOC);
goto Exit;
}
if (!(pBitmapData = (PSTR) GlobalLock(hBitmapData))){
nStatus = Error(DISPLAY_CANTLOCK);
goto Exit;
}
for (nLine = 0; nLine < nLines; nLine++){
pAddress = &pImgSrce->bImageData[0] + (nLine * pImgSrce->nBytesPerLine);
memcpy(pBitmapData + (nLine * nWidthBytes),
pAddress, nWidthBytes);
}
if (!SetBitmapBits(*phBitmap, nLines * nWidthBytes, pBitmapData)){
nStatus = Error(DISPLAY_SETBITMAPBITSFAILED);
goto Exit;
}
Exit:
if (nStatus){
if (*phBitmap){
DeleteObject(*phBitmap);
*phBitmap = NULL;
}
}
if (hBitmapData){
GlobalUnlock(hBitmapData);
GlobalFree(hBitmapData);
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: CorrectDibPalette()
PURPOSE: Will correct the palette in the DIB.
****************************************************************************/
int WINAPI CorrectDibPalette(HPALETTE hpal, PBITMAPINFOHEADER pDib){
int nStatus = 0;
HDC hMemDC;
if (hpal == NULL){
hpal = GetStockObject(DEFAULT_PALETTE);
}
hMemDC = CreateCompatibleDC(NULL);
hpal = SelectPalette(hMemDC, hpal, FALSE);
RealizePalette(hMemDC);
nStatus = CorrectDibPaletteHdc(hpal, pDib, hMemDC);
SelectPalette(hMemDC, hpal, FALSE);
DeleteDC(hMemDC);
return(nStatus);
}
//
/****************************************************************************
FUNCTION: CorrectDibPaletteHdc()
PURPOSE: Will correct the palette in the DIB.
****************************************************************************/
int WINAPI CorrectDibPaletteHdc(HPALETTE hpal, PBITMAPINFOHEADER pDib, HDC hMemDC){
int nStatus = 0;
char *hpDib;
int nPal;
if (hpal == NULL){
hpal = GetStockObject(DEFAULT_PALETTE);
}
hpDib = (char *) pDib;
if (!pDib->biClrUsed){
if (pDib->biBitCount == 1){
pDib->biClrUsed = 2;
}else if (pDib->biBitCount == 4){
pDib->biClrUsed = 16;
}else if (pDib->biBitCount == 8){
pDib->biClrUsed = 256;
}else if (pDib->biBitCount == 16){
pDib->biClrUsed = 32768;
}else if (pDib->biBitCount == 24){
pDib->biClrUsed = 0;
}
}
if (pDib->biClrUsed){
GetSystemPaletteEntries(hMemDC, 0, pDib->biClrUsed,
(PPALETTEENTRY)(hpDib + pDib->biSize));
for (nPal = 0; nPal < (int) pDib->biClrUsed; nPal++){
*(hpDib + pDib->biSize + (nPal * 4) + 3)
= *(hpDib + pDib->biSize + (nPal * 4) + 0);
*(hpDib + pDib->biSize + (nPal * 4) + 0)
= *(hpDib + pDib->biSize + (nPal * 4) + 2);
*(hpDib + pDib->biSize + (nPal * 4) + 2)
= *(hpDib + pDib->biSize + (nPal * 4) + 3);
*(hpDib + pDib->biSize + (nPal * 4) + 3) = 0;
}
}
return(nStatus);
}
//
/****************************************************************************
FUNCTION: CheckSelection(PANO_IMAGE pAnoImage, int ACL_flag)
PURPOSE: Checks mark selection states to determine which marks
need to be temporarily selected for the operation
****************************************************************************/
int WINAPI CheckSelection(PANO_IMAGE pAnoImage, int ACL_flag){
int nStatus = 0;
int nMarkIndex;
int nMarkIndex2;
PMARK far*ppMarks;
PMARK pMark;
PMARK pMark2;
LRECT lrRect;
ppMarks = pAnoImage->Annotations.ppMarks;
GetSelectBox (pAnoImage, &lrRect);
for (nMarkIndex = pAnoImage->Annotations.nMarks -1; nMarkIndex >= 0; nMarkIndex--){
pMark = ppMarks[nMarkIndex];
pMark->bTempSelected = FALSE;
if (!pMark->bSelected && (pMark->Attributes.dwPermissions & ACL_flag)){
if (lrRect.left < pMark->Attributes.lrBounds.right
&& lrRect.right > pMark->Attributes.lrBounds.left
&& lrRect.top < pMark->Attributes.lrBounds.bottom
&& lrRect.bottom > pMark->Attributes.lrBounds.top){
pMark->bTempSelected = TRUE;
continue;
}
for (nMarkIndex2 = nMarkIndex; nMarkIndex2 >= 0; nMarkIndex2--){
pMark2 = ppMarks[nMarkIndex2];
if (pMark2->bSelected){
if (pMark2->Attributes.lrBounds.left < pMark->Attributes.lrBounds.right
&& pMark2->Attributes.lrBounds.right > pMark->Attributes.lrBounds.left
&& pMark2->Attributes.lrBounds.top < pMark->Attributes.lrBounds.bottom
&& pMark2->Attributes.lrBounds.bottom > pMark->Attributes.lrBounds.top){
pMark->bTempSelected = TRUE;
break;
}
}
}
}
}
return (nStatus);
}
//
/*****************************************************************************
FUNCTION: OiAnRenderClipboardFormat
PURPOSE: To produce the Wang Annotations only or DIB format for
the clipboard from the Wang Annotations Image format
*****************************************************************************/
int WINAPI OiAnRenderClipboardFormat(HWND hWnd, UINT uType){
int nStatus;
PWINDOW pWindow;
PANO_IMAGE pAnoImage;
PIMAGE pImage;
int nType = uType;
HANDLE hLocalWangAnnotatedImageFormat;
HPSTR hpLocalWangAnnotatedImageFormat;
long lMarksSize;
PMARK *ppClipboardMarks = 0;
int nMarks = 0;
PIMG pDummyImg = 0;
LRECT lrBounds;
int nMarkIndex;
PBITMAPINFOHEADER pDib = 0;
PMARK pMark;
int nOldScale;
long lOldHOff;
long lOldVOff;
PAN_IMAGE_STRUCT pAnImage = 0;
int nLoop;
int nNamedBlockIndex;
long lSizeofBlock;
HANDLE hGDib = 0;
PBITMAPINFOHEADER pGDib = 0;
int nHScale;
int nVScale;
if (nStatus = Init(hWnd, &pWindow, &pAnoImage, FALSE, FALSE)){
if (nStatus == DISPLAY_IHANDLEINVALID){
nStatus = 0;
goto Exit;
}
goto Exit;
}
pImage = pAnoImage->pBaseImage;
if (!(bRenderWangAnnotatedIFormat && (!nType || nType == nWangAnnotatedImageFormat))
&& !(bRenderWangAnnotations && (!nType || nType == nWangAnnotationFormat))
&& !(bRenderDib && (!nType || nType == CF_DIB))){
// Nothing to do.
goto Exit;
}
/* we always render at full scale */
CheckError2( TranslateScale(1000, pImage->nHRes, pImage->nVRes, &nHScale, &nVScale));
if (nType && nType != CF_DIB && nType != nWangAnnotatedImageFormat
&& nType != nWangAnnotationFormat){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
if (!pAnoImage->pWangAnnotatedImageFormat){
Error2(DISPLAY_NO_CLIPBOARD); // No data to render, but dont return error
goto Exit;
}
if ((!nType || nType == nWangAnnotatedImageFormat) && bRenderWangAnnotatedIFormat){
if (!(hLocalWangAnnotatedImageFormat = GlobalAlloc(GMEM_DDESHARE,
*((long *) pAnoImage->pWangAnnotatedImageFormat)))){
nStatus = Error(DISPLAY_CANTALLOC);
goto Exit;
}
if (!(hpLocalWangAnnotatedImageFormat = GlobalLock(hLocalWangAnnotatedImageFormat))){
nStatus = Error(DISPLAY_CANTLOCK);
goto Exit;
}
memcpy (hpLocalWangAnnotatedImageFormat, pAnoImage->pWangAnnotatedImageFormat,
*((long *) pAnoImage->pWangAnnotatedImageFormat));
GlobalUnlock(hLocalWangAnnotatedImageFormat);
SetClipboardData(nWangAnnotatedImageFormat, hLocalWangAnnotatedImageFormat);
bRenderWangAnnotatedIFormat = FALSE;
}
if ((!nType || nType == nWangAnnotationFormat) && bRenderWangAnnotations){
bRenderWangAnnotations = FALSE;
}
if ((!nType || nType == CF_DIB) && bRenderDib){
lMarksSize = *((long *) pAnoImage->pWangAnnotatedImageFormat);
CheckError2( AllocateMemory(lMarksSize, (PPSTR) &ppClipboardMarks, ZERO_INIT));
memset((PBYTE) ppClipboardMarks, 0, lMarksSize);
pAnoImage->hpAnoBlock = pAnoImage->pWangAnnotatedImageFormat;
pAnoImage->lAnoBlockIndex = 12;
pAnoImage->lAnoBlockCount = lMarksSize - 12;
pAnoImage->bAnoBlockUseMemOnly = TRUE;
CheckError2( ReadAnnotations(hWnd, pAnoImage, &ppClipboardMarks, &nMarks));
pAnoImage->hpAnoBlock = NULL;
pAnoImage->lAnoBlockIndex = 0;
pAnoImage->lAnoBlockCount = 0;
pAnoImage->bAnoBlockUseMemOnly = 0;
if (*ppClipboardMarks == 0){
// mark might not always exist, example when the application goes away
// and does not have marks saved in the memory block.
goto Exit;
}
pMark = ppClipboardMarks[0];
CopyRect (lrBounds, pMark->Attributes.lrBounds);
for (nMarkIndex = 0; nMarkIndex < nMarks; nMarkIndex++){
pMark = ppClipboardMarks[nMarkIndex];
if (((int) pMark->Attributes.uType == OIOP_AN_LINE)
|| ((int) pMark->Attributes.uType == OIOP_AN_FREEHAND)
|| ((int) pMark->Attributes.uType == OIOP_AN_HOLLOW_RECT)){
lrBounds.left = lmin(lrBounds.left,
pMark->Attributes.lrBounds.left - (((int) pMark->Attributes.uLineSize + 1)/2));
lrBounds.top = lmin(lrBounds.top,
pMark->Attributes.lrBounds.top - (((int) pMark->Attributes.uLineSize + 1)/2));
lrBounds.right = lmax(lrBounds.right,
pMark->Attributes.lrBounds.right + (((int) pMark->Attributes.uLineSize + 1)/2));
lrBounds.bottom = lmax(lrBounds.bottom,
pMark->Attributes.lrBounds.bottom + (((int) pMark->Attributes.uLineSize + 1)/2));
}else{
lrBounds.left = lmin(lrBounds.left, pMark->Attributes.lrBounds.left);
lrBounds.top = lmin(lrBounds.top, pMark->Attributes.lrBounds.top);
lrBounds.right = lmax(lrBounds.right, pMark->Attributes.lrBounds.right);
lrBounds.bottom = lmax(lrBounds.bottom, pMark->Attributes.lrBounds.bottom);
}
}
// if there is only one mark, and it is an image type then dont call
// render, which will change the image to 24 bit rgb or bw. Convert it
// to a dib as is, so that for example if an 8 bit pal image is cut, the
// data can be pasted back into it
if ((int) pMark->Attributes.uType == OIOP_AN_IMAGE && nMarks == 1){
CheckError2( GetAMarkNamedBlock(pMark, szOiDIB, (PPSTR) &pAnImage));
if (!pAnImage){
nStatus = Error(DISPLAY_CANTLOCK);
goto Exit;
}
for (nNamedBlockIndex = 0; nNamedBlockIndex
< pMark->nNamedBlocks; nNamedBlockIndex++){
if (!memcmp(pMark->ppNamedBlock[nNamedBlockIndex]->szName, szOiDIB, 8)){
lSizeofBlock = pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
}
}
if (!(hGDib = GlobalAlloc(GHND | GMEM_DDESHARE, lSizeofBlock))){
nStatus = Error(DISPLAY_CANTALLOC);
goto Exit;
}
if (!(pGDib = (VOID *) GlobalLock(hGDib))){
nStatus = Error(DISPLAY_CANTLOCK);
goto Exit;
}
memcpy(pGDib, (PSTR) pAnImage, lSizeofBlock);
GlobalUnlock(hGDib);
}else{
nOldScale = pWindow->nScale;
pWindow->nScale = 1000;
lOldHOff = pWindow->lHOffset;
lOldVOff = pWindow->lVOffset;
pWindow->lHOffset = 0L;
pWindow->lVOffset = 0L;
#ifdef new
hDCScreen = GetDC(hWnd);
CheckError2( GetDisplayValues(hWnd, pWindow, pImage, &nDisplayPalette, &nDisplayType,
&nNumberOfPaletteEntries, &hPalette, &bForceBackgroundPalette));
if (hPalette){
hOldPaletteScreen = SelectPalette(hDCScreen, hPalette, bForceBackgroundPalette);
RealizePalette(hDCScreen);
}
if (!(hDCMemory = CreateCompatibleDC(hDCScreen))){
nStatus = Error(DISPLAY_SETBITMAPBITSFAILED);
goto Exit;
}
if (!(hBitmapMemory = CreateCompatibleBitmap(hDCScreen,
(int)(lrBounds.right - lrBounds.left),
(int)(lrBounds.bottom - lrBounds.top)))){
nStatus = Error(DISPLAY_SETBITMAPBITSFAILED);
goto Exit;
}
hOldBitmapMemory = SelectObject(hDCMemory, hBitmapMemory);
SetLRect(lrTemp, 0, 0, 0, 0);
SetRRect(rRepaintRect, 0, 0, lrBounds.right - lrBounds.left,
lrBounds.bottom - lrBounds.top);
// Make background area white (image is a mark).
BitBlt(hDCMemory, 0, 0, rRepaintRect.right, rRepaintRect.bottom,
NULL, 0, 0, WHITENESS);
// Draw annotation stuff here.
for (nMarkIndex = 0; nMarkIndex < *pnMarks; nMarkIndex++){
pMark = (*pppMarks)[nMarkIndex];
if ((int) pMark->Attributes.uType == OIOP_AN_IMAGE){
CheckError2( GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation));
if (pAnRotation && pAnRotation->bFormMark){
pAnRotation->bClipboardOp = TRUE;
break;
}
}
}
CheckError2( PaintAnnotations(hWnd, *phDCMem, pWindow, pImage, *prRepaintRect,
PaintAnnoFlag, bPaintSelectedWithoutHandles, 1000, nHScale, nVScale, 0, 0,
&(*pppMarks), &(*pnMarks), OIAN_CLIPBOARD_OPERATION, bUseBilevelDithering,
DONT_FORCE_OPAQUE_RECTANGLES));
if (pAnRotation && !pAnRotation->bFormMark){
pAnRotation->bClipboardOp = FALSE;
}
#endif
if (nStatus = RenderIP (hWnd, NULL, pWindow, pImage, pImage->pImg,
&pDummyImg, lrBounds, 0, FALSE, SAVE_ANO_ALL, &pDib, TRUE,
&ppClipboardMarks, &nMarks, nHScale, nVScale)){
/* restore the actual display scale */
pWindow->nScale = nOldScale;
pWindow->lHOffset = lOldHOff;
pWindow->lVOffset = lOldVOff;
goto Exit;
}
/* restore the actual display scale */
pWindow->nScale = nOldScale;
pWindow->lHOffset = lOldHOff;
pWindow->lVOffset = lOldVOff;
lSizeofBlock = sizeof(BITMAPINFOHEADER) + (pDib->biClrUsed * 4) + pDib->biSizeImage;
// This must remain GlobalAlloc.
if (!(hGDib = GlobalAlloc(GHND | GMEM_DDESHARE, lSizeofBlock))){
nStatus = Error(DISPLAY_CANTALLOC);
goto Exit;
}
if(!(pGDib = (VOID *) GlobalLock(hGDib))){
nStatus = Error(DISPLAY_CANTLOCK);
goto Exit;
}
memcpy(pGDib, pDib, lSizeofBlock);
GlobalUnlock(hGDib);
CheckError2( FreeMemory((PPSTR) &pDib));
}
// Move the data to the clipboard.
SetClipboardData(CF_DIB, hGDib);
hGDib = 0;
bRenderDib = FALSE;
}
Exit:
if (ppClipboardMarks){
// free the local clipboard marks memory
for (nLoop = nMarks; nLoop; nLoop--){
pMark = ppClipboardMarks[nLoop - 1];
DeleteMarkNamedBlocks(pMark);
FreeMemory((PPSTR) &ppClipboardMarks[nLoop - 1]);
}
FreeMemory((PPSTR) ppClipboardMarks);
}
if (hGDib){
GlobalUnlock(hGDib);
GlobalFree(hGDib);
}
DeInit(FALSE, FALSE);
return (nStatus);
}
//
/*****************************************************************************
FUNCTION: CreatePartialMark
PURPOSE: To create a partial mark based on the ACL bit set to
must include. It is a new mark which includes only a
portion of the original mark
*****************************************************************************/
int WINAPI CreatePartialMark (HWND hWnd, PMARK pNewMarks, PMARK pMark,
LRECT lrCopyBounds, PINT pnMarks){
int nStatus = 0;
PAN_POINTS pPoints = 0;
int nNamedBlockIndex;
PSTR pBlock;
LRECT lrRect;
PWINDOW pWindow;
PANO_IMAGE pAnoImage;
PBITMAPINFOHEADER pDib;
PBITMAPINFOHEADER pDisplayDib;
PAN_IMAGE_STRUCT pAnImage = 0;
PAN_IMAGE_STRUCT pDisplayAnImage = 0;
PAN_IMAGE_STRUCT pNewMarkDisplayAnImage = 0;
int nWidthBytes;
int nNewWidthBytes;
PBITMAPINFOHEADER pNewDib = 0;
int nLine;
int nStartLine, nEndLine;
int nLeft, nRight;
int nLoop;
int nShiftLeft, nShiftRight;
BYTE LeftByte, RightByte;
int nNewDibLine, nNewDibLoop;
int nTemp;
int nRightPixels;
int nPixelsPerByte;
PAN_NAME_STRUCT pAnName =0;
PSTR pFileName;
HANDLE hdib = 0;
char FileName[256];
PAN_NEW_ROTATE_STRUCT pAnRotation = 0;
PAN_NEW_ROTATE_STRUCT pAnNewMarkRotation = 0;
CheckError2( Init(hWnd, &pWindow, &pAnoImage, FALSE, TRUE));
memcpy (&pNewMarks[0].Attributes, &pMark->Attributes,
sizeof(OIAN_MARK_ATTRIBUTES));
switch ((int) pMark->Attributes.uType){
case OIOP_AN_LINE:
//copy all named blocks from old mark to new mark
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK) * (pNewMarks[0].nNamedBlocks + 1),
(PPSTR) &pNewMarks[0].ppNamedBlock, ZERO_INIT));
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
(PPSTR) &pNewMarks[0].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
memcpy (pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->lSize =
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
memcpy(pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->szName,
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
pNewMarks[0].nNamedBlocks++;
}
CheckError2( GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pPoints));
SetLRect(lrRect, pPoints->ptPoint[0].x + pMark->Attributes.lrBounds.left,
pPoints->ptPoint[0].y + pMark->Attributes.lrBounds.top,
pPoints->ptPoint[1].x + pMark->Attributes.lrBounds.left,
pPoints->ptPoint[1].y + pMark->Attributes.lrBounds.top);
ConvertRect(pWindow, &lrRect, CONV_FULLSIZE_TO_WINDOW);
if (ReduceLineToLRect(&lrRect, lrCopyBounds)){
ConvertRect(pWindow, &lrRect, CONV_WINDOW_TO_FULLSIZE);
pPoints = 0;
CheckError2( AddAMarkNamedBlock(&pNewMarks[0], szOiAnoDat,
(PPSTR) &pPoints, sizeof(AN_POINTS) + (sizeof(POINT) * 2)));
pPoints->nMaxPoints = 2;
pPoints->nPoints = 2;
if (lrRect.left < lrRect.right){
pNewMarks[0].Attributes.lrBounds.left = lrRect.left - lrCopyBounds.left;
pNewMarks[0].Attributes.lrBounds.right = lrRect.right - lrCopyBounds.left;
}else{
pNewMarks[0].Attributes.lrBounds.left = lrRect.right - lrCopyBounds.left;
pNewMarks[0].Attributes.lrBounds.right = lrRect.left - lrCopyBounds.left;
}
if (lrRect.top < lrRect.bottom){
pNewMarks[0].Attributes.lrBounds.top = lrRect.top - lrCopyBounds.top;
pNewMarks[0].Attributes.lrBounds.bottom = lrRect.bottom - lrCopyBounds.top;
}else{
pNewMarks[0].Attributes.lrBounds.top = lrRect.bottom - lrCopyBounds.top;
pNewMarks[0].Attributes.lrBounds.bottom = lrRect.top - lrCopyBounds.top;
}
pPoints->ptPoint[0].x = (int) ((lrRect.left - lrCopyBounds.left)
- pNewMarks[0].Attributes.lrBounds.left);
pPoints->ptPoint[0].y = (int) ((lrRect.top - lrCopyBounds.top)
- pNewMarks[0].Attributes.lrBounds.top);
pPoints->ptPoint[1].x = (int) ((lrRect.right - lrCopyBounds.left)
- pNewMarks[0].Attributes.lrBounds.left);
pPoints->ptPoint[1].y = (int) ((lrRect.bottom - lrCopyBounds.top)
- pNewMarks[0].Attributes.lrBounds.top);
*pnMarks = 1;
}
break;
case OIOP_AN_FILLED_RECT:
//copy all named blocks from old mark to new mark
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
* (pNewMarks[0].nNamedBlocks + 1),
(PPSTR) &pNewMarks[0].ppNamedBlock, ZERO_INIT));
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
(PPSTR) &pNewMarks[0].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, ZERO_INIT));
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
memcpy (pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->lSize =
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
memcpy(pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->szName,
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
pNewMarks[0].nNamedBlocks++;
}
if (pMark->Attributes.lrBounds.left < lrCopyBounds.left){
pNewMarks[0].Attributes.lrBounds.left = 0;
}else{
pNewMarks[0].Attributes.lrBounds.left =
pMark->Attributes.lrBounds.left - lrCopyBounds.left;
}
if (pMark->Attributes.lrBounds.right > lrCopyBounds.right){
pNewMarks[0].Attributes.lrBounds.right =
lrCopyBounds.right - lrCopyBounds.left;
}else{
pNewMarks[0].Attributes.lrBounds.right =
pMark->Attributes.lrBounds.right - lrCopyBounds.left;
}
if (pMark->Attributes.lrBounds.top < lrCopyBounds.top){
pNewMarks[0].Attributes.lrBounds.top = 0;
}else{
pNewMarks[0].Attributes.lrBounds.top =
pMark->Attributes.lrBounds.top - lrCopyBounds.top;
}
if (pMark->Attributes.lrBounds.bottom > lrCopyBounds.bottom){
pNewMarks[0].Attributes.lrBounds.bottom =
lrCopyBounds.bottom - lrCopyBounds.top;
}else{
pNewMarks[0].Attributes.lrBounds.bottom =
pMark->Attributes.lrBounds.bottom - lrCopyBounds.top;
}
*pnMarks = 1;
break;
case OIOP_AN_HOLLOW_RECT:
*pnMarks = 0;
// if the hollow rect is wholly contained, then dont break it
// np into lines, just adjust its bounds
if (pMark->Attributes.lrBounds.left >= lrCopyBounds.left &&
pMark->Attributes.lrBounds.right <= lrCopyBounds.right &&
pMark->Attributes.lrBounds.top >= lrCopyBounds.top &&
pMark->Attributes.lrBounds.bottom <= lrCopyBounds.bottom){
memcpy (&pNewMarks[*pnMarks].Attributes, &pMark->Attributes,
sizeof(OIAN_MARK_ATTRIBUTES));
//copy all named blocks from old mark to new mark
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
* (pNewMarks[*pnMarks].nNamedBlocks + 1),
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock, ZERO_INIT));
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
memcpy (pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->lSize =
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
memcpy(pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->szName,
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
pNewMarks[*pnMarks].nNamedBlocks++;
}
pNewMarks[*pnMarks].Attributes.lrBounds.left =
pMark->Attributes.lrBounds.left - lrCopyBounds.left;
pNewMarks[*pnMarks].Attributes.lrBounds.right =
pMark->Attributes.lrBounds.right - lrCopyBounds.left;
pNewMarks[*pnMarks].Attributes.lrBounds.top =
pMark->Attributes.lrBounds.top - lrCopyBounds.top;
pNewMarks[*pnMarks].Attributes.lrBounds.bottom =
pMark->Attributes.lrBounds.bottom - lrCopyBounds.top;
(*pnMarks)++;
goto Exit; // not an error
}
if (pMark->Attributes.lrBounds.right <= lrCopyBounds.right){
memcpy (&pNewMarks[*pnMarks].Attributes, &pMark->Attributes,
sizeof(OIAN_MARK_ATTRIBUTES));
//copy all named blocks from old mark to new mark
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
* (pNewMarks[*pnMarks].nNamedBlocks + 1),
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock, ZERO_INIT));
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
memcpy (pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->lSize =
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
memcpy(pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->szName,
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
pNewMarks[*pnMarks].nNamedBlocks++;
}
pPoints = 0;
CheckError2( AddAMarkNamedBlock(&pNewMarks[*pnMarks], szOiAnoDat,
(PPSTR) &pPoints, sizeof(AN_POINTS) + (sizeof(POINT) * 2)));
pPoints->nMaxPoints = 2;
pPoints->nPoints = 2;
pNewMarks[*pnMarks].Attributes.uType = OIOP_AN_LINE;
pNewMarks[*pnMarks].Attributes.lrBounds.left =
pMark->Attributes.lrBounds.right - lrCopyBounds.left;
pNewMarks[*pnMarks].Attributes.lrBounds.right =
pNewMarks[*pnMarks].Attributes.lrBounds.left;
pNewMarks[*pnMarks].Attributes.lrBounds.top = lmax(0,
pMark->Attributes.lrBounds.top - lrCopyBounds.top);
pNewMarks[*pnMarks].Attributes.lrBounds.bottom =
lmin(lrCopyBounds.bottom - lrCopyBounds.top,
pMark->Attributes.lrBounds.bottom - lrCopyBounds.top);
pPoints->ptPoint[0].x = 0;
pPoints->ptPoint[0].y = 0;
pPoints->ptPoint[1].x = 0;
pPoints->ptPoint[1].y = (int) (pNewMarks[*pnMarks].Attributes.lrBounds.bottom
- pNewMarks[*pnMarks].Attributes.lrBounds.top);
(*pnMarks)++;
}
if (pMark->Attributes.lrBounds.left >= lrCopyBounds.left){
memcpy (&pNewMarks[*pnMarks].Attributes, &pMark->Attributes,
sizeof(OIAN_MARK_ATTRIBUTES));
//copy all named blocks from old mark to new mark
for (nNamedBlockIndex = 0; nNamedBlockIndex < pMark->nNamedBlocks; nNamedBlockIndex++){
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
* (pNewMarks[*pnMarks].nNamedBlocks + 1),
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock, ZERO_INIT));
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
memcpy (pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->lSize =
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
memcpy(pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->szName,
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
pNewMarks[*pnMarks].nNamedBlocks++;
}
pPoints = 0;
CheckError2( AddAMarkNamedBlock(&pNewMarks[*pnMarks], szOiAnoDat,
(PPSTR) &pPoints, sizeof(AN_POINTS) + (sizeof(POINT) * 2)));
pPoints->nMaxPoints = 2;
pPoints->nPoints = 2;
pNewMarks[*pnMarks].Attributes.uType = OIOP_AN_LINE;
pNewMarks[*pnMarks].Attributes.lrBounds.left =
pMark->Attributes.lrBounds.left - lrCopyBounds.left;
pNewMarks[*pnMarks].Attributes.lrBounds.right =
pNewMarks[*pnMarks].Attributes.lrBounds.left;
pNewMarks[*pnMarks].Attributes.lrBounds.top = lmax(0,
pMark->Attributes.lrBounds.top - lrCopyBounds.top);
pNewMarks[*pnMarks].Attributes.lrBounds.bottom =
lmin(lrCopyBounds.bottom - lrCopyBounds.top,
pMark->Attributes.lrBounds.bottom - lrCopyBounds.top);
pPoints->ptPoint[0].x = 0;
pPoints->ptPoint[0].y = 0;
pPoints->ptPoint[1].x = 0;
pPoints->ptPoint[1].y = (int) (pNewMarks[*pnMarks].Attributes.lrBounds.bottom
- pNewMarks[*pnMarks].Attributes.lrBounds.top);
(*pnMarks)++;
}
if (pMark->Attributes.lrBounds.bottom <= lrCopyBounds.bottom){
memcpy (&pNewMarks[*pnMarks].Attributes, &pMark->Attributes,
sizeof(OIAN_MARK_ATTRIBUTES));
//copy all named blocks from old mark to new mark
for (nNamedBlockIndex = 0; nNamedBlockIndex <
pMark->nNamedBlocks; nNamedBlockIndex++){
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
* (pNewMarks[*pnMarks].nNamedBlocks + 1),
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock, ZERO_INIT));
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
memcpy (pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->lSize =
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
memcpy(pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->szName,
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
pNewMarks[*pnMarks].nNamedBlocks++;
}
pPoints = 0;
CheckError2( AddAMarkNamedBlock(&pNewMarks[*pnMarks], szOiAnoDat,
(PPSTR) &pPoints, sizeof(AN_POINTS) + (sizeof(POINT) * 2)));
pPoints->nMaxPoints = 2;
pPoints->nPoints = 2;
pNewMarks[*pnMarks].Attributes.uType = OIOP_AN_LINE;
pNewMarks[*pnMarks].Attributes.lrBounds.left =
lmax(0, pMark->Attributes.lrBounds.left - lrCopyBounds.left);
pNewMarks[*pnMarks].Attributes.lrBounds.right =
lmin(pMark->Attributes.lrBounds.right - lrCopyBounds.left,
lrCopyBounds.right - lrCopyBounds.left);
pNewMarks[*pnMarks].Attributes.lrBounds.top =
pMark->Attributes.lrBounds.bottom - lrCopyBounds.top;
pNewMarks[*pnMarks].Attributes.lrBounds.bottom =
pNewMarks[*pnMarks].Attributes.lrBounds.top;
pPoints->ptPoint[0].x = 0;
pPoints->ptPoint[0].y = 0;
pPoints->ptPoint[1].x = (int) (pNewMarks[*pnMarks].Attributes.lrBounds.right
- pNewMarks[*pnMarks].Attributes.lrBounds.left);
pPoints->ptPoint[1].y = 0;
(*pnMarks)++;
}
if (pMark->Attributes.lrBounds.top >= lrCopyBounds.top){
memcpy (&pNewMarks[*pnMarks].Attributes, &pMark->Attributes,
sizeof(OIAN_MARK_ATTRIBUTES));
//copy all named blocks from old mark to new mark
for (nNamedBlockIndex = 0; nNamedBlockIndex <
pMark->nNamedBlocks; nNamedBlockIndex++){
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
* (pNewMarks[*pnMarks].nNamedBlocks + 1),
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock, ZERO_INIT));
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
(PPSTR) &pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
memcpy (pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->lSize =
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
memcpy(pNewMarks[*pnMarks].ppNamedBlock[nNamedBlockIndex]->szName,
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
pNewMarks[*pnMarks].nNamedBlocks++;
}
pPoints = 0;
CheckError2( AddAMarkNamedBlock(&pNewMarks[*pnMarks], szOiAnoDat,
(PPSTR) &pPoints, sizeof(AN_POINTS) + (sizeof(POINT) * 2)));
pPoints->nMaxPoints = 2;
pPoints->nPoints = 2;
pNewMarks[*pnMarks].Attributes.uType = OIOP_AN_LINE;
pNewMarks[*pnMarks].Attributes.lrBounds.left =
lmax(0, pMark->Attributes.lrBounds.left - lrCopyBounds.left);
pNewMarks[*pnMarks].Attributes.lrBounds.right =
lmin(pMark->Attributes.lrBounds.right - lrCopyBounds.left,
lrCopyBounds.right - lrCopyBounds.left);
pNewMarks[*pnMarks].Attributes.lrBounds.top =
pMark->Attributes.lrBounds.top - lrCopyBounds.top;
pNewMarks[*pnMarks].Attributes.lrBounds.bottom =
pNewMarks[*pnMarks].Attributes.lrBounds.top;
pPoints->ptPoint[0].x = 0;
pPoints->ptPoint[0].y = 0;
pPoints->ptPoint[1].x = (int) (pNewMarks[*pnMarks].Attributes.lrBounds.right -
pNewMarks[*pnMarks].Attributes.lrBounds.left);
pPoints->ptPoint[1].y = 0;
(*pnMarks)++;
}
break;
case OIOP_AN_TEXT:
case OIOP_AN_TEXT_FROM_A_FILE:
case OIOP_AN_TEXT_STAMP:
case OIOP_AN_ATTACH_A_NOTE:
//copy all named blocks from old mark to new mark
for (nNamedBlockIndex = 0; nNamedBlockIndex <
pMark->nNamedBlocks; nNamedBlockIndex++){
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK) * (pNewMarks[0].nNamedBlocks + 1),
(PPSTR) &pNewMarks[0].ppNamedBlock, ZERO_INIT));
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
(PPSTR) &pNewMarks[0].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
memcpy (pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->lSize =
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
memcpy(pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->szName,
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
pNewMarks[0].nNamedBlocks++;
}
// set text rect to a filled rect the color of the background
pNewMarks[0].Attributes.uType = OIOP_AN_FILLED_RECT;
pNewMarks[0].Attributes.lrBounds.left =
lmax(0, pMark->Attributes.lrBounds.left - lrCopyBounds.left);
pNewMarks[0].Attributes.lrBounds.right = lmin(pMark->Attributes.lrBounds.right - lrCopyBounds.left,
lrCopyBounds.right - lrCopyBounds.left);
pNewMarks[0].Attributes.lrBounds.top = lmax(0, pMark->Attributes.lrBounds.top - lrCopyBounds.top);
pNewMarks[0].Attributes.lrBounds.bottom = lmin(pMark->Attributes.lrBounds.bottom - lrCopyBounds.top,
lrCopyBounds.bottom - lrCopyBounds.top);
(*pnMarks)++;
break;
case OIOP_AN_IMAGE:
case OIOP_AN_IMAGE_BY_REFERENCE:
case OIOP_AN_FORM:
//copy all named blocks from old mark to new mark
for (nNamedBlockIndex = 0; nNamedBlockIndex <
pMark->nNamedBlocks; nNamedBlockIndex++){
CheckError2( ReAllocateMemory(sizeof(PNAMED_BLOCK)
* (pNewMarks[0].nNamedBlocks + 1),
(PPSTR) &pNewMarks[0].ppNamedBlock, ZERO_INIT));
CheckError2( AllocateMemory(sizeof(NAMED_BLOCK),
(PPSTR) &pNewMarks[0].ppNamedBlock[nNamedBlockIndex], ZERO_INIT));
CheckError2( AllocateMemory(pMark->ppNamedBlock[nNamedBlockIndex]->lSize, &pBlock, NO_INIT));
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock = pBlock;
memcpy(pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->pBlock,
pMark->ppNamedBlock[nNamedBlockIndex]->lSize);
pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->lSize =
pMark->ppNamedBlock[nNamedBlockIndex]->lSize;
memcpy(pNewMarks[0].ppNamedBlock[nNamedBlockIndex]->szName,
pMark->ppNamedBlock[nNamedBlockIndex]->szName, 8);
pNewMarks[0].nNamedBlocks++;
}
CheckError2( GetAMarkNamedBlock(pMark, szOiDIB, (PPSTR) &pAnImage));
if (!pAnImage){ // create the dib from the name
CheckError2( GetAMarkNamedBlock(pMark, szOiFilNam, (PPSTR) &pAnName));
if (!pAnName){
nStatus = Error(DISPLAY_DATACORRUPTED);
goto Exit;
}
pFileName = FileName;
GetFileName (pFileName, (PSTR) pAnName->name);
CheckError2( OiImageToDib(hWnd, pFileName, &pDib));
pAnImage = 0;
CheckError2( AddAMarkNamedBlock(pMark, szOiDIB,
(PPSTR) &pAnImage, sizeof(BITMAPINFOHEADER)
+ (pDib->biClrUsed*4) + (pDib->biSizeImage)));
memcpy (pAnImage->dibInfo, pDib,
sizeof(BITMAPINFOHEADER) + (pDib->biClrUsed*4) + (pDib->biSizeImage));
}else{
pDib = (PBITMAPINFOHEADER) pAnImage;
}
CheckError2( GetAMarkNamedBlock(pMark, szOiZDpDIB, (PPSTR) &pDisplayAnImage));
if (!pDisplayAnImage){
CheckError2( GetAMarkNamedBlock(pMark, szOiAnoDat, (PPSTR) &pAnRotation));
if (pAnRotation == 0){
nStatus = Error (DISPLAY_DATACORRUPTED);
goto Exit;
}
CheckError2( ConvResolutionAnoBitmap(hWnd, pMark, pAnRotation->rotation, OI_SCALE_ALG_NORMAL));
CheckError2( GetAMarkNamedBlock(pMark, szOiZDpDIB, (PPSTR) &pDisplayAnImage));
}
pDisplayDib = (PBITMAPINFOHEADER) pDisplayAnImage;
pNewMarks[0].Attributes.lrBounds.left =
lmax(0, pMark->Attributes.lrBounds.left - lrCopyBounds.left);
pNewMarks[0].Attributes.lrBounds.right =
lmin(pMark->Attributes.lrBounds.right - lrCopyBounds.left,
lrCopyBounds.right - lrCopyBounds.left);
pNewMarks[0].Attributes.lrBounds.top =
lmax(0, pMark->Attributes.lrBounds.top - lrCopyBounds.top);
pNewMarks[0].Attributes.lrBounds.bottom =
lmin(pMark->Attributes.lrBounds.bottom - lrCopyBounds.top,
lrCopyBounds.bottom - lrCopyBounds.top);
nWidthBytes = ((((pMark->Attributes.lrBounds.right
- pMark->Attributes.lrBounds.left) * pDisplayDib->biBitCount) + 31) / 32) * 4;
nNewWidthBytes = ((((pNewMarks[0].Attributes.lrBounds.right
- pNewMarks[0].Attributes.lrBounds.left) * pDisplayDib->biBitCount) + 31) / 32) * 4;
CheckError2( AllocateMemory(sizeof(BITMAPINFOHEADER)
+ (pDisplayDib->biClrUsed * 4) + (nNewWidthBytes *
(pNewMarks[0].Attributes.lrBounds.bottom
- pNewMarks[0].Attributes.lrBounds.top)), (PPSTR) &pNewDib, ZERO_INIT));
pNewDib->biSize = sizeof(BITMAPINFOHEADER);
pNewDib->biWidth = pNewMarks[0].Attributes.lrBounds.right -
pNewMarks[0].Attributes.lrBounds.left;
pNewDib->biHeight = pNewMarks[0].Attributes.lrBounds.bottom -
pNewMarks[0].Attributes.lrBounds.top;
pNewDib->biPlanes = 1;
pNewDib->biBitCount = pDisplayDib->biBitCount;
pNewDib->biCompression = BI_RGB;
pNewDib->biSizeImage = nNewWidthBytes *
(pNewMarks[0].Attributes.lrBounds.bottom -
pNewMarks[0].Attributes.lrBounds.top);
pNewDib->biXPelsPerMeter = 0;
pNewDib->biYPelsPerMeter = 0;
pNewDib->biClrUsed = pDisplayDib->biClrUsed;
pNewDib->biClrImportant = pDisplayDib->biClrImportant;
// copy the palette to the new dib
memcpy((PSTR) pNewDib + sizeof(BITMAPINFOHEADER),
(PSTR) pDisplayDib + sizeof(BITMAPINFOHEADER),
(pDisplayDib->biClrUsed * 4));
nStartLine = (int) lmax(0, lrCopyBounds.top - pMark->Attributes.lrBounds.top);
nEndLine = (int) lmin(pMark->Attributes.lrBounds.bottom
- lmax(lrCopyBounds.top, pMark->Attributes.lrBounds.top),
lrCopyBounds.bottom - lmax(lrCopyBounds.top,
pMark->Attributes.lrBounds.top)) + nStartLine;
// now adjust for the fact that dibs are stored npside down
nTemp = nStartLine;
nStartLine = (int)(pDisplayDib->biHeight - nEndLine);
nEndLine = (int)(pDisplayDib->biHeight - nTemp);
nLeft = (int)lmax(0, lrCopyBounds.left - pMark->Attributes.lrBounds.left);
nRight = (int)lmin(pMark->Attributes.lrBounds.right
- lmax(lrCopyBounds.left, pMark->Attributes.lrBounds.left),
lrCopyBounds.right - lmax(lrCopyBounds.left, pMark->Attributes.lrBounds.left)) + nLeft;
// set shift bits according to image type
if (pDisplayDib->biBitCount == 1){
nShiftLeft = nLeft & 7;
nShiftRight = 8 - nShiftLeft;
}
if (pDisplayDib->biBitCount == 4){
nShiftLeft = nLeft & 1;
if (nShiftLeft){ // need to shift by 4 bits
nShiftLeft = 4;
nShiftRight = 4;
}else{
nShiftLeft = 0;
nShiftRight = 8;
}
}
// save value of nRight in pixels in case nRight changes
nRightPixels = nRight;
// adjust nLeft and nRight from pixels to bytes
if (pDisplayDib->biBitCount == 1){
nPixelsPerByte = 8;
}
if (pDisplayDib->biBitCount == 4){
nPixelsPerByte = 2;
}
if ((pDisplayDib->biBitCount == 1) || (pDisplayDib->biBitCount == 4)){
nLeft = nLeft / nPixelsPerByte;
nRight = nRight / nPixelsPerByte;
}
if (pDisplayDib->biBitCount == 24){
nLeft = nLeft * 3;
nRight = nRight * 3;
}
switch (pDisplayDib->biBitCount){
case 1: //black and white
case 4: // 4 bits per pixel
for (nLine = nStartLine, nNewDibLine = 0; nLine < nEndLine;
nLine++, nNewDibLine++){
for (nLoop = nLeft, nNewDibLoop=0; nLoop <= nRight;
nLoop++, nNewDibLoop++){
LeftByte = *((BYTE *) pDisplayDib + sizeof(BITMAPINFOHEADER) +
(pDisplayDib->biClrUsed * 4) + ((ulong)nWidthBytes *
nLine) + nLoop) << nShiftLeft;
if ((nLoop * nPixelsPerByte) + nShiftLeft <= nRightPixels){
RightByte = *((BYTE *) pDisplayDib + sizeof(BITMAPINFOHEADER) +
(pDisplayDib->biClrUsed * 4)
+ ((ulong)nWidthBytes * nLine) + nLoop +1)
>> nShiftRight;
*((BYTE *) pNewDib + sizeof(BITMAPINFOHEADER)+
(pDisplayDib->biClrUsed * 4) + ((ulong)nNewWidthBytes *
nNewDibLine) + nNewDibLoop) = LeftByte | RightByte;
}else{
break;
}
}
}
break;
case 8:
case 24:
for (nLine = nStartLine, nNewDibLine = 0; nLine < nEndLine;
nLine++, nNewDibLine++){
for (nLoop = nLeft, nNewDibLoop=0; nLoop < nRight;
nLoop++, nNewDibLoop++){
*((BYTE *) pNewDib + sizeof(BITMAPINFOHEADER)+
(pDisplayDib->biClrUsed * 4) + ((ulong)nNewWidthBytes
* nNewDibLine) + nNewDibLoop)
= *((BYTE *) pDisplayDib + sizeof(BITMAPINFOHEADER)
+ (pDisplayDib->biClrUsed * 4) + ((ulong)nWidthBytes * nLine) + nLoop);
}
}
break;
default:
nStatus = Error(DISPLAY_DATACORRUPTED);
goto Exit;
}
CheckError2( GetAMarkNamedBlock(&pNewMarks[0], szOiZDpDIB,
(PPSTR) &pNewMarkDisplayAnImage));
if (pNewMarkDisplayAnImage){
CheckError2( DeleteAMarkNamedBlock (&pNewMarks[0], szOiZDpDIB));
}
pNewMarkDisplayAnImage = 0;
CheckError2( AddAMarkNamedBlock(&pNewMarks[0], szOiDIB,
(PPSTR) &pNewMarkDisplayAnImage, sizeof(BITMAPINFOHEADER)
+ (pNewDib->biClrUsed*4) + (pNewDib->biSizeImage)));
memcpy (pNewMarkDisplayAnImage->dibInfo, pNewDib,
sizeof(BITMAPINFOHEADER) + (pNewDib->biClrUsed*4) + (pNewDib->biSizeImage));
CheckError2( GetAMarkNamedBlock(&pNewMarks[0], szOiAnoDat,
(PPSTR) &pAnNewMarkRotation));
// partial marks cannot be converted back to form or image by
// reference marks
if (pAnNewMarkRotation && pAnNewMarkRotation->bFormMark){
pAnNewMarkRotation->bFormMark = FALSE;
pAnNewMarkRotation->bClipboardOp = FALSE;
}
(*pnMarks)++;
break;
default:
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
Exit:
FreeMemory((PPSTR) &pDib);
FreeMemory((PPSTR) &pNewDib);
DeInit(FALSE, TRUE);
return (nStatus);
}
//
/*****************************************************************************
FUNCTION: CopyImageIDK
PURPOSE: Copys a piece of an image from 1 buffer to another.
rSourceRect = source rectangle (including width and height).
rDestRect.left,top = npper left of dest rect.
rDestRect.right,bottom = ignored (modified to be correct).
*****************************************************************************/
int WINAPI CopyImageIDK(PIMG pSourceImg, PIMG pDestImg, RECT rSourceRect,
RECT rDestRect){
int nStatus = 0;
int nWidth=0;
int nHeight;
int nSourceLine;
int nLastSourceLine;
PBYTE pSourceLine;
int nDestLine;
PBYTE pDestLine;
BYTE cDestByte;
int nLoop;
int nPixels;
int nBitsPerPixel;
BOOL bTopToBottom;
BOOL bLeftToRight;
BYTE cLeftShift;
BYTE cRightShift;
BYTE cFirstDestMask;
int nFirstSourceByte;
int nFirstDestByte;
BOOL bDoFirstLeftShift = FALSE;
BOOL bDoFirstRightShift = FALSE;
int nMiddleBytes;
BOOL bDoLastLeftShift = FALSE;
BOOL bDoLastRightShift = FALSE;
BYTE cLastDestMask;
if (!pSourceImg){
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
goto Exit;
}
if (rSourceRect.bottom <= rSourceRect.top || rSourceRect.right <= rSourceRect.left
|| rSourceRect.top < 0 || rSourceRect.left < 0
|| rDestRect.top < 0 || rDestRect.left < 0){
nStatus = Error(DISPLAY_INVALIDRECT);
goto Exit;
}
if (pSourceImg->nType != pDestImg->nType){
nStatus = Error(DISPLAY_INVALID_OPTIONS);
goto Exit;
}
nWidth = rSourceRect.right - rSourceRect.left;
nHeight = rSourceRect.bottom - rSourceRect.top;
rDestRect.right = rDestRect.left + nWidth;
rDestRect.bottom = rDestRect.top + nHeight;
switch (pSourceImg->nType){
case ITYPE_BI_LEVEL:
nBitsPerPixel = 1;
switch (nWidth){
case 1: cFirstDestMask = 0x80; break;
case 2: cFirstDestMask = 0xc0; break;
case 3: cFirstDestMask = 0xe0; break;
case 4: cFirstDestMask = 0xf0; break;
case 5: cFirstDestMask = 0xf8; break;
case 6: cFirstDestMask = 0xfc; break;
case 7: cFirstDestMask = 0xfe; break;
default: cFirstDestMask = 0xff; break;
}
cFirstDestMask >>= rDestRect.left & 7;
if ((rSourceRect.left & 7) >= (rDestRect.left & 7)){
cLeftShift = (rSourceRect.left & 7) - (rDestRect.left & 7);
}else{
cLeftShift = (8 + (rSourceRect.left & 7)) - (rDestRect.left & 7);
}
cRightShift = 8 - cLeftShift;
if (!cLeftShift || (rDestRect.left & 7) < cRightShift){
bDoFirstLeftShift = TRUE;
}
if (cLeftShift && ((rDestRect.left & 7) + nWidth) > cRightShift){
bDoFirstRightShift = TRUE;
}
nPixels = nWidth;
nPixels -= min(nWidth, 8 - (rDestRect.left & 7));
nMiddleBytes = nPixels >> 3;
nPixels &= 7;
if (nPixels){
bDoLastLeftShift = TRUE;
if (nPixels > cRightShift){
bDoLastRightShift = TRUE;
}
}
switch (nPixels){
case 1: cLastDestMask = 0x80; break;
case 2: cLastDestMask = 0xc0; break;
case 3: cLastDestMask = 0xe0; break;
case 4: cLastDestMask = 0xf0; break;
case 5: cLastDestMask = 0xf8; break;
case 6: cLastDestMask = 0xfc; break;
case 7: cLastDestMask = 0xfe; break;
default: cLastDestMask = 0x00; break;
}
break;
case ITYPE_GRAY4:
case ITYPE_PAL4:
nBitsPerPixel = 4;
if (nWidth > 1){
cFirstDestMask = 0xff;
}else{
cFirstDestMask = 0xf0;
}
if (rDestRect.left & 1){
cFirstDestMask >>= 4;
}
if ((rSourceRect.left & 1) != (rDestRect.left & 1)){
cLeftShift = 4;
}else{
cLeftShift = 0;
}
cRightShift = 8 - cLeftShift;
nPixels = nWidth;
if ((rDestRect.left & 1) || nWidth == 1){
if ((rSourceRect.left & 1) || !(rDestRect.left & 1)){
bDoFirstLeftShift = TRUE;
}else{
bDoFirstRightShift = TRUE;
}
nPixels--;
}
nMiddleBytes = nPixels >> 1;
nPixels &= 1;
if (nPixels){
bDoLastLeftShift = TRUE;
cLastDestMask = 0xf0;
}
break;
case ITYPE_GRAY7:
case ITYPE_GRAY8:
case ITYPE_CUSPAL8:
case ITYPE_COMPAL8:
nBitsPerPixel = 8;
cLeftShift = 0;
cRightShift = 0;
nMiddleBytes = nWidth;
break;
case ITYPE_RGB24:
case ITYPE_BGR24:
nBitsPerPixel = 24;
cLeftShift = 0;
cRightShift = 0;
nMiddleBytes = nWidth * 3;
break;
default:
nStatus = Error(DISPLAY_IMAGETYPENOTSUPPORTED);
goto Exit;
}
if (pSourceImg != pDestImg || rSourceRect.top >= rDestRect.top){
bTopToBottom = TRUE;
nDestLine = rDestRect.top;
nSourceLine = rSourceRect.top;
nLastSourceLine = rSourceRect.bottom - 1;
}else{
bTopToBottom = FALSE;
nDestLine = rDestRect.bottom - 1;
nSourceLine = rSourceRect.bottom - 1;
nLastSourceLine = rSourceRect.top;
}
if (pSourceImg != pDestImg || rSourceRect.left >= rDestRect.left
|| rSourceRect.top != rDestRect.top){
bLeftToRight = TRUE;
nFirstSourceByte = (rSourceRect.left * nBitsPerPixel) >> 3;
nFirstDestByte = (rDestRect.left * nBitsPerPixel) >> 3;
}else{
bLeftToRight = FALSE;
nFirstSourceByte = ((rSourceRect.right * nBitsPerPixel) - 1) >> 3;
nFirstDestByte = ((rDestRect.right * nBitsPerPixel) - 1) >> 3;
}
while(1){
pSourceLine = &pSourceImg->bImageData[0] + (nSourceLine * pSourceImg->nBytesPerLine);
pDestLine = &pDestImg->bImageData[0] + (nDestLine * pDestImg->nBytesPerLine);
pSourceLine += nFirstSourceByte;
pDestLine += nFirstDestByte;
if (bLeftToRight){
// Do first byte
cDestByte = 0;
if (bDoFirstLeftShift){
cDestByte = *(pSourceLine++) << cLeftShift;
}
if (bDoFirstRightShift){
cDestByte |= *pSourceLine >> cRightShift;
}
if (bDoFirstLeftShift || bDoFirstRightShift){
*pDestLine = (*pDestLine & ~cFirstDestMask) | (cDestByte & cFirstDestMask);
pDestLine++;
}
// Do middle bytes?
if (nMiddleBytes){
if (!cLeftShift){
memcpy(pDestLine, pSourceLine, nMiddleBytes);
pDestLine += nMiddleBytes;
pSourceLine += nMiddleBytes;
}else{
for (nLoop = nMiddleBytes; nLoop; nLoop--){
cDestByte = *(pSourceLine++) << cLeftShift;
*(pDestLine++) = cDestByte | (*pSourceLine >> cRightShift);
}
}
}
// Do last byte?
if (bDoLastLeftShift){
cDestByte = *(pSourceLine++) << cLeftShift;
if (bDoLastRightShift){
cDestByte |= *pSourceLine >> cRightShift;
}
*pDestLine = (*pDestLine & ~cLastDestMask) | (cDestByte & cLastDestMask);
}
}else{ // Right to left.
// Do last byte?
cDestByte = 0;
if (bDoLastRightShift){
cDestByte = *(pSourceLine--) >> cRightShift;
}
if (bDoLastLeftShift){
cDestByte |= *pSourceLine << cLeftShift;
}
if (bDoLastLeftShift || bDoLastRightShift){
*(pDestLine--) = (*pDestLine & ~cLastDestMask) | (cDestByte & cLastDestMask);
if (!cLeftShift){
--pSourceLine;
}
}
// Do middle bytes?
if (nMiddleBytes){
if (!cLeftShift){
for (nLoop = nMiddleBytes; nLoop; nLoop--){
*(pDestLine--) = *(pSourceLine--);
}
}else{
for (nLoop = nMiddleBytes; nLoop; nLoop--){
cDestByte = *(pSourceLine--) >> cRightShift;
*(pDestLine--) = cDestByte | (*pSourceLine << cLeftShift);
}
}
}
// Do first byte
if (bDoFirstRightShift || bDoFirstLeftShift){
cDestByte = 0;
if (bDoFirstRightShift){
cDestByte = *(pSourceLine--) >> cRightShift;
}
if (bDoFirstLeftShift){
cDestByte |= *pSourceLine << cLeftShift;
}
*pDestLine = (*pDestLine & ~cFirstDestMask) | (cDestByte & cFirstDestMask);
}
}
if (nSourceLine == nLastSourceLine){
break;
}
if (bTopToBottom){
nDestLine++;
nSourceLine++;
}else{
nDestLine--;
nSourceLine--;
}
}
Exit:
return(nStatus);
}