windows-nt/Source/XPSP1/NT/com/oleutest/letest/outline/outlline.c

732 lines
16 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*************************************************************************
**
** OLE 2 Sample Code
**
** outlline.c
**
** This file contains Line functions.
**
** (c) Copyright Microsoft Corp. 1992 - 1993 All Rights Reserved
**
*************************************************************************/
#include "outline.h"
OLEDBGDATA
extern LPOUTLINEAPP g_lpApp;
/* Line_Init
* ---------
*
* Init the calculated data of a line object
*/
void Line_Init(LPLINE lpLine, int nTab, HDC hDC)
{
lpLine->m_lineType = UNKNOWNLINETYPE;
lpLine->m_nTabLevel = nTab;
lpLine->m_nTabWidthInHimetric = Line_CalcTabWidthInHimetric(lpLine,hDC);
lpLine->m_nWidthInHimetric = 0;
lpLine->m_nHeightInHimetric = 0;
lpLine->m_fSelected = FALSE;
#if defined( USE_DRAGDROP )
lpLine->m_fDragOverLine = FALSE;
#endif
}
/* Line_Edit
* ---------
*
* Edit the line object.
*
* Returns TRUE if line was changed
* FALSE if the line was NOT changed
*/
BOOL Line_Edit(LPLINE lpLine, HWND hWndDoc, HDC hDC)
{
switch (lpLine->m_lineType) {
case TEXTLINETYPE:
return TextLine_Edit((LPTEXTLINE)lpLine, hWndDoc, hDC);
#if defined( OLE_CNTR )
case CONTAINERLINETYPE:
ContainerLine_Edit((LPCONTAINERLINE)lpLine, hWndDoc, hDC);
break;
#endif
default:
return FALSE; // unknown line type
}
}
/* Line_GetLineType
* ----------------
*
* Return type of the line
*/
LINETYPE Line_GetLineType(LPLINE lpLine)
{
if (! lpLine) return 0;
return lpLine->m_lineType;
}
/* Line_GetTextLen
* ---------------
*
* Return length of string representation of the Line
* (not considering the tab level).
*/
int Line_GetTextLen(LPLINE lpLine)
{
switch (lpLine->m_lineType) {
case TEXTLINETYPE:
return TextLine_GetTextLen((LPTEXTLINE)lpLine);
#if defined( OLE_CNTR )
case CONTAINERLINETYPE:
return ContainerLine_GetTextLen((LPCONTAINERLINE)lpLine);
#endif
default:
return 0; // unknown line type
}
}
/* Line_GetTextData
* ----------------
*
* Return the string representation of the Line.
* (not considering the tab level).
*/
void Line_GetTextData(LPLINE lpLine, LPSTR lpszBuf)
{
switch (lpLine->m_lineType) {
case TEXTLINETYPE:
TextLine_GetTextData((LPTEXTLINE)lpLine, lpszBuf);
break;
#if defined( OLE_CNTR )
case CONTAINERLINETYPE:
ContainerLine_GetTextData((LPCONTAINERLINE)lpLine, lpszBuf);
break;
#endif
default:
*lpszBuf = '\0';
return; // unknown line type
}
}
/* Line_GetOutlineData
* -------------------
*
* Return the CF_OUTLINE format representation of the Line.
*/
BOOL Line_GetOutlineData(LPLINE lpLine, LPTEXTLINE lpBuf)
{
switch (lpLine->m_lineType) {
case TEXTLINETYPE:
return TextLine_GetOutlineData((LPTEXTLINE)lpLine, lpBuf);
#if defined( OLE_CNTR )
case CONTAINERLINETYPE:
return ContainerLine_GetOutlineData(
(LPCONTAINERLINE)lpLine,
lpBuf
);
#endif
default:
return FALSE; // unknown line type
}
}
/* Line_CalcTabWidthInHimetric
* ---------------------------
*
* Recalculate the width for the line's current tab level
*/
static int Line_CalcTabWidthInHimetric(LPLINE lpLine, HDC hDC)
{
int nTabWidthInHimetric;
nTabWidthInHimetric=lpLine->m_nTabLevel * TABWIDTH;
return nTabWidthInHimetric;
}
/* Line_Indent
* -----------
*
* Increment the tab level for the line
*/
void Line_Indent(LPLINE lpLine, HDC hDC)
{
lpLine->m_nTabLevel++;
lpLine->m_nTabWidthInHimetric = Line_CalcTabWidthInHimetric(lpLine, hDC);
#if defined( INPLACE_CNTR )
if (Line_GetLineType(lpLine) == CONTAINERLINETYPE)
ContainerLine_UpdateInPlaceObjectRects((LPCONTAINERLINE)lpLine, NULL);
#endif
}
/* Line_Unindent
* -------------
*
* Decrement the tab level for the line
*/
void Line_Unindent(LPLINE lpLine, HDC hDC)
{
if(lpLine->m_nTabLevel > 0) {
lpLine->m_nTabLevel--;
lpLine->m_nTabWidthInHimetric = Line_CalcTabWidthInHimetric(lpLine, hDC);
}
#if defined( INPLACE_CNTR )
if (Line_GetLineType(lpLine) == CONTAINERLINETYPE)
ContainerLine_UpdateInPlaceObjectRects((LPCONTAINERLINE)lpLine, NULL);
#endif
}
/* Line_GetTotalWidthInHimetric
* ----------------------------
*
* Calculate the total width of the line
*/
UINT Line_GetTotalWidthInHimetric(LPLINE lpLine)
{
return lpLine->m_nWidthInHimetric + lpLine->m_nTabWidthInHimetric;
}
/* Line_SetWidthInHimetric
* -----------------------
*
* Set the width of the line
*/
void Line_SetWidthInHimetric(LPLINE lpLine, int nWidth)
{
if (!lpLine)
return;
lpLine->m_nWidthInHimetric = nWidth;
}
/* Line_GetWidthInHimetric
* -----------------------
*
* Return the width of the line
*/
UINT Line_GetWidthInHimetric(LPLINE lpLine)
{
if (!lpLine)
return 0;
return lpLine->m_nWidthInHimetric;
}
/* Line_GetTabLevel
* ----------------
*
* Return the tab level of a line object.
*/
UINT Line_GetTabLevel(LPLINE lpLine)
{
return lpLine->m_nTabLevel;
}
/* Line_DrawToScreen
* -----------------
*
* Draw the item in the owner-draw listbox
*/
void Line_DrawToScreen(
LPLINE lpLine,
HDC hDC,
LPRECT lprcPix,
UINT itemAction,
UINT itemState,
LPRECT lprcDevice
)
{
if (!lpLine || !hDC || !lprcPix || !lprcDevice)
return;
/* Draw a list box item in its normal drawing action.
* Then check if it is selected or has the focus state, and call
* functions to handle drawing for these states if necessary.
*/
if(itemAction & (ODA_SELECT | ODA_DRAWENTIRE)) {
HFONT hfontOld;
int nMapModeOld;
RECT rcWindowOld;
RECT rcViewportOld;
RECT rcLogical;
// NOTE: we have to set the device context to HIMETRIC in order
// draw the line; however, we have to restore the HDC before
// we draw focus or dragfeedback...
rcLogical.left = 0;
rcLogical.bottom = 0;
rcLogical.right = lpLine->m_nWidthInHimetric;
rcLogical.top = lpLine->m_nHeightInHimetric;
{
HBRUSH hbr;
RECT rcDraw;
lpLine->m_fSelected = (BOOL)(itemState & ODS_SELECTED);
if (ODS_SELECTED & itemState) {
/*Get proper txt colors */
hbr = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
}
else {
hbr = CreateSolidBrush(GetSysColor(COLOR_WINDOW));
}
rcDraw = *lprcPix;
rcDraw.right = lprcDevice->left;
FillRect(hDC, lprcPix, hbr);
rcDraw = *lprcPix;
rcDraw.left = lprcDevice->right;
FillRect(hDC, lprcPix, hbr);
DeleteObject(hbr);
}
nMapModeOld=SetDCToAnisotropic(hDC, lprcDevice, &rcLogical,
(LPRECT)&rcWindowOld, (LPRECT)&rcViewportOld);
// Set the default font size, and font face name
hfontOld = SelectObject(hDC, OutlineApp_GetActiveFont(g_lpApp));
Line_Draw(lpLine, hDC, &rcLogical, NULL, (ODS_SELECTED & itemState));
SelectObject(hDC, hfontOld);
ResetOrigDC(hDC, nMapModeOld, (LPRECT)&rcWindowOld,
(LPRECT)&rcViewportOld);
#if defined( OLE_CNTR )
if ((itemState & ODS_SELECTED) &&
(Line_GetLineType(lpLine)==CONTAINERLINETYPE))
ContainerLine_DrawSelHilight(
(LPCONTAINERLINE)lpLine,
hDC,
lprcPix,
ODA_SELECT,
ODS_SELECTED
);
#endif
}
/* If a list box item just gained or lost the focus,
* call function (which could check if ODS_FOCUS bit is set)
* and draws item in focus or non-focus state.
*/
if(itemAction & ODA_FOCUS )
Line_DrawFocusRect(lpLine, hDC, lprcPix, itemAction, itemState);
#if defined( OLE_CNTR )
if (Line_GetLineType(lpLine) == CONTAINERLINETYPE) {
LPCONTAINERLINE lpContainerLine = (LPCONTAINERLINE)lpLine;
LPCONTAINERDOC lpDoc = lpContainerLine->m_lpDoc;
BOOL fIsLink;
RECT rcObj;
if (ContainerDoc_GetShowObjectFlag(lpDoc)) {
ContainerLine_GetOleObjectRectInPixels(lpContainerLine, &rcObj);
fIsLink = ContainerLine_IsOleLink(lpContainerLine);
OleUIShowObject(&rcObj, hDC, fIsLink);
}
}
#endif
#if defined( USE_DRAGDROP )
if (lpLine->m_fDragOverLine)
Line_DrawDragFeedback(lpLine, hDC, lprcPix, itemState );
#endif
}
/* Line_Draw
* ---------
*
* Draw a line on a DC.
*
* Parameters:
* hDC - DC to which the line will be drawn
* lpRect - the object rect in logical coordinates
*/
void Line_Draw(
LPLINE lpLine,
HDC hDC,
LPRECT lpRect,
LPRECT lpRectWBounds,
BOOL fHighlight
)
{
switch (lpLine->m_lineType) {
case TEXTLINETYPE:
TextLine_Draw(
(LPTEXTLINE)lpLine, hDC, lpRect,lpRectWBounds,fHighlight);
break;
#if defined( OLE_CNTR )
case CONTAINERLINETYPE:
ContainerLine_Draw(
(LPCONTAINERLINE)lpLine,hDC,lpRect,lpRectWBounds,fHighlight);
break;
#endif
default:
return; // unknown line type
}
return;
}
/* Line_DrawSelHilight
* -------------------
*
* Handles selection of list box item
*/
void Line_DrawSelHilight(LPLINE lpLine, HDC hDC, LPRECT lpRect, UINT itemAction, UINT itemState)
{
switch (lpLine->m_lineType) {
case TEXTLINETYPE:
TextLine_DrawSelHilight((LPTEXTLINE)lpLine, hDC, lpRect,
itemAction, itemState);
break;
#if defined( OLE_CNTR )
case CONTAINERLINETYPE:
ContainerLine_DrawSelHilight((LPCONTAINERLINE)lpLine, hDC, lpRect,
itemAction, itemState);
break;
#endif
default:
return; // unknown line type
}
return;
}
/* Line_DrawFocusRect
* ------------------
*
* Handles focus state of list box item
*/
void Line_DrawFocusRect(LPLINE lpLine, HDC hDC, LPRECT lpRect, UINT itemAction, UINT itemState)
{
if(lpLine)
DrawFocusRect(hDC, lpRect);
}
#if defined( USE_DRAGDROP )
/* Line_DrawDragFeedback
* ---------------------
*
* Handles focus state of list box item
*/
void Line_DrawDragFeedback(LPLINE lpLine, HDC hDC, LPRECT lpRect, UINT itemState )
{
if(lpLine)
DrawFocusRect(hDC, lpRect);
}
#endif // USE_DRAGDROP
/* Line_GetHeightInHimetric
* ------------------------
*
* Return the height of the item in HIMETRIC units
*/
UINT Line_GetHeightInHimetric(LPLINE lpLine)
{
if (!lpLine)
return 0;
return (UINT)lpLine->m_nHeightInHimetric;
}
/* Line_SetHeightInHimetric
* ------------------------
*
* Set the height of the item in HIMETRIC units.
*/
void Line_SetHeightInHimetric(LPLINE lpLine, int nHeight)
{
if (!lpLine)
return;
switch (lpLine->m_lineType) {
case TEXTLINETYPE:
TextLine_SetHeightInHimetric((LPTEXTLINE)lpLine, nHeight);
break;
#if defined( OLE_CNTR )
case CONTAINERLINETYPE:
ContainerLine_SetHeightInHimetric((LPCONTAINERLINE)lpLine,
nHeight);
break;
#endif
}
}
/* Line_Delete
* -----------
*
* Delete the Line structure
*/
void Line_Delete(LPLINE lpLine)
{
switch (lpLine->m_lineType) {
case TEXTLINETYPE:
TextLine_Delete((LPTEXTLINE)lpLine);
break;
#if defined( OLE_CNTR )
case CONTAINERLINETYPE:
ContainerLine_Delete((LPCONTAINERLINE)lpLine);
break;
#endif
default:
break; // unknown line type
}
}
/* Line_CopyToDoc
* --------------
*
* Copy a line to another Document (usually ClipboardDoc)
*/
BOOL Line_CopyToDoc(LPLINE lpSrcLine, LPOUTLINEDOC lpDestDoc, int nIndex)
{
switch (lpSrcLine->m_lineType) {
case TEXTLINETYPE:
return TextLine_CopyToDoc((LPTEXTLINE)lpSrcLine,lpDestDoc,nIndex);
break;
#if defined( OLE_CNTR )
case CONTAINERLINETYPE:
return ContainerLine_CopyToDoc(
(LPCONTAINERLINE)lpSrcLine,
lpDestDoc,
nIndex
);
break;
#endif
default:
return FALSE; // unknown line type
}
}
/* Line_SaveToStg
* --------------
*
* Save a single line object to a storage
*
* Return TRUE if successful, FALSE otherwise
*/
BOOL Line_SaveToStg(LPLINE lpLine, UINT uFormat, LPSTORAGE lpSrcStg, LPSTORAGE lpDestStg, LPSTREAM lpLLStm, BOOL fRemember)
{
LINERECORD_ONDISK lineRecord;
ULONG nWritten;
HRESULT hrErr;
BOOL fStatus;
LARGE_INTEGER dlibSavePos;
LARGE_INTEGER dlibZeroOffset;
LISet32( dlibZeroOffset, 0 );
/* save seek position before line record is written in case of error */
hrErr = lpLLStm->lpVtbl->Seek(
lpLLStm,
dlibZeroOffset,
STREAM_SEEK_CUR,
(ULARGE_INTEGER FAR*)&dlibSavePos
);
if (hrErr != NOERROR) return FALSE;
#if defined( OLE_CNTR )
if (lpLine->m_lineType == CONTAINERLINETYPE) {
/* OLE2NOTE: asking an OLE object to save may cause the
** object to send an OnViewChange notification if there are any
** outstanding changes to the object. this is particularly true
** for objects with coarse update granularity like OLE 1.0
** objects. if an OnViewChange notification is received then the
** object's presentation cache will be updated BEFORE it is
** saved. It is important that the extents stored as part of
** the ContainerLine/Line record associated with the OLE object
** are updated before the Line data is saved to the storage. it
** is important that this extent information matches the data
** saved with the OLE object. the Line extent information is
** updated in the IAdviseSink::OnViewChange method implementation.
*/
// only save the OLE object if format is compatible.
if (uFormat != ((LPCONTAINERAPP)g_lpApp)->m_cfCntrOutl)
goto error;
fStatus = ContainerLine_SaveOleObjectToStg(
(LPCONTAINERLINE)lpLine,
lpSrcStg,
lpDestStg,
fRemember
);
if (! fStatus) goto error;
}
#endif
// Compilers should handle aligment correctly
lineRecord.m_lineType = (USHORT) lpLine->m_lineType;
lineRecord.m_nTabLevel = (USHORT) lpLine->m_nTabLevel;
lineRecord.m_nTabWidthInHimetric = (USHORT) lpLine->m_nTabWidthInHimetric;
lineRecord.m_nWidthInHimetric = (USHORT) lpLine->m_nWidthInHimetric;
lineRecord.m_nHeightInHimetric = (USHORT) lpLine->m_nHeightInHimetric;
lineRecord.m_reserved = 0;
/* write line record header */
hrErr = lpLLStm->lpVtbl->Write(
lpLLStm,
(LPVOID)&lineRecord,
sizeof(lineRecord),
&nWritten
);
if (hrErr != NOERROR) {
OleDbgOutHResult("Write Line header returned", hrErr);
goto error;
}
switch (lpLine->m_lineType) {
case TEXTLINETYPE:
fStatus = TextLine_SaveToStm((LPTEXTLINE)lpLine, lpLLStm);
if (! fStatus) goto error;
break;
#if defined( OLE_CNTR )
case CONTAINERLINETYPE:
fStatus=ContainerLine_SaveToStm((LPCONTAINERLINE)lpLine,lpLLStm);
if (! fStatus) goto error;
break;
#endif
default:
goto error; // unknown line type
}
return TRUE;
error:
/* retore seek position prior to writing Line record */
lpLLStm->lpVtbl->Seek(
lpLLStm,
dlibSavePos,
STREAM_SEEK_SET,
NULL
);
return FALSE;
}
/* Line_LoadFromStg
* ----------------
*
* Load a single line object from storage
*/
LPLINE Line_LoadFromStg(LPSTORAGE lpSrcStg, LPSTREAM lpLLStm, LPOUTLINEDOC lpDestDoc)
{
LINERECORD_ONDISK lineRecord;
LPLINE lpLine = NULL;
ULONG nRead;
HRESULT hrErr;
/* read line record header */
hrErr = lpLLStm->lpVtbl->Read(
lpLLStm,
(LPVOID)&lineRecord,
sizeof(lineRecord),
&nRead
);
if (hrErr != NOERROR) {
OleDbgOutHResult("Read Line header returned", hrErr);
return NULL;
}
switch ((LINETYPE) lineRecord.m_lineType) {
case TEXTLINETYPE:
lpLine = TextLine_LoadFromStg(lpSrcStg, lpLLStm, lpDestDoc);
break;
#if defined( OLE_CNTR )
case CONTAINERLINETYPE:
lpLine = ContainerLine_LoadFromStg(lpSrcStg, lpLLStm, lpDestDoc);
break;
#endif
default:
return NULL; // unknown line type
}
lpLine->m_lineType = (LINETYPE) lineRecord.m_lineType;
lpLine->m_nTabLevel = (UINT) lineRecord.m_nTabLevel;
lpLine->m_nTabWidthInHimetric = (UINT) lineRecord.m_nTabWidthInHimetric;
lpLine->m_nWidthInHimetric = (UINT) lineRecord.m_nWidthInHimetric;
lpLine->m_nHeightInHimetric = (UINT) lineRecord.m_nHeightInHimetric;
return lpLine;
}
/* Line_IsSelected
* ---------------
*
* Return the selection state of the line
*/
BOOL Line_IsSelected(LPLINE lpLine)
{
if (!lpLine)
return FALSE;
return lpLine->m_fSelected;
}