Example #1
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#EndUndoTask}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::EndUndoTask()
{
	BEGIN_COM_METHOD;

	if (m_fUndoOrRedoInProgress)
		return S_OK;

	if (m_nDepth <= 0)
	{
		return E_UNEXPECTED;
	}
	else
	{
		--m_nDepth;
		if (m_nDepth == 0)
		{
			// cleans no-op undo tasks
			EndOuterUndoTask();
		}
	}

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta;
	sta.Format("EndUndoTask:");
	sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
		m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
	::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Example #2
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#AddAction}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::AddAction(IUndoAction * puact)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(puact);

	if (m_fUndoOrRedoInProgress)
		return S_OK;

	if(m_fCreateMarkIfNeeded && m_viMarks.Size() == 0)
	{
		// m_fCreateMarkIfNeeded probably didn't get reset (TE-4856)
		Assert(m_nDepth <= 0 || m_fStartedNext);

		int hmark;
		CheckHr(Mark(&hmark));
		Assert(hmark == 1); // Should only have 1 mark!
	}
	ContinueUndoTask();
	AddActionAux(puact);
	EndUndoTask();

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta;
	sta.Format("AddAction:");
	sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
		m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
	::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Example #3
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#BreakUndoTask}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::BreakUndoTask(BSTR bstrUndo, BSTR bstrRedo)
{
	BEGIN_COM_METHOD;
	ChkComBstrArg(bstrUndo);
	ChkComBstrArg(bstrRedo);

	if (m_fUndoOrRedoInProgress)
		return S_OK;

	int nSaveDepth = m_nDepth;

	EndOuterUndoTask();

	BeginUndoTask(bstrUndo, bstrRedo);

	m_nDepth = nSaveDepth;

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta;
	sta.Format("BreakUndoTask:");
	sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
		m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
	::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Example #4
0
void MacroBase::WriteUni(StrUni param)
{
	if (!m_outfile.is_open())	return;
	// All unicode strings are first transformed into ansi strings and then written to file as
	// an ansi
	StrAnsi staAnsi = param.Chars();
	m_outfile << staAnsi.Chars() << "_" << " ";
}
Example #5
0
/*----------------------------------------------------------------------------------------------
	Callback for DebugProcs
----------------------------------------------------------------------------------------------*/
void __stdcall DebugReport::ReportHandler(int reportType, char * szMsg)
{
	if (KernelGlobals::s_qReportSink)
	{
		StrAnsi sta = szMsg;
		SmartBstr bstr;
		sta.GetBstr(&bstr);
		KernelGlobals::s_qReportSink->Report((CrtReportType)reportType, bstr);
	}
}
Example #6
0
StrUni MacroBase::ReadUni()
{
	if (!m_infile.is_open())	return NULL;

	// Both Unicode and Ansi are written as Ansi to file. Convert to Unicode after retrieiving
	// ansi interpretation
	StrAnsi ans = ReadAnsi();
	StrUni stuUni = ans.Chars();
	return stuUni;
}
Example #7
0
	void WriteToStream(std::ostream & strmOut, bool fNoPath)
	{
		int ich = m_staFile.Length();
		// Strip off the file path.
		while (fNoPath && ich > 0 && m_staFile[ich - 1] != '\\')
			ich--;

		StrAnsi staStripped = m_staFile.Right(m_staFile.Length() - ich);
		strmOut << staStripped.Chars() << "(" << m_nLineOrig << ")";
	}
Example #8
0
void __stdcall DebugReport::AssertProcWrapper(const char * pszExp, const char * pszFile, int nLine,
		HMODULE)
{
	if (KernelGlobals::s_qReportSink)
	{
		StrAnsi sta = pszExp;
		SmartBstr exp;
		sta.GetBstr(&exp);
		SmartBstr file;
		sta = pszFile;
		sta.GetBstr(&file);
		KernelGlobals::s_qReportSink->AssertProc(exp, file, nLine);
	}
}
Example #9
0
void MacroBase::AddTstFunc(StrAnsi name, int ID)
{
	// If no valid file object
	if (!m_outfile.is_open())	return;
	// name is just for visual reference, ID actually identifies the function
	m_outfile << name.Chars() << " " << ID << " ";
}
Example #10
0
/*----------------------------------------------------------------------------------------------
	This function can be installed to translate windows exceptions into C++ internal error
	exceptions. Only the main program should do this. To install, just call
	_set_se_translator(TransFuncDump);.

	This is of dubious value because if the error occurs inside a COM component, the Throwable
	exception will not be recognized, and exception handling will just catch "..." and generate
	a new stack dump. However, installing it at least achieves better stack dumps for errors
	in code linked into the main program.

	We could install at the start of every COM interface method, and restore upon return.
	However this would be computationally expensive. Consider doing this in a particular method
	if you are trying to track down a problem in that method.

	We could have each module install this function on being loaded, and check whether the
	error occurs in its own code, and if not call the previous error handler. But this
	only works reliably if modules are never unloaded, or only in reverse order of loading,
	which I don't see how to ensure.

	We could also get really fancy, with some sort of central manager which knows which error
	translator to use for each module. This has not seemed worthwhile to me so far.
----------------------------------------------------------------------------------------------*/
void TransFuncDump( unsigned int u, EXCEPTION_POINTERS * pExp)
{
#ifdef WIN32
	HANDLE hThread;
	DWORD dwCode = pExp->ExceptionRecord->ExceptionCode;
	StrUni stuException = ConvertException(dwCode);
	DuplicateHandle( GetCurrentProcess(), GetCurrentThread(),
		GetCurrentProcess(), &hThread, 0, false, DUPLICATE_SAME_ACCESS );
	StrAnsi staMsg;
	staMsg.Format("Stack Dump for exception: %S (%d)", stuException.Chars(), dwCode);
	StackDumper::ShowStack( hThread, *(pExp->ContextRecord), const_cast<char *>(staMsg.Chars()) );
	CloseHandle( hThread );
	StrUni stuMsg(staMsg.Chars());
	throw ThrowableSd(E_UNEXPECTED, stuMsg.Chars(), 0, StackDumper::GetDump());
#endif
}
Example #11
0
/*----------------------------------------------------------------------------------------------
	This method checks for duplicates in list names.  If the given name exists then return true.

	@param pszName name to check to see if it exists.
	@return True if name already exists.
----------------------------------------------------------------------------------------------*/
bool ListsPropDlg::CheckName(const achar * pszName)
{
	AfMainWnd * pafw = MainWindow();
	AssertPtr(pafw);
	AfLpInfo * plpi = pafw->GetLpInfo();
	AssertPtr(plpi);
	Vector<HVO> & vhvo = plpi->GetPsslIds();

	AfDbInfoPtr qdbi = plpi->GetDbInfo();
	AssertPtr(qdbi);
	IOleDbEncapPtr qode;
	qdbi->GetDbAccess(&qode);

	StrAnsi sta;
	int i;
	StrUni stuIds;
	int cv = vhvo.Size();
	Assert(cv);

	ComBool fIsNull;
	ComBool fMoreRows;
	ULONG cbSpaceTaken;
	IOleDbCommandPtr qodc;

	const int kcchBuffer = MAX_PATH;
	OLECHAR rgchName[kcchBuffer];
	HVO hvo;
	StrUni stu;
	for (i = 0; i < cv; ++i)
	{
		hvo = vhvo[i];
		stu.Format(L"exec GetOrderedMultiTxt '%d', %d",
			hvo, kflidCmMajorObject_Name);
		CheckHr(qode->CreateCommand(&qodc));
		CheckHr(qodc->ExecCommand(stu.Bstr(), knSqlStmtStoredProcedure));
		CheckHr(qodc->GetRowset(0));
		CheckHr(qodc->NextRow(&fMoreRows));
		Assert(fMoreRows); // This proc should always return something.
		CheckHr(qodc->GetColValue(1, reinterpret_cast <BYTE *>(rgchName),
			kcchBuffer * isizeof(OLECHAR), &cbSpaceTaken, &fIsNull, 2));
		sta = rgchName;
		if (hvo != m_hvoObj && sta.Equals(pszName))
			return false;
	}
	return true;
}
Example #12
0
void MacroBase::WriteAnsi(StrAnsi param)
{
	if (!m_outfile.is_open())	return;
	// All strings are terminated by the ALT-255 character. It is doubtful the user will type this
	// character and so terminate the actual log prematurely. Using this obscure character
	// safeguards against that
	m_outfile << param.Chars() << "_" << " ";
}
Example #13
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#Commit}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::Commit()
{
	BEGIN_COM_METHOD;

	HRESULT hr = E_FAIL;
	HRESULT hrFinal = S_OK;
	if (m_vquact.Size())
	{
		// JohnT 10/22/01: this can happen, typically if the only thing in the sequence is a
		// position mark. We could try to check for that but it doesn't seem worth it. Nothing
		// actually depends on having at least one sequence start here.
		//Assert(m_viSeqStart.Size() > 0);

		// Commit all actions.
		for (int i = 0; i <= m_iuactCurr; i++)
		{
			// If for some reason, we cannot commit an action that is part of a sequence, it's
			// just too bad.  We can't undo a commited action so we might as well just amble on
			// and hope for the best.
			IgnoreHr(hr = m_vquact[i]->Commit());
			if (FAILED(hr))
			{
				hrFinal = hr;
			}
		}

		EmptyStack();
	}

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta;
	sta.Format("Commit:");
	sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
		m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
	::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER

	return hrFinal;

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Example #14
0
bool MacroBase::SetMacroOut(StrAnsi staMcr)
{
	// Same functionality as SetMacroIn, except used for writing to files
	if (!strcmp(staMcr.Chars(),""))
		return false;

	m_stafileout = staMcr;

	if (m_outfile.is_open())
		m_outfile.close();
	m_outfile.open(m_stafileout.Chars(), ios_base::out);
	return m_outfile.is_open();
}
Example #15
0
/*----------------------------------------------------------------------------------------------
	Save the text to a file.
----------------------------------------------------------------------------------------------*/
bool WpDa::SaveToFile(StrAnsi staFileName)
{
	IStreamPtr qstrm;
	FileStream::Create(staFileName.Chars(), kfstgmWrite | kfstgmCreate, &qstrm);
//	FileStream::Create("c:\\output.txt", kfstgmWrite | kfstgmCreate, &qstrm);

	ULONG cbWritten;
	//	Write byte-order mark.
	byte b = 0xFF;
	CheckHr(qstrm->Write(&b, 1, &cbWritten));
	b = 0xFE;
	CheckHr(qstrm->Write(&b, 1, &cbWritten));

	int ctss;
	CheckHr(get_VecSize(1, kflidStText_Paragraphs, &ctss));

	for (int itss = 0; itss < ctss; itss++)
	{
		ITsStringPtr qtss;
		CheckHr(get_StringProp(itss + 2, kflidStTxtPara_Contents, &qtss));
		BSTR bstr = NULL;
		int cchw;
		CheckHr(qtss->get_Length(&cchw));
		qtss->GetChars(0, cchw, &bstr);

		//	Write the string to the file.
		if (cchw > 0)
		{
			Assert(bstr);
			CheckHr(qstrm->Write(bstr, cchw * isizeof(wchar), &cbWritten));
		}

		if (itss < ctss - 1)
		{
			//	CRLF--little-endian
			b = 13;
			CheckHr(qstrm->Write(&b, 1, &cbWritten));
			b = 0;
			CheckHr(qstrm->Write(&b, 1, &cbWritten));
			b = 10;
			CheckHr(qstrm->Write(&b, 1, &cbWritten));
			b = 0;
			CheckHr(qstrm->Write(&b, 1, &cbWritten));
		}

		ReleaseBstr(bstr);
	}

	return true;
}
Example #16
0
/*----------------------------------------------------------------------------------------------
	Inserts a mark and returns a handle that can be used later to discard all Undo items
	back to the mark. Handle will never be zero.
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::Mark(int * phMark)
{
	BEGIN_COM_METHOD;
	ChkComOutPtr(phMark);

	// It's only valid to place a mark while no action sequence is in progress.
	if (m_nDepth > 0 && !m_fStartedNext)
		ThrowHr(WarnHr(E_UNEXPECTED));

	m_fCanContinueTask = false; // Can't merge another action into the current task.

	// For now, we are only supporting one mark at a time.
	Assert(m_viMarks.Size() == 0);

	m_viMarks.Push(m_iuactCurr + 1); // index of next action to be added
	*phMark = m_viMarks.Size();

	//StrAnsi sta;
	//sta.Format("mark location: %d\n", m_iuactCurr + 1);
	//::OutputDebugStringA(sta.Chars());

	//::OutputDebugStringA("MARK\n");
	//StrAnsi sta;
	//sta.Format("depth = %d; m_fStartedNext = %d; action %d of %d; seq %d of %d; marks %d%n",
	//	m_nDepth, m_fStartedNext, m_iuactCurr, m_vquact.Size(), m_iCurrSeq, m_viSeqStart.Size(), m_viMarks.Size());
	//::OutputDebugStringA(sta.Chars());

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta;
	sta.Format("Mark:%d", *phMark);
	sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
		m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
	::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Example #17
0
bool MacroBase::SetMacroIn(StrAnsi staMcr)
{
	// Open file "staMcr" for reading unless no name given
	if (!strcmp(staMcr.Chars(), ""))
		return false;

	// Assign file to open to class member
	m_stafilein = staMcr;

	// If the file is already open, close it before opening it again
	if (m_infile.is_open())
		m_infile.close();
	// Now open the file
	m_infile.open(m_stafilein.Chars(), ios_base::in);
	return m_infile.is_open();
}
Example #18
0
/*----------------------------------------------------------------------------------------------
	Set the keyboard the Windows API way
----------------------------------------------------------------------------------------------*/
void SetKeyboard_Windows(int lcid)
{
#ifdef Tracing_KeybdSelection
	StrAnsi sta;
	sta.Format("LgTextServices::SetKeyboard(%d) [not Keyman]%n", lcid);
	::OutputDebugStringA(sta.Chars());
#endif
	int nLangId = LANGIDFROMLCID(lcid);
	HKL hkl = (HKL)nLangId;
	if (hkl == 0)
		hkl = (HKL)::GetSystemDefaultLangID();

	// If we're not activating a Keyman keyboard, activate the appropriate OS IM.
	// Microsoft says we should only do this if we were not able to do it using
	// ActivateLanguageProfile (private communication to JohnT).
#ifdef Tracing_KeybdSelection
	sta.Format("LgTextServices::SetKeyboard(%d) - "
		"hkl = %x, ::GetKeyboardLayout() = %x%n",
		lcid, hkl, ::GetKeyboardLayout(0));
	::OutputDebugStringA(sta.Chars());
#endif
	if (hkl != ::GetKeyboardLayout(0))
	{
		// We need to work out whether we're using at least W2000, because
		// KLF_SETFORPROCESS is not supported before that.
		UINT flags = 0;
		if (IsWin2kOrHigher())
		{
			//Windows 2000 or better, we can use KLF_SETFORPROCESS.
			flags = KLF_SETFORPROCESS;
		}
#ifdef Tracing_KeybdSelection
		StrAnsi sta;
		sta.Format("LgTextServices::SetKeyboard(%d) - "
			"::ActivateKeyboardLayout(%x, %x) [nLangId = %d]\n",
			lcid, hkl, flags, nLangId);
		::OutputDebugStringA(sta.Chars());
#endif
		::ActivateKeyboardLayout(hkl, flags);
		Assert(sizeof(int) >= sizeof(hkl));
	}
}
Example #19
0
void ViewTest2::WrapOnExtendedKey(int _chw, VwShiftStatus _ss)
{
	StrAnsi staExt;
	switch (_ss)
	{
		case kfssNone:
			staExt.Append("None");
			break;
		case kgrfssShiftControl:
			staExt.Append("Shift + Control");
			break;
		case kfssShift:
			staExt.Append("Shift ");
			break;
		case kfssControl:
			staExt.Append("Control ");
			break;
		default:
			staExt.Append("Undefined state");
	}
	m_psts->OutputFormat("  FUNCTION: OnExtendedKey(%d, %s)\n", _chw, staExt.Chars());
	CheckHr(m_qrootb->OnExtendedKey(_chw, _ss));
}
Example #20
0
/*----------------------------------------------------------------------------------------------
	The edit box changed. We need to validate what was done.
	@param pedit
	@return
----------------------------------------------------------------------------------------------*/
bool AfDeFeCliRef::OnChange(AfDeFeEdBoxBut::DeEdit * pedit)
{
	if (m_fRecurse)
	{
		m_fRecurse = false;
		return true;
	}
	if (!m_hwnd)
		return true; // We aren't completely set up yet, so ignore this.

	// Get the characters from the edit box.
	ITsStringPtr qtss;
	::SendMessage(m_hwnd, FW_EM_GETTEXT, 0, (LPARAM)&qtss);

	int ichMin;
	int ichLim;
	::SendMessage(m_hwnd, EM_GETSEL, (WPARAM)&ichMin, (LPARAM)&ichLim);

	int cchTyped; // number of characters in the typed string
	// JohnT: use a StrUni rather than an StrUniBuf, because some user sometime will accidentally
	// paste something long here, and performance here is not critical.
	StrUni stuTyped;
	OLECHAR * pchBuf;
	qtss->get_Length(&cchTyped);

	if (cchTyped > kcchPossNameAbbrMax)
	{
		if (ichMin == cchTyped)
			ichMin = kcchPossNameAbbrMax;
		if (ichLim == cchTyped)
			ichLim = kcchPossNameAbbrMax;
		cchTyped = kcchPossNameAbbrMax;
		m_fRecurse = true; // Stop the recursion caused by the next instruction.
		// Note: This recursively calls this procedure.
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)qtss.Ptr());
		::SendMessage(m_hwnd, EM_SETSEL, ichMin, ichMin);
	}

	stuTyped.SetSize(cchTyped, &pchBuf);
	qtss->FetchChars(0, cchTyped, pchBuf);

#ifdef DEBUG_THIS_FILE
	StrAnsi sta;
	sta.Format("AfDeFeCliRef::OnChange:  pedit->m_ch=%d; ichMin=%d; ichLim=%d; pedit->m_cchMatched=%d; cchTyped=%d.\n",
										 pedit->m_ch,    ichMin,    ichLim,    pedit->m_cchMatched,    cchTyped);
	OutputDebugString(sta.Chars());
#endif

	bool fTypeAhead = false; // allow type ahead only when adding characters at end of current item
							// or backspacing at end of current item.
	bool fNeedCompare;
	if (pedit->m_ch == 0) // (see kcidEditPaste special code)
	{
		// If we pasted something, force a compare.
		fNeedCompare = true;
	}
	else if (ichMin == pedit->m_cchMatched + 1 && pedit->m_ch != VK_BACK && pedit->m_ch != VK_DELETE)
	{
		// Need to compare if we typed a character and we are one greater than last match.
		fNeedCompare = true;
		if (cchTyped == ichMin)
		{
			fTypeAhead = true;
#ifdef DEBUG_THIS_FILE
			sta.Format("OnChange: 1 - setting fTypeAhead to true.\n");
			OutputDebugString(sta.Chars());
#endif
		}
	}
	else if (ichMin > pedit->m_cchMatched)
	{
		// Don't compare any other time we are past the last match.
		fNeedCompare = false;
	}
//	else if ((cchTyped == ichMin) && (ichMin == ichLim) && (pedit->m_ch != kscDelForward))
	else if ((cchTyped == ichMin) && (ichMin == ichLim) && (pedit->m_ch != 46))
	{
		// Need to compare if we typed a character and we are at the end of the item
		// Need to compare if we delete the last character in the non-type-ahead string
		fNeedCompare = true;
		fTypeAhead = true;
#ifdef DEBUG_THIS_FILE
		sta.Format("OnChange:  kscDelForward=%d.\n");
		OutputDebugString(sta.Chars());
		sta.Format("OnChange: 2 - setting fTypeAhead to true.\n");
		OutputDebugString(sta.Chars());
#endif
	}
	else
	{
		// Always compare if we are not past the last match.
		fNeedCompare = true;
	}

	int cch;

	// Since the edit box deletes the selection on backspace, we need to use
	// some extra logic to make backspace actually move the selection back.
	if (pedit->m_cchMatched && pedit->m_ch == VK_BACK && m_pss)
	{
		// If we had a previous match and we got a backspace, we always decrement the matched
		// characters and start looking at that point.
		cch = --pedit->m_cchMatched;
	}
	else
	{
		// Otherwise we start looking at the cursor location.
		cch = ichMin;
	}

	AfLpInfo * plpi = GetLpInfo();
	AssertPtr(plpi);

	PossListInfoPtr qpli;
	plpi->LoadPossList(m_hvoPssl, m_wsMagic, &qpli);
	AssertPtr(qpli);

	PossItemInfo * ppii = NULL;
	ComBool fExactMatch = false;

	fNeedCompare = true;

	if (cchTyped == 0)
	{
		// If nothing to match, get the first item in the possibility list. If we are
		// already at that item, remove the item. If we are already cleared, do nothing.
		if (!m_pss)
			return true;
		// If everything is highlighted, we want to clear the item with Del or Bsp.
		// But when we are backspacing, if there is only one character left and we backspace
		// over that, we want to switch to the first item in the list.
		ppii = qpli->GetPssFromIndex(0);
		if (ichMin != 1)
		{
			m_pss = 0;
			m_qtss = NULL;
			pedit->m_cchMatched = 0; // Keep cursor at beginning of item.
			m_fRecurse = true;
			::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)m_qtss.Ptr());
			return true;
		}
	}
	else if (fNeedCompare)
	{
		// Try to find an item that matches what the user typed in the possibility list.
		StrUni stuMatch(stuTyped);
/////		stuMatch.Replace(cch, stuMatch.Length(), L"");// Delete chars to right of cursor.
		Locale loc = GetLpInfo()->GetLocale(m_ws);
		if (m_fHier)
		{
			ppii = qpli->FindPssHier(stuMatch.Chars(), loc, m_pnt, fExactMatch);
		}
		else
		{
			ppii = qpli->FindPss(stuMatch.Chars(), loc, m_pnt);
		}

		if (ppii)
		{
			// found a match that starts with stuTyped
			int ipssTemp;

			// TODO TimP:  check for hierarchy.  If stuTyped contains hierarchy,

			// Was the match exact (rather than just starting with stuTyped) ?
			if (fExactMatch) // May have matched in the FindPssHier() call above.
			{
#ifdef DEBUG_THIS_FILE
				sta.Format("OnChange:  Exact match (hier).\n");
				OutputDebugString(sta.Chars());
#endif
			}
			else
			{
				fExactMatch = ! qpli->PossUniqueName(-1, stuTyped, m_pnt, ipssTemp);
				if (fExactMatch)
				{
#ifdef DEBUG_THIS_FILE
					sta.Format("OnChange:  Exact match.\n");
					OutputDebugString(sta.Chars());
#endif
					// in case FindPss() above matches "ABC" but "AB" is also in list.
					ppii = qpli->GetPssFromIndex(ipssTemp);
				}
				else
				{
#ifdef DEBUG_THIS_FILE
					sta.Format("OnChange:  Not exact match.\n");
					OutputDebugString(sta.Chars());
#endif
				}
			}
		}
	}
	else
		ppii = NULL;

	StrUni stuFound;
	int ws = m_ws;
	if (ppii && (fTypeAhead || fExactMatch))
	{
		// If found, process the new item.
		int pss = ppii->GetPssId();
		m_pss = pss;
		if (m_fHier)
			ppii->GetHierName(qpli, stuFound, m_pnt);
		else
			ppii->GetName(stuFound, m_pnt);
		ws = ppii->GetWs();

		// If the last character was a delimiter, we need to set cch accordingly.
		if (m_fHier && (stuTyped.Length() > 0) && (pedit->m_ch != VK_BACK) &&
			(stuTyped.GetAt(stuTyped.Length() - 1) == kchHierDelim))
		{
			// Need to set cch to the position of the last delimiter.
			cch = stuFound.FindCh(kchHierDelim, cch - 1) + 1;
		}

		pedit->m_cchMatched = cch;
	}
	else
	{
		// Something illegal was typed. Assume they are adding a new item.
		if (pedit->m_cchMatched + 1 == cch && pedit->m_ch != VK_BACK)
			::MessageBeep(MB_ICONEXCLAMATION); // Beep on the first unmatched character.
		// Underline the string with a red squiggly.
		ITsIncStrBldrPtr qtisb;
		qtisb.CreateInstance(CLSID_TsIncStrBldr);
		qtisb->SetIntPropValues(ktptWs, ktpvDefault, m_ws);
		CheckHr(qtisb->SetIntPropValues(ktptUnderColor, ktpvDefault, kclrRed));
		CheckHr(qtisb->SetIntPropValues(ktptUnderline, ktpvEnum, kuntSquiggle));
		qtisb->AppendRgch(stuTyped.Chars(), stuTyped.Length());
		qtisb->GetString(&m_qtss);
		m_fRecurse = true; // Stop the recursion caused by the next instruction.
		// Note: This recursively calls this procedure.
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)m_qtss.Ptr());
		::SendMessage(m_hwnd, EM_SETSEL, ichMin, ichMin);
		m_pss = 0; // We no longer have a matched HVO.
		return true;
	}

	// Update the edit box text and selection.
	ITsStrFactoryPtr qtsf;
	qtsf.CreateInstance(CLSID_TsStrFactory);
	qtsf->MakeStringRgch(stuFound.Chars(), stuFound.Length(), ws, &qtss);
	m_qtss = qtss;

#ifdef DEBUG_THIS_FILE
	sta.Format("AfDeFeCliRef::OnChange:  pedit->m_cchMatched=%d; stuFound.Length()=%d; ichMin=%d; ichLim=%d.\n",
										 pedit->m_cchMatched,    stuFound.Length(),    ichMin,    ichLim);
	OutputDebugString(sta.Chars());
#endif

	m_fRecurse = true; // Shortcut the recursion caused by the next instruction.
	if (fTypeAhead)
	{
		// Note: This recursively calls this procedure.
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)qtss.Ptr());
		::SendMessage(m_hwnd, EM_SETSEL, pedit->m_cchMatched, stuFound.Length());
#ifdef DEBUG_THIS_FILE
	sta.Format("AfDeFeCliRef::OnChange:  type ahead.\n");
	OutputDebugString(sta.Chars());
#endif
	}
	else
	{
		// Note: This recursively calls this procedure.
		::SendMessage(m_hwnd, FW_EM_SETTEXT, 0, (LPARAM)qtss.Ptr());
		::SendMessage(m_hwnd, EM_SETSEL, ichMin, ichMin);
#ifdef DEBUG_THIS_FILE
	sta.Format("AfDeFeCliRef::OnChange:  NOT type ahead.\n");
	OutputDebugString(sta.Chars());
#endif
	}

	return true;
}
Example #21
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);
}
Example #22
0
/*----------------------------------------------------------------------------------------------
	This static method provides the basic window procedure used in this application framework.

	@param hwnd Handle of the window to which the message is directed.
	@param wm Window message identifier.
	@param wp First message parameter -- depends on the message.
	@param lp Second message parameter -- depends on the message.

	@return Result of the message processing -- depends on the message.
----------------------------------------------------------------------------------------------*/
LRESULT CALLBACK AfWnd::WndProc(HWND hwnd, uint wm, WPARAM wp, LPARAM lp)
{
	Assert(hwnd);

	AfWndPtr qwnd = reinterpret_cast<AfWnd *>(::GetWindowLong(hwnd, GWL_USERDATA));
	AssertPtrN(qwnd);
#ifdef _DEBUG
	if (DebugWindowMessages)
	{
		const type_info & myTypeInfo (typeid(*(qwnd.Ptr())));
		StrAnsi staT;
		staT.Format("Message %x sent to %s (%x)\n", wm, myTypeInfo.name(), hwnd);
		::OutputDebugStringA(staT.Chars());
	}
#endif

	if (!qwnd)
	{
		if (wm != WM_CREATE)
			return ::DefWindowProc(hwnd, wm, wp, lp);

		CREATESTRUCT * pcs = reinterpret_cast<CREATESTRUCT *>(lp);
		if (!pcs || !pcs->lpCreateParams)
			return ::DefWindowProc(hwnd, wm, wp, lp);

		AssertPtr(pcs);
		AfWndCreate * pafwc = reinterpret_cast<AfWndCreate *>(pcs->lpCreateParams);
		AssertPtr(pafwc);
		qwnd = pafwc->pwnd;
		AssertPtr(qwnd);

		try
		{
			qwnd->AttachHwnd(hwnd);
		}
		catch (...)
		{
			Warn("AttachHwnd failed.");
			return -1;
		}

		// Put the user-defined value back into pcs so that the subclass will have it.
		pcs->lpCreateParams = pafwc->pv;
	}

	Assert(qwnd->m_hwnd == hwnd);

	bool fRet;
	long lnRet = 0;

	BEGIN_TOP_LEVEL_ACTION
		// Call the pre non-virtual WndProc.
		fRet = qwnd->FWndProcPre(wm, wp, lp, lnRet);

		// Call the virtual window proc.
		if (!fRet)
			fRet = qwnd->FWndProc(wm, wp, lp, lnRet);

		qwnd->WndProcPost(fRet, hwnd, wm, wp, lp, lnRet);
	END_TOP_LEVEL_ACTION

	// Assert(_CrtCheckMemory()); //Not a bad place to insert this if having memory troubles.
	return lnRet;
}
Example #23
0
bool GdlRenderer::PreCompileFeatures(GrcManager * pcman, GrcFont * pfont, int * pfxdFeatVersion)
{
	*pfxdFeatVersion = 0x00010000;

	int nInternalID = 0;

	Set<unsigned int> setID;

	for (int ipfeat = 0; ipfeat < m_vpfeat.Size(); ipfeat++)
	{
		GdlFeatureDefn * pfeat = m_vpfeat[ipfeat];
		unsigned int nID = pfeat->ID();
		if (setID.IsMember(nID))
		{
			char rgch[20];
			if (nID > 0x00FFFFFF)
			{
				char rgchID[5];
				memcpy(rgch, &nID, 4);
				rgchID[0] = rgch[3]; rgchID[1] = rgch[2]; rgchID[2] = rgch[1]; rgchID[3] = rgch[0];
				rgchID[4] = 0;
				StrAnsi staTmp = "'";
				staTmp.Append(rgchID);
				staTmp.Append("'");
				memcpy(rgch, staTmp.Chars(), staTmp.Length() + 1);
			}
			else
				itoa(nID, rgch, 10);
			g_errorList.AddError(3152, pfeat, "Duplicate feature ID: ", rgch);
		}
		else
			setID.Insert(nID);

		if (pfeat->ErrorCheck())
		{
			pfeat->SetStdStyleFlag();
			pfeat->FillInBoolean(pcman->SymbolTable());
			pfeat->ErrorCheckContd();
			pfeat->CalculateDefault();
			pfeat->AssignInternalID(nInternalID);
			pfeat->RecordDebugInfo();
		}

		if (nID > 0x0000FFFF)
			*pfxdFeatVersion = 0x00020000;

		nInternalID++;
	}

	if (m_vpfeat.Size() > kMaxFeatures)
	{
		char rgchMax[20];
		itoa(kMaxFeatures, rgchMax, 10);
		char rgchCount[20];
		itoa(m_vpfeat.Size(), rgchCount, 10);
		g_errorList.AddError(3153, NULL,
			"Number of features (",
			rgchCount,
			") exceeds maximum of ",
			rgchMax);
	}

	return true;
}
Example #24
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#Undo}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::Undo(UndoResult * pures)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(pures);

	*pures = kuresSuccess;

	Assert(m_iCurrSeq >= 0);
	Assert(m_vquact.Size() > 0);

	HRESULT hr = E_FAIL;
	HRESULT hrFinal = S_OK;

	m_fCanContinueTask = false; // Can't 'continue' the previous task from before the Undo.
	m_fUndoOrRedoInProgress = true;

	try // to ensure in progress gets cleared.
	{
		int handle;
		// Start a 'transaction' if possible to group together all the stuff we're going to Undo.
		if (m_qundg)
		{
			m_qundg->BeginGroup(&handle);
		}

		// Loop through all of the actions that are about to be undone and see if any of them
		// require a refresh.
		Vector<long> vhvoCreatedObjects;
		for (int i = m_iuactCurr; (m_iCurrSeq >= 0) && (i >= m_viSeqStart[m_iCurrSeq]); i--)
		{
			CheckHr(m_vquact[i]->put_SuppressNotification(true));
		}

		// Undo all actions from the current action back to the first action of the current action
		// sequence.
		bool fRedoable = true;
		IgnoreHr(hrFinal = CallUndo(pures, fRedoable, true));

		// Now do all the PropChangeds
		for (int i = m_iuactCurr; (m_iCurrSeq >= 0) && (i >= m_viSeqStart[m_iCurrSeq]); i--)
		{
			CheckHr(m_vquact[i]->put_SuppressNotification(false));
		}

		// REVIEW (TimS/EberhardB): What do we do if the call to CallUndo above failed somewhere?
		// Should we do this at all? Or just until the failed action? Or everything?
		UndoResult uresTmp;
		IgnoreHr(hr = CallUndo(&uresTmp, fRedoable, false));
		if (FAILED(hr))
		{
			hrFinal = hr;
			*pures = uresTmp;
		}
		else if (uresTmp == kuresFailed)
		{
			*pures = uresTmp;
		}

		// dlh testing
		if (*pures == kuresError || * pures == kuresFailed)
		{
			if (m_qundg)
				m_qundg->CancelGroup(handle);
			EmptyStack();
		}
		else // normal success case
		{
			// Set the current action and start of the current action sequence.
			if (m_iCurrSeq >= 0)
			{
				m_iuactCurr = m_viSeqStart[m_iCurrSeq] - 1;
				m_iCurrSeq = m_iCurrSeq - 1;
			}
			if (m_qundg)
				m_qundg->EndGroup(handle);
		}

		// Delete any marks that now point after current undo action
		CleanUpMarks();

		if (!fRedoable)
			CleanUpRedoActions(true);

#ifdef DEBUG_ACTION_HANDLER
		StrAnsi sta;
		sta.Format("Undo:");
		sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
			m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
		::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER
	}
	catch(...)
	{
		CleanUpMarks();
		m_fUndoOrRedoInProgress = false;
		throw;
	}
	m_fUndoOrRedoInProgress = false;

	return hrFinal;

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Example #25
0
/*----------------------------------------------------------------------------------------------
	${IActionHandler#Redo}
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::Redo(UndoResult * pures)
{
	BEGIN_COM_METHOD;
	ChkComArgPtr(pures);

	*pures = kuresSuccess;
	// Do not allow actions to be redone if they have not been undone.
	Assert(m_viSeqStart.Size() > 0);
	Assert(m_iCurrSeq <= m_viSeqStart.Size() - 1);

	m_fCanContinueTask = false; // Can't 'continue' the previous task from before the Undo.
	m_fUndoOrRedoInProgress = true;
	HRESULT hrFinal = S_OK;
	int iSeqToRedo = m_iCurrSeq + 1;

	try // to ensure in progress gets cleared.
	{
		int handle;
		// Start a 'transaction' if possible to group together all the stuff we're going to Undo.
		if (m_qundg)
		{
			m_qundg->BeginGroup(&handle);
		}

		// Determine the last action to be redone; The last action to redo is the action
		// before the next redo sequence. Or the last existing action if there is not a
		// redo sequence after the sequence we are about to redo.
		int iLastRedoAct = m_vquact.Size() - 1;
		if (iSeqToRedo <= m_viSeqStart.Size() - 2)
			iLastRedoAct = m_viSeqStart[iSeqToRedo + 1] - 1;

		// Loop through all of the actions that are about to be redone and see if any of them
		// require a refresh.
		for (int i = m_viSeqStart[iSeqToRedo]; i <= iLastRedoAct; i++)
		{
			CheckHr(m_vquact[i]->put_SuppressNotification(true));
		}

		// Redo all the actions in the next action sequence that change data.
		hrFinal = CallRedo(pures, true, iSeqToRedo, iLastRedoAct);

		// Now do all the PropChangeds
		for (int i = m_viSeqStart[iSeqToRedo]; i <= iLastRedoAct; i++)
		{
			CheckHr(m_vquact[i]->put_SuppressNotification(false));
		}

		// REVIEW (TimS/EberhardB): What do we do if the call to CallRedo above failed somewhere?
		// Should we do this at all? Or just until the failed action? Or everything?
		UndoResult uresTmp = kuresSuccess;
		// Redo all the actions in the next action sequence that don't change data.
		HRESULT hr;
		IgnoreHr(hr = CallRedo(&uresTmp, false, iSeqToRedo, iLastRedoAct));
		if (FAILED(hr))
		{
			hrFinal = hr;
			*pures = uresTmp;
		}
		else if (uresTmp == kuresFailed)
		{
			*pures = uresTmp;
		}

		// dlh testing
		if (*pures == kuresError || * pures == kuresFailed)
		{
			if (m_qundg)
				m_qundg->CancelGroup(handle);
			EmptyStack();
		}
		else // normal success case
		{
			// Set the current sequence and action.
			m_iCurrSeq++;
			m_iuactCurr = m_vquact.Size() - 1;
			if (m_iCurrSeq < m_viSeqStart.Size() - 1)
			{
				m_iuactCurr = m_viSeqStart[m_iCurrSeq + 1] - 1;
			}
			if (m_qundg)
				m_qundg->EndGroup(handle);
		}


#ifdef DEBUG_ACTION_HANDLER
		StrAnsi sta;
		sta.Format("Redo:");
		sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
			m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
		::OutputDebugStringA(sta.Chars());
#endif //DEBUG_ACTION_HANDLER
	}
	catch(...)
	{
		m_fUndoOrRedoInProgress = false;
		throw;
	}
	m_fUndoOrRedoInProgress = false;

	return hrFinal;

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Example #26
0
/*----------------------------------------------------------------------------------------------
	Set the keyboard through TSF
----------------------------------------------------------------------------------------------*/
bool SetKeyboard_TSF(bool fDoingKeyman, int lcid, int * pnActiveLangId)
{
#ifdef Tracing_KeybdSelection
	StrAnsi sta;
	sta.Format("LgTextServices::SetKeyboard(%d) [making TSF calls]%n", lcid);
	::OutputDebugStringA(sta.Chars());
	sta.Format("LgTextServices::SetKeyboard(%d) - ::GetKeyboardLayout() = %x%n",
		lcid, ::GetKeyboardLayout(0));
	::OutputDebugStringA(sta.Chars());
#endif
	HRESULT hr = S_OK;
	ITfInputProcessorProfilesPtr qtfipp;
	int nLangId = LANGIDFROMLCID(lcid);
	bool fSetInputLang = false;
	// Don't check the HR or use CreateInstance; I (JohnT) think this may fail if TSF is not
	// fully active.
	::CoCreateInstance(CLSID_TF_InputProcessorProfiles, NULL, CLSCTX_ALL,
		IID_ITfInputProcessorProfiles, (void **)&qtfipp);
	if (!qtfipp)
	{
		Warn("Could not get ITfInputProcessorProfiles to set Keyman text service\n");
	}
	else
	{
		// Have to make the language active before we can set the profile;
		// and want to set the language even if we aren't doing Keyman.
		if (*pnActiveLangId != (LANGID)nLangId)
		{
			// Do NOT do this if the right langID is already current. In some bizarre cases
			// during WM_INPUTLANGCHANGED it can lead to a new input-lang-changed in a
			// DIFFERENT language and an infinite loop.
			*pnActiveLangId = (LANGID)nLangId;
			IgnoreHr(hr = qtfipp->ChangeCurrentLanguage((LANGID)nLangId));
		}
#ifdef Tracing_KeybdSelection
		sta.Format(
			"LgTextServices::SetKeyboard(%d) [qtfipp->ChangeCL(%d) => hr = %x]%n",
			lcid, nLangId, hr);
		::OutputDebugStringA(sta.Chars());
#endif
		if (FAILED(hr))
		{
			Warn("failed to change language\n");
		}
		else if (fDoingKeyman)
		{
			// Make sure the Keyman text service is turned on. For some bizarre reason there is
			// no API to just ask for the service to turn on for the langid, we have to do our
			// own search for the profile that corresponds to this langid and text service.
			IEnumTfLanguageProfilesPtr qenum;
	#ifdef Tracing_KeybdSelection
			sta.Format("LgTextServices::SetKeyboard(%d) [qtfipp->EnumLP(%d)]%n",
				lcid, nLangId);
			::OutputDebugStringA(sta.Chars());
			sta.Format("LgTextServices::SetKeyboard(%d) - ::GetKeyboardLayout() = %x%n",
				lcid, ::GetKeyboardLayout(0));
			::OutputDebugStringA(sta.Chars());
	#endif
			IgnoreHr(hr = qtfipp->EnumLanguageProfiles((LANGID)nLangId, &qenum));
			if (FAILED(hr))
			{
				Warn("Could not get enumerator for language profiles\n");
			}
			else
			{
				// If doing keyman try to turn on Keyman text service.
				TF_LANGUAGEPROFILE profile;
				for ( ; ; )
				{
					ULONG cprofile;
					IgnoreHr(hr = qenum->Next(1, &profile, &cprofile));
					if (FAILED(hr) || cprofile != 1)
					{
						Warn("failed to find language profiled for Keyman\n");
						break;
					}
					if (kclsidKMTipTextService == profile.clsid)
					{
						// got it at last!
#ifdef Tracing_KeybdSelection
						StrAnsi sta;
						sta.Format("LgTextServices::SetKeyboard(%d) - "
							"qtfipp->ActivateLanguageProfile(nLangId = %d)\n",
							lcid, nLangId);
						::OutputDebugStringA(sta.Chars());
#endif
						IgnoreHr(hr = qtfipp->ActivateLanguageProfile(
							kclsidKMTipTextService, (LANGID)nLangId, profile.guidProfile));
						if (FAILED(hr))
						{
							Warn("failed to activate language profile\n");
						}
						else
						{
							fSetInputLang = true;
						}
						break;
					}
				}
			}
#ifdef Tracing_KeybdSelection
			sta.Format("LgTextServices::SetKeyboard(%d) [after qtfipp->ChangeCL(%d)]%n",
				lcid, nLangId);
			::OutputDebugStringA(sta.Chars());
			sta.Format("LgTextServices::SetKeyboard(%d) - ::GetKeyboardLayout() = %x%n",
				lcid, ::GetKeyboardLayout(0));
			::OutputDebugStringA(sta.Chars());
#endif
		}
		else
		{
			// We're not doing keyman, but we already set the input language.
			fSetInputLang = true;
		}
	}
	return fSetInputLang;
}
Example #27
0
/*----------------------------------------------------------------------------------------------
	Set a keyman keyboard
----------------------------------------------------------------------------------------------*/
HRESULT SetKeyboard_Keyman(int lcid, BSTR bstrKeymanKbd, BSTR * pbstrActiveKeymanKbd,
	ComBool * pfSelectLangPending)
{
#ifdef Tracing_KeybdSelection
	StrAnsi sta;
	sta.Format("LgTextServices::SetKeyboard(%d) [setting Keyman kbd]%n", lcid);
	::OutputDebugStringA(sta.Chars());
#endif
	int nLangId = LANGIDFROMLCID(lcid);
	HRESULT hr = S_OK;
	ILgKeymanHandlerPtr qkh;
	qkh.CreateInstance(CLSID_LgKeymanHandler);
	// Tell Keyman about the particular keyboard (but only if it changed).
	if (IsKeyboardDifferent(bstrKeymanKbd, *pbstrActiveKeymanKbd))
	{
		// Activate the particular layout we want.
		// John Durdin says this next step is necessary.
		//::ActivateKeyboardLayout(::GetKeyboardLayout(0), 0);
		// JohnT: discovered that if we've never set a keyboard before, the current one
		// won't be right, but forcing the right langid into the low word seems to help.
		// Keyman always uses the US English keyboard, which is the magic number we're
		// stuffing into the high word.
		HKL hklDesired = (HKL)(0x04090000 | (nLangId & 0xffff));
#ifdef Tracing_KeybdSelection
		StrAnsi sta;
		sta.Format("LgTextServices::SetKeyboard(%d) - "
			"::ActivateKeyboardLayout(%d [%x], 0) for keyman setup\n",
			lcid, hklDesired, hklDesired);
		::OutputDebugStringA(sta.Chars());
#endif
		::ActivateKeyboardLayout(hklDesired, 0);

		try
		{
			CheckHr(qkh->put_ActiveKeyboardName(bstrKeymanKbd));
#ifdef TRACING_KEYMAN
			StrUni stuMsg;
			stuMsg.Format(L"%b is now the active Keyman keyboard.\n",
				bstrKeymanKbd);
			::OutputDebugStringW(stuMsg.Chars());
#endif
			if (*pbstrActiveKeymanKbd)
				::SysFreeString(*pbstrActiveKeymanKbd);
			CopyBstr(pbstrActiveKeymanKbd, bstrKeymanKbd);
			*pfSelectLangPending = true;
		}
		catch (Throwable& thr)
		{
			hr = thr.Result();
#ifdef TRACING_KEYMAN
			StrAnsi staMsg;
			staMsg.Format("Cannot make %B the active Keyman keyboard!?\n",
				bstrKeymanKbd);
			::OutputDebugStringA(staMsg.Chars());
#endif
			if (BstrLen(*pbstrActiveKeymanKbd))
			{
				// We failed, so ensure it's turned off.
				TurnOffKeymanKbd(pbstrActiveKeymanKbd);
				*pfSelectLangPending = true;
			}
		}
	}
	return hr;
}
Example #28
0
/*----------------------------------------------------------------------------------------------
	Write the given FontInfo string text property value in readable XML format.

	@param pstrm Pointer to an IStream for output.
	@param bstrVal
----------------------------------------------------------------------------------------------*/
void FwXml::WriteBulNumFontInfo(IStream * pstrm, BSTR bstrVal, int cchIndent)
{
	AssertPtr(pstrm);
	Assert(cchIndent >= 0);
	int cchProps = ::SysStringLen(bstrVal);
	if (!cchProps)
		return;

	Vector<char> vchIndent;
	vchIndent.Resize(cchIndent + 1);
	memset(vchIndent.Begin(), ' ', cchIndent);

	const OLECHAR * pchProps = bstrVal;
	const OLECHAR * pchPropsLim = pchProps + cchProps;

	FormatToStream(pstrm, "%s<BulNumFontInfo", vchIndent.Begin());
	StrAnsi staItalic;
	StrAnsi staBold;
	StrAnsi staSuperscript;
	StrAnsi staUnderline;
	StrAnsi staFontsize;
	StrAnsi staOffset;
	StrAnsi staForecolor;
	StrAnsi staBackcolor;
	StrAnsi staUndercolor;
	StrAnsi staXXX;
	int tpt;
	while (pchProps < pchPropsLim)
	{
		tpt = *pchProps++;
		if (tpt == ktptFontFamily)
			break;

		int nVal = *pchProps + ((*(pchProps + 1)) << 16);
		pchProps += 2;
		switch (tpt)
		{
		case ktptItalic:
			staItalic.Format(" italic=\"%s\"", ToggleValueName((byte)nVal));
			break;
		case ktptBold:
			staBold.Format(" bold=\"%s\"", ToggleValueName((byte)nVal));
			break;
		case ktptSuperscript:
			staSuperscript.Format(" superscript=\"%s\"", SuperscriptValName((byte)nVal));
			break;
		case ktptUnderline:
			staUnderline.Format(" underline=\"%s\"", UnderlineTypeName((byte)nVal));
			break;
		case ktptFontSize:
			staFontsize.Format(" fontsize=\"%dmpt\"", nVal);
			break;
		case ktptOffset:
			staOffset.Format(" offset=\"%dmpt\"", nVal);
			break;
		case ktptForeColor:
			staForecolor.Format(" forecolor=\"%s\"", ColorName(nVal));
			break;
		case ktptBackColor:
			staBackcolor.Format(" backcolor=\"%s\"", ColorName(nVal));
			break;
		case ktptUnderColor:
			staUndercolor.Format(" undercolor=\"%s\"", ColorName(nVal));
			break;
		default:
			staXXX.FormatAppend(" prop_%u=\"%d\"", tpt, nVal);
			break;
		}
	}
	ULONG cb;
	// Write the integer valued properties in alphabetical order.
	if (staBackcolor.Length())
		pstrm->Write(staBackcolor.Chars(), staBackcolor.Length(), &cb);
	if (staBold.Length())
		pstrm->Write(staBold.Chars(), staBold.Length(), &cb);
	if (staFontsize.Length())
		pstrm->Write(staFontsize.Chars(), staFontsize.Length(), &cb);
	if (staForecolor.Length())
		pstrm->Write(staForecolor.Chars(), staForecolor.Length(), &cb);
	if (staItalic.Length())
		pstrm->Write(staItalic.Chars(), staItalic.Length(), &cb);
	if (staOffset.Length())
		pstrm->Write(staOffset.Chars(), staOffset.Length(), &cb);
	if (staSuperscript.Length())
		pstrm->Write(staSuperscript.Chars(), staSuperscript.Length(), &cb);
	if (staUndercolor.Length())
		pstrm->Write(staUndercolor.Chars(), staUndercolor.Length(), &cb);
	if (staUnderline.Length())
		pstrm->Write(staUnderline.Chars(), staUnderline.Length(), &cb);
	if (staXXX.Length())
		pstrm->Write(staXXX.Chars(), staXXX.Length(), &cb);
	// Write the string valued property (if it exists).
	if (tpt == ktptFontFamily && pchProps < pchPropsLim)
	{
		FormatToStream(pstrm, " fontFamily=\"");
		WriteXmlUnicode(pstrm, pchProps, pchPropsLim - pchProps);
		FormatToStream(pstrm, "\"");
	}
	FormatToStream(pstrm, "/>%n");
}
Example #29
0
/*----------------------------------------------------------------------------------------------
	Discard all Undo items back to the specified mark (or the most recent mark, if any,
	if handle is zero).
----------------------------------------------------------------------------------------------*/
STDMETHODIMP ActionHandler::DiscardToMark(int hMark)
{
	BEGIN_COM_METHOD;
	// It's only valid to discard while no action sequence is in progress.
	if (m_nDepth > 0)
	{
		ThrowHr(WarnHr(E_UNEXPECTED));
	}
	m_fCanContinueTask = false; // Can't merge another action into the current task.

	// The handle hMark is 1 + the position of the mark in the mark stack.
	int iMarkGoal = (hMark == 0) ? m_viMarks.Size() - 1 : hMark - 1;

	if (iMarkGoal >= m_viMarks.Size() || iMarkGoal < 0)
		return E_INVALIDARG;

	//::OutputDebugStringA("Entering DiscardToMark\n");
	//StrAnsi sta;
	//sta.Format("depth = %d; m_fStartedNext = %d; action %d of %d; seq %d of %d; marks %d%n",
	//	m_nDepth, m_fStartedNext, m_iuactCurr, m_vquact.Size(), m_iCurrSeq, m_viSeqStart.Size(), m_viMarks.Size());
	//::OutputDebugStringA(sta.Chars());

	int iuactMark = m_viMarks[iMarkGoal];
	int iuact;
	for (iuact = m_vquact.Size() - 1; iuact >= iuactMark; iuact--)
	{
		m_vquact.Delete(iuact);
	}
	m_iuactCurr = min(m_iuactCurr, m_vquact.Size() - 1);

	for (iuact = m_viSeqStart.Size() - 1; iuact >= 0; iuact--)
	{
		if (m_viSeqStart[iuact] < m_vquact.Size())
			break;
		m_viSeqStart.Delete(iuact);
		m_vstuUndo.Delete(iuact);
		m_vstuRedo.Delete(iuact);
	}
	m_iCurrSeq = min(m_iCurrSeq, m_viSeqStart.Size() - 1);

	// Delete the mark(s).
	for (int iMarkTmp = m_viMarks.Size() - 1; iMarkTmp >= iMarkGoal; iMarkTmp--)
	{
		m_viMarks.Delete(iMarkTmp);
	}

	//::OutputDebugStringA("After DiscardToMark\n");
	//sta.Format("depth = %d; m_fStartedNext = %d; action %d of %d; seq %d of %d; marks %d%n",
	//	m_nDepth, m_fStartedNext, m_iuactCurr, m_vquact.Size(), m_iCurrSeq, m_viSeqStart.Size(), m_viMarks.Size());
	//::OutputDebugStringA(sta.Chars());

	// For now, we are only supporting one mark at a time:
	Assert(m_viMarks.Size() == 0);

	// If the depth is greater than zero, we're in the middle of recording a task, so
	// get back in the state where we can close it out.
	if (m_nDepth > 0)
	{
		Assert(m_viSeqStart.Size() == m_vstuUndo.Size());
		Assert(m_viSeqStart.Size() == m_vstuRedo.Size());

		m_fStartedNext = true;

		//::OutputDebugStringA("Leaving DiscardToMark\n");
		//sta.Format("depth = %d; m_fStartedNext = %d; action %d of %d; seq %d of %d; marks %d%n",
		//	m_nDepth, m_fStartedNext, m_iuactCurr, m_vquact.Size(), m_iCurrSeq, m_viSeqStart.Size(), m_viMarks.Size());
		//::OutputDebugStringA(sta.Chars());
	}

#ifdef DEBUG_ACTION_HANDLER
	StrAnsi sta;
	sta.Format("DiscardToMark:%d", hMark);
	sta.FormatAppend(" m_iCurrSeq=%d, m_viSeqStart=%d, m_iuactCurr=%d, m_vquact=%d, m_viMarks=%d, m_nDepth=%d\n",
		m_iCurrSeq, m_viSeqStart.Size(), m_iuactCurr, m_vquact.Size(), m_viMarks.Size(), m_nDepth);
	::OutputDebugStringA(sta.Chars());
#endif//DEBUG_ACTION_HANDLER

	END_COM_METHOD(g_factActh, IID_IActionHandler);
}
Example #30
0
/*----------------------------------------------------------------------------------------------
	Read the text to render from the file being opened.
----------------------------------------------------------------------------------------------*/
void WpDa::ReadTextFromFile(StrAnsi staFileName, Vector<StrUni> & vstu)
{
	OLECHAR pswzData[5000];
	memset(pswzData, 0, 5000);

	char pszData[10000];
	memset(pszData, 0, 10000);

	FILE * f = fopen(staFileName.Chars(), "rb");

//	IStreamPtr qstrm;
//	FileStream::Create(staFileName.Chars(),kfstgmRead,&qstrm);

	if (!f)
	{
		//	No such file
		ThrowHr(WarnHr(E_FAIL));
	}

	fread(pszData, 1, 10000, f);
	fclose(f);

	char * pch = pszData;
	OLECHAR * pchw;
	if (*pch == 0xFFFFFFFF && *(pch + 1) == 0xFFFFFFFE)
	{
		//	UTF16
		memcpy(pswzData, pszData + 2, 9998);
	}
	else if (*pch == 0xFFFFFFFE && *(pch + 1) == 0xFFFFFFFF)
	{
		//	UTF16 with the byte order reversed.
		pch += 2;
		pchw = pswzData;
		while (pch < pszData + 10000 && *pch != 0)
		{
			*pchw = (wchar)(*pch << 8 | *(pch + 1));
			pch += 2;
			pchw++;
		}
	}
	else
	{
		//	Assume plain 8-bit ANSI data.
		pchw = pswzData;
		while (pch < pszData + 5000 && *pch != 0)
		{
			*pchw = *pch;
			pch++;
			pchw++;
		}
	}

	//	Make a list of strings.

	pchw = pswzData;
	OLECHAR * pchwStrMin = pchw;
	while (pchw < pswzData + 5000 && *pchw != 0)
	{
		if (*pchw == 13 && *(pchw + 1) == 10)	// CRLF
		{
			//	Make a new string;
			StrUni stu(pchwStrMin, pchw - pchwStrMin);
			vstu.Push(stu);
			pchw += 2;	// skip CRLF
			pchwStrMin = pchw;
		}
		else
			pchw++;
	}
	StrUni stu(pchwStrMin, pchw - pchwStrMin);
	vstu.Push(stu);
}