protected virtual IVsTextLines GetTextBuffer(System.IntPtr docDataExisting, string filename) { IVsTextLines textLines; if (docDataExisting == IntPtr.Zero) { // Create a new IVsTextLines buffer. Type textLinesType = typeof(IVsTextLines); Guid riid = textLinesType.GUID; Guid clsid = typeof(VsTextBufferClass).GUID; textLines = _package.CreateInstance(ref clsid, ref riid, textLinesType) as IVsTextLines; // set the buffer's site ((IObjectWithSite)textLines).SetSite(_serviceProvider.GetService(typeof(IOleServiceProvider))); } else { // Use the existing text buffer Object dataObject = Marshal.GetObjectForIUnknown(docDataExisting); textLines = dataObject as IVsTextLines; if (textLines == null) { // Try get the text buffer from textbuffer provider IVsTextBufferProvider textBufferProvider = dataObject as IVsTextBufferProvider; if (textBufferProvider != null) { textBufferProvider.GetTextBuffer(out textLines); } } if (textLines == null) { // Unknown docData type then, so we have to force VS to close the other editor. throw Marshal.GetExceptionForHR(VSConstants.VS_E_INCOMPATIBLEDOCDATA); } } return(textLines); }
/// <include file='doc\EditorFactory.uex' path='docs/doc[@for="EditorFactory.CreateEditorInstance"]/*' /> /// <summary> /// This method checks to see if the specified file is one that your editor supports /// and if so, creates the core text editor and associated your language service /// with it. To figure out if the file is one that your editor supports it performs /// the following check: /// <list> /// <item> /// Call IsRegisteredExtension to see if the file extension is explicitly /// registered to your editor. /// </item> /// <item> /// Call GetUserDefinedEditor to see if the user has explicitly mapped the /// extension to your editor. /// </item> /// <item> /// If your editor registered the "*" extension, then it also calls /// IsFileExtensionWeShouldEditAnyway and IsOurFileFormat to let you sniff /// the file and see if you think it contains stuff that your editor recognizes /// </item> /// </list> /// If all this is true then it goes ahead with the next step which is to /// get an IVsTextLines buffer and set it up as follows: /// <list> /// <item> /// If existingDocData is non-null then it checks to see if it can get an /// IVsTextLines buffer from this docData, and if not, returns VS_E_INCOMPATIBLEDOCDATA. /// Otherwise it creates a new VsTextBufferClass. /// </item> /// Calls IVsUserData.SetData on the IVsTextLines buffer with any code page prompt /// flags you have provided via the CodePagePrompt property. /// </list> /// <list> /// Calls SetLanguageServiceID to pass in your language service Guid and /// sets the GuidVSBufferDetectLangSid IVsUserData to false to stop the core /// text editor from looking up a different language service. /// </list> /// Lastly it calls CreateEditorView to create the docView. /// </summary> public virtual int CreateEditorInstance(uint createDocFlags, string moniker, string physicalView, IVsHierarchy pHier, uint itemid, IntPtr existingDocData, out IntPtr docView, out IntPtr docData, out string editorCaption, out Guid cmdUI, out int cancelled) { docView = IntPtr.Zero; docData = IntPtr.Zero; editorCaption = null; cmdUI = Guid.Empty; cancelled = 0; int hr = VSErr.S_OK; if (this.promptFlags == __PROMPTONLOADFLAGS.codepagePrompt && existingDocData != IntPtr.Zero) { //since we are trying to open with encoding just return hr = (int)VSConstants.VS_E_INCOMPATIBLEDOCDATA; goto cleanup; } bool takeover = false; if (!string.IsNullOrEmpty(moniker)) { string ext = Path.GetExtension(moniker); docData = IntPtr.Zero; docView = IntPtr.Zero; editorCaption = null; bool openSpecific = (createDocFlags & (uint)__VSCREATEEDITORFLAGS2.CEF_OPENSPECIFIC) != 0; bool isOurs = IsRegisteredExtension(ext); bool isUserDefined = (GetUserDefinedEditor(ext) == this.GetType().GUID); // If this file extension belongs to a different language service, then we should not open it, // unless the user specifically requested our editor in the Open With... dialog. if (!isOurs && !isUserDefined && !this.IsFileExtensionWeShouldEditAnyway(ext) && !openSpecific) { return(VSConstants.VS_E_UNSUPPORTEDFORMAT); } takeover = (CheckAllFileTypes() && !isOurs); if (takeover && !isOurs && !isUserDefined && !openSpecific) { if (!IsOurFileFormat(moniker)) { return(VSConstants.VS_E_UNSUPPORTEDFORMAT); } } } IVsTextLines buffer = null; if (existingDocData != IntPtr.Zero) { object dataObject = Marshal.GetObjectForIUnknown(existingDocData); buffer = dataObject as IVsTextLines; if (buffer == null) { IVsTextBufferProvider bp = dataObject as IVsTextBufferProvider; if (bp != null) { Marshal.ThrowExceptionForHR(bp.GetTextBuffer(out buffer)); } } if (buffer == null) { // unknown docData type then, so we have to force VS to close the other editor. hr = VSConstants.VS_E_INCOMPATIBLEDOCDATA; goto cleanup; } } else { // Create a new IVsTextLines buffer. Type textLinesType = typeof(IVsTextLines); Guid riid = textLinesType.GUID; Guid clsid = typeof(VsTextBufferClass).GUID; buffer = (IVsTextLines)package.CreateInstance(ref clsid, ref riid, textLinesType); if (!string.IsNullOrEmpty(moniker)) { IVsUserData iud = buffer as IVsUserData; if (iud != null) { Guid GUID_VsBufferMoniker = typeof(IVsUserData).GUID; // Must be set in time for language service GetColorizer call in case the colorizer // is file name dependent. Marshal.ThrowExceptionForHR(iud.SetData(ref GUID_VsBufferMoniker, moniker)); } } IObjectWithSite ows = buffer as IObjectWithSite; if (ows != null) { ows.SetSite(this.site.GetService(typeof(IOleServiceProvider))); } } if (this.promptFlags == __PROMPTONLOADFLAGS.codepagePrompt && buffer is IVsUserData) { IVsUserData iud = (IVsUserData)buffer; Guid GUID_VsBufferEncodingPromptOnLoad = new Guid(0x99ec03f0, 0xc843, 0x4c09, 0xbe, 0x74, 0xcd, 0xca, 0x51, 0x58, 0xd3, 0x6c); Marshal.ThrowExceptionForHR(iud.SetData(ref GUID_VsBufferEncodingPromptOnLoad, (uint)this.CodePagePrompt)); } Guid langSid = GetLanguageServiceGuid(); if (langSid != Guid.Empty) { Guid vsCoreSid = new Guid("{8239bec4-ee87-11d0-8c98-00c04fc2ab22}"); Guid currentSid; Marshal.ThrowExceptionForHR(buffer.GetLanguageServiceID(out currentSid)); // If the language service is set to the default SID, then // set it to our language if (currentSid == vsCoreSid) { Marshal.ThrowExceptionForHR(buffer.SetLanguageServiceID(ref langSid)); } else if (currentSid != langSid) { // Some other language service has it, so return VS_E_INCOMPATIBLEDOCDATA hr = VSConstants.VS_E_INCOMPATIBLEDOCDATA; goto cleanup; } takeover = true; } if (takeover) { IVsUserData vud = (IVsUserData)buffer; Guid bufferDetectLang = GuidVSBufferDetectLangSid; Marshal.ThrowExceptionForHR(vud.SetData(ref bufferDetectLang, false)); } if (existingDocData != IntPtr.Zero) { docData = existingDocData; Marshal.AddRef(docData); } else { docData = Marshal.GetIUnknownForObject(buffer); } docView = CreateEditorView(moniker, buffer, physicalView, out editorCaption, out cmdUI); if (docView == IntPtr.Zero) { // We couldn't create the view, so return this special error code so // VS can try another editor factory. hr = VSConstants.VS_E_UNSUPPORTEDFORMAT; } cleanup: if (docView == IntPtr.Zero) { if (existingDocData != docData && docData != IntPtr.Zero) { Marshal.Release(docData); docData = IntPtr.Zero; } } return(hr); }