/* * @doc INTERNAL * * @module OLSOLE.CPP -- OlsOle LineServices object class * * Author: * Murray Sargent (with lots of help from RickSa's ols code) * * Copyright (c) 1997-2000 Microsoft Corporation. All rights reserved. */ #include "_common.h" #ifndef NOLINESERVICES #include "_font.h" #include "_edit.h" #include "_disp.h" #include "_ols.h" #include "_render.h" extern "C" { #include "objdim.h" #include "pobjdim.h" #include "plsdnode.h" #include "dispi.h" #include "pdispi.h" #include "fmti.h" #include "lsdnset.h" #include "lsdnfin.h" #include "brko.h" #include "pbrko.h" #include "locchnk.h" #include "lsqout.h" #include "lsqin.h" #include "lsimeth.h" } extern BOOL g_OLSBusy; /* * OlsOleCreateILSObj(pols, plsc, pclscbk, dword, ppilsobj) * * @func * Create LS Ole object handler. We don't have any need for * this, so just set it to 0. * * @rdesc * LSERR */ LSERR WINAPI OlsOleCreateILSObj( POLS pols, //[IN]: COls * PLSC plsc, //[IN]: LineServices context PCLSCBK, DWORD, PILSOBJ *ppilsobj) //[OUT]: ptr to ilsobj { *ppilsobj = 0; return lserrNone; } /* * OlsOleDestroyILSObj(pilsobj) * * @func * Destroy LS Ole handler object. Nothing to do, since we don't * use the ILSObj. * * @rdesc * LSERR */ LSERR WINAPI OlsOleDestroyILSObj( PILSOBJ pilsobj) { return lserrNone; } /* * OlsOleSetDoc(pilsobj, pclsdocinf) * * @func * Set doc info. Nothing to do for Ole objects * * @rdesc * LSERR */ LSERR WINAPI OlsOleSetDoc( PILSOBJ, PCLSDOCINF) { // Ole objects don't care about this return lserrNone; } /* * OlsOleCreateLNObj(pilsobj, pplnobj) * * @func * Create the line object. Nothing needed in addition to the ped, * so just return the ped as the LN object. * * @rdesc * LSERR */ LSERR WINAPI OlsOleCreateLNObj( PCILSOBJ pilsobj, PLNOBJ * pplnobj) { *pplnobj = (PLNOBJ)g_pols->_pme->GetPed(); // Just the ped return lserrNone; } /* * OlsOleDestroyLNObj(plnobj) * * @func * Destroy LN object. Nothing to do, since ped is destroyed * elsewhere * * @rdesc * LSERR */ LSERR WINAPI OlsOleDestroyLNObj( PLNOBJ plnobj) { return lserrNone; } /* * OlsOleFmt(plnobj, pcfmtin, pfmres) * * @func * Compute dimensions of a particular Ole object * * @rdesc * LSERR */ LSERR WINAPI OlsOleFmt( PLNOBJ plnobj, PCFMTIN pcfmtin, FMTRES *pfmres) { const LONG cp = pcfmtin->lsfrun.plsrun->_cp; //Cannot trust LS cps LONG dup = 0; LSERR lserr; OBJDIM objdim; CMeasurer * pme = g_pols->_pme; COleObject * pobj = pme->GetObjectFromCp(cp); Assert(pobj); ZeroMemory(&objdim, sizeof(objdim)); pobj->MeasureObj(pme->_dvrInch, pme->_durInch, objdim.dur, objdim.heightsRef.dvAscent, objdim.heightsRef.dvDescent, pcfmtin->lstxmRef.dvDescent, pme->GetTflow()); pobj->MeasureObj(pme->_dvpInch, pme->_dupInch, dup, objdim.heightsPres.dvAscent, objdim.heightsPres.dvDescent, pcfmtin->lstxmPres.dvDescent, pme->GetTflow()); pobj->_plsdnTop = pcfmtin->plsdnTop; lserr = g_plsc->dnFinishRegular(1, pcfmtin->lsfrun.plsrun, pcfmtin->lsfrun.plschp, (PDOBJ)pobj, &objdim); if(lserrNone == lserr) { lserr = g_plsc->dnSetRigidDup(pcfmtin->plsdnTop, dup); if(lserrNone == lserr) { *pfmres = fmtrCompletedRun; if (pcfmtin->lsfgi.urPen + objdim.dur > pcfmtin->lsfgi.urColumnMax && !pcfmtin->lsfgi.fFirstOnLine) { *pfmres = fmtrExceededMargin; } } } return lserr; } /* * OlsOleTruncateChunk(plocchnk, posichnk) * * @func * Truncate chunk plocchnk at the point posichnk * * @rdesc * LSERR */ LSERR WINAPI OlsOleTruncateChunk( PCLOCCHNK plocchnk, // (IN): locchnk to truncate PPOSICHNK posichnk) // (OUT): truncation point { LSERR lserr; OBJDIM objdim; PLSCHNK plschnk = plocchnk->plschnk; COleObject * pobj; long ur = plocchnk->lsfgi.urPen; long urColumnMax = plocchnk->lsfgi.urColumnMax; for(DWORD i = 0; ur <= urColumnMax; i++) { AssertSz(i < plocchnk->clschnk, "OlsOleTruncateChunk: exceeded group of chunks"); pobj = (COleObject *)plschnk[i].pdobj; Assert(pobj); lserr = g_plsc->dnQueryObjDimRange(pobj->_plsdnTop, pobj->_plsdnTop, &objdim); if(lserr != lserrNone) return lserr; ur += objdim.dur; } posichnk->ichnk = i - 1; posichnk->dcp = 1; return lserrNone; } /* * OlsOleFindPrevBreakChunk(plocchnk, pposichnk, brkcond, pbrkout) * * @func * Find previous break in chunk * * @rdesc * LSERR */ LSERR WINAPI OlsOleFindPrevBreakChunk( PCLOCCHNK plocchnk, PCPOSICHNK pposichnk, BRKCOND brkcond, //(IN): recommendation about break after chunk PBRKOUT pbrkout) { ZeroMemory(pbrkout, sizeof(*pbrkout)); if (pposichnk->ichnk == ichnkOutside && (brkcond == brkcondPlease || brkcond == brkcondCan)) { pbrkout->fSuccessful = fTrue; pbrkout->posichnk.ichnk = plocchnk->clschnk - 1; pbrkout->posichnk.dcp = plocchnk->plschnk[plocchnk->clschnk - 1].dcp; COleObject *pobj = (COleObject *)plocchnk->plschnk[plocchnk->clschnk - 1].pdobj; Assert(pobj); g_plsc->dnQueryObjDimRange(pobj->_plsdnTop, pobj->_plsdnTop, &pbrkout->objdim); } else pbrkout->brkcond = brkcondPlease; return lserrNone; } /* * OlsOleForceBreakChunk(plocchnk, pposichnk, pbrkout) * * @func * Called when forced to break a line. * * @rdesc * LSERR */ LSERR WINAPI OlsOleForceBreakChunk( PCLOCCHNK plocchnk, PCPOSICHNK pposichnk, PBRKOUT pbrkout) { ZeroMemory(pbrkout, sizeof(*pbrkout)); pbrkout->fSuccessful = fTrue; if (plocchnk->lsfgi.fFirstOnLine && pposichnk->ichnk == 0 || pposichnk->ichnk == ichnkOutside) { pbrkout->posichnk.dcp = 1; COleObject *pobj = (COleObject *)plocchnk->plschnk[0].pdobj; Assert(pobj); g_plsc->dnQueryObjDimRange(pobj->_plsdnTop, pobj->_plsdnTop, &pbrkout->objdim); } else { pbrkout->posichnk.ichnk = pposichnk->ichnk; pbrkout->posichnk.dcp = 0; } return lserrNone; } /* * OlsOleSetBreak(pdobj, brkkind, nBreakRecord, rgBreakRecord, nActualBreakRecord) * * @func * Set break * * @rdesc * LSERR */ LSERR WINAPI OlsOleSetBreak( PDOBJ pdobj, // (IN): dobj which is broken BRKKIND brkkind, // (IN): Previous/Next/Force/Imposed was chosen DWORD nBreakRecord, // (IN): size of array BREAKREC* rgBreakRecord, // (OUT): array of break records DWORD* nActualBreakRecord) // (OUT): actual number of used elements in array { return lserrNone; } LSERR WINAPI OlsOleGetSpecialEffectsInside( PDOBJ pdobj, // (IN): dobj UINT *pEffectsFlags) // (OUT): Special effects for this object { *pEffectsFlags = 0; return lserrNone; } LSERR WINAPI OlsOleCalcPresentation( PDOBJ, // (IN): dobj long, // (IN): dup of dobj LSKJUST, // (IN): LSKJUST BOOL fLastVisibleOnLine)// (IN): this object is last visible object on line { return lserrNone; } /* * OlsOleQueryPointPcp(pdobj, ppointuvQuery, plsqin, plsqout) * * @func * Query Ole object PointFromCp. * * @rdesc * LSERR */ LSERR WINAPI OlsOleQueryPointPcp( PDOBJ pdobj, //(IN): dobj to query PCPOINTUV ppointuvQuery, //(IN): query point (uQuery,vQuery) PCLSQIN plsqin, //(IN): query input PLSQOUT plsqout) //(OUT): query output { ZeroMemory(plsqout, sizeof(LSQOUT)); plsqout->heightsPresObj = plsqin->heightsPresRun; plsqout->dupObj = plsqin->dupRun; return lserrNone; } /* * OlsOleQueryCpPpoint(pdobj, dcp, plsqin, plsqout) * * @func * Query Ole object CpFromPoint. * * @rdesc * LSERR */ LSERR WINAPI OlsOleQueryCpPpoint( PDOBJ pdobj, //(IN): dobj to query LSDCP dcp, //(IN): dcp for query PCLSQIN plsqin, //(IN): query input PLSQOUT plsqout) //(OUT): query output { ZeroMemory(plsqout, sizeof(LSQOUT)); plsqout->heightsPresObj = plsqin->heightsPresRun; plsqout->dupObj = plsqin->dupRun; return lserrNone; } /* * OlsOleDisplay(pdobj, pcdispin) * * @func * Display object * * @rdesc * LSERR */ LSERR WINAPI OlsOleDisplay( PDOBJ pdobj, //(IN): dobj to query PCDISPIN pcdispin) //(IN): display info { COleObject *pobj = (COleObject *)pdobj; Assert(pobj); CRenderer *pre = g_pols->GetRenderer(); const CDisplay *pdp = pre->GetPdp(); POINTUV ptuv = {pcdispin->ptPen.x, pcdispin->ptPen.y - pre->GetLine().GetDescent()}; if (pcdispin->lstflow == lstflowWS) ptuv.u -= pcdispin->dup - 1; pre->SetSelected(pcdispin->plsrun->IsSelected()); pre->Check_pccs(); pre->SetFontAndColor(pcdispin->plsrun->_pCF); if (pre->_fEraseOnFirstDraw) pre->EraseLine(); pre->SetCurPoint(ptuv); pre->SetClipLeftRight(pcdispin->dup); if (!pobj->FWrapTextAround()) { COls *polsOld = g_pols; CLineServices *plscOld = g_plsc; BOOL fOLSBusyOld = g_OLSBusy; BOOL fRestore = FALSE; if (g_plsc && g_pols) { // This is to fix a re-entrance problem. // We first NULL out the two globals. If the OleObject is using Richedit, it will // create a new LineService context. By the time it get back to here, we will free that // context and restore the current context. This is necessary since LineService will returns // error when we are using the same context in the Parent and then in the Ole Object using RE. g_plsc = NULL; g_pols = NULL; g_OLSBusy = FALSE; fRestore = TRUE; } pobj->DrawObj(pdp, pre->_dvpInch, pre->_dupInch, pre->GetDC(), &pre->GetClipRect(), pdp->IsMetafile(), &ptuv, pcdispin->ptPen.y - ptuv.v, pre->GetLine().GetDescent(), pre->GetTflow()); if (fRestore) { // Time to delete the new context created within the DrawObject. if (g_pols) delete g_pols; // Restore old globals g_pols = polsOld; g_plsc = plscOld; g_OLSBusy = fOLSBusyOld; } } return lserrNone; } /* * OlsOleDistroyDObj(pdobj) * * @func * Destroy object: nothing to do since object is destroyed elsewhere * * @rdesc * LSERR */ LSERR WINAPI OlsOleDestroyDObj( PDOBJ pdobj) { return lserrNone; } extern const LSIMETHODS vlsimethodsOle = { OlsOleCreateILSObj, OlsOleDestroyILSObj, OlsOleSetDoc, OlsOleCreateLNObj, OlsOleDestroyLNObj, OlsOleFmt, 0,//OlsOleFmtResume 0,//OlsOleGetModWidthPrecedingChar 0,//OlsOleGetModWidthFollowingChar OlsOleTruncateChunk, OlsOleFindPrevBreakChunk, 0,//OlsOleFindNextBreakChunk OlsOleForceBreakChunk, OlsOleSetBreak, OlsOleGetSpecialEffectsInside, 0,//OlsOleFExpandWithPrecedingChar 0,//OlsOleFExpandWithFollowingChar OlsOleCalcPresentation, OlsOleQueryPointPcp, OlsOleQueryCpPpoint, 0,//pfnEnum OlsOleDisplay, OlsOleDestroyDObj }; #endif // NOLINESERVICES