/* Copyright (C) 2014-2019 de4dot@gmail.com This file is part of dnSpy dnSpy is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. dnSpy is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with dnSpy. If not, see . */ using System; using System.Collections.Specialized; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using dnlib.DotNet; using dnSpy.AsmEditor.Commands; using dnSpy.AsmEditor.Properties; using dnSpy.AsmEditor.ViewHelpers; using dnSpy.Contracts.MVVM; using dnSpy.Contracts.Text; namespace dnSpy.AsmEditor.MethodBody { sealed class ExceptionHandlersListHelper : ListBoxHelperBase { readonly TypeSigCreator typeSigCreator; protected override string AddNewBeforeSelectionMessage => dnSpy_AsmEditor_Resources.EH_Command1; protected override string AddNewAfterSelectionMessage => dnSpy_AsmEditor_Resources.EH_Command2; protected override string AppendNewMessage => dnSpy_AsmEditor_Resources.EH_Command3; protected override string RemoveSingularMessage => dnSpy_AsmEditor_Resources.EH_Command4; protected override string RemovePluralMessage => dnSpy_AsmEditor_Resources.EH_Command5; protected override string RemoveAllMessage => dnSpy_AsmEditor_Resources.EH_Command6; public ExceptionHandlersListHelper(ListView listView, Window ownerWindow) : base(listView) => typeSigCreator = new TypeSigCreator(ownerWindow); protected override ExceptionHandlerVM[] GetSelectedItems() => listBox.SelectedItems.Cast().ToArray(); protected override void OnDataContextChangedInternal(object dataContext) { coll = ((MethodBodyVM)dataContext).CilBodyVM.ExceptionHandlersListVM; coll.CollectionChanged += coll_CollectionChanged; InitializeExceptionHandlers(coll); AddStandardMenuHandlers(); Add(new ContextMenuHandler { Header = "res:CopyMetaDataToken", HeaderPlural = "res:CopyMetaDataTokens", Command = new RelayCommand(a => CopyCatchTypeMDTokens((ExceptionHandlerVM[])a!), a => CopyCatchTypeMDTokensCanExecute((ExceptionHandlerVM[])a!)), InputGestureText = "res:ShortCutKeyCtrlM", Modifiers = ModifierKeys.Control, Key = Key.M, }); } void CopyCatchTypeMDTokens(ExceptionHandlerVM[] ehs) { var sb = new StringBuilder(); int lines = 0; for (int i = 0; i < ehs.Length; i++) { uint? token = GetCatchTypeToken(ehs[i].CatchType); if (token is null) continue; if (lines++ > 0) sb.AppendLine(); sb.Append($"0x{token.Value:X8}"); } if (lines > 1) sb.AppendLine(); var text = sb.ToString(); if (text.Length > 0) { try { Clipboard.SetText(text); } catch (ExternalException) { } } } bool CopyCatchTypeMDTokensCanExecute(ExceptionHandlerVM[] ehs) => ehs.Any(a => GetCatchTypeToken(a.CatchType) is not null); static uint? GetCatchTypeToken(ITypeDefOrRef? type) => type is null ? (uint?)null : type.MDToken.Raw; void coll_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { if (e.NewItems is not null) InitializeExceptionHandlers(e.NewItems); } void InitializeExceptionHandlers(System.Collections.IList list) { foreach (ExceptionHandlerVM? eh in list) eh!.TypeSigCreator = typeSigCreator; } protected override void CopyItemsAsText(ExceptionHandlerVM[] ehs) { Array.Sort(ehs, (a, b) => a.Index.CompareTo(b.Index)); var output = new StringBuilderTextColorOutput(); for (int i = 0; i < ehs.Length; i++) { if (i > 0) output.WriteLine(); var eh = ehs[i]; output.Write(BoxedTextColor.Number, eh.Index.ToString()); output.Write(BoxedTextColor.Text, "\t"); BodyUtils.WriteObject(output, eh.TryStartVM.SelectedItem); output.Write(BoxedTextColor.Text, "\t"); BodyUtils.WriteObject(output, eh.TryEndVM.SelectedItem); output.Write(BoxedTextColor.Text, "\t"); BodyUtils.WriteObject(output, eh.FilterStartVM.SelectedItem); output.Write(BoxedTextColor.Text, "\t"); BodyUtils.WriteObject(output, eh.HandlerStartVM.SelectedItem); output.Write(BoxedTextColor.Text, "\t"); BodyUtils.WriteObject(output, eh.HandlerEndVM.SelectedItem); output.Write(BoxedTextColor.Text, "\t"); output.Write(BoxedTextColor.Text, ((EnumVM)eh.HandlerTypeVM.Items[eh.HandlerTypeVM.SelectedIndex]).Name); output.Write(BoxedTextColor.Text, "\t"); BodyUtils.WriteObject(output, eh.CatchType); } if (ehs.Length > 1) output.WriteLine(); try { Clipboard.SetText(output.ToString()); } catch (ExternalException) { } } } }