/*---------------------------------------------------------------------------------------------- Generate the sort key as a BSTR ----------------------------------------------------------------------------------------------*/ STDMETHODIMP LgUnicodeCollater::get_SortKey(BSTR bstrValue, LgCollatingOptions colopt, BSTR * pbstrKey) { BEGIN_COM_METHOD ChkComBstrArg(bstrValue); ChkComOutPtr(pbstrKey); HRESULT hr; int cchw; *pbstrKey = NULL; // Passing 0 and null just produces a length IgnoreHr(hr = SortKeyRgch(bstrValue, BstrLen(bstrValue), colopt, 0, NULL, &cchw)); if (FAILED(hr)) return hr; BSTR bstrOut; bstrOut = SysAllocStringLen(NULL, cchw); if (!bstrOut) return E_OUTOFMEMORY; IgnoreHr(hr = SortKeyRgch(bstrValue, BstrLen(bstrValue), colopt, cchw, bstrOut, &cchw)); if (FAILED(hr)) { SysFreeString(bstrOut); return hr; } *pbstrKey = bstrOut; END_COM_METHOD(g_fact, IID_ILgCollatingEngine); }
/*---------------------------------------------------------------------------------------------- Sets the name of the class that this is a virtual property of. Normally set by whatever creates the handler. The cache does not call this, so it may be left unimplemented if there is a more convenient way to initialize the property. ---------------------------------------------------------------------------------------------*/ STDMETHODIMP VwBaseVirtualHandler::put_ClassName(BSTR bstr) { BEGIN_COM_METHOD; ChkComBstrArg(bstr) m_stuClass.Assign(bstr, BstrLen(bstr)); END_COM_METHOD(g_fact, IID_IVwVirtualHandler); }
/*---------------------------------------------------------------------------------------------- Perform whatever action is appropriate when the use clicks on a hot link ----------------------------------------------------------------------------------------------*/ STDMETHODIMP VwBaseVc::DoHotLinkAction(BSTR bstrData, ISilDataAccess * psda) { BEGIN_COM_METHOD; ChkComArgPtrN(ptss); if (BstrLen(bstrData) > 0 && bstrData[0] == kodtExternalPathName) { StrAppBuf strbFile(bstrData + 1); if (::UrlIs(strbFile.Chars(), URLIS_URL)) { // If it's a URL launch whatever it means. ::ShellExecute(NULL, L"open", strbFile.Chars(), NULL, NULL, SW_SHOWNORMAL); return S_OK; } if (AfApp::Papp()) { AfMainWnd * pafw = AfApp::Papp()->GetCurMainWnd(); if (pafw && pafw->GetLpInfo()) pafw->GetLpInfo()->MapExternalLink(strbFile); AfApp::LaunchHL(NULL, _T("open"), strbFile.Chars(), NULL, NULL, SW_SHOW); } } return S_OK; END_COM_METHOD(g_fact, IID_IVwViewConstructor); }
/*---------------------------------------------------------------------------------------------- Create a property with the given writing system, old writing system, and named style (ktptNamedStyle). Note that ktptCharStyle (which this used to use) is effectively obsolete. ----------------------------------------------------------------------------------------------*/ STDMETHODIMP TsPropsFact::MakeProps(BSTR bstr, int ws, int ows, ITsTextProps ** ppttp) { BEGIN_COM_METHOD; ChkComBstrArgN(bstr); ChkComOutPtr(ppttp); if ((uint)ws > kwsLim) ThrowInternalError(E_INVALIDARG, "Magic writing system invalid in string"); return MakePropsRgch(bstr, BstrLen(bstr), ws, ows, ppttp); END_COM_METHOD(g_factPropsFact, IID_ITsPropsFactory); }
/*---------------------------------------------------------------------------------------------- Do a direct string comparison. ----------------------------------------------------------------------------------------------*/ STDMETHODIMP LgUnicodeCollater::Compare(BSTR bstrValue1, BSTR bstrValue2, LgCollatingOptions colopt, int * pnVal) { BEGIN_COM_METHOD ChkComBstrArg(bstrValue1); ChkComBstrArg(bstrValue2); ChkComOutPtr(pnVal); HRESULT hr; int cchw1; int cchw2; IgnoreHr(hr = SortKeyRgch(bstrValue1, BstrLen(bstrValue1), colopt, 0, NULL, &cchw1)); if (FAILED(hr)) return hr; IgnoreHr(hr = SortKeyRgch(bstrValue2, BstrLen(bstrValue2), colopt, 0, NULL, &cchw2)); if (FAILED(hr)) return hr; OLECHAR * pchKey1 = (OLECHAR *) _alloca(cchw1 * isizeof(OLECHAR)); OLECHAR * pchKey2 = (OLECHAR *) _alloca(cchw2 * isizeof(OLECHAR)); IgnoreHr(hr = SortKeyRgch(bstrValue1, BstrLen(bstrValue1), colopt, cchw1, pchKey1, &cchw1)); if (FAILED(hr)) return hr; IgnoreHr(hr = SortKeyRgch(bstrValue2, BstrLen(bstrValue2), colopt, cchw2, pchKey2, &cchw2)); if (FAILED(hr)) return hr; int nVal = u_strncmp(pchKey1, pchKey2, min(cchw1, cchw2)); if (!nVal) { // equal as far as length of shortest key if (BstrLen(bstrValue1) < BstrLen(bstrValue2)) nVal = -1; else if (BstrLen(bstrValue1) > BstrLen(bstrValue2)) nVal = 1; } *pnVal = nVal; END_COM_METHOD(g_fact, IID_ILgCollatingEngine); }
/*---------------------------------------------------------------------------------------------- Generate the sort key as a byte * ----------------------------------------------------------------------------------------------*/ byte * LgIcuCollator::GetSortKey(BSTR bstrValue, byte* prgbKey, int32_t* pcbKey) { byte * pbKey; int32_t crgbKey = *pcbKey; EnsureCollator(); *pcbKey = m_pCollator->getSortKey(bstrValue, BstrLen(bstrValue), prgbKey, crgbKey); if (*pcbKey > crgbKey) { // sort key is too long, the caller has to pass us a bigger buffer. pbKey = NULL; } else { // sort key is less than 1024 bytes pbKey = prgbKey; } return pbKey; }
// Get the display name of the locale represented by this enumerator. // The display name will be in the selected locale if it is non-empty; // pass null or an empty string to get the system default locale. STDMETHODIMP LgIcuLocaleEnumerator::get_DisplayName(int iloc, BSTR bstrLocaleName, BSTR * pbstrName) { BEGIN_COM_METHOD ChkComOutPtr(pbstrName); ChkComBstrArgN(bstrLocaleName); if (iloc >= m_clocale) ThrowHr(WarnHr(E_INVALIDARG)); UnicodeString ust; if (BstrLen(bstrLocaleName) == 0) m_prgLocales[iloc].getDisplayName(ust); else { StrAnsi staLocaleName(bstrLocaleName); Locale loc = Locale::createFromName(staLocaleName.Chars()); m_prgLocales[iloc].getDisplayName(loc, ust); } *pbstrName = UnicodeStringToBstr(ust); END_COM_METHOD(g_factLocEnum, IID_ILgIcuLocaleEnumerator); }
/*---------------------------------------------------------------------------------------------- Set the system keyboard and TSF language. ----------------------------------------------------------------------------------------------*/ STDMETHODIMP LgTextServices::SetKeyboard(int lcid, BSTR bstrKeymanKbd, int * pnActiveLangId, BSTR * pbstrActiveKeymanKbd, ComBool * pfSelectLangPending) { BEGIN_COM_METHOD; ChkComBstrArgN(bstrKeymanKbd); ChkComArgPtr(pnActiveLangId); ChkComArgPtr(pbstrActiveKeymanKbd); ChkComArgPtr(pfSelectLangPending); HRESULT hr; int nLangId = LANGIDFROMLCID(lcid); bool fDoingKeyman = BstrLen(bstrKeymanKbd) > 0; bool fSetInputLang = false; #ifdef ENABLE_TSF if (IsKeyboardDifferent(bstrKeymanKbd, *pbstrActiveKeymanKbd) || (LANGID)nLangId != (LANGID)*pnActiveLangId) { fSetInputLang = SetKeyboard_TSF(fDoingKeyman, lcid, pnActiveLangId); } #endif /*ENABLE_TSF*/ if (fDoingKeyman) { hr = SetKeyboard_Keyman(lcid, bstrKeymanKbd, pbstrActiveKeymanKbd, pfSelectLangPending); } else // no keyman keyboard wanted. { if (!fSetInputLang) SetKeyboard_Windows(lcid); TurnOffKeymanKbd(pbstrActiveKeymanKbd); *pfSelectLangPending = true; } END_COM_METHOD(g_fact, IID_ILgTextServices); }
/*---------------------------------------------------------------------------------------------- Return the text string that gets shown to the user when this object needs to be displayed. This is the method for displaying the name of a single reference. This view shows the name for an RnGenericRec consisting of the type of record, hyphen, title, hyphen, creation date. "Subevent - Fishing for pirana - 3/22/2001" @param pguid Pointer to a database object's assigned GUID. @param pptss Address of a pointer to an ITsString COM object used for returning the text string. @return S_OK, E_POINTER, or E_FAIL. ----------------------------------------------------------------------------------------------*/ STDMETHODIMP CleRecVc::GetStrForGuid(BSTR bstrGuid, ITsString ** pptss) { Assert(false); // rework BEGIN_COM_METHOD; ChkComBstrArg(bstrGuid); ChkComOutPtr(pptss); if (BstrLen(bstrGuid) != 8) ReturnHr(E_INVALIDARG); CleMainWnd * pcmw = dynamic_cast<CleMainWnd *>(AfApp::Papp()->GetCurMainWnd()); AssertPtr(pcmw); CleLpInfo * plpi = dynamic_cast<CleLpInfo *>(pcmw->GetLpInfo()); AssertPtr(plpi); HVO hvo = plpi->GetDbInfo()->GetIdFromGuid((GUID *)bstrGuid); CustViewDaPtr qcvd; plpi->GetDataAccess(&qcvd); AssertPtr(qcvd); int clid; HVO hvoOwn; int64 ntim; ITsStringPtr qtssTitle; CheckHr(qcvd->get_IntProp(hvo, kflidCmObject_Class, &clid)); CheckHr(qcvd->get_ObjectProp(hvo, kflidCmObject_Owner, &hvoOwn)); // REVIEW KenZ(RandyR) Whey are DN flids in this app? CheckHr(qcvd->get_TimeProp(hvo, kflidRnGenericRec_DateCreated, &ntim)); CheckHr(qcvd->get_StringProp(hvo, kflidRnGenericRec_Title, &qtssTitle)); int stid; // REVIEW KenZ(RandyR) Whey are DN flids in this app? if (clid == kclidRnEvent) { if (pcmw->GetRootObj() == hvoOwn) stid = kstidEvent; else stid = kstidSubevent; } else if (clid == kclidRnAnalysis) { if (pcmw->GetRootObj() == hvoOwn) stid = kstidAnalysis; else stid = kstidSubanalysis; } StrUni stu(stid); StrUni stuSep(kstidSpHyphenSp); ITsStrFactoryPtr qtsf; ITsIncStrBldrPtr qtisb; qtsf.CreateInstance(CLSID_TsStrFactory); CheckHr(qtsf->GetIncBldr(&qtisb)); CheckHr(qtisb->Append(stu.Bstr())); CheckHr(qtisb->Append(stuSep.Bstr())); CheckHr(qtisb->AppendTsString(qtssTitle)); // The title. CheckHr(qtisb->Append(stuSep.Bstr())); // Leave the date blank if a date doesn't exist. if (ntim) { // Convert the date to a system date. SilTime tim = ntim; SYSTEMTIME stim; stim.wYear = (unsigned short) tim.Year(); stim.wMonth = (unsigned short) tim.Month(); stim.wDay = (unsigned short) tim.Date(); // Then format it to a time based on the current user locale. achar rgchDate[50]; // Tuesday, August 15, 2000 mardi 15 août 2000 ::GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &stim, NULL, rgchDate, 50); stu = rgchDate; CheckHr(qtisb->Append(stu.Bstr())); } CheckHr(qtisb->GetString(pptss)); return S_OK; END_COM_METHOD(g_fact2, IID_IVwViewConstructor) }
/*---------------------------------------------------------------------------------------------- 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; }
/*---------------------------------------------------------------------------------------------- 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); }
/*---------------------------------------------------------------------------------------------- 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); }