context: // ---------------------------------------------------------------------------------------------
  #region // Copyright (c) 2005-2015, SIL International.
  // <copyright from='2005' to='2015' company='SIL International'>
  //		Copyright (c) 2005-2015, SIL International.
  //    
  //		This software is distributed under the MIT License, as specified in the LICENSE.txt file.
  // </copyright> 
  #endregion
  // 
  #if !__MonoCS__
  #define UNITY_STANDALONE_WIN
  #endif
  
  using System;
  using System.Drawing;
  using System.Globalization;
  using System.IO;
  using System.Linq;
  #if UNITY_STANDALONE_WIN
  using System.Management;
  #endif
  using System.Reflection;
  using System.Runtime.InteropServices;
  using System.Text;
  using System.Windows.Forms;
  using System.Xml.Serialization;
  using L10NSharp;
  using Microsoft.Win32;
  
  namespace SilTools
  {
  	public static class Utils
  	{
  		public const char kObjReplacementChar = '\uFFFC';
  		//internal static ISplashScreen s_splashScreen;
  		private static bool s_msgBoxJustShown;
  
  		/// ------------------------------------------------------------------------------------
  		/// <summary>
  		/// Gets or sets a value indicating whether or not calls to MsgBox will actaully show
  		/// a message box.
  		/// </summary>
  		/// ------------------------------------------------------------------------------------
  		public static bool SuppressMsgBoxInteractions { get; set; }
  
  #region OS-specific stuff
  		[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
  		public struct RECT
  		{
  			public int left;
  			public int top;
  			public int right;
  			public int bottom;
  		}
  
  #if UNITY_STANDALONE_WIN
  		[DllImport("user32")]
  		public static extern int UpdateWindow(IntPtr hwnd);
  #else
  		public static int UpdateWindow(IntPtr hwnd)
  		{
  			Console.WriteLine("Warning--using unimplemented method UpdateWindow"); // FIXME Linux
  			return(0);
  		}
  #endif
  
  #if UNITY_STANDALONE_WIN
  		[DllImport("user32.dll", CharSet = CharSet.Auto)]
  		public static extern int FindWindowEx(IntPtr hWnd, int hwndChildAfter,
  			string windowClass, string windowName);
  #else
  		public static int FindWindowEx(IntPtr hWnd, int hwndChildAfter,
  			string windowClass, string windowName)
  		{
  			Console.WriteLine("Warning--using unimplemented method FindWindowEx"); // FIXME Linux
  			return(0);
  		}
  #endif
  
  #if UNITY_STANDALONE_WIN
  		[DllImport("User32.dll")]
  		public extern static bool GetWindowRect(IntPtr hWnd, out RECT rect);
  #else
  		public static bool GetWindowRect(IntPtr hWnd, out RECT rect)
  		{
  			Console.WriteLine("Warning--using unimplemented method GetWindowRect"); // FIXME Linux
  			rect.left = 0;
  			rect.right = 0;
  			rect.top = 0;
  			rect.bottom = 0;
  			return(false);
  		}
  #endif
  
  #if UNITY_STANDALONE_WIN
  		[DllImport("user32.dll", CharSet = CharSet.Auto)]
  		public static extern bool PostMessage(int hWnd, uint msg, int wParam, int lParam);
  #else
  		public static bool PostMessage(int hWnd, uint msg, int wParam, int lParam)
  		{
  			Console.WriteLine("Warning--using unimplemented method PostMessage"); // FIXME Linux
  			return(false);
  		}
  #endif
  
  #if UNITY_STANDALONE_WIN
  		[DllImport("user32.dll", CharSet = CharSet.Auto)]
  		public static extern uint RegisterWindowMessage(string msgName);
  #else
  		public static uint RegisterWindowMessage(string msgName)
  		{
  			Console.WriteLine("Warning--using unimplemented method RegisterWindowMessage"); // FIXME Linux
  			return(0);
  		}
  #endif
  
  		private const int WM_SETREDRAW = 0xB;
  		public const int HWND_BROADCAST = 0xFFFF;
  
  		/// <summary>
  		/// The <c>MemoryStatus</c> structure contains information about the current 
  		/// state of both physical and virtual memory.
  		/// </summary>
  		public struct MemoryStatus
  		{
  			/// <summary>
  			/// Size of the <c>MemoryStatus</c> data structure, in bytes. You do not 
  			/// need to set this member before calling the <see cref="GlobalMemoryStatus"/> 
  			/// function; the function sets it. 
  			/// </summary>
  			public uint dwLength;
  			/// <summary>See MSDN documentation</summary>
  			public uint dwMemoryLoad;
  			/// <summary>Total size of physical memory, in bytes.</summary>
  			public uint dwTotalPhys;
  			/// <summary>Size of physical memory available, in bytes. </summary>
  			public uint dwAvailPhys;
  			/// <summary>Size of the committed memory limit, in bytes. </summary>
  			public uint dwTotalPageFile;
  			/// <summary>Size of available memory to commit, in bytes.</summary>
  			public uint dwAvailPageFile;
  			/// <summary>Total size of the user mode portion of the virtual address space of 
  			/// the calling process, in bytes.</summary>
  			public uint dwTotalVirtual;
  			/// <summary>Size of unreserved and uncommitted memory in the user mode portion 
  			/// of the virtual address space of the calling process, in bytes.</summary>
  			public uint dwAvailVirtual;
  		};
  
  		/// <summary>
  		/// The <c>GlobalMemoryStatus</c> function obtains information about the system's 
  		/// current usage of both physical and virtual memory.
  		/// </summary>
  		/// <param name="ms">Pointer to a <see cref="MemoryStatus"/>  structure. The 
  		/// <c>GlobalMemoryStatus</c> function stores information about current memory 
  		/// availability into this structure.</param>
  #if UNITY_STANDALONE_WIN
  		[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
  		extern public static void GlobalMemoryStatus(ref MemoryStatus ms);
  #else
  		public static void GlobalMemoryStatus(ref MemoryStatus ms)
  		{
  			Console.WriteLine("Warning--using unimplemented method GlobalMemoryStatus"); // FIXME Linux
  			return;
  		}
  #endif
  
  #endregion
  
  		/// ------------------------------------------------------------------------------------
  		/// <summary>
  		/// If the splash screen is showing, this will force it to be closed.
  		/// </summary>
  		/// ------------------------------------------------------------------------------------
  		public static void ForceCloseOfSplashScreen()
  		{
  			//if (s_splashScreen != null)
  			//	s_splashScreen.Close();
  		}
  
  		/// ------------------------------------------------------------------------------------
  		public static void CenterFormInScreen(Form frm)
  		{
  			Rectangle rc = Screen.GetWorkingArea(frm);
  			if (rc == Rectangle.Empty)
  				rc = Screen.PrimaryScreen.WorkingArea;
  
  			if (frm.Width > rc.Width)
  				frm.Width = rc.Width;
  
  			if (frm.Height > rc.Height)
  				frm.Height = rc.Height;
  
  			frm.Location = new Point((rc.Width - frm.Width) / 2, (rc.Height - frm.Height) / 2);
  		}
  
  		/// ------------------------------------------------------------------------------------
  		/// <summary>
  		/// Makes relPath relative to fixedPath, but only if relPath is rooted.
  		/// </summary>
  		/// ------------------------------------------------------------------------------------
  		public static string MakeRelativePath(string fixedPath, string relPath)
  		{
  			if (!Path.IsPathRooted(fixedPath))
  				throw new ArgumentException("Fixed path is not rooted.", "fixedPath");
  
  			if (!Path.IsPathRooted(relPath))
  				throw new ArgumentException("Relative path is not rooted.", "relPath");
  
  			if (relPath.IndexOf(fixedPath, StringComparison.Ordinal) != 0)
  				return relPath;
  
  			relPath = relPath.Remove(0, fixedPath.Length);
  			return relPath.TrimStart(Path.DirectorySeparatorChar);
  		}
  
  		/// ------------------------------------------------------------------------------------
  		/// <summary>
  		/// Makes the specified name safe to use as file name in the target OS. This is done
  		/// by replacing all invalid file name characters found in the specified file name
  		/// with the specified replacement character. Passing '\0' as the replacement character
  		/// will remove invalid characters without replacing any.
  		/// </summary>
  		/// ------------------------------------------------------------------------------------
  		public static string MakeSafeFileName(string fileName, char replacementChar)
  		{
  			string replacement = (replacementChar == '\0' ?
  				string.Empty : replacementChar.ToString(CultureInfo.InvariantCulture));
  
  			fileName = Path.GetInvalidFileNameChars()
  				.Aggregate(fileName, (curr, c) => curr.Replace(c.ToString(CultureInfo.InvariantCulture), replacement));
  
  			return fileName.Trim();
  		}
  
  		/// ------------------------------------------------------------------------------------
  		/// <summary>
  		/// Since a file path may contain '\n' and passing a string to STMsgBox will convert
  		/// those to a new line character (which would not be good for a file path), this
  		/// method will go through the specified file path and prepare it to be properly
  		/// displayed in a message box via the STMsgBox method.
  		/// </summary>
  		/// ------------------------------------------------------------------------------------
  		public static string PrepFilePathForMsgBox(string filepath)
  		{
  			if (filepath == null)
  				return string.Empty;
  
  			filepath = filepath.Replace(Environment.NewLine, kObjReplacementChar.ToString(CultureInfo.InvariantCulture));
  			return filepath.Replace("\\n", kObjReplacementChar.ToString(CultureInfo.InvariantCulture));
  		}
  
  		/// ------------------------------------------------------------------------------------
  		/// <summary>
  		/// Displays a speech tools message box with just an OK button and an information icon.
  		/// </summary>
  		/// ------------------------------------------------------------------------------------
  		public static DialogResult MsgBox(string message, string msg)
  		{
  			return MessageBox.Show(msg, message);
  		}
  
  		/// ------------------------------------------------------------------------------------
  		/// <summary>
  		/// Displays a speech tools message box with just an OK button and an information icon.
  		/// </summary>
  		/// ------------------------------------------------------------------------------------
  		public static DialogResult MsgBox(string msg, MessageBoxIcon icon)
  		{
  			return MessageBox.Show(msg, String.Empty, MessageBoxButtons.OK, icon);
  		}
  
  		/// ------------------------------------------------------------------------------------
  		/// <summary>
  		/// Displays a speech tools message box with an icon that is determined by the buttons.
  		/// </summary>
  		/// ------------------------------------------------------------------------------------
  		public static DialogResult MsgBox(string msg, MessageBoxButtons buttons)
  		{
  			MessageBoxIcon icon;
  
  			if (buttons == MessageBoxButtons.YesNo || buttons == MessageBoxButtons.YesNoCancel)
  				icon = MessageBoxIcon.Question;
  			else if (buttons == MessageBoxButtons.AbortRetryIgnore || buttons == MessageBoxButtons.RetryCancel)
  				icon = MessageBoxIcon.Exclamation;
  			else
  				icon = MessageBoxIcon.Information;
  
  			return MessageBox.Show(msg, String.Empty, buttons, icon);
  		}
  
  		/// ------------------------------------------------------------------------------------
  		/// <summary>
  		/// Displays a speech tools message box.
  		/// </summary>
  		/// ------------------------------------------------------------------------------------
  		public static DialogResult MsgBox(string msg, string title, MessageBoxButtons buttons, MessageBoxIcon icon)
  		{
  			if (SuppressMsgBoxInteractions)
  				return DialogResult.None;
  
  			s_msgBoxJustShown = true;
  			msg = MappingButtonText(msg);
  			if (title.Length == 0)
  				title = Application.ProductName;
  			title = LocalizationManager.GetString("CustomMessageBox.Title", title);
  			return MessageBox.Show(msg, title, buttons, icon);
  		}
  
  		private static string MappingButtonText(string msg)
  		{
  			msg = ConvertLiteralNewLines(msg);
  			msg = msg.Replace(kObjReplacementChar.ToString(CultureInfo.InvariantCulture), Environment.NewLine);
  			MessageBoxExtender.OK = LocalizationManager.GetString("CustomMessageBox.OK", "OK");
  			MessageBoxExtender.Abort = LocalizationManager.GetString("CustomMessageBox.Abort", "Abort");
  			MessageBoxExtender.Cancel = LocalizationManager.GetString("CustomMessageBox.Cancel", "Cancel");
  			MessageBoxExtender.Ignore = LocalizationManager.GetString("CustomMessageBox.Ignore", "Ignore");
  			MessageBoxExtender.No = LocalizationManager.GetString("CustomMessageBox.No", "No");
  			MessageBoxExtender.Retry = LocalizationManager.GetString("CustomMessageBox.Retry", "Retry");
  			MessageBoxExtender.Yes = LocalizationManager.GetString("CustomMessageBox.Yes", "Yes");
  			MessageBoxExtender.Register();
  			return msg;
  		}
  
  		/// ------------------------------------------------------------------------------------
  		/// <summary>
  		/// Displays a speech tools message box.
  		/// </summary>
  		/// ------------------------------------------------------------------------------------
  		public static DialogResult MsgBox(string msg, string title, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton button)
  		{
  			if (SuppressMsgBoxInteractions)
  				return DialogResult.None;
  
  			s_msgBoxJustShown = true;
  			msg = MappingButtonText(msg);
  			if (title.Length == 0)
  				title = Application.ProductName;
  			title = LocalizationManager.GetString("CustomMessageBox.Title", title);
  			return MessageBox.Show(msg, title, buttons, icon, button);
  		}
  
  		/// ------------------------------------------------------------------------------------
  		/// <summary>
  		/// Gets or sets a flag indicating whether or not the MsgBox method was just used
  		/// to display a message box.
  		/// </summary>
  		/// ------------------------------------------------------------------------------------
  		public static bool MessageBoxJustShown
  		{
  			get { return s_msgBoxJustShown; }
  			set { s_msgBoxJustShown = value; }
  		}
  
  		/// ------------------------------------------------------------------------------------
  		/// <summary>
  		/// Removes the ampersand accerlerator prefix from the specified text.
  		/// </summary>
  		/// ------------------------------------------------------------------------------------
  		public static string RemoveAcceleratorPrefix(string text)
  		{
  			text = text.Replace("&&", kObjReplacementChar.ToString(CultureInfo.InvariantCulture));
  
gt: 			text = text.Replace("&", string.Empty);