1 /* 2 KeePass Password Safe - The Open-Source Password Manager 3 Copyright (C) 2003-2021 Dominik Reichl <dominik.reichl@t-online.de> 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 10 This program is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program; if not, write to the Free Software 17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 using System; 21 using System.Collections.Generic; 22 using System.ComponentModel; 23 using System.Diagnostics; 24 using System.Drawing; 25 using System.Drawing.Text; 26 using System.Text; 27 using System.Windows.Forms; 28 29 using KeePass.App; 30 using KeePass.App.Configuration; 31 using KeePass.Native; 32 using KeePass.Resources; 33 using KeePass.UI; 34 using KeePass.Util; 35 36 using KeePassLib; 37 using KeePassLib.Utility; 38 39 using NativeLib = KeePassLib.Native.NativeLib; 40 41 namespace KeePass.Forms 42 { 43 public partial class DataEditorForm : Form 44 { 45 private string m_strDataDesc = string.Empty; 46 private byte[] m_pbData = null; 47 private byte[] m_pbEditedData = null; 48 49 private bool m_bModified = false; 50 private bool m_bURtfWithHighChar = false; 51 52 private uint m_uBlockEvents = 0; 53 private Stack<KeyValuePair<int, int>> m_lSelections = 54 new Stack<KeyValuePair<int, int>>(); 55 private BinaryDataClass m_bdc = BinaryDataClass.Unknown; 56 private bool m_bNewLinesWin = true; 57 58 private string m_strInitialFormRect = string.Empty; 59 private RichTextBoxContextMenu m_ctxText = new RichTextBoxContextMenu(); 60 61 /// <summary> 62 /// Get the edited, new data. This property is non-<c>null</c> only 63 /// if the user has really edited the data (i.e. if the user makes no 64 /// changes, <c>null</c> is returned). 65 /// </summary> 66 public byte[] EditedBinaryData 67 { 68 get { return m_pbEditedData; } 69 } 70 71 public MenuStrip MainMenuEx { get { return m_menuMain; } } 72 SupportsDataType(BinaryDataClass bdc)73 public static bool SupportsDataType(BinaryDataClass bdc) 74 { 75 return ((bdc == BinaryDataClass.Text) || (bdc == BinaryDataClass.RichText)); 76 } 77 InitEx(string strDataDesc, byte[] pbData)78 public void InitEx(string strDataDesc, byte[] pbData) 79 { 80 if(strDataDesc != null) m_strDataDesc = strDataDesc; 81 82 m_pbData = pbData; 83 } 84 DataEditorForm()85 public DataEditorForm() 86 { 87 InitializeComponent(); 88 89 GlobalWindowManager.InitializeForm(this); 90 Program.Translation.ApplyTo("KeePass.Forms.DataEditorForm.m_menuMain", m_menuMain.Items); 91 } 92 OnFormLoad(object sender, EventArgs e)93 private void OnFormLoad(object sender, EventArgs e) 94 { 95 Debug.Assert(m_pbData != null); 96 if(m_pbData == null) throw new InvalidOperationException(); 97 98 GlobalWindowManager.AddWindow(this); 99 100 this.Icon = AppIcons.Default; 101 this.DoubleBuffered = true; 102 103 m_strInitialFormRect = UIUtil.SetWindowScreenRectEx(this, 104 Program.Config.UI.DataEditorRect); 105 106 m_bdc = BinaryDataClassifier.Classify(m_strDataDesc, m_pbData); 107 uint uStartOffset; 108 StrEncodingInfo seiGuess = BinaryDataClassifier.GetStringEncoding( 109 m_pbData, out uStartOffset); 110 string strData; 111 try 112 { 113 strData = (seiGuess.Encoding.GetString(m_pbData, (int)uStartOffset, 114 m_pbData.Length - (int)uStartOffset) ?? string.Empty); 115 strData = StrUtil.ReplaceNulls(strData); 116 } 117 catch(Exception) { Debug.Assert(false); strData = string.Empty; } 118 119 ++m_uBlockEvents; 120 121 UIUtil.AssignShortcut(m_menuFileSave, Keys.Control | Keys.S); 122 UIUtil.AssignShortcut(m_menuFileExit, Keys.Escape, null, true); 123 UIUtil.AssignShortcut(m_menuEditUndo, Keys.Control | Keys.Z, null, true); 124 UIUtil.AssignShortcut(m_menuEditRedo, Keys.Control | Keys.Y, null, true); 125 UIUtil.AssignShortcut(m_menuEditCut, Keys.Control | Keys.X, null, true); 126 UIUtil.AssignShortcut(m_menuEditCopy, Keys.Control | Keys.C, null, true); 127 UIUtil.AssignShortcut(m_menuEditPaste, Keys.Control | Keys.V, null, true); 128 UIUtil.AssignShortcut(m_menuEditDelete, Keys.Delete, null, true); 129 UIUtil.AssignShortcut(m_menuEditSelectAll, Keys.Control | Keys.A, null, true); 130 UIUtil.AssignShortcut(m_menuEditFind, Keys.Control | Keys.F); 131 132 UIUtil.ConfigureTbButton(m_tbFileSave, KPRes.Save, null, m_menuFileSave); 133 UIUtil.ConfigureTbButton(m_tbEditCut, KPRes.Cut, null, m_menuEditCut); 134 UIUtil.ConfigureTbButton(m_tbEditCopy, KPRes.Copy, null, m_menuEditCopy); 135 UIUtil.ConfigureTbButton(m_tbEditPaste, KPRes.Paste, null, m_menuEditPaste); 136 UIUtil.ConfigureTbButton(m_tbEditUndo, KPRes.Undo, null, m_menuEditUndo); 137 UIUtil.ConfigureTbButton(m_tbEditRedo, KPRes.Redo, null, m_menuEditRedo); 138 UIUtil.ConfigureTbButton(m_tbFind, null, KPRes.Find, m_menuEditFind); 139 140 // Formatting keyboard shortcuts are implemented by CustomRichTextBoxEx 141 UIUtil.ConfigureTbButton(m_tbFormatBold, KPRes.Bold, KPRes.Bold + 142 " (" + UIUtil.GetKeysName(Keys.Control | Keys.B) + ")", null); 143 UIUtil.ConfigureTbButton(m_tbFormatItalic, KPRes.Italic, KPRes.Italic + 144 " (" + UIUtil.GetKeysName(Keys.Control | Keys.I) + ")", null); 145 UIUtil.ConfigureTbButton(m_tbFormatUnderline, KPRes.Underline, KPRes.Underline + 146 " (" + UIUtil.GetKeysName(Keys.Control | Keys.U) + ")", null); 147 UIUtil.ConfigureTbButton(m_tbFormatStrikeout, KPRes.Strikeout, null); 148 UIUtil.ConfigureTbButton(m_tbColorForeground, KPRes.TextColor, null); 149 UIUtil.ConfigureTbButton(m_tbColorBackground, KPRes.BackgroundColor, null); 150 UIUtil.ConfigureTbButton(m_tbAlignLeft, KPRes.AlignLeft, KPRes.AlignLeft + 151 " (" + UIUtil.GetKeysName(Keys.Control | Keys.L) + ")", null); 152 UIUtil.ConfigureTbButton(m_tbAlignCenter, KPRes.AlignCenter, KPRes.AlignCenter + 153 " (" + UIUtil.GetKeysName(Keys.Control | Keys.E) + ")", null); 154 UIUtil.ConfigureTbButton(m_tbAlignRight, KPRes.AlignRight, KPRes.AlignRight + 155 " (" + UIUtil.GetKeysName(Keys.Control | Keys.R) + ")", null); 156 157 string strSearchTr = ((WinUtil.IsAtLeastWindowsVista ? 158 string.Empty : " ") + KPRes.Search); 159 UIUtil.SetCueBanner(m_tbFind, strSearchTr); 160 161 UIUtil.SetToolTip(m_tbFontCombo, KPRes.Font, true); 162 UIUtil.SetToolTip(m_tbFontSizeCombo, KPRes.Size, true); 163 164 UIUtil.EnableAutoCompletion(m_tbFontCombo, true); 165 UIUtil.EnableAutoCompletion(m_tbFontSizeCombo, true); 166 167 m_rtbText.WordWrap = Program.Config.UI.DataEditorWordWrap; 168 m_ctxText.Attach(m_rtbText, this); 169 m_tssStatusMain.Text = KPRes.Ready; 170 171 InitFormattingToolBar(); 172 173 bool bSimpleText = true, bDefaultFont = true; 174 if(m_bdc == BinaryDataClass.RichText) 175 { 176 try 177 { 178 if(strData.Length > 0) 179 { 180 m_rtbText.Rtf = StrUtil.RtfFix(strData); 181 bDefaultFont = false; 182 } 183 else m_rtbText.Text = string.Empty; 184 185 bSimpleText = false; 186 } 187 catch(Exception) { } // Show as simple text 188 } 189 190 if(bSimpleText) 191 { 192 m_rtbText.Text = strData; 193 m_rtbText.SimpleTextOnly = true; 194 195 // CR is upgraded to CR+LF 196 m_bNewLinesWin = (StrUtil.GetNewLineSeq(strData) != "\n"); 197 } 198 else m_menuViewFont.Text = KPRes.FontDefault + "..."; 199 200 if(bDefaultFont && Program.Config.UI.DataEditorFont.OverrideUIDefault) 201 { 202 m_rtbText.SelectAll(); 203 m_rtbText.SelectionFont = Program.Config.UI.DataEditorFont.ToFont(); 204 } 205 206 m_rtbText.Select(0, 0); 207 --m_uBlockEvents; 208 UpdateUIState(false, true); 209 } 210 InitFormattingToolBar()211 private void InitFormattingToolBar() 212 { 213 if(m_bdc != BinaryDataClass.RichText) 214 { 215 m_toolFormat.Visible = false; 216 return; 217 } 218 219 using(InstalledFontCollection c = new InstalledFontCollection()) 220 { 221 foreach(FontFamily ff in c.Families) 222 m_tbFontCombo.Items.Add(ff.Name); 223 } 224 225 int[] vSizes = new int[] { 8, 9, 10, 11, 12, 14, 16, 18, 20, 226 22, 24, 26, 28, 36, 48, 72 }; 227 foreach(int nSize in vSizes) 228 m_tbFontSizeCombo.Items.Add(nSize.ToString()); 229 } 230 UpdateUIState(bool bSetModified, bool bFocusText)231 private void UpdateUIState(bool bSetModified, bool bFocusText) 232 { 233 ++m_uBlockEvents; 234 if(bSetModified) m_bModified = true; 235 236 this.Text = (((m_strDataDesc.Length > 0) ? (m_strDataDesc + 237 (m_bModified ? "*" : string.Empty) + " - ") : string.Empty) + 238 KPRes.DataEditorKP); 239 240 // m_menuViewFont.Enabled = (m_bdc == BinaryDataClass.Text); 241 UIUtil.SetChecked(m_menuViewWordWrap, m_rtbText.WordWrap); 242 243 m_tbFileSave.Image = (m_bModified ? Properties.Resources.B16x16_FileSave : 244 Properties.Resources.B16x16_FileSave_Disabled); 245 246 UIUtil.SetEnabledFast(m_rtbText.CanUndo, m_menuEditUndo, m_tbEditUndo); 247 UIUtil.SetEnabledFast(m_rtbText.CanRedo, m_menuEditRedo, m_tbEditRedo); 248 249 bool bSel = (m_rtbText.SelectionLength != 0); 250 UIUtil.SetEnabledFast(bSel, m_menuEditCut, m_tbEditCut, 251 m_menuEditCopy, m_tbEditCopy, m_menuEditDelete); 252 253 Font fSel = m_rtbText.SelectionFont; 254 if(fSel != null) 255 { 256 m_tbFormatBold.Checked = fSel.Bold; 257 m_tbFormatItalic.Checked = fSel.Italic; 258 m_tbFormatUnderline.Checked = fSel.Underline; 259 m_tbFormatStrikeout.Checked = fSel.Strikeout; 260 261 string strFontName = fSel.Name; 262 if(m_tbFontCombo.Items.IndexOf(strFontName) >= 0) 263 m_tbFontCombo.SelectedItem = strFontName; 264 else m_tbFontCombo.Text = strFontName; 265 266 string strFontSize = fSel.SizeInPoints.ToString(); 267 if(m_tbFontSizeCombo.Items.IndexOf(strFontSize) >= 0) 268 m_tbFontSizeCombo.SelectedItem = strFontSize; 269 else m_tbFontSizeCombo.Text = strFontSize; 270 } 271 272 HorizontalAlignment ha = m_rtbText.SelectionAlignment; 273 m_tbAlignLeft.Checked = (ha == HorizontalAlignment.Left); 274 m_tbAlignCenter.Checked = (ha == HorizontalAlignment.Center); 275 m_tbAlignRight.Checked = (ha == HorizontalAlignment.Right); 276 277 --m_uBlockEvents; 278 if(bFocusText) UIUtil.SetFocus(m_rtbText, this); 279 } 280 UISelectAllText(bool bSelect)281 private void UISelectAllText(bool bSelect) 282 { 283 if(bSelect) 284 { 285 m_lSelections.Push(new KeyValuePair<int, int>(m_rtbText.SelectionStart, 286 m_rtbText.SelectionLength)); 287 m_rtbText.SelectAll(); 288 } 289 else 290 { 291 KeyValuePair<int, int> kvp = m_lSelections.Pop(); 292 m_rtbText.Select(kvp.Key, kvp.Value); 293 } 294 } 295 OnFileSave(object sender, EventArgs e)296 private void OnFileSave(object sender, EventArgs e) 297 { 298 if(m_bdc == BinaryDataClass.RichText) 299 { 300 string strRtf = m_rtbText.Rtf; 301 302 if(StrUtil.RtfIsURtf(strRtf)) 303 m_bURtfWithHighChar = StrUtil.ContainsHighChar(m_rtbText.Text); 304 else m_bURtfWithHighChar = false; 305 306 m_pbEditedData = StrUtil.Utf8.GetBytes(StrUtil.RtfFix(strRtf)); 307 } 308 else 309 { 310 string strData = m_rtbText.Text; 311 strData = StrUtil.NormalizeNewLines(strData, m_bNewLinesWin); 312 m_pbEditedData = StrUtil.Utf8.GetBytes(strData); 313 } 314 315 m_bModified = false; 316 UpdateUIState(false, false); 317 } 318 OnFormClosing(object sender, FormClosingEventArgs e)319 private void OnFormClosing(object sender, FormClosingEventArgs e) 320 { 321 if(m_bModified) 322 { 323 DialogResult dr = MessageService.Ask(KPRes.SaveBeforeCloseQuestion, 324 PwDefs.ShortProductName, MessageBoxButtons.YesNoCancel); 325 326 if(dr == DialogResult.Yes) 327 OnFileSave(sender, EventArgs.Empty); 328 else if(dr == DialogResult.No) { } 329 else 330 { 331 e.Cancel = true; 332 return; 333 } 334 } 335 336 if(m_bURtfWithHighChar && (m_pbEditedData != null) && 337 !MemUtil.ArraysEqual(m_pbEditedData, m_pbData)) 338 { 339 string strUrl = AppHelp.GetOnlineUrl(AppDefs.HelpTopics.KbFaq, 340 AppDefs.HelpTopics.KbFaqURtf); 341 string strLink = VistaTaskDialog.CreateLink(strUrl, strUrl); 342 string strMsg = KPRes.URtfProblem + MessageService.NewParagraph + 343 KPRes.URtfCheck + MessageService.NewParagraph + 344 KPRes.URtfSuggestion + MessageService.NewParagraph + 345 KPRes.MoreInfo + ":" + MessageService.NewLine; 346 347 VistaTaskDialog dlg = new VistaTaskDialog(); 348 dlg.AddButton((int)DialogResult.Cancel, KPRes.Ok, null); 349 dlg.CommandLinks = false; 350 dlg.Content = strMsg + strLink; 351 dlg.DefaultButtonID = (int)DialogResult.Cancel; 352 dlg.EnableHyperlinks = true; 353 dlg.SetIcon(VtdIcon.Warning); 354 dlg.WindowTitle = PwDefs.ShortProductName; 355 356 if(!dlg.ShowDialog()) 357 MessageService.ShowWarning(strMsg + strUrl); 358 } 359 360 Debug.Assert(m_uBlockEvents == 0); 361 362 string strRect = UIUtil.GetWindowScreenRect(this); 363 if(strRect != m_strInitialFormRect) // Don't overwrite "" 364 Program.Config.UI.DataEditorRect = strRect; 365 } 366 OnFormClosed(object sender, FormClosedEventArgs e)367 private void OnFormClosed(object sender, FormClosedEventArgs e) 368 { 369 m_ctxText.Detach(); 370 GlobalWindowManager.RemoveWindow(this); 371 } 372 ToggleSelectionFormat(FontStyle fs)373 private void ToggleSelectionFormat(FontStyle fs) 374 { 375 if((m_uBlockEvents > 0) || (m_bdc != BinaryDataClass.RichText)) return; 376 377 UIUtil.RtfToggleSelectionFormat(m_rtbText, fs); 378 UpdateUIState(true, true); 379 } 380 OnFormatBoldClicked(object sender, EventArgs e)381 private void OnFormatBoldClicked(object sender, EventArgs e) 382 { 383 ToggleSelectionFormat(FontStyle.Bold); 384 } 385 OnFormatItalicClicked(object sender, EventArgs e)386 private void OnFormatItalicClicked(object sender, EventArgs e) 387 { 388 ToggleSelectionFormat(FontStyle.Italic); 389 } 390 OnFormatUnderlineClicked(object sender, EventArgs e)391 private void OnFormatUnderlineClicked(object sender, EventArgs e) 392 { 393 ToggleSelectionFormat(FontStyle.Underline); 394 } 395 OnFormatStrikeoutClicked(object sender, EventArgs e)396 private void OnFormatStrikeoutClicked(object sender, EventArgs e) 397 { 398 ToggleSelectionFormat(FontStyle.Strikeout); 399 } 400 OnTextSelectionChanged(object sender, EventArgs e)401 private void OnTextSelectionChanged(object sender, EventArgs e) 402 { 403 if(m_uBlockEvents > 0) return; 404 405 UpdateUIState(false, false); 406 } 407 ShowColorDialog(Color clrCurrent, out Color clrSelected)408 private static bool ShowColorDialog(Color clrCurrent, out Color clrSelected) 409 { 410 Color? clrNew = UIUtil.ShowColorDialog(clrCurrent); 411 clrSelected = clrNew.GetValueOrDefault(clrCurrent); 412 return clrNew.HasValue; 413 } 414 OnColorForegroundClicked(object sender, EventArgs e)415 private void OnColorForegroundClicked(object sender, EventArgs e) 416 { 417 if((m_uBlockEvents > 0) || (m_bdc != BinaryDataClass.RichText)) return; 418 419 Color clr; 420 if(ShowColorDialog(m_rtbText.SelectionColor, out clr)) 421 { 422 m_rtbText.SelectionColor = clr; 423 UpdateUIState(true, true); 424 } 425 } 426 OnColorBackgroundClicked(object sender, EventArgs e)427 private void OnColorBackgroundClicked(object sender, EventArgs e) 428 { 429 if((m_uBlockEvents > 0) || (m_bdc != BinaryDataClass.RichText)) return; 430 431 Color clr; 432 if(ShowColorDialog(m_rtbText.SelectionBackColor, out clr)) 433 { 434 m_rtbText.SelectionBackColor = clr; 435 UpdateUIState(true, true); 436 } 437 } 438 OnFileExit(object sender, EventArgs e)439 private void OnFileExit(object sender, EventArgs e) 440 { 441 this.DialogResult = DialogResult.OK; 442 } 443 OnTextTextChanged(object sender, EventArgs e)444 private void OnTextTextChanged(object sender, EventArgs e) 445 { 446 if(m_uBlockEvents > 0) return; 447 448 UpdateUIState(true, false); 449 } 450 OnAlignLeftClicked(object sender, EventArgs e)451 private void OnAlignLeftClicked(object sender, EventArgs e) 452 { 453 if((m_uBlockEvents > 0) || (m_bdc != BinaryDataClass.RichText)) return; 454 455 m_rtbText.SelectionAlignment = HorizontalAlignment.Left; 456 457 UpdateUIState(true, true); 458 } 459 OnAlignCenterClicked(object sender, EventArgs e)460 private void OnAlignCenterClicked(object sender, EventArgs e) 461 { 462 if((m_uBlockEvents > 0) || (m_bdc != BinaryDataClass.RichText)) return; 463 464 m_rtbText.SelectionAlignment = HorizontalAlignment.Center; 465 466 UpdateUIState(true, true); 467 } 468 OnAlignRightClicked(object sender, EventArgs e)469 private void OnAlignRightClicked(object sender, EventArgs e) 470 { 471 if((m_uBlockEvents > 0) || (m_bdc != BinaryDataClass.RichText)) return; 472 473 m_rtbText.SelectionAlignment = HorizontalAlignment.Right; 474 475 UpdateUIState(true, true); 476 } 477 OnFontComboSelectedIndexChanged(object sender, EventArgs e)478 private void OnFontComboSelectedIndexChanged(object sender, EventArgs e) 479 { 480 if((m_uBlockEvents > 0) || (m_bdc != BinaryDataClass.RichText)) return; 481 482 try 483 { 484 string strName = m_tbFontCombo.Text; 485 486 Font f = m_rtbText.SelectionFont; 487 if(f != null) 488 m_rtbText.SelectionFont = new Font(strName, f.Size, 489 f.Style, f.Unit, f.GdiCharSet, f.GdiVerticalFont); 490 else if(FontUtil.DefaultFont != null) 491 m_rtbText.SelectionFont = FontUtil.CreateFont(strName, 492 FontUtil.DefaultFont.SizeInPoints, FontStyle.Regular); 493 else 494 m_rtbText.SelectionFont = FontUtil.CreateFont(strName, 495 12.0f, FontStyle.Regular); 496 } 497 catch(Exception ex) { MessageService.ShowWarning(ex); } 498 499 UpdateUIState(true, true); 500 } 501 OnFontSizeComboSelectedIndexChanged(object sender, EventArgs e)502 private void OnFontSizeComboSelectedIndexChanged(object sender, EventArgs e) 503 { 504 if((m_uBlockEvents > 0) || (m_bdc != BinaryDataClass.RichText)) return; 505 506 try 507 { 508 Font f = m_rtbText.SelectionFont; 509 float fSize; 510 if(!float.TryParse(m_tbFontSizeCombo.Text, out fSize)) 511 { 512 if(f != null) fSize = f.SizeInPoints; 513 else if(FontUtil.DefaultFont != null) 514 fSize = FontUtil.DefaultFont.SizeInPoints; 515 else fSize = 12.0f; 516 } 517 518 if(f != null) 519 m_rtbText.SelectionFont = new Font(f.Name, fSize, f.Style, 520 GraphicsUnit.Point, f.GdiCharSet, f.GdiVerticalFont); 521 else if(!NativeLib.IsUnix()) 522 UIUtil.RtfSetFontSize(m_rtbText, fSize); 523 else // Unix 524 m_rtbText.SelectionFont = FontUtil.CreateFont( 525 FontFamily.GenericSansSerif, fSize, FontStyle.Regular); 526 } 527 catch(Exception ex) { MessageService.ShowWarning(ex); } 528 529 UpdateUIState(true, true); 530 } 531 OnFontComboKeyDown(object sender, KeyEventArgs e)532 private void OnFontComboKeyDown(object sender, KeyEventArgs e) 533 { 534 if(e.KeyCode == Keys.Return) // Return == Enter 535 { 536 UIUtil.SetHandled(e, true); 537 OnFontComboSelectedIndexChanged(sender, e); 538 } 539 } 540 OnFontSizeComboKeyDown(object sender, KeyEventArgs e)541 private void OnFontSizeComboKeyDown(object sender, KeyEventArgs e) 542 { 543 if(e.KeyCode == Keys.Return) // Return == Enter 544 { 545 UIUtil.SetHandled(e, true); 546 OnFontSizeComboSelectedIndexChanged(sender, e); 547 } 548 } 549 OnEditCut(object sender, EventArgs e)550 private void OnEditCut(object sender, EventArgs e) 551 { 552 m_rtbText.Cut(); 553 UpdateUIState(true, true); 554 } 555 OnEditCopy(object sender, EventArgs e)556 private void OnEditCopy(object sender, EventArgs e) 557 { 558 m_rtbText.Copy(); 559 UpdateUIState(false, true); 560 } 561 OnEditPaste(object sender, EventArgs e)562 private void OnEditPaste(object sender, EventArgs e) 563 { 564 m_rtbText.PasteAcceptable(); 565 UpdateUIState(true, true); 566 } 567 OnEditUndo(object sender, EventArgs e)568 private void OnEditUndo(object sender, EventArgs e) 569 { 570 m_rtbText.Undo(); 571 UpdateUIState(true, true); 572 } 573 OnEditRedo(object sender, EventArgs e)574 private void OnEditRedo(object sender, EventArgs e) 575 { 576 m_rtbText.Redo(); 577 UpdateUIState(true, true); 578 } 579 OnViewFont(object sender, EventArgs e)580 private void OnViewFont(object sender, EventArgs e) 581 { 582 FontDialog dlg = UIUtil.CreateFontDialog(true); 583 dlg.Font = Program.Config.UI.DataEditorFont.ToFont(); 584 dlg.ShowColor = false; 585 586 if(dlg.ShowDialog() == DialogResult.OK) 587 { 588 Program.Config.UI.DataEditorFont = new AceFont(dlg.Font); 589 Program.Config.UI.DataEditorFont.OverrideUIDefault = true; 590 591 if(m_bdc == BinaryDataClass.Text) 592 { 593 bool bModified = m_bModified; // Save modified state 594 595 UISelectAllText(true); 596 m_rtbText.SelectionFont = dlg.Font; 597 UISelectAllText(false); 598 599 m_bModified = bModified; 600 UpdateUIState(false, false); 601 } 602 } 603 dlg.Dispose(); 604 } 605 OnViewWordWrap(object sender, EventArgs e)606 private void OnViewWordWrap(object sender, EventArgs e) 607 { 608 m_rtbText.WordWrap = !m_rtbText.WordWrap; 609 Program.Config.UI.DataEditorWordWrap = m_rtbText.WordWrap; 610 UpdateUIState(false, false); 611 } 612 ProcessCmdKey(ref Message msg, Keys keyData)613 protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 614 { 615 bool bDown; 616 if(!NativeMethods.GetKeyMessageState(ref msg, out bDown)) 617 return base.ProcessCmdKey(ref msg, keyData); 618 619 if(keyData == Keys.Escape) // No modifiers 620 { 621 if(bDown) Close(); 622 return true; 623 } 624 625 return base.ProcessCmdKey(ref msg, keyData); 626 } 627 ConvertAttachment(string strDesc, byte[] pbData)628 internal static byte[] ConvertAttachment(string strDesc, byte[] pbData) 629 { 630 BinaryDataClass bdc = BinaryDataClassifier.Classify(strDesc, pbData); 631 if(bdc == BinaryDataClass.Text) 632 { 633 string strContext = (KPRes.File + (string.IsNullOrEmpty(strDesc) ? 634 string.Empty : (": " + strDesc))); 635 636 TextEncodingForm dlg = new TextEncodingForm(); 637 dlg.InitEx(strContext, pbData); 638 if(UIUtil.ShowDialogNotValue(dlg, DialogResult.OK)) return null; 639 640 Encoding enc = dlg.SelectedEncoding; 641 int iStart = (int)dlg.DataStartOffset; 642 UIUtil.DestroyForm(dlg); 643 if(enc != null) 644 { 645 try 646 { 647 string strText = (enc.GetString(pbData, iStart, 648 pbData.Length - iStart) ?? string.Empty); 649 strText = StrUtil.ReplaceNulls(strText); 650 return StrUtil.Utf8.GetBytes(strText); 651 } 652 catch(Exception) { Debug.Assert(false); } 653 } 654 } 655 656 return pbData; 657 } 658 OnTextFindKeyDown(object sender, KeyEventArgs e)659 private void OnTextFindKeyDown(object sender, KeyEventArgs e) 660 { 661 if(e.KeyCode == Keys.Return) // Return == Enter 662 { 663 UIUtil.SetHandled(e, true); 664 PerformQuickFind(); 665 } 666 } 667 OnTextFindKeyUp(object sender, KeyEventArgs e)668 private void OnTextFindKeyUp(object sender, KeyEventArgs e) 669 { 670 if(e.KeyCode == Keys.Return) // Return == Enter 671 UIUtil.SetHandled(e, true); 672 } 673 PerformQuickFind()674 private void PerformQuickFind() 675 { 676 string strNeedle = m_tbFind.Text; 677 if(string.IsNullOrEmpty(strNeedle)) return; 678 679 int iStart = m_rtbText.SelectionStart + m_rtbText.SelectionLength; 680 if(iStart < 0) { Debug.Assert(false); iStart = 0; } 681 if(iStart >= m_rtbText.TextLength) iStart = 0; 682 683 int p = m_rtbText.Find(strNeedle, iStart, -1, RichTextBoxFinds.None); 684 if(p < 0) m_rtbText.Find(strNeedle, 0, -1, RichTextBoxFinds.None); 685 } 686 OnEditSelectAll(object sender, EventArgs e)687 private void OnEditSelectAll(object sender, EventArgs e) 688 { 689 m_rtbText.SelectAll(); 690 } 691 OnEditFind(object sender, EventArgs e)692 private void OnEditFind(object sender, EventArgs e) 693 { 694 m_tbFind.SelectAll(); 695 UIUtil.SetFocus(m_tbFind.Control, this, true); 696 } 697 OnEditDelete(object sender, EventArgs e)698 private void OnEditDelete(object sender, EventArgs e) 699 { 700 m_rtbText.SelectedText = string.Empty; 701 } 702 } 703 } 704