source: branches/eraser6/DefaultPlugins/CustomMethodPassEditor.cs @ 585

Revision 585, 5.8 KB checked in by lowjoel, 6 years ago (diff)

Fully implemented the Custom method editor and its associated error handling code

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Drawing;
5using System.Data;
6using System.Linq;
7using System.Text;
8using System.Windows.Forms;
9using Eraser.Util;
10
11namespace Eraser.DefaultPlugins
12{
13    public partial class CustomMethodPassEditor : UserControl
14    {
15        public CustomMethodPassEditor()
16        {
17            InitializeComponent();
18        }
19
20        /// <summary>
21        /// The different pass types which this editor can edit.
22        /// </summary>
23        public enum PassTypes
24        {
25            TEXT,
26            HEX,
27            RANDOM
28        }
29
30        /// <summary>
31        /// Gets or sets the type of this pass.
32        /// </summary>
33        [Description("The type of pass being edited")]
34        [Category("Behavior")]
35        public PassTypes PassType
36        {
37            get
38            {
39                if (passTypeText.Checked)
40                    return PassTypes.TEXT;
41                else if (passTypeHex.Checked)
42                    return PassTypes.HEX;
43                return PassTypes.RANDOM;
44            }
45            set
46            {
47                switch (value)
48                {
49                    case PassTypes.TEXT:
50                    case PassTypes.HEX:
51                        UpdateEditorSuitably();
52                        break;
53                    default:
54                        passTypeRandom.Checked = true;
55                        break;
56                }
57            }
58        }
59
60        [Description("The pass constant being edited.")]
61        [Category("Behavior")]
62        public byte[] PassData
63        {
64            get
65            {
66                //Return the cached string if the pass is a constant-writing pass.
67                switch (PassType)
68                {
69                    case PassTypes.RANDOM:
70                        return null;
71                    default:
72                        return passData;
73                }
74            }
75            set
76            {
77                //Store the data into our class variable, so it can be edited.
78                passData = value;
79
80                //Update the UI
81                UpdateEditorSuitably();
82            }
83        }
84
85
86        /// <summary>
87        /// Parses a string either for UTF-8 characters or hexadecimal digits, returning
88        /// its value in a byte array.
89        /// </summary>
90        /// <param name="text">The string to parse.</param>
91        /// <param name="parseHex">Parses <paramref name="text"/> as a string of
92        /// hexadecimal numbers if true; a UTF-8 string otherwise.</param>
93        /// <returns>An array containing the byte-wise representation of the input
94        /// string.</returns>
95        /// <exception cref="FormatException">Throws a <see cref="System.FormatException"/>
96        /// if the array cannot be displayed in the given representation.</exception>
97        private static byte[] GetConstantArray(string text, bool parseHex)
98        {
99            if (parseHex)
100            {
101                string str = text.Replace(" ", "").ToUpper();
102                List<byte> passConstantList = new List<byte>();
103
104                if (str.Length >= 2)
105                {
106                    for (int i = 0, j = str.Length - 2; i < j; i += 2)
107                        passConstantList.Add(Convert.ToByte(str.Substring(i, 2), 16));
108                    passConstantList.Add(Convert.ToByte(str.Substring(str.Length - 2), 16));
109                }
110
111                byte[] result = new byte[passConstantList.Count];
112                passConstantList.CopyTo(result);
113                return result;
114            }
115
116            return Encoding.UTF8.GetBytes(text);
117        }
118
119        /// <summary>
120        /// Displays the pass constant stored by the <see cref="GetConstantArray"/>
121        /// function.
122        /// </summary>
123        /// <param name="array">The array containing the constant to display.</param>
124        /// <param name="asHex">Sets whether the array should be displayed as a
125        /// hexadecimal string.</param>
126        /// <exception cref="System.FormatException">Thrown when the constant string
127        /// cannot be parsed as a hexadecimal string.</exception>
128        /// <returns>A string containing the user-visible representation of the
129        /// input array.</returns>
130        private static string GetConstantStr(byte[] array, bool asHex)
131        {
132            if (array == null || array.Length == 0)
133                return string.Empty;
134
135            if (asHex)
136            {
137                StringBuilder displayText = new StringBuilder();
138                foreach (byte b in array)
139                    displayText.Append(string.Format("{0,2} ", Convert.ToString(b, 16)));
140                return displayText.ToString();
141            }
142
143            UTF8Encoding encoding = new UTF8Encoding(false, true);
144            return encoding.GetString(array);
145        }
146
147        /// <summary>
148        /// Updates the editor with the pass constant, choosing a suitable display
149        /// format based on the data.
150        /// </summary>
151        private void UpdateEditorSuitably()
152        {
153            //Try to display the pass data as a string, if possible, since it is
154            //easier for users to understand.
155            if (passData != null && passData.Length > 0)
156                try
157                {
158                    passTxt.Text = GetConstantStr(passData, false);
159                    passTypeText.Checked = true;
160                }
161                catch (DecoderFallbackException)
162                {
163                    passTxt.Text = GetConstantStr(passData, true);
164                    passTypeHex.Checked = true;
165                }
166        }
167
168        /// <summary>
169        /// Updates the editor with the pass constant in the format requested by the user.
170        /// </summary>
171        private void UpdateEditor()
172        {
173            try
174            {
175                //Display the constant on the Text Field, if the pass type requires it.
176                if (!passTypeRandom.Checked)
177                    passTxt.Text = GetConstantStr(passData, passTypeHex.Checked);
178                else
179                    passTxt.Text = string.Empty;
180                passTxt.Enabled = PassType != PassTypes.RANDOM;
181            }
182            catch (DecoderFallbackException)
183            {
184                MessageBox.Show(this, S._("The pass constant cannot be displayed as " +
185                    "text because it contains invalid characters."), S._("Eraser"),
186                     MessageBoxButtons.OK, MessageBoxIcon.Information);
187                passTypeHex.Checked = true;
188            }
189        }
190
191        private void passText_Validating(object sender, CancelEventArgs e)
192        {
193            //Try to parse the pass constant, showing the error if it fails.
194            try
195            {
196                passData = GetConstantArray(passTxt.Text, passTypeHex.Checked);
197            }
198            catch (FormatException)
199            {
200                e.Cancel = true;
201                errorProvider.SetError(passTxt, S._("The input text is invalid " +
202                    "for the current data type. Valid hexadecimal characters are the " +
203                    "digits 0-9 and letters A-F"));
204            }
205        }
206
207        private void passType_CheckedChanged(object sender, EventArgs e)
208        {
209            //We are only concerned with the check event (since the uncheck event is
210            //processed by the validate function.)
211            if (!((RadioButton)sender).Checked)
212                return;
213
214            //Ok, update the UI.
215            UpdateEditor();
216        }
217
218        /// <summary>
219        /// The last-saved pass data.
220        /// </summary>
221        private byte[] passData;
222    }
223}
Note: See TracBrowser for help on using the repository browser.