/*---------------------------------------------------------------------------------------------- Close the current editor, saving changes that were made. This also updates the the cache if the name or abbr fields were edited, this then causing the treebar to be updated. @param fForce True if we want to force the editor closed without making any validity checks or saving any changes. ----------------------------------------------------------------------------------------------*/ void CleDeFeString::EndEdit(bool fForce) { if (fForce) { SuperClass::EndEdit(fForce); return; } CleMainWnd * pcmw = dynamic_cast<CleMainWnd *>(MainWindow()); Assert(pcmw); PossListInfoPtr qpli = pcmw->GetPossListInfoPtr(); int ipss = qpli->GetIndexFromId(m_hvoObj); if (ipss < 0) { SuperClass::EndEdit(fForce); // Closing an old editor after an item was removed. return; } PossItemInfo * ppii = qpli->GetPssFromIndex(ipss); AssertPtr(ppii); StrUni stu; const OLECHAR * prgwch; int cch; ITsStringPtr qtss; AssertPtr(m_qadsc->MainWindow()); AfLpInfo * plpi = m_qadsc->MainWindow()->GetLpInfo(); AssertPtr(plpi); AfDbInfo * pdbi; pdbi = plpi->GetDbInfo(); AssertPtr(pdbi); int wsMagic = qpli->GetWs(); int ws = plpi->ActualWs(wsMagic); // At this point, all strings in a PossList cache are assumed to have the same writing system. // However, if that writing system is missing, a non-null string from a different writing system is // loaded. Thus if FRN is the writing system for the PossList cache, we can't tell from the // cache whether the string we are getting is FRN or ENG, or some other writing system. When // we display strings in this editor, we show actual strings for each writing system shown. // Suppose we are showing FRN and ENG, but FRN is missing. If a person edits the ENG // string that is showing, the user would expect the tree to reflect this change, since // FRN is still missing. However we can't do this at this point because we don't know // which writing system is actually being substituted in the tree. It could actually be a GER // string because there also wasn't an ENG string. So until we cache encodings with each // string, the best we can do is only modify the PossList cache if the string for the // primary writing system changed. In that case, we now have a FRN string, so it should show // in the tree as well. CustViewDaPtr qcvd = pcmw->MainDa(); AssertPtr(qcvd); // Get the current primary string. CheckHr(qcvd->get_MultiStringAlt(m_hvoObj, m_flid, ws, &qtss)); if (qtss) { qtss->LockText(&prgwch, &cch); qtss->UnlockText(prgwch); } // Trim leading and trailing space characters. UnicodeString ust(prgwch, cch); ust.trim(); stu.Assign(ust.getBuffer(), ust.length()); // We don't expect to use this for anything except name or abbr. Assert(m_flid == kflidCmPossibility_Name || m_flid == kflidCmPossibility_Abbreviation); // We don't allow long strings. if (stu.Length() > kcchPossNameAbbrMax) // Need constant here and the line below. { ::MessageBeep(MB_ICONEXCLAMATION); // Beep if we truncated the length. stu.Replace(kcchPossNameAbbrMax, stu.Length(), L""); } ITsStrFactoryPtr qtsf; qtsf.CreateInstance(CLSID_TsStrFactory); qtsf->MakeStringRgch(stu.Chars(), stu.Length(), ws, &qtss); // If we changed the length, store the trimmed string. if (cch != stu.Length()) { // Check if the record has been edited by someone else since we first loaded the data. HRESULT hrTemp; if ((hrTemp = qcvd->CheckTimeStamp(m_hvoObj)) != S_OK) { // If it was changed and the user does not want to overwrite it, perform a refresh // so the displayed field will revert to its original value. CheckHr(qcvd->PropChanged(NULL, kpctNotifyAll, m_hvoObj, m_flid, 0, 1, 1)); return; } // Update the value in the cache and refresh views. CheckHr(qcvd->SetMultiStringAlt(m_hvoObj, m_flid, ws, qtss)); CheckHr(qcvd->PropChanged(NULL, kpctNotifyAll, m_hvoObj, m_flid, 0, 1, 1)); } SuperClass::EndEdit(fForce); // See if the primary string has changed. ComBool fEqual; CheckHr(qtss->Equals(m_qtssOld, &fEqual)); if (fEqual) return; // No change was made, so we don't need to do anything else. // A change was made. if (m_flid != kflidCmPossibility_Name && m_flid != kflidCmPossibility_Abbreviation) return; // Nothing more to do if it isn't a name or abbreviation. // We've changed the primary name or abbreviation, so update the PossList cache. ppii->SetName(stu, m_flid == kflidCmPossibility_Name ? kpntName : kpntAbbreviation); if (qpli->GetIsSorted()) { // The list is sorted, so we need to move the item to its new location. if (qpli->PutInSortedPosition(m_hvoObj, false)) { int ihvo; pcmw->LoadData(); HvoClsidVec & vhc = pcmw->Records(); for (ihvo = vhc.Size(); --ihvo >= 0; ) { if (vhc[ihvo].hvo == m_hvoObj) break; } Assert(ihvo >= 0); // Should have found item. pcmw->SetCurRecIndex(ihvo); } } // We can't do a sync in this method that opens new editors, so just flag // that it needs to be done. // We need to sync if either name or abbreviation has changed. Even though we may only // be showing one or the other in our lists, there may be overlays or something else // showing the other, so to be safe, we need to do a sync if either changed. dynamic_cast<CleDeSplitChild *>(m_qadsc.Ptr())->SetNeedSync(true); }
/*---------------------------------------------------------------------------------------------- Check to see if the edit box has valid data. if so return true. If not then put up a message to the user, then return false. ----------------------------------------------------------------------------------------------*/ bool CleDeFeString::IsOkToClose(bool fWarn) { CleMainWnd * pcmw = dynamic_cast<CleMainWnd *>(m_qadsc->MainWindow()); Assert(pcmw); IVwSelectionPtr qvwsel; CheckHr(m_qrootb->get_Selection(&qvwsel)); if (qvwsel) { ComBool fOk; CheckHr(qvwsel->Commit(&fOk)); } PossListInfoPtr qpli = pcmw->GetPossListInfoPtr(); int ipss = qpli->GetIndexFromId(m_hvoObj); StrUni stuNew; const OLECHAR * prgwch; int cch; ITsStringPtr qtss; CustViewDaPtr qcvd; GetDataAccess(&qcvd); AssertPtr(qcvd); int ws = m_qsvc->WritingSystems()[0]; CheckHr(qcvd->get_MultiStringAlt(m_hvoObj, m_flid, ws, &qtss)); Assert(qtss); qtss->LockText(&prgwch, &cch); qtss->UnlockText(prgwch); // Trim leading and trailing space characters. UnicodeString ust(prgwch, cch); ust.trim(); stuNew.Assign(ust.getBuffer(), ust.length()); // Obtain pointer to IOleDbEncap interface. IOleDbEncapPtr qode; IOleDbCommandPtr qodc; StrUni stuSql; ComBool fIsNull; ComBool fMoreRows; AssertPtr(m_qadsc->MainWindow()); AfLpInfo * plpi = m_qadsc->MainWindow()->GetLpInfo(); AssertPtr(plpi); AfDbInfo * pdbi = plpi->GetDbInfo(); AssertPtr(pdbi); pdbi->GetDbAccess(&qode); AssertPtr(qode); CheckHr(qode->CreateCommand(&qodc)); int cpii = qpli->GetCount(); if ((m_flid == kflidCmPossibility_Name) || (m_flid == kflidCmPossibility_Abbreviation)) { // Make sure it does not have a ":" or a " - " in the string int ich = stuNew.FindStr(L":"); StrUni stuTmp; bool fFixed = false; while (ich > 0) { stuNew.Replace(ich,ich + 1,"-"); fFixed = true; ich = stuNew.FindStr(L":"); } ich = stuNew.FindStr(L" - "); while (ich > 0) { stuNew.Replace(ich,ich + 3,"-"); fFixed = true; ich = stuNew.FindStr(L" - "); } if (fFixed) { if (fWarn) { ITsStrFactoryPtr qtsf; qtsf.CreateInstance(CLSID_TsStrFactory); qtsf->MakeStringRgch(stuNew.Chars(), stuNew.Length(), pcmw->UserWs(), &qtss); CheckHr(qcvd->SetMultiStringAlt(m_hvoObj, m_flid, ws, qtss)); CheckHr(qcvd->PropChanged(NULL, kpctNotifyAll, m_hvoObj, m_flid, 0, 1, 1)); StrApp strMsg(kstidFixedStr); StrApp strTitle(kstidFixedStrTitle); ::MessageBox(m_hwnd, strMsg.Chars(), strTitle.Chars(), MB_OK | MB_ICONINFORMATION); } return false; } } if (qpli->GetAllowDup()) return true; ILgWritingSystemFactoryPtr qwsf; pdbi->GetLgWritingSystemFactory(&qwsf); AssertPtr(qwsf); switch (m_flid) { case kflidCmPossibility_Name: { for (int ipii = 0; ipii < cpii; ipii++) { if (ipii == ipss) continue; PossItemInfo * ppii = qpli->GetPssFromIndex(ipii); AssertPtr(ppii); StrUni stu; ppii->GetName(stu, kpntName); if (stu == stuNew) { stuSql.Format(L"select ws from CmPossibility_Name " L"where obj = %d and ws = %d", ppii->GetPssId(), ws); CheckHr(qode->CreateCommand(&qodc)); CheckHr(qodc->ExecCommand(stuSql.Bstr(), knSqlStmtSelectWithOneRowset)); CheckHr(qodc->GetRowset(0)); CheckHr(qodc->NextRow(&fMoreRows)); if (fMoreRows) { if (fWarn) { // this name already exists IWritingSystemPtr qws; CheckHr(qwsf->get_EngineOrNull(ws, &qws)); AssertPtr(qws); SmartBstr sbstr; qws->get_Name(ws, &sbstr); StrUni stu(kstidDupItemName); StrUni stuMsg; stuMsg.Format(stu,sbstr.Chars()); StrApp str(stuMsg); StrApp strTitle(kstidDupItemTitle); ::MessageBox(m_hwnd, str.Chars(), strTitle.Chars(), MB_OK | MB_ICONINFORMATION); } return false; } } } break; } case kflidCmPossibility_Abbreviation: { for (int ipii = 0; ipii < cpii; ipii++) { if (ipii == ipss) continue; PossItemInfo * ppii = qpli->GetPssFromIndex(ipii); AssertPtr(ppii); StrUni stu; ppii->GetName(stu, kpntAbbreviation); if (stu == stuNew) { stuSql.Format(L"select ws from CmPossibility_Abbreviation " L"where obj = %d and ws = %d", ppii->GetPssId(), ws); CheckHr(qode->CreateCommand(&qodc)); CheckHr(qodc->ExecCommand(stuSql.Bstr(), knSqlStmtSelectWithOneRowset)); CheckHr(qodc->GetRowset(0)); CheckHr(qodc->NextRow(&fMoreRows)); if (fMoreRows) { if (fWarn) { // this abbreviation already exists IWritingSystemPtr qws; CheckHr(qwsf->get_EngineOrNull(ws, &qws)); AssertPtr(qws); SmartBstr sbstr; qws->get_Name(ws, &sbstr); StrUni stu(kstidDupItemAbbr); StrUni stuMsg; stuMsg.Format(stu,sbstr.Chars()); StrApp str(stuMsg); StrApp strTitle(kstidDupItemTitle); ::MessageBox(m_hwnd, str.Chars(), strTitle.Chars(), MB_OK | MB_ICONINFORMATION); } return false; } } } break; } } return true; }