Beispiel #1
0
HRESULT VwGraphicsCairo::XYFromGlyphPoint(int chw, int nPoint, int * pxRet, int * pyRet)
{
 BEGIN_COM_METHOD;
	ThrowHr(E_NOTIMPL);
 END_COM_METHOD(g_fact, IID_IVwGraphics);
}
Beispiel #2
0
HRESULT VwGraphicsCairo::GetSubscriptYOffsetRatio(int* piNumerator, int* piDenominator)
{
BEGIN_COM_METHOD;
	ThrowHr(E_NOTIMPL);
END_COM_METHOD(g_fact, IID_IVwGraphics);
}
Beispiel #3
0
/*----------------------------------------------------------------------------------------------
	The standard method for generating a segment in a paragraph, where a line break might be
	necessary.

	Generally called with fEndLine true; then change segment to make it false if we want to
	try to put something else after.

	TODO SharonC?: try implementing and see whether we can handle all the possible complications relating
	to adjacent segments that can't be separated, such as English parens around Hebrew text.

	@param pgjus		- NULL if no justification will ever be needed for the resulting segment
	@param ichMin/Lim			- part of string to use
	@param ichwLimBacktrack		- when backtracking, where to start looking for a new break
	@param fNeedFinalBreak		- if false, assume it is okay to make a segment ending at
									ichwLim; if true, assume the text source has at least one
									more character at ichwLim, and end the segment at ichwLim
									only if that is a valid break point
	@param fStartLine			- seg is logically first on line? (we assume it is logically last)
	@param dxMaxWidth			- available width in x coords of graphics object
	@param lbPref				- try for longest segment ending with this breakweight
	@param lbMax				- max (last resort) breakweight if no preferred break possible
	@param twsh					- how we are handling trailing white-space
	@param fParaRtl				- overall paragraph direction
	@param pplsegRet			- segment produced, or null if nothing fits
	@param pichwLimSeg			- end of segment produced, beginning of next
	@param pdxWidth				- width of newly-created segment
	@param pest					- what caused the segment to end
	@param cpPrev				- byte size of pbPrevSegDat buffer
	@param pbPrevSegDat			- for initializing from previous segment
	@param cbNextMax			- max size of pbNextSegDat buffer
	@param pbNextSegDat			- for initializing next segment
	@param pcbNextSegDat		- size of pbNextSegDat buffer
	@param pdichwContext		- for the following segment, the index of the first char of
									interest to it; ie, edits before this character will not
									affect how the next segment behaves
----------------------------------------------------------------------------------------------*/
STDMETHODIMP FwGrEngine::FindBreakPoint(
	IVwGraphics * pvg, IVwTextSource * pts, IVwJustifier * pvjus,
	int ichwMin, int ichwLim, int ichwLimBacktrack,
	ComBool fNeedFinalBreak,
	ComBool fStartLine,
	int dxMaxWidth,
	LgLineBreak lbPref, LgLineBreak lbMax,
	LgTrailingWsHandling twsh, ComBool fParaRtl,
	ILgSegment ** ppsegRet,
	int * pdichwLimSeg,
	int * pdxWidth, LgEndSegmentType * pest,
	ILgSegment * plgsegPrev)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(pvg);
	ChkComArgPtr(pts);
	ChkComArgPtrN(pvjus);
	ChkComOutPtr(ppsegRet);
	ChkComOutPtr(pdichwLimSeg);
	ChkComArgPtr(pdxWidth);
	ChkComArgPtr(pest);

	HRESULT hr = S_OK;

	// Use wrappers that fit what is expected by the Graphite implementation code:
	//////FwGrGraphics gg(pvg);

	// Create these on the heap so they can be stored in the segment.
	FwGrTxtSrc * pgts = new FwGrTxtSrc(pts, m_useNFC);
	//FwGrJustifier * pgjus = (pvjus) ? new FwGrJustifier(pvjus) : NULL;
	if (pvjus && !s_pgjus)
	{
		s_pgjus = new FwGrJustifier(pvjus);
		m_pgjus = s_pgjus; // make this engine responsible for deleting it
	}

	FwGrSegmentPtr qfwgrseg;
	if (*ppsegRet)
	{
		return E_INVALIDARG;
		//CheckHr((*ppsegRet)->QueryInterface(CLSID_FwGrSegment, (void**)&qfwgrseg));
		//pgrseg = qfwgrseg->GraphiteSegment();
	}

	Segment * psegPrev = NULL;
	if (plgsegPrev)
	{
		FwGrSegment * pfwgrseg = dynamic_cast<FwGrSegment *>(plgsegPrev);
		if (pfwgrseg)
			psegPrev = pfwgrseg->GraphiteSegment();
		// otherwise, not a Graphite segment
	}

	// Need-final-break is true if and only if we are backtracking.
	Assert((ichwLim != ichwLimBacktrack) == fNeedFinalBreak);

	// Adjust the font in the graphics device for super/subscripting.

	SetUpGraphics(pvg, pgts, ichwMin);

	HDC hdc;
	IVwGraphicsWin32Ptr qvg32;
	CheckHr(pvg->QueryInterface(IID_IVwGraphicsWin32, (void **)&qvg32));
	CheckHr(qvg32->GetDeviceContext(&hdc));
	////gg.GetDeviceContext(&hdc);

	Segment * pgrseg;
	WinFont * pfontSeg;
	try
	{
		// DON'T use m_pfont, which might be for the wrong size; use a new font
		// specifically for this size font.
		FwWinFont font(hdc);
		int xInch, yInch;
		pvg->get_XUnitsPerInch(&xInch);
		pvg->get_YUnitsPerInch(&yInch);
		font.SetDPI(xInch, yInch);

		std::ofstream strmLog;
		std::ostream * pstrmLog = CreateLogFile(strmLog, (psegPrev != NULL));

		// for testing UTF-8:
		//gr::utf16 prgchw[1000];
		//int cchwLen;
		//pts->get_Length(&cchwLen);
		//pts->Fetch(ichwMin, cchwLen, prgchw);
		//ichwLim = CountUtf8FromUtf16(prgchw, ichwLim);
		//ichwLimBacktrack = ichwLim;
		/////////////////////

		LayoutEnvironment layout;
		layout.setStartOfLine(fStartLine);
		layout.setEndOfLine(true);
		layout.setBestBreak(lbPref);
		layout.setWorstBreak(lbMax);
		layout.setRightToLeft(fParaRtl);
		layout.setTrailingWs(twsh);
		layout.setPrevSegment(psegPrev);
		layout.setJustifier(s_pgjus);
		layout.setLoggingStream(pstrmLog);
		layout.setDumbFallback(true);

		//for allowing hyphen breaks:
		//layout.setBestBreak(max(klbHyphenBreak, lbPref));
		//layout.setWorstBreak(max(klbHyphenBreak, lbMax));

		bool fBacktracking = (ichwLimBacktrack < ichwLim);
		int grIchwMin = pgts->VwToGrOffset(ichwMin);
		int grIchwLim = fBacktracking ? pgts->VwToGrOffset(ichwLimBacktrack) : pgts->VwToGrOffset(ichwLim);

		pgrseg = new LineFillSegment(&font, pgts, &layout,
			grIchwMin, grIchwLim,
			(float)dxMaxWidth, fBacktracking);
		gr::Font & fontSeg = pgrseg->getFont();
		pfontSeg = dynamic_cast<WinFont *>(&fontSeg);
		pfontSeg->replaceDC(hdc);
		*pest = pgrseg->segmentTermination();
		if (*pest != kestNothingFit)
		{
			int grIchwLimSeg = pgrseg->stopCharacter() - pgrseg->startCharacter();
			*pdichwLimSeg = pgts->GrToVwOffset(grIchwLimSeg);
			*pdxWidth = gr::GrEngine::RoundFloat(pgrseg->advanceWidth());
			// there is a limit in the number of pixels (about 2^16) that the ExtTextOut function
			// can render, which is what Graphite uses to render text on Windows. If this
			// segment is over that limit, we reduce the number of characters in this segment
			// so that when it is rendered it is less than the limit. The main place this
			// can happen is in concordance views.
			// TODO (DamienD): This fix removes characters from the end of the segment. If the
			// segment is too long on the left side of the arrow in the concordance view,
			// characters should be removed from the beginning. This case would have to be
			// handled in Views somewhere.
			// TODO (DamienD): If Graphite ever fixes the limit, we can safely remove this
			// hack.
			if (*pdxWidth > SHRT_MAX)
			{
				delete pgrseg;
				int avgCharWidth = *pdxWidth / (grIchwMin + grIchwLimSeg);
				// we use 30000 here, because avgCharWidth is just an estimate,
				// this gives us some padding to ensure that the resulting segment
				// is less than the limit
				grIchwLim = grIchwMin + (30000 / avgCharWidth);
				pgrseg = new LineFillSegment(&font, pgts, &layout,
					grIchwMin, grIchwLim,
					(float)dxMaxWidth, fBacktracking);

				// reset variables for new segment
				gr::Font & fontSeg = pgrseg->getFont();
				pfontSeg = dynamic_cast<WinFont *>(&fontSeg);
				pfontSeg->replaceDC(hdc);

				*pest = pgrseg->segmentTermination();
				if (*pest != kestNothingFit)
				{
					*pdichwLimSeg = pgts->GrToVwOffset(pgrseg->stopCharacter() - pgrseg->startCharacter());
					*pdxWidth = gr::GrEngine::RoundFloat(pgrseg->advanceWidth());
				}
			}
		}

		strmLog.close();
	}
	catch (FontException & fexptn)
	{
		// Error in initializing the font.
		FontErrorCode ferr = fexptn.errorCode;
		LgCharRenderProps chrp;
		int ichwMinBogus, ichwLimBogus;
		pgts->GetCharProps(ichwMin, &chrp, &ichwMinBogus, &ichwLimBogus);
		StrUni stuMsg = L"Error in initializing Graphite font ";
		stuMsg.Append(chrp.szFaceName);
		stuMsg.Append(": ");
		std::wstring stuErrMsg = FontLoadErrorDescription(ferr, 0, 0, &hr);
		stuMsg.Append(stuErrMsg.c_str());
		StackDumper::RecordError(IID_IRenderEngine, stuMsg, L"SIL.Graphite.FwGrEngine", 0, L"");
		return hr;
	}

	// if we are at the end of the requested range, but the text source still has more text in
	// it, Graphite will determine that the break was bad or okay, even though it broke
	// because there was no more text, so we go ahead and change the reason here to no more text
	if (ichwMin + *pdichwLimSeg == ichwLim && (*pest == kestOkayBreak || *pest == kestBadBreak))
		*pest = kestNoMore;

	bool fError = false;
	std::pair<GlyphIterator, GlyphIterator> pairGfit = pgrseg->glyphs();
	GlyphIterator gfit = pairGfit.first;
	GlyphIterator gfitEnd = pairGfit.second;
	for ( ; gfit != gfitEnd ; ++gfit)
	{
		if ((*gfit).erroneous())
		{
			fError = true;
			break;
		}
	}

	if (fError)
	{
		LgCharRenderProps chrp;
		int ichwMinBogus, ichwLimBogus;
		pgts->GetCharProps(ichwMin, &chrp, &ichwMinBogus, &ichwLimBogus);
		StrUni stuMsg = L"Error in Graphite rendering using font ";
		stuMsg.Append(chrp.szFaceName);
		StackDumper::RecordError(IID_IRenderEngine, stuMsg, L"SIL.Graphite.FwGrEngine", 0, L"");
		hr = E_FAIL;
	}

	//// TEMPORARY - for testing
	//pairGfit = pgrseg->glyphs();
	//gfit = pairGfit.first;
	//gfitEnd = pairGfit.second;
	//for ( ; gfit != gfitEnd ; ++gfit)
	//{
	//	GlyphInfo ginf = *gfit;
	//	gid16 gid = ginf.glyphID();
	//	gid = ginf.pseudoGlyphID();

	//	int n = ginf.logicalIndex();
	//	float xy = ginf.origin();
	//	xy = ginf.advanceWidth();
	//	xy = ginf.advanceHeight();
	//	xy = ginf.yOffset();
	//	gr::Rect bb = ginf.bb();
	//	bool f = ginf.isSpace();
	//	f = ginf.insertBefore();
	//	toffset ich = ginf.firstChar();
	//	int ich = ginf.lastChar();
	//	unsigned int dir = ginf.directionality();
	//	dir = ginf.directionLevel();
	//	n = ginf.attachedTo();

	//	n = ginf.numberOfComponents();
	//	for (int i = 0; i < n; i++)
	//	{
	//		bb = ginf.componentBox(i);
	//		ich = ginf.componentFirstChar(i);
	//	}

	//	std::pair<GlyphIterator, GlyphIterator> pairGlyphRange
	//		= pgrseg->charToGlyphs(ginf.firstChar());

	//	for ( ; pairGlyphRange.first != pairGlyphRange.second ; ++(pairGlyphRange.first))
	//	{
	//		ginf = *pairGlyphRange.first;
	//		gid = ginf.glyphID();
	//	}
	//}

	//// for testing:
	//int rgigbb[100];
	//bool rgfClusterStart[100];
	//int cch, cf;
	//pgrseg->getUniscribeClusters(rgigbb, 100, &cch, rgfClusterStart, 100, &cf);

	//// for testing
	//for (int dxWidth = 50; dxWidth < 500; dxWidth += 50)
	//{
	//	int ichBreak;
	//	float dxRetWidth;
	//	ichBreak = pgrseg->findNextBreakPoint(4, klbWsBreak, klbWsBreak, (float)dxWidth, &dxRetWidth, false, false);
	//	int x;
	//	x = 3;
	//}

	pfontSeg->restoreDC();

	// Even if there was an error, if a segment was created, we want to return it.

	if (pgrseg && (*pest != kestNothingFit))
	{
		////qfwgrseg = dynamic_cast<FwGrSegment *>(pgrseg);
		////Assert(qfwgrseg);

		FwGrSegment * psegTmp;
		if (!qfwgrseg)
		{
			psegTmp = NewObj FwGrSegment;
			qfwgrseg = dynamic_cast<FwGrSegment *>(psegTmp);
			Assert(qfwgrseg);
		}
		else
			psegTmp = qfwgrseg.Ptr();

		qfwgrseg->SetGraphiteSegment(pgrseg);

		HRESULT hrTmp;
		CheckHr(hrTmp = qfwgrseg->QueryInterface(IID_ILgSegment, (void **)ppsegRet));
		if (FAILED(hrTmp))
			hr = hrTmp;
		////pgrseg->DecRefCount();
		psegTmp->Release();

		qfwgrseg->SetFwGrEngine(this);
		qfwgrseg->SetTextSource(pgts);

		//pgts->IncRefCount();	// not needed; pgts holds a smart pointer that increments
								// the ref count on the FW text source
	}
	else
	{
		delete pgrseg;
		delete pgts;
		qfwgrseg = NULL;
	}

	return hr;

	END_COM_METHOD(g_fact, IID_IRenderEngine);
}
Beispiel #4
0
HRESULT VwGraphicsCairo::GetFontDataRgch(int nTableId, int * pcbTableSz, OLECHAR * prgch, int cchMax)
{
 BEGIN_COM_METHOD;
	ThrowHr(E_NOTIMPL);
 END_COM_METHOD(g_fact, IID_IVwGraphics);
}
Beispiel #5
0
/*----------------------------------------------------------------------------------------------
	Adjust the stream seek pointer, returning the new value.
	@return STG_E_SEEKERROR if the new position would be negative.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP FileStream::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin,
	ULARGE_INTEGER * plibNewPosition)
{
	BEGIN_COM_METHOD;
	ChkComArgPtrN(plibNewPosition);

#if WIN32
	if (m_hfile == NULL)
		ThrowHr(WarnHr(E_UNEXPECTED));

	DWORD dwLow;
	long dwHigh;
	LARGE_INTEGER dlibNew; // attempted new seek position

	switch (dwOrigin)
	{
	case STREAM_SEEK_SET:
		dlibNew.QuadPart = dlibMove.QuadPart;
		break;
	case STREAM_SEEK_CUR:
		dlibNew.QuadPart = (int64)m_ibFilePos.QuadPart + dlibMove.QuadPart;
		break;
	case STREAM_SEEK_END:
		// Find out where EOF is by calling for a zero move of the file pointer
		dwHigh = 0;
		dwLow = SetFilePointer(m_hfile, 0, &dwHigh, FILE_END);
		if (dwLow == 0xFFFFFFFF && GetLastError() != NO_ERROR)
			ThrowHr(WarnHr(STG_E_SEEKERROR));

		// Work out new attempted seek pointer value
		dlibNew.LowPart = dwLow;
		dlibNew.HighPart = dwHigh;
		dlibNew.QuadPart += dlibMove.QuadPart;
		break;
	default:
		ThrowHr(WarnHr(STG_E_INVALIDFUNCTION));
	}

	if (dlibNew.QuadPart < 0)
		ThrowHr(WarnHr(STG_E_SEEKERROR));

	// Update the current position.
	m_ibFilePos.QuadPart = (uint64)dlibNew.QuadPart;

	if (plibNewPosition)
		plibNewPosition->QuadPart = (uint64)dlibNew.QuadPart;
#else
	// TODO-Linux: Examine for cross-platform compatibility what was introduced with r576 and semi-addressed in r1482.
	// TODO-Linux: Check correct behavior for seek past EOF
	if (m_file < 0)
		ThrowHr(WarnHr(E_UNEXPECTED));
	off_t dMove = dlibMove.QuadPart;
	if (dMove != dlibMove.QuadPart) {
		return WarnHr(E_UNEXPECTED);
	}

	int whence;

	switch (dwOrigin)
	{
	case STREAM_SEEK_SET:
		whence = SEEK_SET;
		break;
	case STREAM_SEEK_CUR:
		whence = SEEK_CUR;
		break;
	case STREAM_SEEK_END:
		whence = SEEK_END;
		break;
	default:
		ThrowHr(WarnHr(STG_E_INVALIDFUNCTION));
	}

	off_t newPos = lseek(m_file, dMove, whence);

	if (newPos < 0) {
		ThrowHr(WarnHr(STG_E_SEEKERROR));
	}

	if (plibNewPosition) {
		plibNewPosition->QuadPart = newPos;
	}
#endif

	END_COM_METHOD(g_fact, IID_IStream);
}
Beispiel #6
0
/*----------------------------------------------------------------------------------------------
	Renders the data described in a FORMATETC structure and transfers it through the STGMEDIUM
	structure.

	This is a standard COM IDataObject method.

	@param pfmte Pointer to a FORMATETC structure describing the desired data format.
	@param pmedium Pointer to a STGMEDIUM structure that defines the output medium.

	@return S_OK, DV_E_DVASPECT, DV_E_FORMATETC, DV_E_LINDEX, DV_E_TYMED, E_POINTER,
					E_UNEXPECTED, or E_NOTIMPL.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP LgTsDataObject::GetData(FORMATETC * pfmte, STGMEDIUM * pmedium)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(pfmte);
	ChkComArgPtr(pmedium);
	AssertPtr(m_qtsswss.Ptr());
	if (pfmte->lindex != -1 && pfmte->lindex != 1)
		return DV_E_LINDEX;
	if (pfmte->dwAspect && pfmte->dwAspect != DVASPECT_CONTENT)
		return DV_E_DVASPECT;	// Invalid dwAspect value.

	if (pfmte->cfFormat == LgTsDataObject::s_cfTsString)
	{
		if (pfmte->tymed == TYMED_NULL)
		{
			pmedium->tymed = TYMED_NULL;
			pmedium->pstm = NULL;
			pmedium->pUnkForRelease = NULL;
			return S_OK;
		}
		if (pfmte->tymed & TYMED_ISTORAGE)
		{
			// Since we have no idea where to put the IStorage object, this particular request
			// is handled by GetDataHere instead.
			return E_NOTIMPL;
		}
		else
		{
			return DV_E_TYMED;
		}
	}
	else if (pfmte->cfFormat == CF_TEXT)
	{
		if (pfmte->tymed == TYMED_NULL)
		{
			pmedium->tymed = TYMED_NULL;
			pmedium->pstm = NULL;
			pmedium->pUnkForRelease = NULL;
			return S_OK;
		}
		if (pfmte->tymed & TYMED_HGLOBAL)
		{
			SmartBstr sbstr;
			CheckHr(m_qtsswss->get_Text(&sbstr));
			StrUni stu = sbstr.Chars();
			if (!StrUtil::NormalizeStrUni(stu, UNORM_NFC))
				ThrowInternalError(E_FAIL, "Normalize failure in StringDataObject::GetData.");
			StrAnsi sta(stu);
			pmedium->tymed = TYMED_HGLOBAL;
			pmedium->pUnkForRelease = NULL;
			pmedium->hGlobal = ::GlobalAlloc(GHND, (DWORD)(sta.Length() + 1));
			if (pmedium->hGlobal)
			{
				char * pszDst;
				pszDst = (char *)::GlobalLock(pmedium->hGlobal);
				strcpy_s(pszDst, sta.Length() + 1, sta.Chars());
				::GlobalUnlock(pmedium->hGlobal);
			}
			return S_OK;
		}
		if (!(pfmte->tymed & TYMED_HGLOBAL))
			return DV_E_TYMED;
		else
			return E_UNEXPECTED;
	}
	else if (pfmte->cfFormat == CF_OEMTEXT)
	{
		if (pfmte->tymed == TYMED_NULL)
		{
			pmedium->tymed = TYMED_NULL;
			pmedium->pstm = NULL;
			pmedium->pUnkForRelease = NULL;
			return S_OK;
		}
		if (pfmte->tymed & TYMED_HGLOBAL)
		{
			// REVIEW SteveMc: How does CF_OEMTEXT differ from CF_TEXT?
			SmartBstr sbstr;
			CheckHr(m_qtsswss->get_Text(&sbstr));
			StrUni stu = sbstr.Chars();
			if (!StrUtil::NormalizeStrUni(stu, UNORM_NFC))
				ThrowInternalError(E_FAIL, "Normalize failure in StringDataObject::GetData.");
			StrAnsi sta(stu);
			pmedium->tymed = TYMED_HGLOBAL;
			pmedium->pUnkForRelease = NULL;
			pmedium->hGlobal = ::GlobalAlloc(GHND, (DWORD)(sta.Length() + 1));
			if (pmedium->hGlobal)
			{
				char * pszDst;
				pszDst = (char *)::GlobalLock(pmedium->hGlobal);
				strcpy_s(pszDst, sta.Length() + 1, sta.Chars());
				::GlobalUnlock(pmedium->hGlobal);
			}
			return S_OK;
		}
		if (!(pfmte->tymed & TYMED_HGLOBAL))
			return DV_E_TYMED;
	}
	else if (pfmte->cfFormat == CF_UNICODETEXT)
	{
		if (pfmte->tymed == TYMED_NULL)
		{
			pmedium->tymed = TYMED_NULL;
			pmedium->pstm = NULL;
			pmedium->pUnkForRelease = NULL;
			return S_OK;
		}
		if (pfmte->tymed & TYMED_HGLOBAL)
		{
			SmartBstr sbstr;
			CheckHr(m_qtsswss->get_Text(&sbstr));
			StrUni stu = sbstr.Chars();
			if (!StrUtil::NormalizeStrUni(stu, UNORM_NFC))
				ThrowInternalError(E_FAIL, "Normalize failure in StringDataObject::GetData.");
			pmedium->tymed = TYMED_HGLOBAL;
			pmedium->pUnkForRelease = NULL;
			int cb = isizeof(wchar) * (stu.Length() + 1);
			pmedium->hGlobal = ::GlobalAlloc(GHND, (DWORD)cb);
			if (pmedium->hGlobal)
			{
				wchar * pszDst;
				pszDst = (wchar *)::GlobalLock(pmedium->hGlobal);
				memcpy(pszDst, stu.Chars(), cb);
				::GlobalUnlock(pmedium->hGlobal);
			}
			return S_OK;
		}
		if (!(pfmte->tymed & TYMED_HGLOBAL))
			return DV_E_TYMED;
		else
			return E_UNEXPECTED;
	}
	else
	{
		return DV_E_FORMATETC;
	}
	END_COM_METHOD(g_fact, IID_IDataObject);
}
Beispiel #7
0
/*----------------------------------------------------------------------------------------------
	Set up to draw text using the properties specified.
	super/subscript are ignored, as is baseline adjust; client is
	presumed to have handled them. Sets colors and HFONT.
----------------------------------------------------------------------------------------------*/
HRESULT VwGraphicsCairo::SetupGraphics(VwCharRenderProps * pchrp)
{
#if DEBUG
	if (m_loggingFile != NULL)
	{
		UnicodeString8 szFaceName(pchrp->szFaceName, (int)32);
		UnicodeString8 szFontVar(pchrp->szFontVar, (int)64);
		fprintf(m_loggingFile, "SetupGraphics %p %u %u %u %d %d %d %d %d %d %d %d %d \"%s\" \"%s\"\n",
			this,
			pchrp->clrFore, pchrp->clrBack, pchrp->clrUnder, pchrp->dympOffset, pchrp->ws, pchrp->fWsRtl,
			pchrp->nDirDepth, pchrp->ssv, pchrp->unt, pchrp->ttvBold, pchrp->ttvItalic, pchrp->dympHeight,
			szFaceName.c_str(), szFontVar.c_str());
		fflush(m_loggingFile);
	}
#endif
 BEGIN_COM_METHOD;
	CheckDc();

	m_chrp = *pchrp;

	double fontSize = 0;

	// TODO-Linux: Work around for FWNX-179.
	// dympHeight should be in mp.
	const int tooSmall = 100; // A Converative hueristic of a small milli point value which means a invalid value has been specified.
	Assert(m_chrp.dympHeight >= tooSmall || m_chrp.dympHeight == 0);
	if (m_chrp.dympHeight < tooSmall)
	{
		fontSize = m_chrp.dympHeight;
	}
	else
	{
		fontSize = m_chrp.dympHeight * GetYInch() / kdzmpInch;
	}

	UnicodeString8 fontNameUtf8(pchrp->szFaceName);
	const char* fontName = fontNameUtf8.c_str();

	if (pchrp->clrFore == kclrTransparent) {
		VwColor newCol;
		newCol.m_transparent = true;
		m_textColor = newCol;
	}
	else {
		VwColor newCol(pchrp->clrFore);
		m_textColor = newCol;
	}

	if (pchrp->clrBack == kclrTransparent) {
		VwColor newCol;
		newCol.m_transparent = true;
		m_textBackColor = newCol;
	}
	else {
		VwColor newCol(pchrp->clrBack);
		m_textBackColor = newCol;
	}

	m_pangoFontDescription = pango_font_description_new();
	m_ascent = -1;
	m_descent = -1;
	pango_font_description_set_family(m_pangoFontDescription, fontName);
	pango_font_description_set_weight(m_pangoFontDescription, m_chrp.ttvBold == kttvOff ? PANGO_WEIGHT_NORMAL : PANGO_WEIGHT_BOLD);
	pango_font_description_set_style(m_pangoFontDescription, m_chrp.ttvItalic == kttvOff ? PANGO_STYLE_NORMAL : PANGO_STYLE_ITALIC);
	pango_font_description_set_absolute_size(m_pangoFontDescription, fontSize * PANGO_SCALE);

 END_COM_METHOD(g_fact, IID_IVwGraphics);
}
Beispiel #8
0
/*----------------------------------------------------------------------------------------------
	Draw a piece of text (below and to the right of the specified point)
	OPTIMIZE: for performance, should we make the caller responsible to ensure that only text
	reasonably near the clipping box gets drawn?
----------------------------------------------------------------------------------------------*/
HRESULT VwGraphicsCairo::DrawText(int x, int y, int cch, const OLECHAR * prgch, int unused)
{
#if DEBUG
	if (m_loggingFile != NULL)
	{
		UnicodeString8 text(prgch, (int)cch);
		char * strWithoutQuotes = strdup(text.c_str());
		for(char * p = strWithoutQuotes; *p != '\0'; p++)
			if (*p == '\"')
				*p = '\'';
		fprintf(m_loggingFile, "DrawText %p %d %d %d \"%s\" %d\n", this, x, y, cch, strWithoutQuotes, unused);
		fflush(m_loggingFile);
		free(strWithoutQuotes);
	}
#endif
 BEGIN_COM_METHOD;
	RECT rcClip;
	MyGetClipRect(&rcClip);
	// First, see if the text to be drawn is above or below the current clipping rectangle
	if(y > rcClip.bottom || y + (m_chrp.dympHeight * GetYInch() / kdzmpInch) < rcClip.top) {
		return S_OK;
	}

	CheckDc();

	int pangoX, pangoY; // store the offset that pango uses to draw text.
	int ascent;
	int descent;
	FontAscentAndDescent(&ascent, &descent);
	int fontHeight = ascent + descent;

	UnicodeString8 text(prgch, (int)cch);

	// Only draw text thats in the clipping region, by setting a cairo clipping region.
	m_ctxt->reset_clip();
	m_ctxt->rectangle(rcClip.left, rcClip.top, rcClip.right - rcClip.left, rcClip.bottom - rcClip.top);
	m_ctxt->clip();

	// Draw background if required

	if(!m_textBackColor.m_transparent) {
		SetCairoColor(m_ctxt, &m_textBackColor);
		int width, height, xoff, yoff;

		GetTextExtentHelper(cch, prgch, &pangoX, &pangoY, &width, &height);

		xoff = x;
		yoff = y;

		m_ctxt->rectangle(x, y, width, height);

		m_ctxt->fill();
	}

	if(!m_textColor.m_transparent)
	{
		// don't call g_object_unref on the returned layout
		PangoLayout *layout = GetPangoLayoutHelper();

		pango_layout_set_font_description (layout, m_pangoFontDescription);
		pango_layout_set_text (layout, text.data(), text.size());

		SetCairoColor(m_ctxt, &m_textColor);
		m_ctxt->move_to(x, y);

		pango_cairo_show_layout (m_ctxt.operator ->()->cobj(), layout);
	}

	// Undo the cairo clipping region.
	m_ctxt->reset_clip();

 END_COM_METHOD(g_fact, IID_IVwGraphics);
}
STDMETHODIMP FwDbMergeStyles::AddStyleDeletion(BSTR bstrDeleteStyleName)
{
	BEGIN_COM_METHOD;
	m_vstuDelNames.Insert(0, 1, bstrDeleteStyleName);
	END_COM_METHOD(g_fact, IID_IFwDbMergeStyles);
}
Beispiel #10
0
/*----------------------------------------------------------------------------------------------
	Crawl through the database and rename/delete the given styles.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP FwDbMergeStyles::Process(DWORD hWnd)
{
	BEGIN_COM_METHOD;
	Assert(m_vstuOldNames.Size() == m_vstuNewNames.Size());

	if (!m_hvoRoot)
		return E_UNEXPECTED;
	if (!m_pclsidApp)
		return E_UNEXPECTED;

	if (LogFile())
	{
		ULONG cbLog;
		StrAnsi staLog;
		staLog.Format("Changing style names in %S (%S)%n",
			DbName().Chars(), ServerName().Chars());
		LogFile()->Write(staLog.Chars(), staLog.Length(), &cbLog);
	}

	m_qprog->DoModeless((HWND)hWnd);
	StrUni stuMsg(kstidChgStyleLabel);
	m_qprog->put_Title(stuMsg.Bstr());

	ResetConnection();
	BeginTrans();
	CreateCommand();

	SetPercentComplete(0);

	// We want to affect only a subset of the formatting and style information in the database,
	// based on which program is currently running, since different programs may be using
	// different sets of styles.  This information is derived from m_hvoRoot and m_pclsidApp.
	// (Unfortunately, there's no way to derive one of these values from the other one.)  The
	// current scheme works for Data Notebook, List Editor, TE, and LexText.  Additional
	// programs may introduce even more complexities.
	// 1. Find all the owners of StStyle objects.  This should match up to LangProject (Data
	//    Notebook and List Editor), Scripture (TE), or LexDb (LexText).
	// 2. If an owner equals m_hvoRoot, then only those objects owned by m_hvoRoot have the
	//    string and paragraph formatting fixed.  Except that LexText also wants to fix all the
	//    Text objects owned by the LangProject in addition to all the objects owned by the
	//    LexDb, so those have to be added to the collection of objects.
	// 3. If none of the owners equals m_hvoRoot, we must be dealing with Data Notebook or List
	//    Editor, which share a common set of styles owned by the LangProject itself.  In
	//    this case, we want all the objects owned by the LangProject except those owned by
	//    another owner of styles (or the LangProject Text objects, since those use the
	//    LexText styles even though they're not owned by the root object).  (This isn't quite
	//    right if either TE or LexText does not actually own any styles yet, but we won't worry
	//    about this nicety.)
	// 4. After creating a temp table containing just the ids of those objects of interest, we
	//    can then process all the relevant string formatting (via a string crawler) and
	//    paragraph StyleRules (later in this method)
	// 5. Finally, we may need to fix the Style fields of the relevant UserViewField objects.
	//    These are limited by the psclsidApp argument, since the UserView objects are specific
	//    to specific applications.  If pssclidApp indicates either Data Notebook or List
	//    Editor, then UserViewField objects belonging to both of those programs are fixed.
	//    Otherwise, only those UserViewField objects belonging to the specific program
	//    identified by psclsidApp are fixed.

	ComBool fMoreRows;
	UINT cbSpaceTaken;
	ComBool fIsNull;
	int hobj = 0;
	int clid = 0;
	bool fFixOwned = false;
	int clidOwned = 0;
	int hvoLangProj = 0;
	Vector<int> vhvoOwners;
	Vector<int> vclidOwners;
	Vector<int> vhvoTexts;
	StrUni stuCmd;
	stuCmd.Format(L"SELECT DISTINCT c.Owner$, co.Class$ "
		L"FROM CmObject c "
		L"JOIN CmObject co on co.Id = c.Owner$ "
		L"WHERE c.Class$ = %d",
		kclidStStyle);
	CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtSelectWithOneRowset));
	CheckHr(GetOleDbCommand()->GetRowset(0));
	CheckHr(GetOleDbCommand()->NextRow(&fMoreRows));
	while (fMoreRows)
	{
		CheckHr(GetOleDbCommand()->GetColValue(1, reinterpret_cast <BYTE *>(&hobj),
			isizeof(hobj), &cbSpaceTaken, &fIsNull, 0));
		CheckHr(GetOleDbCommand()->GetColValue(2, reinterpret_cast <BYTE *>(&clid),
			isizeof(clid), &cbSpaceTaken, &fIsNull, 0));
		if (hobj == m_hvoRoot)
		{
			fFixOwned = true;
			clidOwned = clid;
		}
		else if (clid == kclidLangProject)
		{
			hvoLangProj = hobj;
		}
		else
		{
			vhvoOwners.Push(hobj);
			vclidOwners.Push(clid);
		}
		CheckHr(GetOleDbCommand()->NextRow(&fMoreRows));
	}
	Assert(hvoLangProj != 0);
// This may not be defined in any of our header files.
#ifndef kclidLexDb
#define kclidLexDb 5005
#endif
	if (!fFixOwned || clidOwned == kclidLexDb)
	{
		// We need the set of LangProject_Texts objects to include or exclude.
		stuCmd.Format(L"SELECT Dst FROM LangProject_Texts WHERE Src = %d", hvoLangProj);
		CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(),
			knSqlStmtSelectWithOneRowset));
		CheckHr(GetOleDbCommand()->GetRowset(0));
		CheckHr(GetOleDbCommand()->NextRow(&fMoreRows));
		while (fMoreRows)
		{
			CheckHr(GetOleDbCommand()->GetColValue(1, reinterpret_cast <BYTE *>(&hobj),
				isizeof(hobj), &cbSpaceTaken, &fIsNull, 0));
			vhvoTexts.Push(hobj);
			CheckHr(GetOleDbCommand()->NextRow(&fMoreRows));
		}
	}
	// Note that dbo.fnGetOwnedObjects$() returns the root object as the first row.
	stuCmd.Format(L"CREATE TABLE #OwnedObjIdsTbl%n"
		L"(%n"
		L"    ObjId int not null%n"
		L")%n"
		L"CREATE CLUSTERED INDEX #OwnedObjIdsTblObjId ON #OwnedObjIdsTbl ([ObjId])%n");
	CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtNoResults));

	const OLECHAR * kpszDefTableFmt =
		L"INSERT INTO #OwnedObjIdsTbl%n"
		L"SELECT ObjId%n"
		L"FROM dbo.fnGetOwnedObjects$('%d', null, 0, 0, 1, null, 0)";

	if (fFixOwned)
	{
		stuCmd.Format(kpszDefTableFmt, m_hvoRoot);
		stuCmd.FormatAppend(L";%n");
		if (vhvoTexts.Size())
		{
			stuCmd.FormatAppend(
				L"INSERT INTO #OwnedObjIdsTbl%n"
				L"SELECT ObjId%n"
				L"FROM dbo.fnGetOwnedObjects$('");
			for (int ihvo = 0; ihvo < vhvoTexts.Size(); ++ihvo)
				if (ihvo == 0)
					stuCmd.FormatAppend(L"%d", vhvoTexts[ihvo]);
				else
					stuCmd.FormatAppend(L",%d", vhvoTexts[ihvo]);
			stuCmd.FormatAppend(L"', null, 0, 0, 1, null, 0);");
		}
	}
	else
	{
	/*
	POSSIBLE SPEED ENHANCEMENT
	--------------------------
	SELECT co.Id
	FROM CmObject co
	WHERE co.Owner$=1 AND co.OwnFlid$ NOT IN (6001006, 6001014, 6001040)

	gives a list of ids which own what we want to look through.  This could then be
	handled by the following query, which runs in one-half to one-third of the time
	required by the current code.

	SELECT 1 UNION SELECT ObjId FROM dbo.fnGetOwnedObjects$('2,54728', null, 0, 0, 1, null, 0)

	whether the C++ code or the SQL code should put together the XML string is a good
	question.
	*/
		// REVIEW (SteveMiller): The temp tables below just slow things down.

		stuCmd.Clear();
		if (vhvoOwners.Size() || vhvoTexts.Size())
		{
			stuCmd.FormatAppend(L"CREATE TABLE #tblUnwanted ( ObjId int not null );%n");
			stuCmd.FormatAppend(L"INSERT INTO #tblUnwanted%n");
			stuCmd.FormatAppend(L"SELECT ObjId%n");
			stuCmd.FormatAppend(L"FROM dbo.fnGetOwnedObjects$('");
			for (int ihvo = 0; ihvo < vhvoOwners.Size(); ++ihvo)
				if (ihvo == 0)
					stuCmd.FormatAppend(L"%d", vhvoOwners[ihvo]);
				else
					stuCmd.FormatAppend(L",%d", vhvoOwners[ihvo]);
			for (int ihvo = 0; ihvo < vhvoTexts.Size(); ++ihvo)
				if (vhvoOwners.Size() < 0)
					// I don't think we can have an ownerless text, but hey...
					stuCmd.FormatAppend(L"%d", vhvoTexts[ihvo]);
				else
					stuCmd.FormatAppend(L",%d", vhvoTexts[ihvo]);
			stuCmd.FormatAppend(L"',null,0,0,1,null,0);%n");
		}
		stuCmd.FormatAppend(kpszDefTableFmt, hvoLangProj);
		if (vhvoOwners.Size() || vhvoTexts.Size())
		{
			stuCmd.FormatAppend(L"WHERE ObjId NOT IN (SELECT ObjId FROM #tblUnwanted);%n");
			stuCmd.FormatAppend(L"DROP TABLE #tblUnwanted");
		}
		stuCmd.FormatAppend(L";%n");	// terminate for Firebird
	}
	CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtNoResults));

	// Do the standard stuff for monolingual and multilingual strings.
	DoAll(kstidChgStylePhaseOne, kstidChgStylePhaseTwo,
		false,	// don't create a new transaction--this method handles it
		L"#OwnedObjIdsTbl");

	// Fix all the StyleRules of instances of StPara.
	stuMsg.Load(kstidChgStylePhaseThree);
	m_qprog->put_Message(stuMsg.Bstr());

	int nPercent = 0;
	SetPercentComplete(nPercent);

	Vector<int> vhobjFix;
	Vector<Vector<byte> > vvbFmtFix;
	vhobjFix.Clear();
	vvbFmtFix.Clear();

	Vector<byte> vbFmt;
	int cbFmt;

	ITsPropsFactoryPtr qtpf;
	qtpf.CreateInstance(CLSID_TsPropsFactory);

	int cRows;
	StrUni stuCmdCnt;
	stuCmdCnt.Format(L"SELECT COUNT(*) FROM StPara a%n"
		L"JOIN #OwnedObjIdsTbl b on b.ObjId = a.Id%n"
		L"WHERE a.StyleRules IS NOT NULL",
		m_hvoRoot);
	CheckHr(GetOleDbCommand()->ExecCommand(stuCmdCnt.Bstr(),
		knSqlStmtSelectWithOneRowset));
	CheckHr(GetOleDbCommand()->GetRowset(0));
	CheckHr(GetOleDbCommand()->NextRow(&fMoreRows));
	CheckHr(GetOleDbCommand()->GetColValue(1, reinterpret_cast <BYTE *>(&cRows),
		isizeof(hobj), &cbSpaceTaken, &fIsNull, 0));

	stuCmd.Format(L"SELECT a.Id, a.StyleRules FROM StPara a%n"
		L"JOIN #OwnedObjIdsTbl b on b.ObjId = a.Id%n"
		L"WHERE a.StyleRules IS NOT NULL",
		m_hvoRoot);
	CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtSelectWithOneRowset));
	CheckHr(GetOleDbCommand()->GetRowset(0));
	CheckHr(GetOleDbCommand()->NextRow(&fMoreRows));
	int iRow = 0;
	ComVector<ITsTextProps> vqttp;
	vqttp.Resize(1);
	while (fMoreRows)
	{
		CheckHr(GetOleDbCommand()->GetColValue(1, reinterpret_cast <BYTE *>(&hobj),
			isizeof(hobj), &cbSpaceTaken, &fIsNull, 0));
		CheckHr(GetOleDbCommand()->GetColValue(2,
			reinterpret_cast <BYTE *>(vbFmt.Begin()), vbFmt.Size(), &cbSpaceTaken, &fIsNull,
			0));
		cbFmt = cbSpaceTaken;
		if (cbFmt >= vbFmt.Size())
		{
			vbFmt.Resize(cbFmt + 1);
			CheckHr(GetOleDbCommand()->GetColValue(2,
				reinterpret_cast <BYTE *>(vbFmt.Begin()),
				vbFmt.Size(), &cbSpaceTaken, &fIsNull, 0));
			cbFmt = cbSpaceTaken;
		}
		vbFmt.Resize(cbFmt);

		ITsTextPropsPtr qttp;
		bool fModify = false;
		int cb = vbFmt.Size();
		CheckHr(qtpf->DeserializePropsRgb(vbFmt.Begin(), &cb, (ITsTextProps **)&qttp));

		// use a vector with exactly 1 item
		vqttp[0] = qttp;
		// Note: using "Normal" doesn't work all the time. For more complex scenarios where the
		// default style depends on the context of the deleted style, a replace should be done
		// instead of a delete. See FwStylesDlg.DeleteAndRenameStylesInDB() in FwStylesDlg.cs.
		fModify = ProcessFormatting(vqttp, g_pszwStyleNormal);
		if (fModify)
		{
			vhobjFix.Push(hobj);
			int cbNeeded;
			HRESULT hr;
			CheckHr(hr = vqttp[0]->SerializeRgb(vbFmt.Begin(), vbFmt.Size(), &cbNeeded));
			if (hr == S_FALSE)
			{
				vbFmt.Resize(cbNeeded);
				hr = vqttp[0]->SerializeRgb(vbFmt.Begin(), vbFmt.Size(), &cbNeeded);
			}
			vbFmt.Resize(cbNeeded);
			vvbFmtFix.Push(vbFmt);
		}
		CheckHr(GetOleDbCommand()->NextRow(&fMoreRows));

		iRow++;
		SetPercentComplete((iRow * 50) / cRows);
	}
	int ceFix = vhobjFix.Size();
	SetPercentComplete(50);
	for (int ieFix = 0; ieFix < ceFix; ++ieFix)
	{
		stuCmd.Format(L"UPDATE StPara SET StyleRules=? WHERE [Id] = %d", vhobjFix[ieFix]);
		// Set the parameter and execute the command.
		CheckHr(GetOleDbCommand()->SetParameter(1, DBPARAMFLAGS_ISINPUT, NULL,
			DBTYPE_BYTES, reinterpret_cast<BYTE *>(vvbFmtFix[ieFix].Begin()),
			vvbFmtFix[ieFix].Size()));
		CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtNoResults));

		SetPercentComplete(50 + ((ieFix * 50) / ceFix));
	}
	SetPercentComplete(100);

	stuCmd.Assign(L"DROP TABLE #OwnedObjIdsTbl");
	CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtNoResults));

	// Fix style names in the view specs.
	// SQL gives us the power to just rename all items in one query. But that
	// won't correctly handle the situation of, for instance, renaming A to B, B to C, and
	// C to A. So we fix one item at a time and then update the database.

	static const GUID clsidNotebook =	// {39886581-4DD5-11D4-8078-0000C0FB81B5}
		{ 0x39886581, 0x4DD5, 0x11D4, { 0x80, 0x78, 0x00, 0x00, 0xC0, 0xFB, 0x81, 0xB5 } };
	static GUID clsidListEditor =	// {5EA62D01-7A78-11D4-8078-0000C0FB81B5}
		{ 0x5EA62D01, 0x7A78, 0x11D4, { 0x80, 0x78, 0x00, 0x00, 0xC0, 0xFB, 0x81, 0xB5 } };

	StrUni stuBaseCmd;
	stuBaseCmd.Format(L"%nFROM UserViewField a%n"
		L"JOIN UserViewRec_Fields uf on uf.Dst = a.Id%n"
		L"JOIN UserView_Records ur on ur.Dst = uf.Src%n"
		L"JOIN UserView uv on uv.Id = ur.Src%n"
		L"WHERE a.Style IS NOT NULL AND");
	if (*m_pclsidApp == clsidNotebook || *m_pclsidApp == clsidListEditor)
	{
		Assert(!fFixOwned);
		stuBaseCmd.FormatAppend(L"%n\tuv.App in ('%g','%g')", &clsidNotebook, &clsidListEditor);
	}
	else
	{
		Assert(fFixOwned);
		stuBaseCmd.FormatAppend(L" uv.App = '%g'", m_pclsidApp);
	}
	stuMsg.Load(kstidChgStylePhaseFour);
	m_qprog->put_Message(stuMsg.Bstr());
	SetPercentComplete(0);

	OLECHAR rgch[1024];
	vhobjFix.Clear();
	Vector<StrUni> vstuFix;

	stuCmdCnt.Format(L"SELECT COUNT(*)%s", stuBaseCmd.Chars());
	CheckHr(GetOleDbCommand()->ExecCommand(stuCmdCnt.Bstr(),
		knSqlStmtSelectWithOneRowset));
	CheckHr(GetOleDbCommand()->GetRowset(0));
	CheckHr(GetOleDbCommand()->NextRow(&fMoreRows));
	CheckHr(GetOleDbCommand()->GetColValue(1, reinterpret_cast <BYTE *>(&cRows),
		isizeof(hobj), &cbSpaceTaken, &fIsNull, 0));

	stuCmd.Format(L"SELECT a.Id, a.Style%s", stuBaseCmd.Chars());

	CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtSelectWithOneRowset));
	CheckHr(GetOleDbCommand()->GetRowset(0));
	CheckHr(GetOleDbCommand()->NextRow(&fMoreRows));
	iRow = 0;
	while (fMoreRows)
	{
		CheckHr(GetOleDbCommand()->GetColValue(1, reinterpret_cast <BYTE *>(&hobj),
			isizeof(hobj), &cbSpaceTaken, &fIsNull, 0));
		CheckHr(GetOleDbCommand()->GetColValue(2, reinterpret_cast <BYTE *>(*&rgch),
			isizeof(rgch), &cbSpaceTaken, &fIsNull, 0));
		int cchw = cbSpaceTaken / isizeof(OLECHAR);

		StrUni stuOld(rgch, cchw);
		StrUni stuNew;
		if (Delete(stuOld))
		{
			vstuFix.Push(L"");
			vhobjFix.Push(hobj);
		}
		else if (Rename(stuOld, stuNew))
		{
			vstuFix.Push(stuNew);
			vhobjFix.Push(hobj);
		}

		CheckHr(GetOleDbCommand()->NextRow(&fMoreRows));

		iRow++;
		SetPercentComplete((iRow * 50) / cRows);
	}
	SetPercentComplete(50);
	Assert(vhobjFix.Size() == vstuFix.Size());

	ceFix = vstuFix.Size();
	for (int ieFix = 0; ieFix < ceFix; ieFix++)
	{
		if (vstuFix[ieFix] == L"")
		{
			stuCmd.Format(L"UPDATE UserViewField SET Style = NULL where [Id] = '%d'",
				vhobjFix[ieFix]);
		}
		else
		{
			StrUtil::NormalizeStrUni(vstuFix[ieFix], UNORM_NFD);
			stuCmd.Format(L"UPDATE UserViewField SET Style = '%s' where [Id] = '%d'",
				vstuFix[ieFix].Chars(), vhobjFix[ieFix]);
		}
		CheckHr(GetOleDbCommand()->ExecCommand(stuCmd.Bstr(), knSqlStmtNoResults));

		SetPercentComplete(50 + ((ieFix * 50) / ceFix));
	}

	SetPercentComplete(100);
	CommitTrans();
	Terminate(m_hvoRoot);

	if (m_qprog)
		m_qprog->DestroyHwnd();
	END_COM_METHOD(g_fact, IID_IFwDbMergeStyles);
}
Beispiel #11
0
/*----------------------------------------------------------------------------------------------
	DeleteForward
		The user pressed a certain number of forward deletes. Forward delete an appropriate
		amount of the string represented by the input string builder, indicating exactly what
		changed.  lso, if there were not enough characters to delete, indicate how many deletes
		were left over.

	 Arguments:
		ichStart				starting position of deletes
		cactDelForward			number of DF pressed
		ptsbOld        			original, unedited text, gets modified
		pichModMin, pichModLim  range in output text affected
		pichIP					position of IP in modified string
		pcactDfRemaining        Number not handled, to affect next writing system

----------------------------------------------------------------------------------------------*/
STDMETHODIMP LgInputMethodEditor::DeleteForward(int ichStart, int cactDelForward,
	ITsStrBldr * ptsbOld, int * pichModMin, int * pichModLim, int * pichIP,
	int * pcactDfRemaining)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(ptsbOld);
	ChkComOutPtr(pichModMin);
	ChkComOutPtr(pichModLim);
	ChkComOutPtr(pichIP);
	ChkComOutPtr(pcactDfRemaining);

	int cCh;
	int ichLim;
	int ich;
	int iDfIn;
	int cDfOut=0;
	SmartBstr sbstr;

	CheckHr(ptsbOld->get_Length(&cCh));
	if (ichStart > cCh - 2)
	{
		*pichModMin = cCh;
		*pichModLim = cCh;
		*pichIP = cCh;
		*pcactDfRemaining = cactDelForward;
		ThrowHr(WarnHr(E_INVALIDARG));
	}

	// Check to make sure the ichStart is not between a surrgante pair.
	if (cCh > ichStart)
	{
		CheckHr(ptsbOld->GetChars(ichStart, ichStart + 1, &sbstr));
		if (sbstr[0] > 0xDBFF && sbstr[0] < 0xE000)
			ichStart--;
	}

	// increase DeleteForward count for any other surrgate pairs.
	iDfIn = cactDelForward;
	ichLim = ichStart + (cactDelForward * 2) + 1;
	if (ichLim > cCh)
		ichLim = cCh;
	CheckHr(ptsbOld->GetChars(ichStart, ichLim, &sbstr));
	ich = ichStart;
	do
	{
		if (sbstr[ich] < 0xDC00 || sbstr[ich] > 0xDFFF)
			--iDfIn;
		++cDfOut;
		if (++ich >= cCh)
			break;
	} while (iDfIn > 0);
	cactDelForward = cDfOut + iDfIn;

	// Now, do the real work
	if (ichStart + cactDelForward < cCh)
	{
		ichLim = ichStart + cactDelForward;
		CheckHr(ptsbOld->Replace(ichStart, ichLim, NULL, NULL));
		*pichModMin = ichStart;
		*pichModLim = ichStart;
		*pichIP = ichStart;
		*pcactDfRemaining = 0;
	}
	else
	{
		CheckHr(ptsbOld->Replace(ichStart, cCh, NULL, NULL));
		*pichModMin = ichStart;
		*pichModLim = ichStart;
		*pichIP = ichStart;
		*pcactDfRemaining = iDfIn;
	}

	END_COM_METHOD(g_fact, IID_ILgFontManager);
}
Beispiel #12
0
/*----------------------------------------------------------------------------------------------
	Backspace
		The user pressed a certain number of backspaces. Delete an appropriate amount of
		the string represented by the input string builder, indicating exactly what changed.
		Also, if there were not enough characters to delete, indicate how many backspaces
		were left over.

	 Arguments:
		ichStart				starting position of backspaces
		cactBackspace			number of backspaces pressed
		ptsbOld        			original, unedited text, gets modified
		pichModMin, pichModLim  range in output text affected
		pichIP					position of IP in modified string
		pcactBsRemaining        Number not handled, to affect previous writing system

----------------------------------------------------------------------------------------------*/
STDMETHODIMP LgInputMethodEditor::Backspace(int ichStart, int cactBackspace,
		ITsStrBldr * ptsbOld, int * pichModMin, int * pichModLim, int * pichIP,
		int * pcactBsRemaining)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(ptsbOld);
	ChkComOutPtr(pichModMin);
	ChkComOutPtr(pichModLim);
	ChkComOutPtr(pichIP);
	ChkComOutPtr(pcactBsRemaining);

	int cCh;
	int ichMin;
	int ich;
	int ichMin1;
	int iBsIn;
	int cBsOut=0;
	SmartBstr sbstr;

	if (ichStart < 1)
	{
		*pichModMin = 0;
		*pichModLim = 0;
		*pichIP = 0;
		*pcactBsRemaining = cactBackspace;
		return S_OK;
	}

	// Check to make sure the ichStart is not between a surrgante pair.
	CheckHr(ptsbOld->get_Length(&cCh));
	if (cCh > ichStart)
	{
		CheckHr(ptsbOld->GetChars(ichStart, ichStart + 1, &sbstr));
		if (sbstr[0] > 0xDBFF && sbstr[0] < 0xE000)
			ichStart++;
	}

	// increase backspace count for any other surrgate pairs.
	iBsIn = cactBackspace;
	ichMin1 = ichStart - (cactBackspace * 2) - 1;
	if (ichMin1 < 0)
		ichMin1 = 0;
	CheckHr(ptsbOld->GetChars(ichMin1, ichStart, &sbstr));
	ich = ichStart - ichMin1 - 1;
	do
	{
		if (sbstr[ich] < 0xDC00 || sbstr[ich] > 0xDFFF)
			--iBsIn;
		++cBsOut;
		if (--ich < 0)
			break;
	} while (iBsIn > 0);
	cactBackspace = cBsOut + iBsIn;

		// Now, do the real work
	if (ichStart > cactBackspace)
	{
		ichMin = ichStart - cactBackspace;
		CheckHr(ptsbOld->Replace(ichMin, ichStart, NULL, NULL));
		*pichModMin = ichMin;
		*pichModLim = ichMin;
		*pichIP = ichMin;
		*pcactBsRemaining = 0;
	}
	else
	{
		CheckHr(ptsbOld->Replace(0, ichStart, NULL, NULL));
		*pichModMin = 0;
		*pichModLim = 0;
		*pichIP = 0;
		*pcactBsRemaining = cactBackspace - ichStart;
	}

	END_COM_METHOD(g_fact, IID_ILgFontManager);
}
Beispiel #13
0
/*----------------------------------------------------------------------------------------------
Replace
	The default implementation just replaces characters from ichMin to ichLim with
	those from bstrInput, then set *pichModMin to ichMin, and *pichModLim and
	*pichIP both to ichMin + BstrLen(bstrInput).

	 Arguments:
		bstrInput				what user typed
		pttpInput          		text properties desired for new text
		ptsbOld        			original, unedited text, gets modified
		ichMin,	ichLim			range in original to replace
		pichModMin, pichModLim  range in output text affected
		pichIP                  position of IP in modified string

----------------------------------------------------------------------------------------------*/
STDMETHODIMP LgInputMethodEditor::Replace(BSTR bstrInput, ITsTextProps * pttpInput,
		ITsStrBldr * ptsbOld, int ichMin, int ichLim, int * pichModMin, int * pichModLim,
		int * pichIP)
{
	BEGIN_COM_METHOD;
	ChkComBstrArgN(bstrInput);
	ChkComArgPtrN(pttpInput);
	ChkComArgPtr(ptsbOld);
	ChkComOutPtr(pichModMin);
	ChkComOutPtr(pichModLim);
	ChkComOutPtr(pichIP);

	int cCh;
	SmartBstr sbstr;
	CheckHr(ptsbOld->get_Length(&cCh));
	if (ichMin < 0 || ichLim > cCh || ichMin > ichLim)
	{
		*pichModMin = 0;
		*pichModLim = 0;
		*pichIP = 0;
		ThrowHr(WarnHr(E_INVALIDARG));
	}

	// Check to make sure the ichMin is not between a surrognte pair.
	do
	{
		if (0 < ichMin)
		{
			CheckHr(ptsbOld->GetChars(ichMin, ichMin + 1, &sbstr));
			if (sbstr[0] < 0xDC00 || sbstr[0] > 0xDFFF)
				break;
		}
		else
		{
			break;
		}
	} while (--ichMin > 0);

	// Check to make sure the ichLim is not between a surrgante pair.
	do
	{
		if (cCh > ichLim)
		{
			CheckHr(ptsbOld->GetChars(ichLim, ichLim + 1, &sbstr));
			if (sbstr[0] < 0xDC00 || sbstr[0] > 0xDFFF)
				break;
		}
		else
		{
			break;
		}
	} while (++ichLim < cCh);

	// Now, do the real work

	CheckHr(ptsbOld->Replace(ichMin, ichLim, bstrInput, pttpInput));
	*pichModMin = ichMin;
	*pichModLim = ichMin + BstrLen(bstrInput);
	*pichIP = ichMin + BstrLen(bstrInput);

	END_COM_METHOD(g_fact, IID_ILgFontManager);
}
Beispiel #14
0
/*----------------------------------------------------------------------------------------------
	Invert the specified rectangle.
----------------------------------------------------------------------------------------------*/
HRESULT VwGraphicsCairo::InvertRect(int xLeft, int yTop, int xRight, int yBottom)
{
#if DEBUG
	if (m_loggingFile != NULL)
	{
		fprintf(m_loggingFile, "InvertRect %p %d %d %d %d\n", this, xLeft, yTop, xRight, yBottom);
		fflush(m_loggingFile);
	}
#endif
	BEGIN_COM_METHOD;
	/*
	 * TODO:
	 * Make this work
	 * Cairo OPERATOR_XOR doesn't seem to work
	 *
	 * Dispite what 'some' documentation may say - reading up on the operators suggests
	 * that it doesn't do what you may expect (ie work like a bitwise XOR)
	 *
	 * in Addition to this given the way we are currently paint the background,
	 * (as a normal rectangle which we draw first) the background would also
	 * interfere with XOR operation.
	 * The internet says that there is no easy way for inverting text using cairo.
	 * The suggested why is using paths (ie remembering when we have drawn the text)
	 * however given the views framework this is likley to be infesible/hugly complicated.
	 *
	 * Therefore given the need to have a carret that stands out more I have special cased it
	 * with a HACK that displays the carrat black when its 2 pixcels wide or smaller and
	 * alpha blends it when its not.
	 */

	CheckDc();

	// See if rectangle is outside clipping box
	RECT rectClip;
	MyGetClipRect(&rectClip);
	RECT rectDraw;
	rectDraw.left = xLeft;
	rectDraw.right = xRight;
	rectDraw.top = yTop;
	rectDraw.bottom = yBottom;
	if(!rectIntersect(&rectClip, &rectDraw)) {
		return S_OK;
	}

	// Only draw rectangles thats in the clipping region, by setting a cairo clipping region.
	m_ctxt->reset_clip();
	m_ctxt->rectangle(rectClip.left, rectClip.top, rectClip.right - rectClip.left, rectClip.bottom - rectClip.top);
	m_ctxt->clip();

	if (xRight - xLeft <= 2)
		m_ctxt->set_source_rgba(0.0, 0.0, 0.0, 1.0);
	else
		m_ctxt->set_source_rgba(0.5, 0.5, 1.0, 0.4);

	m_ctxt->rectangle(xLeft, yTop, xRight - xLeft, yBottom - yTop);
	m_ctxt->fill();

	// Undo the cairo clipping region.
	m_ctxt->reset_clip();

	END_COM_METHOD(g_fact, IID_IVwGraphics);
}
Beispiel #15
0
/*----------------------------------------------------------------------------------------------
	Draw a polygon.
----------------------------------------------------------------------------------------------*/
HRESULT VwGraphicsCairo::DrawPolygon(int cVertices, POINT prgvpnt[])
{
#if DEBUG
	if (m_loggingFile != NULL)
	{
		fprintf(m_loggingFile, "DrawPolygon %p %d", this, cVertices);
		for (int i = 0; i < cVertices; i++)
		{
			fprintf(m_loggingFile, "%d %d", prgvpnt[i].x, prgvpnt[i].y);
		}

		fprintf(m_loggingFile, "\n");
		fflush(m_loggingFile);
	}
#endif
 BEGIN_COM_METHOD;
	// Trivially exit if the color is set to transparent
	if(m_backgroundColor.m_transparent) return S_OK;

	RECT rectBounds;
	rectBounds.left = prgvpnt[0].x;
	rectBounds.top = prgvpnt[0].y;
	rectBounds.right = rectBounds.left;
	rectBounds.bottom = rectBounds.top;

	// determine a bounding rectangle
	for (int i = 0; i < cVertices; i++)
	{
		int x = prgvpnt[i].x;
		int y = prgvpnt[i].y;
		if (x < rectBounds.left)
			rectBounds.left = x;
		if (x > rectBounds.right)
			rectBounds.right = x;
		if (y < rectBounds.top)
			rectBounds.top = y;
		if (y > rectBounds.bottom)
			rectBounds.bottom = y;
	}

	// check whether the bounding rectangle is visible
	RECT rectClip;
	MyGetClipRect(&rectClip);
	if(!rectIntersect(&rectClip, &rectBounds)) {
		return S_OK;
	}

	// Solid, in background color
	CheckDc();
	//Cairo::Context ctxt(m_cr);

	SetCairoColor(m_ctxt, &m_backgroundColor);
	m_ctxt->move_to(prgvpnt[cVertices - 1].x, prgvpnt[cVertices - 1].y);

	for ( int i = 0; i < cVertices; i++) {
	  m_ctxt->line_to(prgvpnt[i].x, prgvpnt[i].y);
	}

	m_ctxt->fill();

 END_COM_METHOD(g_fact, IID_IVwGraphics);
}
Beispiel #16
0
/*----------------------------------------------------------------------------------------------
	Draw a horizontal line that may be dotted or dashed.
	Consider first the behavior if *pdxStart is 0.
	If cdx is 0 or, equivalently, cdx is 1 and *prgdx is MAXINT, it draws a regular line
	line DrawLine from (xLeft, y) to (xRight, y).
	If there are multiple dx values, the line is dashed. A segment of length prgdx[0] is
	first drawn, then a gap of length prgdx[1] is left, then a segment of length prgdx[2],
	and so forth until the specified width is reached (the last segment, if drawn, is
	truncated to the specified length).
	If all values in prgdx are used up, we start again at prgdx[0]. An odd number of segments
	means that on and off alternate; thus, for example, a single width may be used to create
	a dashed line with equal gaps and dashes.
	The function then sets *pdxStart to the distance from xRight to the start of the last
	place where prgdx[0] was drawn (not where it was skipped, if there is an odd number).
	If *pdxStart is not initially zero, it gives a distance to skip through prgdx before
	starting. The normal use is to pass the value returned from a previous call, which
	can be used to draw several adjacent segments and have them seem continuous. You can also
	leave a gap in a dashed line by adding its width to pdxStart.
	(Another good way to use pdxStart is to set it to xLeft. This causes all patterns
	to be aligned, as if they were segments of one continuous pattern from the left margin.)
----------------------------------------------------------------------------------------------*/
HRESULT VwGraphicsCairo::DrawHorzLine(int xLeft, int xRight, int y, int dyHeight,
	int cdx, int * prgdx, int * pdxStart)
{
#if DEBUG
	if (m_loggingFile != NULL)
	{
		fprintf(m_loggingFile, "DrawHorzLine %p %d %d %d %d %d\n", this, xLeft, xRight, y, dyHeight, cdx);
		fflush(m_loggingFile);
	}
#endif
 BEGIN_COM_METHOD;
	// Trivially exit if the color is set to transparent
	if(m_foregroundColor.m_transparent) return S_OK;

	// See if the line to be rendered is out of bounds
	RECT rectClip;
	MyGetClipRect(&rectClip);

	if (y + dyHeight < rectClip.top || y - dyHeight > rectClip.bottom)
		return S_OK;

	CheckDc();
	//PenWrap xpwr(PS_SOLID, dyHeight, m_rgbForeColor, m_hdc);
	//Cairo::Context ctxt(m_cr);

	SetCairoColor(m_ctxt, &m_foregroundColor);
	m_ctxt->set_line_width(dyHeight);

	int * pdxLim = prgdx + cdx;
	// Compute total length of pattern
	int dxPattern = 0;
	int * pdx = prgdx;
	for (; pdx < pdxLim; pdx++)
		dxPattern += *pdx;
	int dxStartOffset = *pdxStart - (*pdxStart / dxPattern) * dxPattern;
	// Now do the drawing...
	int xRightSeg;
	pdx = prgdx;
	// The starting point stays here until we get to the first segment we actually
	// want to draw.
	m_ctxt->move_to(xLeft + .5, y + .5);
	bool fDraw = false;
	for (int x = xLeft - dxStartOffset; x < xRight; x = xRightSeg)
	{
		// Figure the end of the current segment, or the end of the whole line,
		// whichever is smaller.
		xRightSeg = std::min(x + *pdx, xRight);
		// Advance to next segment (circularly)
		if (++pdx >= pdxLim)
		{
			*pdxStart = xLeft;
			pdx = prgdx;
		}
		// Alternate drawing segments and moving past them
		fDraw = !fDraw;
		// If we're in the range we want to draw...
		if (xRightSeg > xLeft)
		{
			if (fDraw)
			{
				m_ctxt->line_to(xRightSeg + .5, y + .5);
				m_ctxt->stroke();
			}
			else
			{
				m_ctxt->move_to(xRightSeg, y + .5);
			}
		}

	}

 END_COM_METHOD(g_fact, IID_IVwGraphics);
}
Beispiel #17
0
// Unused in FieldWorks
HRESULT VwGraphicsCairo::DrawTextExt(int, int, int, const OLECHAR *, UINT, const RECT *, int *)
{
	BEGIN_COM_METHOD;
		ThrowHr(E_NOTIMPL);
	END_COM_METHOD(g_fact, IID_IVwGraphics);
}
/*----------------------------------------------------------------------------------------------
	Generate a sort key.
	If output pointer is null, just gives the needed length in *pcchKey.
	prgchSource: string sort key is to be generated for.
	cchSource: number of characters in prgchSource.
	cchMaxKey: space available in prgchKey.
	prgchKey: variable that will contain sort key.
	pcchKey: Number of characters in prgchKey.
	This method generates a sort key with full decompositions, it takes into consideration
	ignorable characters (fVariant).  It also establishes collating elements for expansions.
	ENHANCE: As of now, this method does not support contractions,  reordering
		  or direction.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP LgUnicodeCollater::SortKeyRgch(const OLECHAR * prgchSource, int cchSource,
			LgCollatingOptions colopt, int cchMaxKey, OLECHAR * prgchKey, int * pcchKey)
{
	BEGIN_COM_METHOD
	ChkComArrayArg(prgchSource, cchSource);
	ChkComArrayArg(prgchKey, cchMaxKey);
	if ((uint) colopt > (uint)fcoLim)
		ThrowInternalError(E_INVALIDARG, "Invalid collating options");
	ChkComArgPtr(pcchKey);

	// Create a pointer to LgCharacterPropertyEngine to access get_FullDecomp
	// ENHANCE JohnT: Should this be the default character property engine or a ws-specific one?
	if (!m_qcpe) //m_qcpe is initialized to null in constructor.
	{
		CheckHr(LgIcuCharPropEngine::GetUnicodeCharProps(&m_qcpe));
	}
	const OLECHAR * pchSource;	// points to next char to process, in prgchSource
	OLECHAR * pch;			// points to next char to process, in rgchDecomp
	OLECHAR * pchLim;
	#define MAXDECOMP 256
	OLECHAR rgchDecomp[MAXDECOMP];	// holds decompositions
	int cchDecomp;			// character count in decomposition

	OLECHAR * pchKey = prgchKey;

	const OLECHAR * pchLimSource = prgchSource + cchSource;
	CollatingElement * pcolel; // pointer to next collating element to do
	CollatingElement * pcolelLim; //will be assigned limit address in "multiple" loop
	int cchOut = 0;				// count of characters we have output
	bool fEven = true;      // true for first char of pair at levels 2 and 3

	int cchMaxOut = cchMaxKey;
	if (!cchMaxKey)
	{
		// Set a large limit so we don't report errors below, and ensure we don't output
		// anything, even if we were given a pointer to a real buffer
		cchMaxOut = INT_MAX;
		pchKey = NULL;
	}

	//Enter weight 1's into sort key
	for (pchSource = prgchSource; pchSource < pchLimSource; pchSource++)
	{
		ComBool fHasDecomp;
		// If there is no decomposition, this routine copies the one character we passed into
		// rgchDecomp.  Otherwise, it puts the decomposition there.
		CheckHr(m_qcpe->FullDecompRgch(*pchSource, MAXDECOMP, rgchDecomp, &cchDecomp,
						&fHasDecomp));
		pchLim = rgchDecomp + cchDecomp;
		for (pch = rgchDecomp; pch < pchLim; pch++)
		{
			int icolel = FindColel(*pch);
			if(icolel == -1)//an index of -1 means the weights are the standard (U, 0x20, 2)
			{
				cchOut++;
				if(cchOut > cchMaxOut)
					return E_FAIL;
				if(pchKey)
					*pchKey++ = *pch;
				continue;
			}
			pcolel = const_cast <CollatingElement *> (g_prgcolel + icolel);
			if((colopt & fcoDontIgnoreVariant) == 0)
			{
				if(pcolel->Variant())
					continue;
			}
			int ccolel = 1; // by default we have just one, the one we point at now
			if (pcolel->Multiple())
			{
				// there are several to process
				ccolel = pcolel->uWeight3; // before we change pcolel!
				// move pcolel to point at the list in the multiple array
				pcolel = const_cast<CollatingElement *>(g_prgcolelMultiple + pcolel->MultipleIndex());
			}
			pcolelLim = pcolel + ccolel;
			for(;pcolel < pcolelLim; pcolel++)
			{
				int nWeight;
				nWeight = pcolel->uWeight1;
				if (nWeight)
				{
					cchOut++;
					if (cchOut > cchMaxOut)
						return E_FAIL;
					if (pchKey)
						*pchKey++ = (OLECHAR) nWeight;
				}
			}
		}
	}

	//enter level separator into array
	if(pchKey)
	{
		*pchKey++ = 0x0001;
	}
	cchOut++;
	if(cchOut > cchMaxOut)
		return E_FAIL;

	//Packing weight 2's two per character.  If there is an odd number of weight 2's, the LSB of the
	//last character is padded with zero.
	for (pchSource = prgchSource; pchSource < pchLimSource; pchSource++)
	{
		ComBool fHasDecomp;
		// If there is no decomposition, this routine copies the one character we passed into
		// rgchDecomp.  Otherwise, it puts the decomposition there.
		CheckHr(m_qcpe->FullDecompRgch(*pchSource, MAXDECOMP, rgchDecomp, &cchDecomp,
												&fHasDecomp));
		pchLim = rgchDecomp + cchDecomp;
		for (pch = rgchDecomp; pch < pchLim; pch++)
		{
			int icolel = FindColel(*pch);
			if(icolel == -1)
			{
				if (!PackWeights(pchKey, cchOut, cchMaxOut, 0x20, fEven))
					return E_FAIL;
				continue;
			}
			pcolel = const_cast<CollatingElement *>(g_prgcolel + icolel);
			if((colopt & fcoDontIgnoreVariant) == 0)
			{
				if(pcolel->Variant())
					continue;
			}

			int ccolel = 1; // by default we have just one, the one we point at now
			if (pcolel->Multiple())
			{
				// there are several to process
				ccolel = pcolel->uWeight3; // before we change pcolel!
				// move pcolel to point at the list in the multiple array
				pcolel =const_cast<CollatingElement *>(g_prgcolelMultiple + pcolel->MultipleIndex());
			}
			pcolelLim = pcolel + ccolel;
			for(;pcolel < pcolelLim; pcolel++)
			{
				int nWeight;
				nWeight = pcolel->uWeight2;
				if (nWeight)
				{
					if (!PackWeights(pchKey, cchOut, cchMaxOut, nWeight, fEven))
						return E_FAIL;
				}
			}
		}
	}
	//uWeight3 is normally a case indicator.  If fcoIgnoreCase is set, case is ignored,
	//therefore uWeight3 is ignored in the sort key.
	if(colopt & fcoIgnoreCase)
	{
		*pcchKey = cchOut;
		return S_OK;
	}
	//enter level separator into array
	if(pchKey)
	{
		*pchKey++ = 0x0001;
	}
	cchOut++;
	if(cchOut > cchMaxOut)
		return E_FAIL;
	fEven = true;

	//Treating weight 3's like weight 2's
	for (pchSource = prgchSource; pchSource < pchLimSource; pchSource++)
	{
		ComBool fHasDecomp;
		// If there is no decomposition, this routine copies the one character we passed into
		// rgchDecomp.  Otherwise, it puts the decomposition there.
		CheckHr(m_qcpe->FullDecompRgch(*pchSource, MAXDECOMP, rgchDecomp, &cchDecomp,
												&fHasDecomp));
		pchLim = rgchDecomp + cchDecomp;
		for (pch = rgchDecomp; pch < pchLim; pch++)
		{
			int icolel = FindColel(*pch);
			if(icolel == -1) //use the standard weights
			{
				if (!PackWeights(pchKey, cchOut, cchMaxOut, 0x02, fEven))
					return E_FAIL;
				continue;
			}
			pcolel = const_cast<CollatingElement *>(g_prgcolel + icolel);
			if((colopt & fcoDontIgnoreVariant) == 0)
			{
				if(pcolel->Variant())
					continue;
			}

			int ccolel = 1; // by default we have just one, the one we point at now
			if (pcolel->Multiple())
			{
				// there are several to process
				ccolel = pcolel->uWeight3; // before we change pcolel!
				// move pcolel to point at the list in the multiple array
				pcolel = const_cast<CollatingElement *>(g_prgcolelMultiple + pcolel->MultipleIndex());
			}
			pcolelLim = pcolel + ccolel;
			for(;pcolel < pcolelLim; pcolel++)
			{
				int nWeight;
				nWeight = pcolel->uWeight3;
				if (nWeight)
				{
					if (!PackWeights(pchKey, cchOut, cchMaxOut, nWeight, fEven))
						return E_FAIL;
				}
			}
		}
	}
	if(pchKey)//level separator
	{
		*pchKey++ = 0x0001;
	}
	cchOut++;
	if(cchOut > cchMaxOut)
		return E_FAIL;

	//add the actual characters to the sort key
	for (pchSource = prgchSource; pchSource < pchLimSource; pchSource++)
	{
		cchOut++;
		if (cchOut > cchMaxOut)
			return E_FAIL;
		if (pchKey)
			*pchKey++ = *pchSource;
	}
	*pcchKey = cchOut;
	END_COM_METHOD(g_fact, IID_ILgCollatingEngine);
}
Beispiel #19
0
HRESULT VwGraphicsCairo::GetFontEmSquare(int * pxyFontEmSquare)
{
 BEGIN_COM_METHOD;
	ThrowHr(E_NOTIMPL);
 END_COM_METHOD(g_fact, IID_IVwGraphics);
}
Beispiel #20
0
/*----------------------------------------------------------------------------------------------
	Get the status of an open IStream (file).
	If the caller uses the value STATFLAG_DEFAULT for grfStatFlag then the user must free
	the memory which this method allocates for the file name at pstatstg->pwcsName.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP FileStream::Stat(STATSTG * pstatstg, DWORD grfStatFlag)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(pstatstg);

#if WIN32
		if (m_hfile == NULL)
		ThrowHr(WarnHr(E_UNEXPECTED));

	BY_HANDLE_FILE_INFORMATION bhfi;

	if (!GetFileInformationByHandle(m_hfile, &bhfi))
	{
		// The caller does not have sufficient permissions for accessing statistics for this
		// stream object.
		ThrowHr(WarnHr(STG_E_ACCESSDENIED));
	}
#else
	if (m_file < 0)
		ThrowHr(WarnHr(E_UNEXPECTED));

	struct stat filestats;

	//errno = 0;
	if (fstat(m_file, &filestats)) {
		//int err = errno;
		//std::cerr << "Error number " << err << " - " << strerror(err) << '\n';
		ThrowHr(WarnHr(STG_E_ACCESSDENIED));
	}
#endif

	pstatstg->pwcsName = NULL;

	switch (grfStatFlag)
	{
		case STATFLAG_DEFAULT:
		{
			// Requests that the statistics include the pwcsName member of the STATSTG structure.
			StrUniBufPath stubpName = m_staPath.Chars();

			pstatstg->pwcsName = (wchar *)CoTaskMemAlloc(
				(stubpName.Length() + 1) * isizeof(wchar));
			if (NULL == pstatstg->pwcsName)
				ThrowHr(WarnHr(STG_E_INSUFFICIENTMEMORY));

			memcpy(pstatstg->pwcsName, stubpName.Chars(), stubpName.Length() * isizeof(wchar));
			pstatstg->pwcsName[stubpName.Length()] = 0;
		}
		// Fall Through.

		case STATFLAG_NONAME:
			// Requests that the statistics not include the pwcsName member of the STATSTG
			// structure. If the name is omitted, there is no need for the Stat methods to allocate
			// and free memory for the string value for the name and the method can save an Alloc
			// and the caller a Free operation.
			pstatstg->type = STGTY_STREAM;
#if WIN32
			pstatstg->cbSize.HighPart = bhfi.nFileSizeHigh;
			pstatstg->cbSize.LowPart = bhfi.nFileSizeLow;
			pstatstg->mtime = bhfi.ftLastWriteTime;
			pstatstg->ctime = bhfi.ftCreationTime;
			pstatstg->atime = bhfi.ftLastAccessTime;
#else
			pstatstg->cbSize.QuadPart = filestats.st_size;
			time_tToFiletime(filestats.st_mtime, &(pstatstg->mtime));
			time_tToFiletime(filestats.st_ctime, &(pstatstg->ctime));
			time_tToFiletime(filestats.st_atime, &(pstatstg->atime));
#endif
			pstatstg->grfMode = m_grfstgm;
			pstatstg->grfLocksSupported = 0;
			pstatstg->clsid = CLSID_NULL;
			pstatstg->grfStateBits = 0;
			return S_OK;

	default:
		ThrowHr(WarnHr(STG_E_INVALIDFLAG));

	}
	END_COM_METHOD(g_fact, IID_IStream);
}
Beispiel #21
0
HRESULT VwGraphicsCairo::GetFontData(int nTableId, int * pcbTableSz, BSTR * pbstrTableData)
{
 BEGIN_COM_METHOD;
	ThrowHr(E_NOTIMPL);
 END_COM_METHOD(g_fact, IID_IVwGraphics);
}
Beispiel #22
0
// We haven't figured a sensible default action for boxes.
STDMETHODIMP VwAccessRoot::accDoDefaultAction(VARIANT varID)
{
	BEGIN_COM_METHOD;
	return E_NOTIMPL;
	END_COM_METHOD(g_fact, IID_IAccessible);
}
Beispiel #23
0
/*----------------------------------------------------------------------------------------------
	Initialize the engine. This must be called before any oher methods of the interface.
	How the data is used is implementation dependent. The UniscribeRenderer does not
	use it at all. The Graphite renderer uses font name, bold, and italic settings
	to initialize itself with the proper font tables. For Graphite, bstrData contains
	(optionally) default settings for any font features.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP FwGrEngine::InitRenderer(IVwGraphics * pvg, BSTR bstrData)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(pvg);
	ChkComBstrArgN(bstrData);

	// Make sure we can create a Graphite font.
	try
	{
		HDC hdc;
		IVwGraphicsWin32Ptr qvg32;
		CheckHr(pvg->QueryInterface(IID_IVwGraphicsWin32, (void **)&qvg32));
		CheckHr(qvg32->GetDeviceContext(&hdc));
		//FwGrGraphics gg(pvg);
		//gg.GetDeviceContext(&hdc);

		// Remember the font face name.
		LgCharRenderProps chrp;
		pvg->get_FontCharProperties(&chrp);
		memcpy(m_szFaceName, chrp.szFaceName, isizeof(m_szFaceName));

		// Make sure there is a cached font object.
		WinFont * pfontOld = m_pfont;
		m_pfont = new FwWinFont(hdc);
		m_fontSize = gr::GrEngine::RoundFloat(m_pfont->ascent() + m_pfont->descent());

		// Instead a code below, a FontException will be thrown.
		//FontErrorCode ferr = m_pfont->isValidForGraphite();
		//HRESULT hr;
		//std::wstring stuMsgBogus = FontLoadErrorDescription(ferr, 0, 0, &hr);

		// Delete this after creating the new one, so that if there happens to be only one
		// the font cache doesn't get destroyed and recreated!
		delete pfontOld;

		// Store the default feature values, which may be different from the font.
		m_cfeatWDefaults = ParseFeatureString((gr::utf16*)bstrData, BstrLen(bstrData), m_rgfsetDefaults);

		// This is kind of a kludge. The m_pfont may be kind of temporary, because the caller may delete
		// the graphics object and the DC. So call something to get set the FontFace set up while the
		// Font is still valid, so we can at least have access to some basic information from the engine.
		// Ideally we should probably create the WinFont with a private device context.
		int nTemp;
		this->get_ScriptDirection(&nTemp);

		return S_OK;
	}
	catch (FontException & fexptn)
	{
		// There was an error in initializing the font.
		FontErrorCode ferr = fexptn.errorCode;
		//int nVersion = fexptn.version;
		//int nSubVersion = fexptn.subVersion;
		HRESULT hr;
		std::wstring stuMsgBogus = FontLoadErrorDescription(ferr, 0, 0, &hr);
		return hr;
	}
	catch (...)
	{
		return kresUnexpected;
	}

	END_COM_METHOD(g_fact, IID_IRenderEngine);
}