/**************************************************************************** ANTEXT.C $Log: S:\products\msprods\oiwh\display\antext.c_v $ * * Rev 1.49 20 Jun 1996 16:00:54 RC * Fixed resize of image and text marks * * Rev 1.48 19 Jun 1996 13:51:32 RC * Fixed text stamps and text from files from being resized at placement time * * Rev 1.47 12 Jun 1996 10:05:28 RC * Added start, continue, endop for all text marks * * Rev 1.46 09 May 1996 15:10:58 RAR61941 * Prevent yellow background of attach-a-note from being drawn outside the * repaint rect. This was preventing some of the attach-a-note border from * printing when it is a large attach-a-note. bug 6340. * * Rev 1.45 03 May 1996 13:56:02 JAR * added a magic number calculation because the ExternalLeading given back by * the GetTextMetric function is sometimes 0 and sometimes 1, both of which * are useless, so we now determine our own * * Rev 1.44 18 Apr 1996 11:10:30 BEG06016 * Added CheckError2 for error handling. * * Rev 1.43 11 Apr 1996 15:12:26 BEG06016 * Optimized named block access some. * * Rev 1.42 22 Mar 1996 10:46:30 RC * Fixed image marks getting scaled when a mismatched res image is rotated * * Rev 1.41 17 Jan 1996 16:15:34 RC * Prevented attach-a-note from being deleted for 0 width and height * attach-a-note * * Rev 1.40 09 Jan 1996 14:48:40 RC * Typecasted uints to ints to provide correct result in establishfont * * Rev 1.39 02 Jan 1996 10:33:26 BLJ * Changed alot of UINTs to ints. * Changed IMG structure to include the image data. * Changed lp prefix to p. * * Rev 1.38 22 Dec 1995 11:13:14 BLJ * Added a parameter for zero init'ing to some memory manager calls. * * Rev 1.37 13 Dec 1995 14:37:50 JAR * modified the annotation text code to remove the nser interface dialog * box entry and allow for the API nser to call to edit the annotation text * strings. The dialog box code has been taken over at the OCX level. * * Rev 1.35 20 Nov 1995 15:37:40 JAR * fixed rect computation bug for re-edit of anno text * * Rev 1.34 15 Nov 1995 14:10:44 RC * Fixed setting of font height in scaleannottext * * Rev 1.33 10 Nov 1995 13:31:16 JCW * P1 5209 * OIUI400.DLL ni\attrbox.c * OIDIS400.DLL display\antext.c * Switch keyboardlayout in the text, text note and text stamp, changes the system * language default. Fixed. * * Rev 1.32 09 Nov 1995 15:43:56 RC * Fixed a one pixel off problem when scrolling while drawing an attach * a note through the app * * Rev 1.31 08 Nov 1995 11:12:14 RC * Took out PAINT_MODE_SELECTED flag as its function is now performed by * PaintHandles * * Rev 1.30 25 Oct 1995 09:40:52 RAR * Use StretchDIBits() instead of Rectangle() for the background of an * ATTACH_A_NOTE annotation as is done for non-highlighted filled * rectangles (only when printing). Work around for printer drivers (HPLJ4 * drivers) that ignore SetROP2() drawing mode. * * Rev 1.29 18 Oct 1995 09:51:32 JAR * finally, the solution to ALL of the wordwrap problems in multibyte, fixed * WithinWordBreak and OurOwnDrawText * * Rev 1.28 16 Oct 1995 13:42:30 BLJ * Bug #5006 Fixed text scaling when converting to non-matched resolutions. * * Rev 1.27 29 Sep 1995 09:31:28 BLJ * Fixed error checking for CanMarkBeScaled. * Also changed its return from BOOL to int to follow normal api returns. * * Rev 1.26 28 Sep 1995 17:15:34 JCW * Fixed the problem the text mark edit box didn't get correct font face and size. * * Rev 1.25 27 Sep 1995 17:17:46 JCW * Fixed the problem repeat edit the text mark the char growth bigger and bigger. * Removed the code of always setting English keyboard as default. * * Rev 1.24 26 Sep 1995 17:29:28 JCW * Adjust the font size in the text edit box. * * Rev 1.23 25 Sep 1995 17:43:26 JCW * Added the multilanguage implementation to antext.c. * * Rev 1.22 22 Sep 1995 13:56:36 JAR * yet another fix for WithinWordBreak for multibyte stuff * * Rev 1.21 22 Sep 1995 09:04:24 JAR * finished fixing the WinthWordBreak problem for multibyte stuff * * Rev 1.20 21 Sep 1995 16:30:44 JAR * attempt to fix problem with WithinWordBreak for multibyte character strings * and changed calls to AnsiNext to CharNext, since AnsiNext is defunct! * * Rev 1.19 21 Sep 1995 14:45:28 RC * Fixed AnTextPaintText to nse scale passed in, not window scale * * Rev 1.18 08 Sep 1995 10:25:00 RC * Changed the way text is printed to always adjust to the display resolution * * Rev 1.17 07 Sep 1995 13:21:58 BLJ * Modified scaling to allow for proper rotation of fax images. * * Rev 1.16 28 Aug 1995 10:55:24 RC * Initialized nbytes in antextreadfile, so it returns 0 if we error out * * Rev 1.15 21 Aug 1995 17:12:04 JCW * Fixed the bug 3421. %m shows 9 for August. * * Rev 1.14 03 Aug 1995 17:48:06 JCW * * Rev 1.13 03 Aug 1995 17:37:04 JCW * Added two new macro for date(%x) and time(%X). * * Rev 1.12 03 Aug 1995 17:19:04 RC * Changed em_setsel in antexteditctldlgproc to pass in the starting and * ending position in wparam and param (in 3.1, only param accepted these * values) * * Rev 1.11 14 Jul 1995 14:16:18 RC * Made attach a notes scaleable in scaleannotationtext * * Rev 1.10 13 Jul 1995 14:45:24 RC * Made changes for clipboard operations to be resolution adjusted with the * base image * * Rev 1.9 05 Jul 1995 09:09:56 BLJ * Added critical mutex to prevent multiprocessing problems. * * Rev 1.8 19 May 1995 13:49:32 BLJ * Fixed Clipboard paste. * Fixed SelectByPointOrRect initial fudge before move. * Fixed GlobalAlloc/FreeMemory conflicts. * Deleted FAR, far, and huge. * * Rev 1.7 11 May 1995 13:44:32 RC * Put in changes to nse allocatemem rather than globalalloc * * Rev 1.4 10 May 1995 16:00:40 RC * Changed edit ctl functions to nse allocatemem rather than globalallocs * ****************************************************************************/ /* includes */ #include "privdisp.h" /* structures */ /* prototypes */ /* defines */ // 9605.03 jar added for better bounding rectangle computing #define OWNDRAWTEXT_MAGIC 250 // used by OurOwnDrawText to compute // the ExternalLeading to use when // creating multple lined text items /**************************************************************************** FUNCTION: StartOperationText PURPOSE: This routine contains the text code for OiStartOperation. ****************************************************************************/ int WINAPI StartOperationText(HWND hWnd, LPOIOP_START_OPERATION_STRUCT pStartStr, POINT ptPoint, WPARAM fwKeys, int nFlags, PWINDOW pWindow, PIMAGE pImage, PMARK pMark, HDC hDC, RECT rClientRect, LRECT lrFullsizeClientRect, PBOOL pbDeleteMark, PBOOL pbMarkComplete, PBOOL pbRepaint){ int nStatus = 0; // 9512.04 jar Text Annotation Externalization LPOIAN_TEXTPRIVDATA pStuff = NULL; int nAmount = 0; // 9512.04 jar Text Annotation Externalization *pbDeleteMark = TRUE; *pbMarkComplete = FALSE; *pbRepaint = FALSE; switch ((int) pMark->Attributes.uType){ case OIOP_AN_TEXT: CheckError2(AnTextStart(hWnd, *pStartStr, ptPoint, fwKeys, nFlags, pWindow, pImage, pMark, hDC, rClientRect, lrFullsizeClientRect, FALSE, pbDeleteMark, pbMarkComplete, pbRepaint)) break; case OIOP_AN_TEXT_FROM_A_FILE: CheckError2(AnTextFromFileStart(hWnd, *pStartStr, ptPoint, fwKeys, nFlags, pWindow, pImage, pMark, hDC, rClientRect, lrFullsizeClientRect, pbDeleteMark, pbMarkComplete, pbRepaint)) break; case OIOP_AN_TEXT_STAMP: CheckError2(AnTextStampStart(hWnd, *pStartStr, ptPoint, fwKeys, nFlags, pWindow, pImage, pMark, hDC, rClientRect, lrFullsizeClientRect, pbDeleteMark, pbMarkComplete, pbRepaint)) break; case OIOP_AN_ATTACH_A_NOTE: // 9512.04 jar Text Annotation Externalization nAmount = strlen(pStartStr->szString) + 1; if ( nAmount > 0){ CheckError2(AllocateTextBuffer(pMark, nAmount, (LPOIAN_TEXTPRIVDATA *)&pStuff)) memcpy( pStuff->szAnoText, pStartStr->szString, nAmount-1); //add null terminator *(PSTR)(pStuff->szAnoText + nAmount) = '\0'; // 9512.11 jar set the creation scale too! //pStuff->uCreationScale = 1000; pStuff->uCreationScale = 72000 / pImage->nVRes; } // 9512.04 jar Text Annotation Externalization SetLRect(pMark->Attributes.lrBounds, ptPoint.x, ptPoint.y, ptPoint.x, ptPoint.y); if (nFlags & PARM_SCALED){ ConvertRect(pWindow, &pMark->Attributes.lrBounds, CONV_SCALED_TO_FULLSIZE); }else if (!(nFlags & PARM_FULLSIZE)){ ConvertRect(pWindow, &pMark->Attributes.lrBounds, CONV_WINDOW_TO_FULLSIZE); } *pbDeleteMark = FALSE; break; default: break; } Exit: return(nStatus); } /**************************************************************************** FUNCTION: ContinueOperationText PURPOSE: This routine contains the text code for OIContinueOperation. ****************************************************************************/ int WINAPI ContinueOperationText(HWND hWnd, POINT ptPoint, int nFlags, PWINDOW pWindow, PIMAGE pImage, PMARK pMark, HDC hDC, RECT rClientRect, LRECT lrFullsizeClientRect){ int nStatus = 0; 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: CheckError2(AnTextContinue(hWnd, ptPoint, nFlags, pWindow, pImage, pMark, hDC, rClientRect, lrFullsizeClientRect)) break; default: break; } Exit: return(nStatus); } /**************************************************************************** FUNCTION: EndOperationText PURPOSE: This routine contains the text code for OIEndOperation. ****************************************************************************/ int WINAPI EndOperationText(HWND hWnd, PWINDOW pWindow, PIMAGE pImage, PMARK pMark, HDC hDC, RECT rClientRect, LRECT lrFullsizeClientRect, PBOOL pbDeleteMark, PBOOL pbRepaint){ int nStatus = 0; *pbDeleteMark = TRUE; *pbRepaint = FALSE; 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: // 9512.04 jar Text Annotation Externalization //if (nStatus = AnTextEnd(hWnd, pWindow, pImage, // pMark, hDC, rClientRect, lrFullsizeClientRect, pbDeleteMark, // pbRepaint)){ // goto Exit; //} CheckError2(AnTextEnd(hWnd, pWindow, pImage, pMark, hDC, rClientRect, lrFullsizeClientRect, FALSE, pbDeleteMark, pbRepaint)) // 9512.04 jar Text Annotation Externalization break; default: break; } Exit: return(nStatus); } /**************************************************************************** FUNCTION: PaintAnnotationText PURPOSE: This routine Paints an annotation on an hDC. This routine contains the text code for PaintAnnotation. INPUTS: nMode - PAINT_MODE_XOR - Draw the mark XORed with white. PAINT_MODE_DRAG - Draw the mark for dragging purposes. PAINT_MODE_NORMAL - Draw the mark as it normally appears. ****************************************************************************/ int WINAPI PaintAnnotationText(HWND hWnd, HDC hDC, PWINDOW pWindow, PIMAGE pImage, PMARK pMark,RECT rRepaintRect, LRECT lrFullsizeRepaintRect,int nMode, int nHScale, int nVScale, long lHOffset, long lVOffset, BOOL bForceOpaqueRectangles){ int nStatus = 0; LRECT lrRect; HBRUSH hOldBrush = 0; HBRUSH hBrush = 0; HPEN hOldPen = 0; HPEN hPen = 0; //LOGPEN LogPen; COLORREF rgbColor; RGBQUAD rgbQuad; RGBQUAD rgbQuad2; int nRopCode; int nOldROP; RECT rRect; int nSize; PBITMAPINFOHEADER pSolidDIB = NULL; PSTR pTemp; int nFlags=0 ; switch (nMode){ case PAINT_MODE_XOR: nRopCode = R2_XORPEN; rgbQuad.rgbRed = 255; rgbQuad.rgbGreen = 255; rgbQuad.rgbBlue = 255; rgbColor = RGB(255, 255, 255); break; case PAINT_MODE_DRAG: nRopCode = R2_XORPEN; rgbQuad.rgbRed = 128; rgbQuad.rgbGreen = 128; rgbQuad.rgbBlue = 128; rgbColor = RGB(128, 128, 128); break; case PAINT_MODE_NORMAL: nRopCode = R2_COPYPEN; rgbQuad.rgbRed = pMark->Attributes.rgbColor1.rgbRed; rgbQuad.rgbGreen = pMark->Attributes.rgbColor1.rgbGreen; rgbQuad.rgbBlue = pMark->Attributes.rgbColor1.rgbBlue; rgbColor = RGB(pMark->Attributes.rgbColor1.rgbRed, pMark->Attributes.rgbColor1.rgbGreen, pMark->Attributes.rgbColor1.rgbBlue); if ((int) pMark->Attributes.uType == OIOP_AN_ATTACH_A_NOTE){ rgbQuad2.rgbRed = pMark->Attributes.rgbColor2.rgbRed; rgbQuad2.rgbGreen = pMark->Attributes.rgbColor2.rgbGreen; rgbQuad2.rgbBlue = pMark->Attributes.rgbColor2.rgbBlue; } break; } nOldROP = SetROP2(hDC, nRopCode); switch ((int) pMark->Attributes.uType){ case OIOP_AN_TEXT: case OIOP_AN_TEXT_STAMP: case OIOP_AN_TEXT_FROM_A_FILE: #ifdef junk if (nMode == PAINT_MODE_NORMAL){ AnTextPaintText(hWnd, hDC, pWindow, pImage, pMark, rgbQuad, rgbQuad, nHScale, nVScale, lHOffset, lVOffset, nFlags); }else{ /* we're xoring, which one cannot do with text */ /* so we draw the outline */ hOldBrush = SelectObject(hDC, GetStockObject(NULL_BRUSH)); LogPen.lopnStyle = PS_DOT; LogPen.lopnWidth.x = 1; LogPen.lopnColor = rgbColor; if (hPen = CreatePenIndirect(&LogPen)){ hOldPen = SelectObject(hDC, hPen); } CopyRect(lrRect, pMark->Attributes.lrBounds); JustifyLRect(&lrRect); ConvertRect2(&lrRect, CONV_FULLSIZE_TO_WINDOW, nHScale, nVScale, lHOffset, lVOffset); rRect.left = (int) max(0, lrRect.left); rRect.top = (int) max(0, lrRect.top); rRect.right = (int) min(rRepaintRect.right, lrRect.right) + 1; rRect.bottom = (int) min(rRepaintRect.bottom, lrRect.bottom)+1; if (nMode == PAINT_MODE_DRAG){ /* snap the rect so that it cannot go negative */ if (rRect.left < 0){ rRect.right = rRect.right - rRect.left; rRect.left = 0; } if (rRect.top < 0){ rRect.bottom = rRect.bottom - rRect.top; rRect.top = 0; } } Rectangle(hDC, rRect.left, rRect.top, rRect.right,rRect.bottom); } break; #endif case OIOP_AN_ATTACH_A_NOTE: // These require a brush. if (pMark->Attributes.uType == OIOP_AN_ATTACH_A_NOTE) { if (rgbColor == RGB(255, 255, 255)){ hOldBrush = SelectObject(hDC, GetStockObject(WHITE_BRUSH)); }else{ hBrush = CreateSolidBrush(rgbColor); if (hBrush){ hOldBrush = SelectObject(hDC, hBrush); } } }else{ if (rgbColor == RGB(255, 255, 255)){ hOldBrush = SelectObject(hDC, GetStockObject(WHITE_BRUSH)); }else if (rgbColor == RGB(128, 128, 128)){ hOldBrush = SelectObject(hDC, GetStockObject(GRAY_BRUSH)); }else{ hOldBrush = SelectObject(hDC, GetStockObject(NULL_BRUSH)); } } hOldPen = SelectObject(hDC, GetStockObject(NULL_PEN)); CopyRect(lrRect, pMark->Attributes.lrBounds); JustifyLRect(&lrRect); ConvertRect2(&lrRect, CONV_FULLSIZE_TO_WINDOW, nHScale, nVScale, lHOffset, lVOffset); rRect.left = (int) max(rRepaintRect.left, lrRect.left); rRect.top = (int) max(rRepaintRect.top, lrRect.top); // this is to adjust for a one pixel off problem when scrolling off the window rRect.right = (int) min(rRepaintRect.right + 1, lrRect.right); rRect.bottom = (int) min(rRepaintRect.bottom + 1, lrRect.bottom); if (nMode == PAINT_MODE_DRAG){ /* snap the rect so that it cannot go negative */ if (rRect.left < 0){ rRect.right = rRect.right - rRect.left; rRect.left = 0; } if (rRect.top < 0){ rRect.bottom = rRect.bottom - rRect.top; rRect.top = 0; } } if (bForceOpaqueRectangles){ // 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. if (!(nStatus = CreateSolidDIB(&pSolidDIB, pMark->Attributes.rgbColor1))){ StretchDIBits(hDC, rRect.left, rRect.top, rRect.right - rRect.left - 1, rRect.bottom - rRect.top - 1, 0, 0, 32, 32, (PSTR)pSolidDIB + sizeof(BITMAPINFOHEADER) + 8, (PBITMAPINFO)pSolidDIB, DIB_RGB_COLORS, SRCCOPY); nStatus = FreeMemory((PPSTR) &pSolidDIB); } }else{ Rectangle(hDC, rRect.left, rRect.top, rRect.right, rRect.bottom); } /* here we must paint the post-it border left,top => thin and right,bottom => thick */ if (nMode == PAINT_MODE_NORMAL && pMark->Attributes.uType == OIOP_AN_ATTACH_A_NOTE){ nSize = max(1, (int) pMark->Attributes.uLineSize); nSize = max(1, nSize * pWindow->nScale / SCALE_DENOMINATOR); ThreeDaMatic( hDC, lrRect, rRepaintRect, nSize); } /* search for the text named block and if we've got one, then we should paint the post-it's text, otherwise, we just paint the post-it rect (the text hasn't been created yet) */ if (nMode == PAINT_MODE_NORMAL){ CheckError2(GetAMarkNamedBlock(pMark, szOiAnTextData, &pTemp)) if (pTemp){ AnTextPaintText(hWnd, hDC, pWindow, pImage, pMark, rgbQuad, rgbQuad2, nHScale, nVScale, lHOffset, lVOffset, nFlags); } } break; default: break; } Exit: if (hOldBrush){ SelectObject(hDC, hOldBrush); if (hBrush){ DeleteObject(hBrush); } } if (hOldPen){ SelectObject(hDC, hOldPen); if (hPen){ DeleteObject(hPen); } } SetROP2(hDC, nOldROP); return nStatus; } /**************************************************************************** NOT FOR FCS FUNCTION: OrientAnnotationText PURPOSE: This routine orients the annotation. This routine contains the text code for OrientAnnotations. ****************************************************************************/ int WINAPI OrientAnnotationText(HWND hWnd, PWINDOW pWindow, PIMAGE pImage, int nOrientation, PMARK pMark){ int nStatus = 0; LPOIAN_TEXTPRIVDATA pStuff = NULL; int Index = 0; /* escapement is measured in tenths of a degree and in a counter-clockwise direction where the x-axis is 0 degrees */ pStuff = GetAnTextData(pMark, &Index); OrientBounds(pImage, pMark, nOrientation); switch(nOrientation){ case OD_FLIP: /* 180 */ pStuff->nCurrentOrientation += 1800; break; case OD_ROTRIGHT: /* 270 */ pStuff->nCurrentOrientation += 2700; break; case OD_ROTLEFT: /* 90 */ pStuff->nCurrentOrientation += 900; break; // for vertical and horiz. mirrors, only the bounds are npdated, // the text remains as is case OD_HMIRROR: break; case OD_VMIRROR: break; default: nStatus = Error(DISPLAY_INVALIDORIENTATION); goto Exit; } if (pStuff->nCurrentOrientation >= 3600){ pStuff->nCurrentOrientation -= 3600; } Exit: return nStatus; } /**************************************************************************** $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ THE LOCAL/PRIVATE ANNOTATION TEXT FUNCTIONS $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ ****************************************************************************/ /**************************************************************************** AnTextActivate activates text, text from file and sticky-note (not stamps though) ****************************************************************************/ int WINAPI AnTextActivate(HWND hWnd, LPOIOP_START_OPERATION_STRUCT pStartStr, POINT ptPoint, WPARAM fwKeys, int nFlags, PWINDOW pWindow, PIMAGE pImage, PMARK pMark, HDC hDC, RECT rClientRect, LRECT lrFullsizeClientRect){ int nStatus = 0; RECT NewRect; LRECT lrNewRect; BOOL bDelDum; BOOL bCompDum; BOOL bRepDum; LPOIAN_TEXTPRIVDATA pStuff = NULL; int Index = 0; /* may wish to set the ptPoint to be the npper left of the annotation */ lrNewRect = pMark->Attributes.lrBounds; ConvertRect(pWindow, &lrNewRect, CONV_FULLSIZE_TO_WINDOW); CopyRectLtoR(NewRect, lrNewRect); ptPoint.x = NewRect.left; ptPoint.y = NewRect.top; switch( (int) pMark->Attributes.uType){ case OIOP_AN_TEXT: case OIOP_AN_TEXT_FROM_A_FILE: CheckError2(AnTextStart( hWnd, *pStartStr, ptPoint, fwKeys, nFlags, pWindow, pImage, pMark, hDC, rClientRect, lrFullsizeClientRect, TRUE, &bDelDum, &bCompDum, &bRepDum)) break; case OIOP_AN_ATTACH_A_NOTE: // 9512.04 jar Text Annotation Externalization //if (nStatus = AnTextEnd( hWnd, pWindow, pImage, pMark, hDC, // rClientRect, lrFullsizeClientRect, &bDelDum, &bRepDum)){ // goto Exit; //} CheckError2(AnTextEnd(hWnd, pWindow, pImage, pMark, hDC, rClientRect, lrFullsizeClientRect, TRUE, &bDelDum, &bRepDum)) // 9512.04 jar Text Annotation Externalization break; case OIOP_AN_TEXT_STAMP: default: break; } Exit: return nStatus; } /**************************************************************************** AnTextStart this is the start op for regular text marks ****************************************************************************/ int WINAPI AnTextStart(HWND hWnd, OIOP_START_OPERATION_STRUCT StartStr, POINT ptPoint, WPARAM fwKeys, int nFlags, PWINDOW pWindow, PIMAGE pImage, PMARK pMark, HDC hDC, RECT rClientRect, LRECT lrFullsizeClientRect, BOOL bActivate, PBOOL pbDeleteMark, PBOOL pbMarkComplete, PBOOL pbRepaint){ int nStatus = 0; int nAmount = 0; RECT NewRect; LRECT lrNewRect; HFONT hFont; HINSTANCE hTheInst = NULL; LPOIAN_TEXTPRIVDATA pStuff = NULL; int nHScale; int nVScale; // 9512.04 jar Text Annotation Externalization int Index = 0; // 9512.04 jar Text Annotation Externalization CheckError2(TranslateScale(pWindow->nScale, pImage->nHRes, pImage->nVRes, &nHScale, &nVScale)) // 9512.04 jar Text Annotation Externalization //if (nStatus = AllocateTextBuffer(pMark, OIAN_TEXTBUFFERSIZE, // (LPOIAN_TEXTPRIVDATA *)&pStuff)) // { // goto Exit; // } if ( !bActivate){ nAmount = strlen( StartStr.szString) + 1; if ( nAmount > 0){ CheckError2(AllocateTextBuffer(pMark, nAmount, (LPOIAN_TEXTPRIVDATA *)&pStuff)) memcpy( pStuff->szAnoText, StartStr.szString, nAmount-1); //add null terminator *(PSTR)(pStuff->szAnoText + nAmount) = '\0'; } lrNewRect.left = 0L; lrNewRect.top = 0L; lrNewRect.right = pMark->Attributes.lrBounds.right; lrNewRect.bottom = pMark->Attributes.lrBounds.bottom; ConvertRect(pWindow, &lrNewRect, CONV_FULLSIZE_TO_WINDOW); CopyRectLtoR(NewRect, lrNewRect); NewRect.left = ptPoint.x; NewRect.top = ptPoint.y; // CopyRectRtoL(pMark->Attributes.lrBounds, NewRect); /* convert to fullsize for bounding rect*/ // ConvertRect(pWindow, &pMark->Attributes.lrBounds, CONV_WINDOW_TO_FULLSIZE); }else{ pStuff = GetAnTextData(pMark, &Index); nAmount = pStuff->uAnoTextLength; // 9511.19 jar we must put together a new rect, ( in window coords) lrNewRect.left = pMark->Attributes.lrBounds.left; lrNewRect.top = pMark->Attributes.lrBounds.top; lrNewRect.right = pMark->Attributes.lrBounds.right; lrNewRect.bottom = pMark->Attributes.lrBounds.bottom; ConvertRect(pWindow, &lrNewRect, CONV_FULLSIZE_TO_WINDOW); CopyRectLtoR(NewRect, lrNewRect); } /* compute the initial bounding rectangle as top,left = input point and bottom, right = bottom, right of image */ /* keep lrBounds in FULLSIZE coordinates */ // 9511.19 jar what else is new, another last minute change! // don't re-do rect if we're re-activating!!!!! // 9512.04 jar this stuff was moved np into the big if block for // bActivate //if ( !bActivate) //{ //lrNewRect.left = 0L; //lrNewRect.top = 0L; //lrNewRect.right = pImage->nWidth; //lrNewRect.bottom = pImage->nHeight; //ConvertRect(pWindow, &lrNewRect, CONV_FULLSIZE_TO_WINDOW); //CopyRectLtoR(NewRect, lrNewRect); // //NewRect.left = ptPoint.x; //NewRect.top = ptPoint.y; //CopyRectRtoL(pMark->Attributes.lrBounds, NewRect); // ///* convert to fullsize for bounding rect*/ //ConvertRect(pWindow, &pMark->Attributes.lrBounds, CONV_WINDOW_TO_FULLSIZE); //} //else //{ // 9511.19 jar we must put together a new rect, ( in window coords) //lrNewRect.left = pMark->Attributes.lrBounds.left; //lrNewRect.top = pMark->Attributes.lrBounds.top; //lrNewRect.right = pMark->Attributes.lrBounds.right; //lrNewRect.bottom = pMark->Attributes.lrBounds.bottom; // //ConvertRect(pWindow, &lrNewRect, CONV_FULLSIZE_TO_WINDOW); //CopyRectLtoR(NewRect, lrNewRect); //} //lrNewRect.left = 0L; //lrNewRect.top = 0L; //lrNewRect.right = pImage->nWidth; //lrNewRect.bottom = pImage->nHeight; //ConvertRect(pWindow, &lrNewRect, CONV_FULLSIZE_TO_WINDOW); //CopyRectLtoR(NewRect, lrNewRect); //NewRect.left = ptPoint.x; //NewRect.top = ptPoint.y; //CopyRectRtoL(pMark->Attributes.lrBounds, NewRect); ///* convert to fullsize for bounding rect*/ //ConvertRect(pWindow, &pMark->Attributes.lrBounds, CONV_WINDOW_TO_FULLSIZE); //hTheInst = hInst; //nAmount = AnTextEditCtl(hWnd, hTheInst, pMark); // 9512.04 jar Text Annotation Externalization if (nAmount > 0L){ /* establish font and do it */ pStuff->uCurrentScale = pWindow->nScale; if (!bActivate){ //pStuff->uCreationScale = 1000; pStuff->uCreationScale = 72000 / pImage->nVRes; } hFont = EstablishFont(hWnd, hDC, pMark, NULL); if (hFont){ EnsconceBoundRect(hWnd, hDC, hFont, pImage->nWidth, pImage->nHeight, pMark, pStuff, NewRect, nAmount, TRUE, nHScale, nVScale, pWindow->lHOffset, pWindow->lVOffset); ConvertRect(pWindow, &pMark->Attributes.lrBounds, CONV_WINDOW_TO_FULLSIZE); // 9512.04 jar Text Annotation Externalization //nStatus = ShrinkFitTextBuffer(pMark, (PPSTR) &pStuff, // nAmount); // 9512.04 jar Text Annotation Externalization AnTextPaintText(hWnd, hDC, pWindow, pImage, pMark, pMark->Attributes.rgbColor1, pMark->Attributes.rgbColor2, nHScale, nVScale, pWindow->lHOffset, pWindow->lVOffset, nFlags); *pbDeleteMark = FALSE; // *pbMarkComplete = TRUE; *pbMarkComplete = FALSE; }else{ nStatus = DISPLAY_OIANT_ERR_NOFONT; } } Exit: *pbRepaint = TRUE; return nStatus; } /**************************************************************************** AnTextContinue this is the continue op for text marks ****************************************************************************/ int WINAPI AnTextContinue(HWND hWnd, POINT ptPoint, int nFlags, PWINDOW pWindow, PIMAGE pImage, PMARK pMark, HDC hDC, RECT rClientRect, LRECT lrFullsizeClientRect){ int nStatus = 0; LRECT lrRect; LRECT lrNewRect; LRECT lrPointRect; int nOldROP; HBRUSH hOldBrush = 0; HPEN hOldPen = 0; // lrRectNew = new rect. SetLRect(lrPointRect, 0, 0, ptPoint.x, ptPoint.y); if (nFlags & PARM_SCALED){ ConvertRect(pWindow, &lrPointRect, CONV_SCALED_TO_FULLSIZE); }else if (!(nFlags & PARM_FULLSIZE)){ ConvertRect(pWindow, &lrPointRect, CONV_WINDOW_TO_FULLSIZE); } /* clip to image boundary too! */ lrPointRect.right = min(lrPointRect.right, pImage->nWidth); lrPointRect.bottom = min(lrPointRect.bottom, pImage->nHeight); lrNewRect.left = min(pMark->Attributes.lrBounds.left, lrPointRect.right); lrNewRect.top = min(pMark->Attributes.lrBounds.top, lrPointRect.bottom); lrNewRect.right = lmax(pMark->Attributes.lrBounds.left, lrPointRect.right); lrNewRect.bottom = lmax(pMark->Attributes.lrBounds.top, lrPointRect.bottom); ConvertRect(pWindow, &lrNewRect, CONV_FULLSIZE_TO_WINDOW); /* get the current rect for the annotation mark */ lrRect.left = min(pMark->Attributes.lrBounds.left, pMark->Attributes.lrBounds.right); lrRect.top = min(pMark->Attributes.lrBounds.top, pMark->Attributes.lrBounds.bottom); lrRect.right = lmax(pMark->Attributes.lrBounds.left, pMark->Attributes.lrBounds.right); lrRect.bottom = lmax(pMark->Attributes.lrBounds.top, pMark->Attributes.lrBounds.bottom); ConvertRect(pWindow, &lrRect, CONV_FULLSIZE_TO_WINDOW); nOldROP = SetROP2(hDC, R2_XORPEN); hOldPen = SelectObject(hDC, GetStockObject(NULL_PEN)); hOldBrush = SelectObject(hDC, GetStockObject(WHITE_BRUSH)); Rectangle(hDC, lrRect.left, lrRect.top, lrRect.right, lrRect.bottom); Rectangle(hDC, lrNewRect.left, lrNewRect.top, lrNewRect.right, lrNewRect.bottom); pMark->Attributes.lrBounds.right = lrPointRect.right; pMark->Attributes.lrBounds.bottom = lrPointRect.bottom; if (hOldBrush){ SelectObject(hDC, hOldBrush); } if (hOldPen){ SelectObject(hDC, hOldPen); } SetROP2(hDC, nOldROP); return nStatus; } /**************************************************************************** AnTextEnd this is the end op for text marks ****************************************************************************/ // 9512.04 jar Text Annotation Externalization //int WINAPI AnTextEnd(HWND hWnd, PWINDOW pWindow, PIMAGE pImage, // PMARK pMark, HDC hDC, RECT rClientRect, // LRECT lrFullsizeClientRect, PBOOL pbDeleteMark, PBOOL pRepaint){ int WINAPI AnTextEnd(HWND hWnd, PWINDOW pWindow, PIMAGE pImage, PMARK pMark, HDC hDC, RECT rClientRect, LRECT lrFullsizeClientRect, BOOL bActivate, PBOOL pbDeleteMark, PBOOL pRepaint){ // 9512.04 jar Text Annotation Externalization int nStatus = 0; int nAmount = 0; HINSTANCE hTheInst = 0; LPOIAN_TEXTPRIVDATA pStuff = NULL; int nHScale; int nVScale; int nFlags=0 ; // 9512.04 jar Text Annotation Externalization int Index = 0; // 9512.04 jar Text Annotation Externalization CheckError2(TranslateScale(pWindow->nScale, pImage->nHRes, pImage->nVRes, &nHScale, &nVScale)) /* establish default repaint for postit */ /* we do this because when this routine is called, the rect of the post-it has be drawn in Xor, so if we cancel out at this point we must tell seqfile to repaint the place nnder the rect */ *pRepaint = TRUE; JustifyLRect(&pMark->Attributes.lrBounds); CheckError2(PaintAnnotationText(hWnd, hDC, pWindow, pImage, pMark, rClientRect, lrFullsizeClientRect, PAINT_MODE_XOR, nHScale, nVScale, pWindow->lHOffset, pWindow->lVOffset, DONT_FORCE_OPAQUE_RECTANGLES)) // Draw the correct mark. CheckError2(PaintAnnotationText( hWnd, hDC, pWindow, pImage, pMark, rClientRect, lrFullsizeClientRect, PAINT_MODE_NORMAL, nHScale, nVScale, pWindow->lHOffset, pWindow->lVOffset, DONT_FORCE_OPAQUE_RECTANGLES)) // 9512.04 jar Text Annotation Externalization /* get buffer for data */ //if (nStatus = AllocateTextBuffer(pMark, OIAN_TEXTBUFFERSIZE, // (LPOIAN_TEXTPRIVDATA *)&pStuff)){ // goto Exit; //} pStuff = GetAnTextData(pMark, &Index); nAmount = pStuff->uAnoTextLength; /* fire np the edit ctl thing */ //hTheInst = hInst; //nAmount = AnTextEditCtl(hWnd, hTheInst, pMark); // 9512.04 jar Text Annotation Externalization if (nAmount > 0L){ pStuff->uCurrentScale = pWindow->nScale; //pStuff->uCreationScale = 1000; pStuff->uCreationScale = 72000 / pImage->nVRes; // 9512.04 jar Text Annotation Externalization //if (nStatus = ShrinkFitTextBuffer(pMark, (PPSTR) &pStuff, nAmount)){ // goto Exit; //} // 9512.04 jar Text Annotation Externalization AnTextPaintText(hWnd, hDC, pWindow, pImage, pMark, pMark->Attributes.rgbColor1, pMark->Attributes.rgbColor2, nHScale, nVScale, pWindow->lHOffset, pWindow->lVOffset, nFlags); *pbDeleteMark = FALSE; *pRepaint = TRUE; } Exit: return nStatus; } /**************************************************************************** AnTextStampStart this is the start op for stamp text marks ****************************************************************************/ int WINAPI AnTextStampStart(HWND hWnd, OIOP_START_OPERATION_STRUCT StartStr, POINT ptPoint, WPARAM fwKeys, int nFlags, PWINDOW pWindow, PIMAGE pImage, PMARK pMark, HDC hDC, RECT rClientRect, LRECT lrFullsizeClientRect, PBOOL pbDeleteMark, PBOOL pbMarkComplete, PBOOL pbRepaint){ int nStatus = 0; int nAmount = 0; RECT NewRect; LRECT lrNewRect; HFONT hFont; HINSTANCE hTheInst = NULL; LPOIAN_TEXTPRIVDATA pStuff = NULL; int nHScale; int nVScale; CheckError2(TranslateScale(pWindow->nScale, pImage->nHRes, pImage->nVRes, &nHScale, &nVScale)) CheckError2(AllocateTextBuffer(pMark, OIAN_STAMPBUFFERSIZE, (LPOIAN_TEXTPRIVDATA *)&pStuff)) hTheInst = hInst; nAmount = ParseTextStampString(hWnd, hTheInst, StartStr.szString, pMark); if (nAmount > 0L){ /* compute the initial bounding rectangle as top,left = input point bottom, right = bottom, right of image */ lrNewRect.left = 0L; lrNewRect.top = 0L; lrNewRect.right = pImage->nWidth; lrNewRect.bottom = pImage->nHeight; ConvertRect(pWindow, &lrNewRect, CONV_FULLSIZE_TO_WINDOW); CopyRectLtoR(NewRect, lrNewRect); NewRect.left = ptPoint.x; NewRect.top = ptPoint.y; CopyRectRtoL(pMark->Attributes.lrBounds, NewRect); /* establish font and do it */ pStuff->uCurrentScale = pWindow->nScale; //pStuff->uCreationScale = 1000; pStuff->uCreationScale = 72000 / pImage->nVRes; if (!(hFont = EstablishFont(hWnd, hDC, pMark, NULL))){ nStatus = Error(DISPLAY_OIANT_ERR_NOFONT); goto Exit; } EnsconceBoundRect(hWnd, hDC, hFont, pImage->nWidth, pImage->nHeight, pMark, pStuff, NewRect, nAmount, TRUE, nHScale, nVScale, pWindow->lHOffset, pWindow->lVOffset); ConvertRect(pWindow, &pMark->Attributes.lrBounds, CONV_WINDOW_TO_FULLSIZE); AnTextPaintText(hWnd, hDC, pWindow, pImage, pMark, pMark->Attributes.rgbColor1, pMark->Attributes.rgbColor2, nHScale, nVScale, pWindow->lHOffset, pWindow->lVOffset, nFlags); *pbDeleteMark = FALSE; *pbMarkComplete = TRUE; // *pbMarkComplete = FALSE; } Exit: *pbRepaint = TRUE; return nStatus; } /**************************************************************************** AnTextFromFile this is the start op for text from file marks ****************************************************************************/ int WINAPI AnTextFromFileStart(HWND hWnd, OIOP_START_OPERATION_STRUCT StartStr, POINT ptPoint, WPARAM fwKeys, int nFlags, PWINDOW pWindow, PIMAGE pImage, PMARK pMark, HDC hDC, RECT rClientRect, LRECT lrFullsizeClientRect, PBOOL pbDeleteMark, PBOOL pbMarkComplete, PBOOL pbRepaint){ int nStatus = 0; int nAmount = 0; RECT NewRect; LRECT lrNewRect; HFONT hFont; HINSTANCE hTheInst = NULL; LPOIAN_TEXTPRIVDATA pStuff = NULL; int nError; int nHScale; int nVScale; CheckError2(TranslateScale(pWindow->nScale, pImage->nHRes, pImage->nVRes, &nHScale, &nVScale)) CheckError2(AllocateTextBuffer(pMark, OIAN_TEXTFILESIZE, (LPOIAN_TEXTPRIVDATA *)&pStuff)) hTheInst = hInst; nAmount = AnTextReadFile(hWnd, StartStr.szString, pMark, &nError); nStatus = nError; if (nAmount > 0L){ /* compute the initial bounding rectangle as top,left = input point bottom, right = bottom, right of image */ /* keep lrBounds in FULLSIZE coordinates */ lrNewRect.left = 0L; lrNewRect.top = 0L; lrNewRect.right = pImage->nWidth; lrNewRect.bottom = pImage->nHeight; ConvertRect(pWindow, &lrNewRect, CONV_FULLSIZE_TO_WINDOW); CopyRectLtoR(NewRect, lrNewRect); NewRect.left = ptPoint.x; NewRect.top = ptPoint.y; CopyRectRtoL(pMark->Attributes.lrBounds, NewRect); /* establish font and do it */ pStuff->uCurrentScale = pWindow->nScale; //pStuff->uCreationScale = 1000; pStuff->uCreationScale = 72000 / pImage->nVRes; if (!(hFont = EstablishFont(hWnd, hDC, pMark, NULL))){ nStatus = Error(DISPLAY_OIANT_ERR_NOFONT); goto Exit; } EnsconceBoundRect( hWnd, hDC, hFont, pImage->nWidth, pImage->nHeight, pMark, pStuff, NewRect, nAmount, TRUE, nHScale, nVScale, pWindow->lHOffset, pWindow->lVOffset); ConvertRect2(&pMark->Attributes.lrBounds, CONV_WINDOW_TO_FULLSIZE, nHScale, nVScale, pWindow->lHOffset, pWindow->lVOffset); /* we will add one to length and tack on the null terminator */ nAmount++; *( pStuff->szAnoText + nAmount) = '\0'; CheckError2(ShrinkFitTextBuffer(pMark, (PPSTR) &pStuff, nAmount)) AnTextPaintText(hWnd, hDC, pWindow, pImage, pMark, pMark->Attributes.rgbColor1, pMark->Attributes.rgbColor2, nHScale, nVScale, pWindow->lHOffset, pWindow->lVOffset, nFlags); *pbDeleteMark = FALSE; *pbMarkComplete = TRUE; // *pbMarkComplete = FALSE; } Exit: *pbRepaint = TRUE; return nStatus; } /**************************************************************************** AnTextPaintText paint annotation text object ****************************************************************************/ VOID WINAPI AnTextPaintText(HWND hWnd, HDC hDC, PWINDOW pWindow, PIMAGE pImage, PMARK pMark, RGBQUAD rgbColor1, RGBQUAD rgbColor2, int nHScale, int nVScale, long lHOffset, long lVOffset, int nFlags){ HFONT hFont; HFONT hOldFont; RECT OurRect; LRECT lrOurRect; LPOIAN_TEXTPRIVDATA pStuff = NULL; int Index = 0; int nHeight = 0; int TotalHeight = 0; int TotalWidth = 0; int x; int y; int nDirection; HRGN hRgn; TEXTMETRIC tmTextMetric; RECT NewRect; /* get current image scale */ pStuff = GetAnTextData(pMark, &Index); if (pStuff){ if (pImage->nHRes >= pImage->nVRes) { pStuff->uCurrentScale = nHScale; }else{ pStuff->uCurrentScale = nVScale ; } if (hFont = EstablishFont(hWnd, hDC, pMark, &nHeight)){ // this is to bound the text mark to the image bounds when it is placed, // thereafter the mark bounds are used to size it (not the image bounds) if (nFlags & PARM_CREATE_TEXT) { if ((int) pMark->Attributes.uType != OIOP_AN_ATTACH_A_NOTE && (int) pMark->Attributes.uType != OIOP_AN_TEXT){ CopyRectLtoR( NewRect, pMark->Attributes.lrBounds); EnsconceBoundRect(hWnd, hDC, hFont, pImage->nWidth, pImage->nHeight, pMark, pStuff, NewRect, pStuff->uAnoTextLength, FALSE, nHScale, nVScale, lHOffset, lVOffset); } } hOldFont = DoTheFontText(hDC, hFont, pMark, rgbColor1, rgbColor2); lrOurRect = pMark->Attributes.lrBounds; ConvertRect2(&lrOurRect, CONV_FULLSIZE_TO_WINDOW, nHScale, nVScale, lHOffset, lVOffset); CopyRectLtoR(OurRect, lrOurRect); /* if this is a post-it we must bring in the edges of the post-it to give appearance of an edge to post-it note */ if ((int) pMark->Attributes.uType == OIOP_AN_ATTACH_A_NOTE){ OurRect.left += OIAN_STICKYNOTE_EDGE; OurRect.top += OIAN_STICKYNOTE_EDGE; OurRect.right -= OIAN_STICKYNOTE_EDGE; OurRect.bottom -= OIAN_STICKYNOTE_EDGE; } /* establish clip */ hRgn = CreateRectRgnIndirect(&OurRect); SelectClipRgn(hDC, hRgn); if (nHeight == 0){ GetTextMetrics(hDC, &tmTextMetric); nHeight = tmTextMetric.tmHeight; } if (pStuff->nCurrentOrientation == 0){ x = OurRect.left; y = OurRect.top; TotalWidth = OurRect.right - x; TotalHeight = OurRect.bottom - y; nDirection = YBOTTOM; OurOwnDrawText(hDC, pStuff->szAnoText, OurRect, x, y, nHeight, TotalHeight, TotalWidth, nDirection, FALSE, NULL, nHScale, nVScale); }else{ if (pStuff->nCurrentOrientation == 900){ x = OurRect.left; y = OurRect.bottom; TotalHeight = OurRect.right - x; TotalWidth = y - OurRect.top; nDirection = XRIGHT; }else if (pStuff->nCurrentOrientation == 1800){ x = OurRect.right; y = OurRect.bottom; TotalHeight = y - OurRect.top; TotalWidth = x - OurRect.left; nDirection = YTOP; }else{ x = OurRect.right; y = OurRect.top; TotalHeight = x - OurRect.left; TotalWidth = OurRect.bottom - y; nDirection = XLEFT; } OurOwnDrawText(hDC, pStuff->szAnoText, OurRect, x, y, nHeight, TotalHeight, TotalWidth, nDirection, FALSE, NULL, nHScale, nVScale); } /* clean np rect region */ SelectClipRgn(hDC, NULL); DeleteObject(hRgn); if (hOldFont){ SelectObject(hDC, hOldFont); if (hFont){ DeleteObject(hFont); } } } } //Exit: return; } /**************************************************************************** ############################################################################ UTILITY ROUTINE SECTION ############################################################################ ****************************************************************************/ /**************************************************************************** AllocateTextBuffer this will allocate a text buffer of sufficient size new allocation scheme ****************************************************************************/ int WINAPI AllocateTextBuffer(PMARK pMark, DWORD dwSize, LPOIAN_TEXTPRIVDATA * ppStuff){ LPOIAN_TEXTPRIVDATA pAnTextData; int nStatus = 0; CheckError2(GetAMarkNamedBlock(pMark, szOiAnTextData, (PPSTR) &pAnTextData)) if (!pAnTextData){ /* there isn't a text block, so we'll create one */ pAnTextData = 0; CheckError2(AddAMarkNamedBlock(pMark, szOiAnTextData, (PPSTR) &pAnTextData, dwSize + OIAN_TEXTPRIVSIZE)) pAnTextData->uAnoTextLength = dwSize; }else{ CheckError2(ReAllocateAMarkNamedBlock(pMark, szOiAnTextData, (PPSTR) &pAnTextData, dwSize + OIAN_TEXTPRIVSIZE)) pAnTextData->uAnoTextLength = dwSize; } Exit: *ppStuff = pAnTextData; return nStatus; } /**************************************************************************** ShrinkFitTextBuffer this will shrink text buffer to it's actual size ****************************************************************************/ int WINAPI ShrinkFitTextBuffer(PMARK pMark, PPSTR ppAnTextData, int nActualSize){ int nStatus = 0; int nLoop; BOOL bFound = FALSE; /* loop thru named block list, look for text block */ for (nLoop = 0; nLoop < pMark->nNamedBlocks; nLoop++){ if (!memcmp(pMark->ppNamedBlock[nLoop]->szName, szOiAnTextData, 8)){ bFound = TRUE; break; } } if (!bFound){ nStatus = Error(DISPLAY_OIANT_ERR_NONAMEDBLK); goto Exit; } nActualSize += OIAN_TEXTPRIVSIZE; CheckError2(ReAllocateMemory(nActualSize, (PPSTR) ppAnTextData, ZERO_INIT)) pMark->ppNamedBlock[nLoop]->lSize = nActualSize; pMark->ppNamedBlock[nLoop]->pBlock = (PSTR)*ppAnTextData; ((LPOIAN_TEXTPRIVDATA)*ppAnTextData)->uAnoTextLength = nActualSize - OIAN_TEXTPRIVSIZE; Exit: return nStatus; } /**************************************************************************** GetAnTextData get the pointer to named block for text data ****************************************************************************/ LPOIAN_TEXTPRIVDATA WINAPI GetAnTextData(PMARK pMark, PINT pIndex){ LPOIAN_TEXTPRIVDATA pData = NULL; int nLoop; /* loop thru named block list, look for text block */ for (nLoop = 0; nLoop < pMark->nNamedBlocks; nLoop++){ if (!memcmp(pMark->ppNamedBlock[nLoop]->szName, szOiAnTextData, 8)){ pData = (LPOIAN_TEXTPRIVDATA) pMark->ppNamedBlock[nLoop]->pBlock; break; } } *pIndex = nLoop; return pData; } /**************************************************************************** EstablishFont this will create a logical font ****************************************************************************/ HFONT WINAPI EstablishFont(HWND hWnd, HDC hDC, PMARK pMark, PINT pHeight){ HFONT hFont; LOGFONT OurFont; LPOIAN_TEXTPRIVDATA pStuff = NULL; int Index = 0; HDC hTempDC = NULL; if (pHeight != NULL){ *pHeight = 0; } OurFont = pMark->Attributes.lfFont; if (OurFont.lfHeight > 0){ /* Convert point size to height */ // OurFont.lfHeight = -MulDiv(OurFont.lfHeight,GetDeviceCaps(hDC, LOGPIXELSY), 72); // this change is to adjust the text to the display resolution. The printer resolution // adjustment is made by oiprt400.dll. The previous code did not work when the printer // DC was passed in as it resulted in double adjustment of the text to the printer res. hTempDC = GetDC (hWnd); OurFont.lfHeight = -MulDiv(OurFont.lfHeight,GetDeviceCaps(hTempDC, LOGPIXELSY), 72); } pStuff = GetAnTextData(pMark, &Index); if (pStuff){ // The uints have to stay typecasted or we get bad values if // ourfont.lfheight is a negative no. OurFont.lfHeight = (int)((OurFont.lfHeight * (int)pStuff->uCurrentScale) / (int)pStuff->uCreationScale); if ( OurFont.lfHeight == 0){ OurFont.lfHeight = -2; } if (pHeight != NULL){ *pHeight = (OurFont.lfHeight * (-1)); } /* angle of orientation */ OurFont.lfEscapement = pStuff->nCurrentOrientation; OurFont.lfOrientation = OurFont.lfEscapement; hFont = CreateFontIndirect(&OurFont); } if (hTempDC){ ReleaseDC (hWnd, hTempDC); } return hFont; } /**************************************************************************** DoTheFontText select font and do it earl! ****************************************************************************/ HFONT WINAPI DoTheFontText(HDC hDC, HFONT hFont, PMARK pMark, RGBQUAD rgbColor1, RGBQUAD rgbColor2){ HFONT hOldFont; SetTextAlign(hDC, TA_LEFT|TA_TOP); if (hFont){ hOldFont = SelectObject(hDC, hFont); } if ((int) pMark->Attributes.uType == OIOP_AN_ATTACH_A_NOTE){ SetTextColor(hDC, RGB(rgbColor2.rgbRed, rgbColor2.rgbGreen, rgbColor2.rgbBlue)); }else{ /* all other text types */ SetTextColor(hDC, RGB(rgbColor1.rgbRed, rgbColor1.rgbGreen, rgbColor1.rgbBlue)); } SetBkMode(hDC, TRANSPARENT); return hOldFont; } // 9512.04 jar Text Annotation Externalization ///**************************************************************************** // // SetPrivateEditData this will construct a private structure containing // annotation text stuff to pass to the edit ctl dialog // for editting text annotation // // ****************************************************************************/ //int WINAPI SetPrivateEditData(PPSTR ppsPrivate, PMARK pMark){ // //int nStatus = 0; //PPRIVATEEDITDATA pPrivate = NULL; //int Index = 0; // // // if (nStatus = AllocateMemory(sizeof(PRIVATEEDITDATA), // ppsPrivate, ZERO_INIT)){ // goto Exit; // } // // pPrivate = (PPRIVATEEDITDATA)(*ppsPrivate); // pPrivate->pMark = pMark; // pPrivate->pText = GetAnTextData(pMark, &Index); // if (pPrivate->pText != NULL){ // pPrivate->nAmount = strlen(((LPOIAN_TEXTPRIVDATA) pPrivate->pText)->szAnoText); // } // //Exit: // return nStatus; //} // 9512.04 jar Text Annotation Externalization /**************************************************************************** ParseTextStampString this will parse the input string, looking for our supported macros, and replacing with the proper data items Macro Name Function ========== ======== %d numerical day of the month (1 thru 31) %B the alphabetical name of the month, e.g., January %b the abbreviated alphabetical name of the month, e.g., Jan %m the numerical name of the month, e.g., 1 %Y the numerical full name of the year, e.g., 1994 %y the numerical abbreviated name of the year, e.g., 94 %I the 12 hour time of day, e.g., 10:09 pm %H the 24 hour time of day, e.g., 22:09 New Improved with Multibyte Enabling!!!! These new macros are from strftime, ANSI standard C call! ****************************************************************************/ int WINAPI ParseTextStampString(HWND hWnd, HINSTANCE hTheInst, PSTR pString, PMARK pMark){ int nMacroID; int nCount = 0; OITIMESTR TimeStr; LPOIAN_TEXTPRIVDATA pStuff = NULL; PSTR pWorker = NULL; int Index = 0; pStuff = GetAnTextData(pMark, &Index); pWorker = pStuff->szAnoText; /* get time and date from system */ GetDateAndTime((POITIMESTR)&TimeStr); /* look for macro(s) and go to town */ while (*pString != '\0'){ if (*pString != '%'){ *pWorker++ = *pString; if (IsDBCSLeadByte(*pString)){ *pWorker++ = *(pString + 1); } pString = CharNext(pString); }else{ pString = CharNext(pString); if (*pString == '%'){ *pWorker++ = '%'; }else{ nMacroID = FindMacro(pString); nCount = ExpandMacro(hTheInst, pWorker, nMacroID, TimeStr); pWorker += nCount; } pString = CharNext(pString); } } *pWorker = '\0'; return (strlen(pStuff->szAnoText)); } /**************************************************************************** FindMacro find the macro string in our table and get the id ****************************************************************************/ int WINAPI FindMacro(PSTR pMacroName){ int nMacroID = 0; int i; BOOL bFound = FALSE; char szMacro[2] = "%\0"; szMacro[0] = *pMacroName; for (i = 0; i < OIAN_MAXMACROS; i++){ if (!(strcmp(szMacro, OiAnTextMacro[i].szMacro))){ nMacroID = OiAnTextMacro[i].nMacroID; bFound = TRUE; break; } } if (!bFound){ nMacroID = OIAN_TEXTMACRONOTFOUND; } return nMacroID; } /**************************************************************************** ExpandMacro expand the found macro into the proper string ****************************************************************************/ int WINAPI ExpandMacro(HINSTANCE hTheInst, PSTR pAnoData, int nMacroID, OITIMESTR TimeStr){ int nAmount = 0; int nCount = 0; char szMonth[OIANMONTHMAX],szBuf[32]; int Min; int Hour; BOOL bAfternoon; switch(nMacroID){ case OIAN_TEXTMACRO_DAY: nAmount = MakeAscii(TimeStr.day, pAnoData, FALSE, 0); break; case OIAN_TEXTMACRO_DATE: nAmount = GetDateFormat(LOCALE_USER_DEFAULT,DATE_SHORTDATE,NULL,NULL,szBuf,32); lstrcpy(pAnoData, szBuf); nAmount -= 1; // minus the trailing NULL break; case OIAN_TEXTMACRO_TIME: nAmount = GetTimeFormat(LOCALE_USER_DEFAULT,0,NULL,NULL,szBuf,32); lstrcpy(pAnoData, szBuf); nAmount -= 1; break; case OIAN_TEXTMACRO_APHAMONTH: // fix bug TimeStr.mon 1-12 8/3/95 JCW nAmount = LoadString(hTheInst, (TimeStr.mon + OIAN_TEXTALPHAMONTHOFF-1), szMonth, OIANMONTHMAX); strcpy(pAnoData, szMonth); break; case OIAN_TEXTMACRO_ABRVMONTH: nAmount = LoadString(hTheInst, (TimeStr.mon + OIAN_TEXTABRVMONTHOFF-1), szMonth, OIANMONTHMAX); strcpy(pAnoData, szMonth); break; case OIAN_TEXTMACRO_NUMMONTH: nAmount = MakeAscii((TimeStr.mon), pAnoData, FALSE, 0); break; case OIAN_TEXTMACRO_YEAR: nAmount = MakeAscii((TimeStr.year + 1900), pAnoData, FALSE, 0); break; case OIAN_TEXTMACRO_ABRVYEAR: if (TimeStr.year > 100) TimeStr.year -= 100; nAmount = MakeAscii(TimeStr.year, pAnoData, TRUE, 2); break; case OIAN_TEXTMACRO_TIME12HR: Min = TimeStr.min; Hour = TimeStr.hour; if (Hour >= 12){ bAfternoon = TRUE; Hour -= 12; }else{ bAfternoon = FALSE; } if (Hour == 0){ Hour = 12; } nAmount = MakeAscii(Hour, pAnoData, FALSE, 0); pAnoData += nAmount; *pAnoData++ = ':'; nAmount++; nCount = MakeAscii(Min, pAnoData, TRUE, 2); pAnoData += nCount; *pAnoData++ = ' '; nAmount += nCount + 1; nCount = LoadString(hTheInst, OIAN_TEXTTIME_AMPM + bAfternoon, szMonth, OIANMONTHMAX); strcpy(pAnoData, szMonth); nAmount += nCount; break; case OIAN_TEXTMACRO_TIME24HR: nAmount = MakeAscii(TimeStr.hour, pAnoData, TRUE, 2); pAnoData += nAmount; *pAnoData++ = ':'; nAmount++; nCount = MakeAscii(TimeStr.min, pAnoData, TRUE, 2); pAnoData += nCount; nAmount += nCount; break; } return nAmount; } /**************************************************************************** MakeAscii makes atring from integer base 10 to ascii ****************************************************************************/ int WINAPI MakeAscii(int Num, PSTR pStr, BOOL bPrecedingZero, int nZeroDigits){ int nAmount = 0; int nDigits[] ={10000, 1000, 100, 10, 1}; int nOurs[] ={0, 0, 0, 0, 0}; char szDigit[OIANMAXDIGITS]; int nFirstNonZero = 0; int i; for (i = 0; i < OIANMAXDIGITS; i++){ nOurs[i] = Num / nDigits[i]; Num -= nOurs[i] * nDigits[i]; if ((!nFirstNonZero) && (nOurs[i] != 0)){ nFirstNonZero = i + 1; } szDigit[i] = (char)(0x30 + nOurs[i]); } if (bPrecedingZero){ i = OIANMAXDIGITS - nZeroDigits; nAmount = nZeroDigits; }else{ i = nFirstNonZero - 1; nAmount = OIANMAXDIGITS + 1 - nFirstNonZero; } if (nAmount){ memcpy(pStr, &szDigit[i], nAmount); } return nAmount; } /**************************************************************************** GetDateAndTime get the current date and time ****************************************************************************/ VOID WINAPI GetDateAndTime(POITIMESTR pTime){ SYSTEMTIME LocalTime; GetLocalTime (&LocalTime); pTime->day = (BYTE)LocalTime.wDay; pTime->mon = (BYTE)LocalTime.wMonth; pTime->year = LocalTime.wYear - 1900; pTime->hour = (BYTE)LocalTime.wHour; pTime->min = (BYTE)LocalTime.wMinute; return; } /**************************************************************************** AnTextReadFile this will read text from a file into text data buffer ****************************************************************************/ int WINAPI AnTextReadFile(HWND hWnd, PSTR pString, PMARK pMark, PINT pError){ int nFileToken; int nLocalFile = 0; int nBytes=0; LPOIAN_TEXTPRIVDATA pStuff; int Index; pStuff = GetAnTextData(pMark, &Index); *pError = 0; nFileToken = IMGFileBinaryOpen32(hWnd, pString, OF_READ, &nLocalFile, pError); if (nFileToken != -1){ nBytes = IMGFileBinaryRead32(hWnd, nFileToken, pStuff->szAnoText, pStuff->uAnoTextLength, pError); IMGFileBinaryClose32(hWnd, nFileToken, pError); } return nBytes; } static char szPalClassName[] = "OiUIToolPaletteClass"; // 9512.04 jar Text Annotation Externalization ///**************************************************************************** // // EditEnumFunc nnknown purpose????? // // ****************************************************************************/ //BOOL WINAPI EditEnumFunc(HWND hWnd, PARAM lParam){ // //char winclass[40]; // // // if (GetClassName(hWnd, winclass, 40)){ // if(!(strcmp(winclass, szPalClassName))){ // *(HANDLE *)lParam = hWnd; // return(0); // } // } // return(1); //} // ///**************************************************************************** // // AnTextEditCtl this is the dialog for text edit by end-nser // //****************************************************************************/ //int WINAPI AnTextEditCtl(HWND hWnd, HINSTANCE hInstanceVal, PMARK pMark){ // //int nAmount = 0; //PSTR psPrivate = NULL; //PPRIVATEEDITDATA pPrivate = NULL; //FARPROC pfnEditCtlDlgProc = NULL; //HANDLE hPalWnd=0; //BOOL bPalEnable; // // // if (!SetPrivateEditData(&psPrivate, pMark)){ // pfnEditCtlDlgProc = GetProcAddress(hInstanceVal, "AnTextEditCtlDlgProc"); //// EnumTaskWindows(GetCurrentTask(), EditEnumFunc, (LPARAM)(HANDLE *)&hPalWnd); // if (hPalWnd){ // bPalEnable = EnableWindow(hPalWnd,FALSE); // } // // DialogBoxParam(hInstanceVal, "AnTextEditCtlDlg", hWnd, // (DLGPROC) pfnEditCtlDlgProc, (LPARAM) psPrivate); // // if (hPalWnd){ // EnableWindow(hPalWnd, !bPalEnable); // backwards flag! // } // // pPrivate = (PPRIVATEEDITDATA) psPrivate; // nAmount = pPrivate->nAmount; // FreeMemory (&psPrivate); // } // return nAmount; //} ///**************************************************************************** // // SwitchKeyboard Switch the keyboard layout according to the charset // //*****************************************************************************/ //void WINAPI SwitchKeyboard(BYTE bCharset, PHKL pOldKeyboard) //{ // if (bCharset == GREEK_CHARSET) // { // if ((*pOldKeyboard = ActivateKeyboardLayout((HKL)0X408,KLF_REORDER)) == 0) // *pOldKeyboard = LoadKeyboardLayout("00000408",KLF_REORDER); // } // else if (bCharset == RUSSIAN_CHARSET) // { // if ((*pOldKeyboard = ActivateKeyboardLayout((HKL)0X419,KLF_REORDER)) == 0) // *pOldKeyboard = LoadKeyboardLayout("00000419",KLF_REORDER); // } // else if ((bCharset == EASTEUROPE_CHARSET) || // (bCharset == TURKISH_CHARSET)) // { // if ((*pOldKeyboard = ActivateKeyboardLayout((HKL)0X405,KLF_REORDER)) == 0) // *pOldKeyboard = LoadKeyboardLayout("00000405",KLF_REORDER); // } // else if (bCharset == BALTIC_CHARSET) // German Standard // { // if ((*pOldKeyboard = ActivateKeyboardLayout((HKL)0X407,KLF_REORDER)) == 0) // *pOldKeyboard = LoadKeyboardLayout("00000407",KLF_REORDER); // } // return; //} ///**************************************************************************** // // AnTextEditCtlDlgProc this is the dialog proc // //*****************************************************************************/ //long WINAPI AnTextEditCtlDlgProc(HWND hDlg, int nMsg, WPARAM wParam, PARAM lParam){ // //PPRIVATEEDITDATA pPrivate = NULL; //PSTR psPrivate = NULL; //int nBytes,nFontHeight; //HWND hWndEditCtl; //static char szAnTextName[]="OIANEDITCTL"; //LPOIAN_TEXTPRIVDATA pStuff = NULL; //char szCaption[OIANCAPTIONMAX]; //byte bCharset; //static HFONT hFont; //static HKL hOldKeyBoard; //HDC hTempDC; // // // switch(nMsg){ // case WM_INITDIALOG: // /* NOTE: FOR DIALOG BOXES, IT IS NOT POSSIBLE FOR US TO ALLOCATE // A LOCAL HEAP FOR THE EDIT CONTROL TO USE (SEE NOTES) */ // /* get the edit control's handle */ // hWndEditCtl = GetDlgItem(hDlg, IDM_EDITCTL); // // /* set edit ctl text limit to the max */ // SendMessage(hWndEditCtl, EM_LIMITTEXT, 0, 0L); // hOldKeyBoard = 0; // psPrivate = (PSTR)lParam; // pPrivate = (PPRIVATEEDITDATA) psPrivate; // // IMGSetProp(hDlg, (PCSTR)szAnTextName, (HANDLE) psPrivate); // hTempDC = GetDC(hWndEditCtl); // nFontHeight = pPrivate->pMark->Attributes.lfFont.lfHeight; // pPrivate->pMark->Attributes.lfFont.lfHeight = // -MulDiv(pPrivate->pMark->Attributes.lfFont.lfHeight, // GetDeviceCaps(hTempDC, LOGPIXELSY), 72); // ReleaseDC(hWndEditCtl,hTempDC); // bCharset = pPrivate->pMark->Attributes.lfFont.lfCharSet; // hFont = 0; // hFont = CreateFontIndirect(&pPrivate->pMark->Attributes.lfFont); // SendMessage(hWndEditCtl, WM_SETFONT,(WPARAM) hFont, 0L); // pPrivate->pMark->Attributes.lfFont.lfHeight = nFontHeight; // // if (pPrivate){ // /* get the proper caption */ // switch(pPrivate->(int) pMark->Attributes.uType){ // case OIOP_AN_ATTACH_A_NOTE: // nBytes = LoadString(hInst, OIAN_ATTACHANOTE_CAPTION, // szCaption, OIANCAPTIONMAX); // if (bCharset != 0) // SwitchKeyboard(bCharset,&hOldKeyBoard); // break; // // case OIOP_AN_TEXT: // nBytes = LoadString(hInst, OIAN_TEXT_CAPTION, // szCaption, OIANCAPTIONMAX); // if (bCharset != 0) // SwitchKeyboard(bCharset,&hOldKeyBoard); // break; // // case OIOP_AN_TEXT_FROM_A_FILE: // nBytes = LoadString(hInst, OIAN_TEXT_FROMFILE_CAPTION, // szCaption, OIANCAPTIONMAX); // break; // // default: // nBytes = 0; // break; // } // // if (nBytes){ // SetWindowText(hDlg, szCaption); // } // // pPrivate->hWndEditCtl = hWndEditCtl; // // if (pPrivate->nAmount){ // pStuff = pPrivate->pText; // SetDlgItemText(hDlg, IDM_EDITCTL, pStuff->szAnoText); // } // // /* put caret into edit ctl at end of text, if any */ // SendMessage(hWndEditCtl, EM_SETSEL, pPrivate->nAmount, // pPrivate->nAmount); // // /* set focus for caret to be in edit ctl */ // SetFocus(hWndEditCtl); // // } // break; // // case WM_COMMAND: // switch(wParam){ // case IDANOK: // psPrivate = (PSTR)IMGGetProp(hDlg, (PCSTR)szAnTextName); // if (psPrivate){ // pPrivate = (PPRIVATEEDITDATA) psPrivate; // if (pPrivate){ // pStuff = pPrivate->pText; // nBytes = (WORD)SendMessage(pPrivate->hWndEditCtl, // WM_GETTEXT, (WPARAM)(pPrivate->pText->uAnoTextLength), // (LPARAM)(pStuff->szAnoText)); // // /* save amount plus the null terminator */ // pPrivate->nAmount = nBytes + 1; // } // } // IMGRemoveProp(hDlg, (PCSTR)szAnTextName); // if (hOldKeyBoard != 0) // ActivateKeyboardLayout(hOldKeyBoard,KLF_REORDER); // if (hFont) // DeleteObject(hFont); // EndDialog(hDlg, 0); // break; // // case IDANCANCEL: // psPrivate = (PSTR)IMGGetProp(hDlg, (PCSTR)szAnTextName); // if (psPrivate){ // pPrivate = (PPRIVATEEDITDATA) psPrivate; // if (pPrivate){ // pPrivate->nAmount = 0; // } // } // IMGRemoveProp(hDlg, (PCSTR)szAnTextName); // if (hOldKeyBoard != 0) // ActivateKeyboardLayout(hOldKeyBoard,KLF_REORDER); // if (hFont) // DeleteObject(hFont); // EndDialog(hDlg, 0); // break; // // default: // return 0L; // } // break; // } // return 0L; //} /**************************************************************************** EnsconceBoundRect this will determine the annotation text mark bound rectangle *****************************************************************************/ VOID WINAPI EnsconceBoundRect(HWND hWnd, HDC hDC, HFONT hFont, int nImageWidth, int nImageHeight, PMARK pMark, LPOIAN_TEXTPRIVDATA pStuff, RECT NewRect, int nAmount, BOOL bCleanUpFont, int nHScale, int nVScale, long lHOffset, long lVOffset){ HFONT hOldFont = 0; HFONT hNotherFont = 0; RECT VeryNewRect; int nHeight = 0; int nOldOrient = 0; int nDeltaY = nImageHeight; int nDeltaX = nImageWidth; BOOL bDiffScale = FALSE; int nOldScale = pStuff->uCurrentScale; int x; int y; int TotalHeight; int TotalWidth; int nDirection; /* we rotate the rect so that it's horizontal for the DrawText CalcRect function, since GDI cannot work at any other orientation, then, we'll spin our rect back to the proper orientation before exit */ if (bDiffScale){ hNotherFont = EstablishFont(hWnd, hDC, pMark, &nHeight); }else{ hNotherFont = hFont; } if (hNotherFont){ hOldFont = DoTheFontText( hDC, hNotherFont, pMark, pMark->Attributes.rgbColor1, pMark->Attributes.rgbColor2); if (pStuff->nCurrentOrientation == 0){ NewRect.right = nDeltaX; NewRect.bottom = nDeltaY; x = NewRect.left; y = NewRect.top; TotalWidth = NewRect.right - x; TotalHeight = NewRect.bottom - y; nDirection = YBOTTOM; }else if (pStuff->nCurrentOrientation == 900){ NewRect.right = nDeltaX; NewRect.top = 0; x = NewRect.left; y = NewRect.bottom; TotalHeight = NewRect.right - x; TotalWidth = y - NewRect.top; nDirection = XRIGHT; }else if (pStuff->nCurrentOrientation == 1800){ NewRect.left = 0; NewRect.top = 0; x = NewRect.right; y = NewRect.bottom; TotalHeight = y - NewRect.top; TotalWidth = x - NewRect.left; nDirection = YTOP; }else{ NewRect.left = 0; NewRect.bottom = nDeltaY; x = NewRect.right; y = NewRect.top; TotalHeight = x - NewRect.left; TotalWidth = NewRect.bottom - y; nDirection = XLEFT; } VeryNewRect = NewRect; OurOwnDrawText(hDC, pStuff->szAnoText, NewRect, x, y, nHeight, TotalHeight, TotalWidth, nDirection, TRUE, &VeryNewRect, nHScale, nVScale); NewRect = VeryNewRect; if (bCleanUpFont || bDiffScale){ if (hOldFont){ SelectObject(hDC, hOldFont); if (hNotherFont){ DeleteObject(hNotherFont); } } }else{ if (hOldFont){ SelectObject(hDC, hOldFont); } } CopyRectRtoL(pMark->Attributes.lrBounds, NewRect); } return; } /**************************************************************************** FUNCTION: ScaleAnnotationText PURPOSE: This scales an annotation down to the size specified in the pSaveEx structure. ****************************************************************************/ int WINAPI ScaleAnnotationText(HWND hWnd, PMARK pMark, int nHScale, int nVScale){ int nStatus = 0; PWINDOW pWindow; PANO_IMAGE pAnoImage; PIMAGE pImage; int Index = 0; LPOIAN_TEXTPRIVDATA pStuff = NULL; HFONT hFont; HDC hDC = NULL; //RECT NewRect; PARM_DIM_STRUCT Dim; int nWidth = 0; int nHeight = 0; CheckError2( Init(hWnd, &pWindow, &pAnoImage, TRUE, TRUE)) pImage = pAnoImage->pBaseImage; /* TODOJAR call get parms to get image width and height */ nStatus = IMGGetParmsCgbw(hWnd, PARM_DIMENSIONS, &Dim, 0); nWidth = Dim.nWidth; nHeight = Dim.nHeight; pStuff = GetAnTextData(pMark, &Index); /* compute the new point size = old * scale/create scale */ pMark->Attributes.lfFont.lfHeight = (pMark->Attributes.lfFont.lfHeight * nHScale) / pStuff->uCreationScale; //pStuff->uCreationScale = 1000; pStuff->uCreationScale = 72000 / pImage->nVRes; pStuff->uCurrentScale = 1000; hDC = GetDC(hWnd); if (hDC){ if (!(hFont = EstablishFont(hWnd, hDC, pMark, NULL))){ nStatus = Error(DISPLAY_OIANT_ERR_NOFONT); goto Exit; } // if ((int) pMark->Attributes.uType != OIOP_AN_ATTACH_A_NOTE){ // CopyRectLtoR(NewRect, pMark->Attributes.lrBounds); // EnsconceBoundRect(hWnd, hDC, hFont, nWidth, nHeight, pMark, pStuff, NewRect, // pStuff->uAnoTextLength, FALSE, nHScale, nVScale, 0, 0); // } pMark->Attributes.lrBounds.left = (pMark->Attributes.lrBounds.left * nHScale) / 1000; pMark->Attributes.lrBounds.right = (pMark->Attributes.lrBounds.right * nHScale) / 1000; pMark->Attributes.lrBounds.top = (pMark->Attributes.lrBounds.top * nVScale) / 1000; pMark->Attributes.lrBounds.bottom = (pMark->Attributes.lrBounds.bottom * nVScale) / 1000; } if (hDC != NULL){ ReleaseDC(hWnd, hDC); } Exit: DeInit(TRUE, TRUE); return nStatus; } /******************************************************************** OrientBounds this will orient the bounding rectangle of the text mark ********************************************************************/ int WINAPI OrientBounds(PIMAGE pImage, PMARK pMark, int nOrientation){ int nStatus = 0; LRECT lrOldMarkBounds; CopyRect(lrOldMarkBounds, pMark->Attributes.lrBounds); switch (nOrientation){ case OD_ROTRIGHT: pMark->Attributes.lrBounds.left = pImage->nHeight - lrOldMarkBounds.bottom; pMark->Attributes.lrBounds.top = lrOldMarkBounds.left; pMark->Attributes.lrBounds.right = pImage->nHeight - lrOldMarkBounds.top; pMark->Attributes.lrBounds.bottom = lrOldMarkBounds.right; break; case OD_ROTLEFT: pMark->Attributes.lrBounds.left = lrOldMarkBounds.top; pMark->Attributes.lrBounds.top = pImage->nWidth - lrOldMarkBounds.right; pMark->Attributes.lrBounds.right = lrOldMarkBounds.bottom; pMark->Attributes.lrBounds.bottom = pImage->nWidth - lrOldMarkBounds.left; break; case OD_FLIP: pMark->Attributes.lrBounds.left = pImage->nWidth - lrOldMarkBounds.right; pMark->Attributes.lrBounds.top = pImage->nHeight - lrOldMarkBounds.bottom; pMark->Attributes.lrBounds.right = pImage->nWidth - lrOldMarkBounds.left; pMark->Attributes.lrBounds.bottom = pImage->nHeight - lrOldMarkBounds.top; break; case OD_HMIRROR: pMark->Attributes.lrBounds.top = pImage->nHeight - lrOldMarkBounds.bottom; pMark->Attributes.lrBounds.bottom = pImage->nHeight - lrOldMarkBounds.top; break; case OD_VMIRROR: pMark->Attributes.lrBounds.left = pImage->nWidth - lrOldMarkBounds.right; pMark->Attributes.lrBounds.right = pImage->nWidth - lrOldMarkBounds.left; break; } return nStatus; } /******************************************************************** OurOwnDrawText this emulates the draw text function but for cases when the text is not horizontal 9605.03 jar added a magic number calculation because the ExternalLeading given back by the GetTextMetric function is sometimes 0 and sometimes 1, both of which are useless, so we now determine our own ********************************************************************/ int WINAPI OurOwnDrawText(HDC hDC, PSTR pStr, RECT TextRect, int x, int y, int nHeight, int TotalHeight, int TotalWidth, int nHeightDirection, BOOL bJustCalc, PRECT pCalcRect, int nHScale, int nVScale){ int nStatus = 0; int TextWidth; DWORD dwExtent; int TotalCount; int nPrevCount; int nCount; PSTR pSrc; BOOL bEnd; BOOL bLineEnd = FALSE; int nHeightCount = 0; BOOL bMoreThanOneWord = FALSE; DWORD dnHeight1; DWORD dnHeight2; int nHeightX; int nBreakCount; int TextWidthMax = 0; int x0 = x; int y0 = y; int Temp; SIZE Size; // 9605.03 jar adding text metric stuff TEXTMETRIC TextMetric; int FudgeNumber = OWNDRAWTEXT_MAGIC; dwExtent = GetTextExtentPoint32(hDC, pStr, strlen(pStr), &Size); // 9605.03 jar adding text metric stuff GetTextMetrics(hDC, &TextMetric); TextWidth = Size.cx; if (nHeight == 0){ nHeight = Size.cy; // we'll fudge our own since the font "designer" doesn't give us // one or just gives us a lousy one to use nHeight += (TextMetric.tmHeight*FudgeNumber)/1000; } /* adjust by inverse of scale factor if we are just calculating rect because we should calc rect in fullsize only */ if (bJustCalc){ if ((nHeightDirection == YTOP) || (nHeightDirection == YBOTTOM)){ Temp = max(1, (nHeight * 1000) / nVScale); if ((Temp * nVScale) < (nHeight * 1000)){ Temp++; } nHeight = Temp; Temp = max(1, (TextWidth * 1000) / nHScale); if ((Temp * nHScale) < (TextWidth * 1000)){ Temp++; } TextWidth = Temp; }else{ Temp = max(1, (TextWidth * 1000) / nVScale); if ((Temp * nVScale) < (TextWidth * 1000)){ Temp++; } TextWidth = Temp; Temp = max(1, (nHeight * 1000) / nHScale); if ((Temp * nHScale) < (nHeight * 1000)){ Temp++; } nHeight = Temp; } } dnHeight1 = nHeight * 1000L; dnHeight1 /= 7; dnHeight2 = (dnHeight1 / 1000L) * 1000L; nHeightX = (dnHeight2/1000L); if ((dnHeight1 - dnHeight2) >= 500L){ nHeightX += 1; } nHeight += nHeightX; /* we've got to wordwrap */ TotalCount = strlen(pStr); pSrc = pStr; nPrevCount = 0; bEnd = FALSE; while ((TotalCount) && (!bEnd)){ nCount = FindNextSpace(pSrc, nPrevCount, &bEnd, &bLineEnd); if ( bLineEnd){ nCount -= 2; } dwExtent = GetTextExtentPoint32(hDC, pSrc, (nCount + nPrevCount), &Size); if (bLineEnd){ nCount += 2; } TextWidth = Size.cx; if (bJustCalc){ if ((nHeightDirection == YTOP) || (nHeightDirection == YBOTTOM)){ Temp =max(1L,((ulong)TextWidth*1000L)/nHScale); if (((ulong)Temp * nHScale) < ((ulong)TextWidth * 1000L)){ Temp++; } }else{ Temp =max(1L,((ulong)TextWidth*1000L)/nVScale); if (((ulong)Temp * nVScale) < ((ulong)TextWidth * 1000L)){ Temp++; } } TextWidth = Temp; } if ( TextWidth > TextWidthMax){ TextWidthMax = TextWidth; } if ((TextWidth > TotalWidth) || (bEnd) || (bLineEnd)){ /* the previous state was the correct one */ if (bEnd){ if (TextWidth > TotalWidth){ if (bMoreThanOneWord){ bEnd = FALSE; }else{ nPrevCount += nCount; } }else{ nPrevCount += nCount; } } if (!bLineEnd){ if ((bMoreThanOneWord) && ( !bJustCalc)){ TextOut(hDC, x, y, pSrc, nPrevCount); }else{ /* we must try to break the word since there's only one */ nBreakCount = WithinWordBreak(hDC, x, y, pSrc, nCount, TotalWidth, bJustCalc, nHeightDirection, nHScale, nVScale); if (nBreakCount){ nPrevCount = nBreakCount; if (bEnd){ bEnd = FALSE; } }else{ nPrevCount = nCount + 1; if (!bJustCalc){ TextOut(hDC, x, y, pSrc, nCount); } } } }else{ bLineEnd = FALSE; if (TextWidth > TotalWidth && bMoreThanOneWord){ if (!bJustCalc){ TextOut(hDC, x, y, pSrc, nPrevCount); } }else{ if (!bMoreThanOneWord && TextWidth > TotalWidth){ /* take off cr/lf */ nPrevCount += nCount - 2; nBreakCount = WithinWordBreak(hDC, x, y, pSrc, nPrevCount, TotalWidth, bJustCalc,nHeightDirection, nHScale, nVScale); nPrevCount -= nCount - 2; if (nBreakCount){ nPrevCount = nBreakCount; if (bEnd){ bEnd = FALSE; } }else{ nPrevCount += nCount - 2; if ((nPrevCount > 0) && ( !bJustCalc)){ TextOut(hDC, x, y, pSrc, nPrevCount); } nPrevCount += 2; } }else{ nPrevCount += nCount - 2; if ((nPrevCount > 0) && ( !bJustCalc)){ TextOut(hDC, x, y, pSrc, nPrevCount); } nPrevCount += 2; } } } if (nHeightDirection == YTOP){ y -= nHeight; } else if (nHeightDirection == YBOTTOM){ y += nHeight; } else if (nHeightDirection == XRIGHT){ x += nHeight; }else{ x -= nHeight; } pSrc += nPrevCount; TotalCount -= nPrevCount; nPrevCount = 0; nHeightCount += nHeight; if (nHeightCount > TotalHeight){ bEnd = TRUE; } bMoreThanOneWord = FALSE; }else{ /* npdate and keep looking */ nPrevCount += nCount + 1; bMoreThanOneWord = TRUE; } } if (bJustCalc && pCalcRect){ if ( nHeightCount == 0){ nHeightCount = nHeight; } if (nHeightDirection == YTOP){ pCalcRect->top = max( 0, ((int)y0 - (int)nHeightCount)); pCalcRect->left = max( 0, ((int)x0 - (int)TextWidthMax)); pCalcRect->bottom = y0; pCalcRect->right = x0; } else if (nHeightDirection == YBOTTOM){ pCalcRect->top = y0; pCalcRect->left = x0; pCalcRect->bottom = min(y0 + nHeightCount, y0 + TotalHeight); pCalcRect->right = min(x0 + TextWidthMax, x0 + TotalWidth); } else if (nHeightDirection == XRIGHT){ pCalcRect->left = x0; pCalcRect->top = max(0, y0 - TextWidthMax); pCalcRect->right = min(x0 + nHeightCount, x0 + TotalHeight); pCalcRect->bottom = y0; }else{ /* this is height increasing left in the x-direction*/ pCalcRect->left = max(0, x0 - nHeightCount); pCalcRect->top = y0; pCalcRect->right = x0; pCalcRect->bottom = min(y0 + TextWidthMax, y0 + TotalWidth); } if (pCalcRect->right < 0){ pCalcRect->left = pCalcRect->right - pCalcRect->left; pCalcRect->right = 5; pCalcRect->left = pCalcRect->right - pCalcRect->left; } if (pCalcRect->bottom < 0){ pCalcRect->top = pCalcRect->bottom - pCalcRect->top; pCalcRect->bottom = 5; pCalcRect->top = pCalcRect->bottom - pCalcRect->top; } } return nStatus; } /******************************************************************** FindNextSpace find the next space/blank in a string ********************************************************************/ int WINAPI FindNextSpace(PSTR pSrc, int nSkipCount, BOOL *pbEnd, BOOL *pbLineEnd){ int nLength = 0; int nCount = 0; PSTR pStr; PSTR pStrDum; BOOL bDone = FALSE; pStr = pSrc + nSkipCount; nLength = strlen(pStr); while (nLength && !bDone){ if (*pStr == ' '){ bDone = TRUE; } else if (*pStr == 0x0d){ pStrDum = CharNext(pStr); if (*pStrDum == 0x0a){ bDone = TRUE; *pbLineEnd = TRUE; pStrDum = CharNext(pStrDum); nCount += pStrDum - pStr; pStr = pStrDum; }else{ pStrDum = CharNext(pStr); nCount += pStrDum - pStr; nLength -= pStrDum - pStr; pStr = pStrDum; } }else{ pStrDum = CharNext(pStr); nCount += pStrDum - pStr; nLength -= pStrDum - pStr; pStr = pStrDum; } } if (nLength == 0){ *pbEnd = TRUE; } return nCount; } /******************************************************************** WithinWordBreak this will, for a single word that does not fit within a line, break the word, so that we fit all the characters of the word on multiple lines ********************************************************************/ int WINAPI WithinWordBreak(HDC hDC, int x, int y, PSTR pSrc, int nCount, int TotalWidth, BOOL bJustCalc, int nHeightDirection, int nHScale, int nVScale){ int nRetCount = 0; int nTotalCount; int TextWidth; DWORD dwExtent; BOOL bDone = FALSE; int Temp; SIZE Size; int nIndex = 0; int nPrevIndex = 0; PSTR pCounterString = NULL; nTotalCount = nCount; GetTextExtentPoint32(hDC, pSrc, nCount, &Size); TextWidth = Size.cx; if (bJustCalc){ if ((nHeightDirection == YTOP) || (nHeightDirection == YBOTTOM)){ Temp = max( 1L, ((ulong)TextWidth*1000L)/nHScale); if (((ulong)Temp * nHScale) < ((ulong)TextWidth * 1000L)){ Temp++; } }else{ Temp = max( 1L, ((ulong)TextWidth*1000L)/nVScale); if (((ulong)Temp * nVScale) < ((ulong)TextWidth * 1000L)){ Temp++; } } TextWidth = Temp; } if (TextWidth > TotalWidth){ // set counter string to next char pCounterString = CharNext( pSrc); nIndex = pCounterString - pSrc; nPrevIndex = nIndex; /* breakin np is hard to do! */ while ( (!bDone) && ( nIndex <= nTotalCount)){ ///* breakin np is hard to do! */ //while (( nCount) && ( !bDone)) //{ //dwExtent = GetTextExtentPoint32(hDC, pSrc, (nCount-1), &Size); dwExtent = GetTextExtentPoint32(hDC, pSrc, nIndex, &Size); TextWidth = Size.cx; if (bJustCalc){ if ((nHeightDirection == YTOP) || (nHeightDirection == YBOTTOM)){ Temp = max( 1L, ((ulong)TextWidth*1000L)/nHScale); if (((ulong)Temp * nHScale) < ((ulong)TextWidth * 1000L)){ Temp++; } }else{ Temp = max( 1L, ((ulong)TextWidth*1000L)/nVScale); if (((ulong)Temp * nVScale) < ((ulong)TextWidth * 1000L)){ Temp++; } } TextWidth = Temp; } //nCount--; //if ( TextWidth <= TotalWidth) if ( TextWidth > TotalWidth){ bDone = TRUE; }else{ pCounterString = CharNext( pCounterString); nPrevIndex = nIndex; nIndex = pCounterString - pSrc; } } //if ( (bDone) && ( nCount > 0)) if ( (bDone) && ( nPrevIndex > 0)){ //nRetCount = nCount; nRetCount = nPrevIndex; }else{ nRetCount = nTotalCount; } //if ( !IsDBCSLeadByte( *(pSrc + nRetCount))) //{ // //ok one more check // if ( IsDBCSLeadByte( *(pSrc + nRetCount-1))) // { // // we've got multi byte case // nRetCount--; // } //} if ( !bJustCalc){ TextOut(hDC, x, y, pSrc, nRetCount); } } return nRetCount; } /******************************************************************** ThreeDaMatic this will put those fancy hi-tech 3-d borders on attach-a-notes, note, special polarized viewing spectacles NOT NEEDED! ********************************************************************/ VOID WINAPI ThreeDaMatic(HDC hDC, LRECT lrActualRect, RECT rRepaintRect, int nWidth){ HPEN hOldPen = NULL; HPEN hPen = NULL; HPEN hPen2 = NULL; LOGPEN LogPen; HRGN hRgn = 0; RECT rNoteRect; CopyRectLtoR(rNoteRect, lrActualRect); LogPen.lopnStyle = PS_SOLID; LogPen.lopnWidth.x = nWidth; LogPen.lopnColor = RGB(0, 0, 0); hPen = CreatePenIndirect(&LogPen); if (hPen){ hOldPen = SelectObject(hDC, hPen); /* establish clip */ hRgn = CreateRectRgnIndirect( &rRepaintRect); SelectClipRgn(hDC, hRgn); /* we go all around and then extra on right, bottom */ MoveToEx(hDC, rNoteRect.left, rNoteRect.top, NULL); LineTo(hDC, rNoteRect.right-1, rNoteRect.top); LineTo(hDC, rNoteRect.right-1, rNoteRect.bottom-1); LineTo(hDC, rNoteRect.left, rNoteRect.bottom-1); LineTo(hDC, rNoteRect.left, rNoteRect.top); LogPen.lopnStyle = PS_SOLID; LogPen.lopnWidth.x = nWidth * 2; LogPen.lopnColor = RGB(0, 0, 0); hPen2 = CreatePenIndirect(&LogPen); if (hPen2){ SelectObject(hDC, hPen2); DeleteObject(hPen); hPen = NULL; MoveToEx(hDC, rNoteRect.left + (nWidth * 4), rNoteRect.bottom + (nWidth/2), 0); LineTo(hDC, rNoteRect.right + (nWidth/2), rNoteRect.bottom + (nWidth/2)); LineTo(hDC, rNoteRect.right + (nWidth/2), rNoteRect.top + (nWidth * 4)); } if (hOldPen){ SelectObject(hDC, hOldPen); if (hPen2){ DeleteObject(hPen2); } if (hPen){ DeleteObject(hPen); } } /* clean np rect region */ SelectClipRgn(hDC, NULL); DeleteObject(hRgn); } return; } /**************************************************************************** FUNCTION: CanMarkBeScaledText PURPOSE: This tests an annotation to see if it can be scaled to a particular scale factor. ****************************************************************************/ int WINAPI CanMarkBeScaledText(HWND hWnd, PMARK pMark, int nScale){ int nStatus = 0; 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: break; default: break; } return nStatus; }