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