// //---------------------------------------------------------------------------- // ObjectComponents // (C) Copyright 1994 by Borland International, All Rights Reserved // // Implementation of TOcView Class //---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include DIAG_DECLARE_GROUP(OcRefCount); const char DocContent[] = "All"; TOcView::TOcView(TOcDocument& doc, TRegList* regList, IUnknown* outer) : OcApp(doc.OcApp), Win(0), OcDocument(doc), ActivePart(0), LinkFormat(-1), RegList(regList), OcData(0), Options(0), #if defined(BI_DATA_NEAR) WinTitle(*new string), Origin(*new TPoint(0,0)), Extent(*new TSize(0,0)), FormatList(*new TOcFormatList), OrgTitle(*new TString) #else Origin(0,0), Extent(0,0) #endif { BContainer = 0; BDocumentI = 0; BDocument = 0; BLDocumentI = 0; SetOuter(outer); AddRef(); // TUnknown defaults to 0, we need 1 if (regList) RegisterClipFormats(*regList); // Necessary to initialize TOcPart for linking // OcDocument.SetActiveView(this); if (SUCCEEDED(OcApp.BOleComponentCreate(&BDocument, (IUnknown*)(IBContainer*)this, cidBOleDocument))) { BDocument->QueryInterface(IID_IBDocument, &(LPVOID)BDocumentI); Release(); } if (SUCCEEDED(OcApp.BOleComponentCreate(&BContainer, (IUnknown*)(IBContainer*)this, cidBOleContainer))) { if (regList) { const char* progid = regList->Lookup(OcApp.IsOptionSet(amDebug) ? "debugprogid" : "progid"); if (progid && SUCCEEDED(BContainer->QueryInterface(IID_IBRootLinkable, &(LPVOID)BLDocumentI))) { Release(); BLDocumentI->Init((TOcView*)this, OleStr(progid)); } } } TRACEX(OcRefCount, 1, "TOcView() @" << (void*)this); } TOcView::~TOcView() { Shutdown(); #if defined(BI_DATA_NEAR) delete &WinTitle; delete &FormatList; delete &Origin; delete &Extent; delete &OrgTitle; #endif } // // called from destructor of this class or of derived class to release helpers // void TOcView::Shutdown() { if (BContainer) { BContainer->Release(); BContainer = 0; } if (BDocument) { BDocument->Release(); BDocument = 0; } } // // Should only be called by the owner/creator of this object // void TOcView::ReleaseObject() { Release(); Win = 0; } // // Callback from TUnknown's implementation of QueryInterface // HRESULT TOcView::QueryObject(const IID far& iid, void far* far* iface) { PRECONDITION(iface); HRESULT hr; // interfaces // SUCCEEDED(hr = IBContainer_QueryInterface(this, iid, iface)) || SUCCEEDED(hr = IBContains_QueryInterface(this, iid, iface)) || SUCCEEDED(hr = IBDataConsumer_QueryInterface(this, iid, iface)) || SUCCEEDED(hr = IBDropDest_QueryInterface(this, iid, iface)) || SUCCEEDED(hr = IBDataNegotiator_QueryInterface(this, iid, iface)) // helpers (BContainer needed for embed/link from file) // || (BContainer && SUCCEEDED(hr = BContainer->QueryInterface(iid, iface))) || (BDocument && SUCCEEDED(hr = BDocument->QueryInterface(iid, iface))) ; // If the QueryInterface failed, try the TOcLinkView // if (hr == HR_NOINTERFACE && iid == IID_IDataObject) { TOcLinkView* view = GetDocLink(); if (view) hr = view->QueryInterface(iid, iface); } return hr; } //---------------------------------------------------------------------------- void TOcView::SetupWindow(HWND hWin, bool embedded) { // Don't register drag&drop target here since it will do QueryInterface // in ComponentCreate before the outer is set up. RefCount will be messed // up in this case. Keep Win==0 while initing BDocumentI. OcRemView will init // later. // Win = embedded ? 0 : hWin; // Make sure at least the BDocument gets its container & application ptrs // setup // if (BDocumentI) BDocumentI->Init(this); if (Win) Rename(); Win = hWin; EvActivate(true); // default to being the active view on creation } // Obtain a TOcLinkView representing the whole document // TOcLinkView* TOcView::GetDocLink() { // Ask the document whether an TOcLinkView corresponding to the item name // already exists // TOcLinkView* ocLinkView = OcDocument.GetViews().Find(DocContent); // If not, Create an TOcLinkView for the linked doc/item // the TOcLinkView should remember the moniker // if (!ocLinkView) { ocLinkView = new TOcLinkView(this, RegList); OcDocument.GetViews().Add(ocLinkView); ocLinkView->SetMoniker(OleStr(DocContent)); ocLinkView->GetLinkRect(); } return ocLinkView; } void TOcView::EvResize() { if (BDocumentI) BDocumentI->OnResize(); } // // View is shuting down // void TOcView::EvClose() { // Release the data provider object // if (OcData) { OcData->Disconnect(); OcData = 0; } if (BContainer && BDocument && BDocumentI) { // Unregisters drag target // BDocumentI->OnClose(); // Unregisters moniker for this container // if (BLDocumentI) BLDocumentI->OnRename(0, 0); } } // // View is activated/deactivated // void TOcView::EvActivate(bool activate) { // Set the current active document // if (BDocumentI) BDocumentI->OnActivate(activate); if (activate) OcDocument.SetActiveView(this); } // // Returns true if view keeps focus, false if the inplace server got it // bool TOcView::EvSetFocus(bool set) { if (BDocumentI) BDocumentI->OnSetFocus(set); return OcApp.EvSetFocus(set); } bool TOcView::EnumLinks(IBLinkInfo far* far* linkInfo) { PRECONDITION(linkInfo); return BDocumentI ? HRSucceeded(BDocumentI->EnumLinks(linkInfo)) : false; } bool TOcView::BrowseLinks() { return BDocumentI ? HRSucceeded(BDocumentI->BrowseLinks()) : false; } bool TOcView::UpdateLinks() { return BDocumentI ? HRSucceeded(BDocumentI->UpdateLinks()) : false; } void TOcView::Rename() { if (!BLDocumentI || OcDocument.GetName().is_null()) return; // update the file moniker // BLDocumentI->OnRename(0, OleStr(OcDocument.GetName().c_str())); OcDocument.RenameParts(BLDocumentI); } //---------------------------------------------------------------------------- // // Return the client rect for the view window // TRect TOcView::GetWindowRect() const { TRect r; const_cast(this)->GetWindowRect(&r); return r; } // // Scroll this container window a give dx,dy // void TOcView::ScrollWindow(int dx, int dy) { Origin += TPoint(dx, dy); } void TOcView::InvalidatePart(TOcPartChangeInfo& changeInfo) { if (changeInfo.GetPart()) { if (!ForwardEvent(OC_VIEWPARTINVALID, &changeInfo)) ::InvalidateRect(GetWindow(), &(changeInfo.GetPart()->GetRect() - *(TSize*)&GetOrigin()), true); } } // // Activate a given part // bool TOcView::ActivatePart(TOcPart* part) { if (part == ActivePart) return true; if (ActivePart && ActivePart->IsActive()) { ActivePart->Activate(false); ActivePart = 0; } if (part) { if (!part->IsActive() && !part->Activate(true)) return false; ActivePart = part; } return true; } uint32 TOcView::ForwardEvent(int eventId, const void far* param) { return ::SendMessage(GetWindow(), WM_OCEVENT, eventId, (LPARAM)param); } uint32 TOcView::ForwardEvent(int eventId, uint32 param) { return ::SendMessage(GetWindow(), WM_OCEVENT, eventId, param); } //---------------------------------------------------------------------------- // IBContains implementation // // Ask the container to load document named // HRESULT _IFUNC TOcView::Init(LPCOLESTR path) { bool result = (bool)ForwardEvent(OC_VIEWOPENDOC, (const char far*)OleStr(path)); if (result) { // register this document in running object table // OcDocument.SetName(string(OleStr(path))); Rename(); } return HRFailIfZero(result); } HRESULT _IFUNC TOcView::GetPart(IBPart far* far* bpart, LPCOLESTR name) { PRECONDITION(bpart); for (TOcPartCollectionIter i(OcDocument.GetParts()); i; i++) { TOcPart* ocPart = (TOcPart*)i.Current(); if (ocPart && strcmp(ocPart->GetName(), OleStr(name)) == 0) { ocPart->FinishLoading(); // In case the part hasn't been loaded if (SUCCEEDED(ocPart->QueryInterface(IID_IBPart, (LPVOID*)bpart))) { return HR_NOERROR; // now there is one more refcount on ocPart } } } // Ask the document whether an TOcLinkView corresponding to the item name // already exists // TOcLinkView* ocLinkView = OcDocument.GetViews().Find(name); if (ocLinkView) { if (SUCCEEDED(ocLinkView->QueryInterface(IID_IBPart, (LPVOID*)bpart))) { return HR_NOERROR; // now there is one more refcount on ocRemView } else return HR_FAIL; } // If not, Create an TOcLinkView for the linked doc/item // the TOcLinkView should remember the moniker // if (!ocLinkView) { ocLinkView = new TOcLinkView(this, RegList); OcDocument.GetViews().Add(ocLinkView); } ocLinkView->SetMoniker(OleStr(name)); ocLinkView->GetLinkRect(); if (SUCCEEDED(ocLinkView->QueryInterface(IID_IBPart, (LPVOID*)bpart)) && ForwardEvent(OC_VIEWSETLINK, ocLinkView)) { return HR_NOERROR; // now there is one more refcount on ocRemView } return HR_FAIL; } //---------------------------------------------------------------------------- // IBDataNegotiator implementation // // Format count // uint _IFUNC TOcView::CountFormats() { return FormatList.Count(); } // // Format retrieval // HRESULT _IFUNC TOcView::GetFormat(uint index, TOcFormatInfo far* fmt) { PRECONDITION(fmt); // Link source is FormatList[0] // Link source will be the first format returned if Link is 0 // Link source will be the last format returned if Link is -1 // index = (index - LinkFormat) % CountFormats(); FormatList[index]->GetFormatInfo(*fmt); return HR_NOERROR; } //---------------------------------------------------------------------------- // IBWindow implementation HWND _IFUNC TOcView::GetWindow() { return Win; } HRESULT _IFUNC TOcView::GetWindowRect(TRect far* r) { PRECONDITION(r); ::GetClientRect(GetWindow(), r); return HR_NOERROR; } LPCOLESTR _IFUNC TOcView::GetWindowTitle() { // Delegate to app's view window to get its title // OrgTitle = (const char far*)ForwardEvent(OC_VIEWTITLE); return (LPCOLESTR)OrgTitle; } // // Append server's doc title info to our view's window title // void _IFUNC TOcView::AppendWindowTitle(LPCOLESTR title) { WinTitle = (const char far*)OleStr(GetWindowTitle()); char in[32]; ::LoadString(_hInstance, IDS_IN, in, sizeof in); string newTitle = (const char far*)OleStr(title); newTitle += in; newTitle += WinTitle; ForwardEvent(OC_VIEWSETTITLE, newTitle.c_str()); } HRESULT _IFUNC TOcView::SetStatusText(LPCOLESTR /*text*/) { return HR_FAIL; } HRESULT _IFUNC TOcView::RequestBorderSpace(const TRect far* space) { PRECONDITION(space); // Let individual views decide this // return HRFailIfZero((bool)ForwardEvent(OC_VIEWBORDERSPACEREQ, space)); } HRESULT _IFUNC TOcView::SetBorderSpace(const TRect far* space) { PRECONDITION(space); // Let individual views do this // return HRFailIfZero((bool)ForwardEvent(OC_VIEWBORDERSPACESET, space)); } HRESULT _IFUNC TOcView::InsertContainerMenus(HMENU, TOcMenuWidths far*) { return HR_FAIL; } HRESULT _IFUNC TOcView::SetFrameMenu(HMENU) { return HR_FAIL; } // // The in-place server is done. Tell the container to restore its normal UI. // void _IFUNC TOcView::RestoreUI() { ForwardEvent(OC_VIEWSETTITLE, WinTitle.c_str()); } HRESULT _IFUNC TOcView::Accelerator(MSG far*) { return HR_FAIL; } HRESULT _IFUNC TOcView::GetAccelerators(HACCEL far*, int far*) { return HR_FAIL; } //---------------------------------------------------------------------------- // IBDropDest implementation // // Drop a part onto this view. Creates the part based on initInfo, activating // it as appropriate // HRESULT _IFUNC TOcView::Drop(TOcInitInfo far* initInfo, TPoint far* where, const TRect far* objPos) { PRECONDITION(initInfo && where && objPos); initInfo->Container = this; TPoint awhere(*where); TRect aobjPos(*objPos); TOcDragDrop dd = { (TOcInitInfo far*)initInfo, &awhere, &aobjPos }; if (PasteNative((TOcInitInfo&)*initInfo, where)) return HR_NOERROR; // Make sure that the view will accept this drop // if (!ForwardEvent(OC_VIEWDROP, &dd)) return HR_FAIL; // Create part now that view approved. BDocument calls AddSite on all views. // try { new TOcPart(OcDocument, *dd.InitInfo, aobjPos); } catch (...) { return HR_FAIL; } Rename(); return HR_NOERROR; } // // Provide feedback to the users drag action in our container window // void _IFUNC TOcView::DragFeedback(TPoint far* where, const TRect far* objPos, TOcMouseAction /*action*/, uint, HRESULT& hr) { PRECONDITION(where && objPos); TPoint awhere(*where); TRect aobjPos(*objPos); TOcDragDrop dd = { 0, &awhere, &aobjPos }; hr = HRFailIfZero((int)ForwardEvent(OC_VIEWDRAG, &dd)); } // // Ask the container view window to scroll itself in a given direction. Asked // by the server when dragging or working in a clipped site. // HRESULT _IFUNC TOcView::Scroll(TOcScrollDir scrollDir) { // Have the real view do the work here. // if (!ForwardEvent(OC_VIEWSCROLL, scrollDir)) return HR_FALSE; return HR_NOERROR; } HRESULT _IFUNC TOcView::GetScrollRect(TRect far*) { return HR_NOERROR; } //---------------------------------------------------------------------------- // IBContainer implementation // // Locate the drop destination object. For default OC, it is just this view. // Other extensions might have subtargets within the view. // HRESULT _IFUNC TOcView::FindDropDest(TPoint far*, IBDropDest far* far* dropDest) { *dropDest = this; return HR_NOERROR; } HRESULT _IFUNC TOcView::BringToFront() { // See if we are in an MDI child & if so activate it // HWND hMdiChild = ::GetParent(GetWindow()); if (hMdiChild) { HWND hMdiClient = ::GetParent(hMdiChild); if (hMdiClient) { HWND hMdiFrame = ::GetParent(hMdiClient); while (::GetParent(hMdiFrame)) { hMdiChild = hMdiClient; hMdiClient = hMdiFrame; hMdiFrame = ::GetParent(hMdiFrame); } ::SendMessage(hMdiClient, WM_MDIACTIVATE, (WPARAM)hMdiChild, 0); } } // Bring our app frame to the top, show it & give it focus. Also make sure // that this view is on top & visible // ::SetWindowPos(OcApp.GetWindow(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW); ::SetFocus(OcApp.GetWindow()); ::ShowWindow(GetWindow(), SW_SHOWNORMAL); ::SetWindowPos(GetWindow(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW); return HR_NOERROR; } HRESULT _IFUNC TOcView::AllowInPlace() { if (IsOptionSet(voNoInPlace)) return HR_FALSE; else return HR_NOERROR; } //---------------------------------------------------------------------------- // Clipboard related // // Register the clipboard formats supported // bool TOcView::RegisterClipFormats(TRegList& regList) { // Register link source first // uint cfLinkSource = ::RegisterClipboardFormat("Link Source"); if (cfLinkSource) FormatList.Add(new TOcFormat(cfLinkSource, "%s", "%s", 4 /*BOLE_MED_STREAM*/, true)); char key[32]; char val[128]; char* buf; uint i = 0; bool succ = true; while (true) { wsprintf(key, "format%d", i); buf = const_cast(regList[key]); if (!buf) break; else { // parse the value string // strcpy(val, buf); buf = val; TOcFormat* format = new TOcFormat; for (int i = 0; i < 3; i++) { char* current = strchr(buf, ','); if (!current) { succ = false; break; // error } *current = 0; switch (i) { case 0: // Format id or name if (isdigit(*buf)) { uint id = atoi(buf); format->SetFormatId(id); format->SetFormatName(id - 1, OcApp); } else { // register the user defined clipboard format uint cf = ::RegisterClipboardFormat(buf); if (cf == cfLinkSource) format->SetLinkable(); format->SetFormatId(cf); format->SetFormatName(buf, OcApp); } break; case 1: // Aspect format->SetAspect((uint)atoi(buf)); break; case 2: format->SetMedium((uint)atoi(buf)); // Storage medium format->SetDirection((uint)atoi(current+1)); // Direction break; } // switch buf = current + 1; } // for if (succ) FormatList.Add(format); // Add to the format list else delete format; } // else i++; } // while return succ; } bool TOcView::BrowseClipboard(TOcInitInfo& initInfo) { return OcApp.BrowseClipboard(initInfo); } // // Paste native data into the container // bool TOcView::PasteNative(TOcInitInfo& init, TPoint far* where) { bool result = false; if ((init.Where == iwHandle) && (init.How == ihEmbed)) { // could be native data TOcFormat* format = FormatList.Find(init.Handle.DataFormat); if (!format) { return false; // not my native data } TOcFormatData formatData(*format, 0, init.Handle.Data, true, where); result = (bool)ForwardEvent(OC_VIEWCLIPDATA, &formatData); if (result) init.ReleaseDataObject(); } return result; } bool TOcView::Paste(bool linking) { LinkFormat = linking ? 0 : -1; TOcInitInfo init(this); bool result = OcApp.Paste(init); if (result) { result = PasteNative(init); if (!result) result = (bool)ForwardEvent(OC_VIEWPASTEOBJECT, &init); } return result; } //----------------------------------------------------------------------------- // TOcFormat // TOcFormat::TOcFormat() { char fstr[] = "%s"; Id = 0; RegName[0] = 0; strcpy(Name, fstr); strcpy(ResultName, fstr); Medium = ocrNull; IsLinkable = false; Aspect = 1; // content Direction = 1; // get } TOcFormat::TOcFormat(uint id, char far* name, char far* resultName, uint medium, bool isLinkable, uint aspect, uint direction) { Id = (WORD)id; Medium = (ocrMedium)medium; IsLinkable = isLinkable; Aspect = aspect; Direction = direction; RegName[0] = 0; strcpy(Name, name); strcpy(ResultName, resultName); } void TOcFormat::operator =(const TOcFormatInfo& f) { Id = f.Id; strcpy(Name, OleStr(f.Name)); strcpy(ResultName, OleStr(f.ResultName)); Medium = f.Medium; IsLinkable = f.IsLinkable; } void TOcFormat::GetFormatInfo(TOcFormatInfo far& f) { f.Id = uint16(Id); #if defined(BI_OLECHAR_WIDE) // lstrcpyW(f.Name, OleStr(Name)); memcpy(f.Name, (LPCWSTR)OleStr(Name), (strlen(Name)+1)*2); // lstrcpyW(f.ResultName, OleStr(ResultName)); memcpy(f.ResultName, (LPCWSTR)OleStr(ResultName), (strlen(ResultName)+1)*2); #else strncpy(f.Name, Name, sizeof Name); strncpy(f.ResultName, ResultName, sizeof ResultName); #endif f.Medium = (ocrMedium)Medium; f.IsLinkable = (BOOL)IsLinkable; } void TOcFormat::SetFormatName(char far* name, TOcApp& ocApp) { TOcFormatName* formatName = ocApp.GetNameList()[name]; if (!formatName) return; strcpy(RegName, name); strcpy(Name, formatName->GetName()); strcpy(ResultName, formatName->GetResultName()); } void TOcFormat::SetFormatName(uint id, TOcApp& ocApp) { TOcFormatName* formatName = ocApp.GetNameList()[id]; if (!formatName) return; strcpy(Name, formatName->GetName()); strcpy(ResultName, formatName->GetResultName()); } //---------------------------------------------------------------------------- // TOcFormatList // TOcFormatList::TOcFormatList() : TICVectorImp(10, 0) { } TOcFormatList::~TOcFormatList() { Clear(); } TOcFormat* TOcFormatList::Find(uint const id) const { for (TOcFormatListIter j(*this); j; j++) { TOcFormat* format = (TOcFormat*)j.Current(); if (format && (format->GetFormatId() == id)) { return format; } } return 0; } //---------------------------------------------------------------------------- // TOcScaleFactor // TOcScaleFactor::TOcScaleFactor() : SiteSize(1, 1), PartSize(1, 1) { } TOcScaleFactor::TOcScaleFactor(const TRect& siteRect, const TSize& partSize) { SiteSize.cx = siteRect.Width(); SiteSize.cy = siteRect.Height(); PartSize = partSize; } TOcScaleFactor::TOcScaleFactor(const TOcScaleInfo far& scale) { *this = scale; } // // Assign a BOle structure to this scale factor // TOcScaleFactor& TOcScaleFactor::operator =(const TOcScaleInfo far& scaleInfo) { SiteSize.cx = (int)scaleInfo.xN; SiteSize.cy = (int)scaleInfo.yN; PartSize.cx = (int)scaleInfo.xD; PartSize.cy = (int)scaleInfo.yD; return *this; } // // Assign one TOcScaleFactor to another // TOcScaleFactor& TOcScaleFactor::operator =(const TOcScaleFactor& scaleFactor) { SiteSize = scaleFactor.SiteSize; PartSize = scaleFactor.PartSize; return *this; } // // Copy a BOle scale factor structure // void TOcScaleFactor::GetScaleFactor(TOcScaleInfo far& scaleInfo) const { scaleInfo.xN = SiteSize.cx; scaleInfo.yN = SiteSize.cy; scaleInfo.xD = PartSize.cx; scaleInfo.yD = PartSize.cy; } // // Whether there is zoom factor // bool TOcScaleFactor::IsZoomed() { return SiteSize != PartSize; } // // Change the scaling factor // void TOcScaleFactor::SetScale(uint16 percent) { PartSize.cx = PartSize.cy = 100; SiteSize.cx = SiteSize.cy = percent; } // // Get the scale percentage // uint16 TOcScaleFactor::GetScale() { return (uint16)(((uint32)SiteSize.cx * 100 + (PartSize.cx >> 1)) / PartSize.cx); } // // Set scaling factor to 1 // void TOcScaleFactor::Reset() { PartSize.cx = PartSize.cy = 1; SiteSize.cx = SiteSize.cy = 1; }