/// /// Copyright © 2003-2008 JetBrains s.r.o. /// You may distribute under the terms of the GNU General Public License, as published by the Free Software Foundation, version 2 (see License.txt in the repository root folder). /// using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.InteropServices; using System.Text; using System.Windows.Forms; using System.Windows.Media; using JetBrains.Annotations; using JetBrains.Omea.OpenAPI; using JetBrains.Util; using Color=System.Drawing.Color; namespace JetBrains.Omea.Base { public class Utils { public static int GetHashCodeInLowerCase( params string[] strings ) { int result = 5381; ushort len = 0xffff; foreach( string str in strings) { foreach ( char ch in str ) { result = ( ( result << 5 ) + result ) ^ Char.ToLower( ch ); ++len; } } return ( result & 0xffffff ) | ( ( len >> 3 ) << 24 ); } public static Exception GetMostInnerException( Exception exception ) { Exception innerExption = exception; while ( innerExption != null ) { exception = innerExption; innerExption = exception.InnerException; } return exception; } public static void DisplayException( Exception e, string caption ) { DisplayException( Core.MainWindow, e, caption ); } public static void DisplayException( IWin32Window parent, Exception e, string caption ) { MessageBox.Show( parent, e.Message, caption, MessageBoxButtons.OK, MessageBoxIcon.Error ); } public static void RunAssociatedApplicationOnFile( string fileName ) { Process p = new Process(); p.StartInfo.RedirectStandardOutput = false; p.StartInfo.FileName = fileName; p.StartInfo.UseShellExecute = true; p.StartInfo.CreateNoWindow = true; p.Start(); p.WaitForExit(); p.Dispose(); } public static string[] SplitString( string orig, string splitter ) { Guard.NullArgument( orig, "orig" ); Guard.EmptyStringArgument( splitter, "splitter" ); ArrayList list = new ArrayList(); string rest = orig; int index = rest.IndexOf( splitter ); while ( index != -1 ) { list.Add( rest.Substring( 0, index ) ); rest = ( ( index + splitter.Length ) >= rest.Length ) ? string.Empty : rest.Substring( index + splitter.Length ); index = rest.IndexOf( splitter ); } if ( rest != string.Empty ) { list.Add( rest ); } return (string[])( list.ToArray( typeof (string) ) ); } public static string QuotedString( string str ) { return ( "\"" + str + "\"" ); } public static string ReadEncodedFile( string FileName ) { FileStream fsin = new FileStream( FileName, FileMode.Open, FileAccess.Read ); BinaryReader br = new BinaryReader( fsin, Encoding.Default ); byte[] Buffer = br.ReadBytes( (int)fsin.Length ); for ( int i = 0; i < Buffer.Length; i++ ) { int shift = i % 6; if ( i / 2 * 2 == i ) { shift = i % 8; } else if ( i / 3 * 3 == i ) { shift = i % 7; } Buffer[ i ] = (byte)( Buffer[ i ] + shift ); } fsin.Close(); return ( Encoding.Default.GetString( Buffer, 0, Buffer.Length ) ); } public static void WriteEncodedFile( string Content, string FileName ) { FileStream fsout = new FileStream( FileName, FileMode.Create ); byte[] Buffer = Encoding.Default.GetBytes( Content ); for ( int i = 0; i < Buffer.Length; i++ ) { Debug.Assert( Buffer[ i ] > _EncodingShift ); int shift = i % 6; if ( i / 2 * 2 == i ) { shift = i % 8; } else if ( i / 3 * 3 == i ) { shift = i % 7; } Buffer[ i ] = (byte)( Buffer[ i ] - shift ); } fsout.Write( Buffer, 0, Buffer.Length ); fsout.Close(); } public static Color ColorFromString( string str ) { Color color = Color.FromName( str ); if ( color.ToArgb() == 0 ) { int argb = Int32.Parse( str, NumberStyles.HexNumber ); color = Color.FromArgb( argb ); } return color; } public static bool StartsWith( string str, string pattern, bool ignoreCase ) { return string.Compare( str, 0, pattern, 0, pattern.Length, ignoreCase ) == 0; } public static int IndexOf( string str, string of, bool ignoreCase ) { return IndexOf( str, of, 0, ignoreCase ); } public static int IndexOf( string str, string of, int start, bool ignoreCase ) { if( !ignoreCase ) { return str.IndexOf( of ); } int ofLen = of.Length; int len = str.Length - ofLen; for( int i = start; i < len; ++i ) { if( string.Compare( str, i, of, 0, ofLen, true ) == 0 ) { return i; } } return -1; } public static string MergeStrings( string[] array, char delim ) { Guard.NullArgument( array, "array" ); string result = string.Empty; foreach ( string str in array ) { if ( str == null ) { throw new ArgumentNullException( "array", "Some string component in the array is null" ); } if ( str.Length > 0 ) { result += str + delim; } } if ( result.Length > 0 ) { result = result.Remove( result.Length - 1, 1 ); } return result; } /// /// Returns string read from the stream in еру UTF8 encoding. /// /// /// public static string StreamToString( Stream stream ) { return StreamToString( stream, Encoding.UTF8 ); } /// /// Returns string read from the stream in specified encoding. /// /// /// /// public static string StreamToString( Stream stream, Encoding encoding ) { Guard.NullArgument( stream, "stream" ); Guard.NullArgument( encoding, "stream" ); StreamReader reader = new StreamReader( stream, encoding ); return StreamReaderReadToEnd( reader ); } /// /// Memory saving replacement for the TextReader.ReadToEnd() method. /// public static string StreamReaderReadToEnd( TextReader reader ) { Guard.NullArgument( reader, "reader" ); StringBuilder builder = StringBuilderPool.Alloc(); try { int nextChar; while( ( nextChar = reader.Read() ) >= 0 ) { builder.Append( (char) nextChar ); } return builder.ToString(); } finally { StringBuilderPool.Dispose( builder ); } } private delegate void UpdateHttpStatusDelegate( IStatusWriter writer, string name, int kilobytes ); public static void UpdateHttpStatus( IStatusWriter writer, string name, int bytes ) { IAsyncProcessor ap = Core.UserInterfaceAP; if( !ap.IsOwnerThread ) { // update status in UI thread, because size formatting requires that ap.QueueJob( JobPriority.Immediate, new UpdateHttpStatusDelegate( UpdateHttpStatus ), writer, name, bytes ); } else { bytes &=~1023; StringBuilder builder = StringBuilderPool.Alloc(); try { builder.Append( "Downloading " ); builder.Append( name ); if( bytes == 0 ) { builder.Append( "..." ); } else { builder.Append( " (" ); builder.Append( SizeToString( bytes ) ); builder.Append( ')' ); } writer.ShowStatus( builder.ToString() ); } finally { StringBuilderPool.Dispose( builder ); } } } /// /// Converts a numeric value into a string that represents the number /// expressed as a size value in bytes, kilobytes, megabytes, or gigabytes, /// depending on the size. /// public static string SizeToString( long size ) { #region Preconditions if (!Core.UserInterfaceAP.IsOwnerThread) throw new InvalidOperationException("Formatting must be called on the UI AP thread."); #endregion Preconditions // Invoke the system formatting routine if(StrFormatByteSize64A( size, _buffer, (uint)_buffer.Length ) == IntPtr.Zero) return size.ToString( "N" ) + " bytes"; // Format manually on failure // Measure string length int nLen; for(nLen = 0; (nLen < _buffer.Length) && (_buffer[nLen] != 0); nLen++); // Convert to a string return Encoding.Default.GetString( _buffer, 0, nLen ); } /// /// Analyze the networking activity on the current computer. Analysis is performed /// in periods of time not lesser than "_MaxTimeDiff" in order to minimize the /// performance overload. /// /// True if computer is connected to the network and any adapter is active. public static bool IsNetworkConnected() { bool result = _isNetworkConnected; int ticks = Environment.TickCount; if( ticks > _lastCheckNetworkTicks + _checkNetworkFrequency ) { _lastCheckNetworkTicks = ticks; _isNetworkConnected = result = SystemInformation.Network; if( _wasNetworkConnected != result ) { _wasNetworkConnected = result; MethodInvoker changed = NetworkConnectedStateChanged; if( changed != null ) { changed(); } } } return result; } public static bool IsNetworkConnectedLight() { return _isNetworkConnected; } public static event MethodInvoker NetworkConnectedStateChanged; public static Icon GetFlagResourceIcon( IResource flag ) { string asmName = flag.GetStringProp( "IconAssembly" ); string iconName = flag.GetStringProp( "IconName" ); if( asmName != null && iconName != null ) { return TryGetEmbeddedResourceIconFromAssembly( asmName, iconName ); } return null; } public static Image GetFlagResourceImage( IResource flag ) { string asmName = flag.GetStringProp( "IconAssembly" ); string iconName = flag.GetStringProp( "IconName" ); if( asmName != null && iconName != null ) { return TryGetEmbeddedResourceImageFromAssembly( asmName, iconName ); } return null; } [CanBeNull] public static Icon TryGetEmbeddedResourceIconFromAssembly([NotNull] string asmName, [NotNull] string resName ) { Icon icon = null; Assembly iconAssembly = FindAssembly( asmName ); Stream iconStream = iconAssembly.GetManifestResourceStream( resName ); return ( iconStream != null ) ? new Icon( iconStream ) : null; } [CanBeNull] public static Image TryGetEmbeddedResourceImageFromAssembly([NotNull] string asmName, [NotNull] string resName ) { return TryGetEmbeddedResourceImageFromAssembly( FindAssembly( asmName ), resName ); } [CanBeNull] public static Image TryGetEmbeddedResourceImageFromAssembly([CanBeNull] Assembly asm, [NotNull] string resName ) { if( asm != null ) { Stream stream = asm.GetManifestResourceStream( resName ); if( stream != null ) return Image.FromStream( stream ); } return null; } /// /// Makes an Avalon Pack Absolute URI for a resource whose relative name is and which is packaged in the . /// [NotNull] public static Uri MakeResourceUri([NotNull] string sRelativeNameInCallingAssembly, [NotNull] Assembly assembly) { if(sRelativeNameInCallingAssembly.IsEmpty()) throw new ArgumentNullException("sRelativeNameInCallingAssembly"); if(assembly == null) throw new ArgumentNullException("assembly"); sRelativeNameInCallingAssembly = sRelativeNameInCallingAssembly.TrimStart('/'); return new Uri(string.Format("pack://application:,,,/{0};component/{1}", assembly.GetName().Name, sRelativeNameInCallingAssembly), UriKind.Absolute); } /// /// Loads a raster or relative image from the application Pack Resources. /// // TODO: implement loading vector images. /// /// Pack URI of the resource. [NotNull] public static ImageSource LoadResourceImage([NotNull] Uri uriPack) { if(uriPack == null) throw new ArgumentNullException("uriPack"); var result = (ImageSource)TypeDescriptor.GetConverter(typeof(ImageSource)).ConvertFrom(uriPack); if(result == null) throw new InvalidOperationException(string.Format("Could not load an image from the Pack URI {0}.", uriPack)); return result; } /// /// Loads a raster or relative image from the application Pack Resources. /// // TODO: implement loading vector images. /// /// Relative name of the Pack resource. [NotNull] public static ImageSource LoadResourceImage([NotNull] string sRelativeNameInCallingAssembly) { return LoadResourceImage(sRelativeNameInCallingAssembly, Assembly.GetCallingAssembly()); } /// /// Loads a raster or relative image from the application Pack Resources. /// // TODO: implement loading vector images. /// /// Relative name of the Pack resource. /// Assembly that contains the resource. [NotNull] public static ImageSource LoadResourceImage([NotNull] string sRelativeNameInCallingAssembly, [NotNull] Assembly assembly) { if(sRelativeNameInCallingAssembly.IsEmpty()) throw new ArgumentNullException("sRelativeNameInCallingAssembly"); if(assembly == null) throw new ArgumentNullException("assembly"); return LoadResourceImage(MakeResourceUri(sRelativeNameInCallingAssembly, assembly)); } /// /// Makes an Avalon Pack Absolute URI for a resource whose relative name is and which is packaged in the calling assembly. /// [NotNull] public static Uri MakeResourceUri([NotNull] string sRelativeNameInCallingAssembly) { return MakeResourceUri(sRelativeNameInCallingAssembly, Assembly.GetCallingAssembly()); } /// /// Save image in the system-dependent Temp directory in the ".png" format /// (if it is not present already) and return the result path for the file. /// Use image's GetHashCode for file name. /// [NotNull] public static string IconPath([NotNull] Image img ) { if(img == null) throw new ArgumentNullException("img"); string iconName = img.GetHashCode() + ".png"; string path = Path.Combine( Path.GetTempPath(), iconName ); if( !File.Exists( path ) ) { using( FileStream fs = new FileStream( path, FileMode.Append, FileAccess.Write, FileShare.Read )) img.Save( fs, ImageFormat.Png ); } return path; } [NotNull] public static Assembly FindAssembly([NotNull] string name) { #region Preconditions if( name == null ) throw new ArgumentNullException( "name" ); #endregion Preconditions foreach(Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { if(asm.GetName().Name == name) return asm; } throw new InvalidOperationException(string.Format("The assembly “{0}” could not be found.", name)); } /// /// Compares two collections for equality. /// public static bool AreEqual([NotNull] ICollection one, [NotNull] ICollection two) { if(one == null) throw new ArgumentNullException("one"); if(two == null) throw new ArgumentNullException("two"); if(one.Count != two.Count) return false; using(IEnumerator enumOne = one.GetEnumerator()) using(IEnumerator enumTwo = two.GetEnumerator()) { for(;;) { bool bOne = enumOne.MoveNext(); bool bTwo = enumTwo.MoveNext(); if(bOne != bTwo) return false; if(!bOne) return true; // End of collection if(!Equals(enumOne.Current, enumTwo.Current)) return false; } } } /// /// Formatting buffer for the routine. /// protected static byte[] _buffer = new byte[0x100]; /// /// Converts a numeric value into a string that represents the number /// expressed as a size value in bytes, kilobytes, megabytes, or gigabytes, /// depending on the size. /// /// Numeric value to be converted. /// Pointer to a buffer to hold the converted number. Note: this function is bound to call the ANSI version. /// Size of the buffer, in characters. Note: in our case, in bytes. /// Returns the address of the converted string, or if the conversion fails. /// /// The following table illustrates how this function converts a numeric value into a text string. /// /// Numeric value -> Text string /// 532 -> 532 bytes /// 1340 -> 1.30KB /// 23506 -> 22.9KB /// 2400016 -> 2.29MB /// 2400000000 -> 2.23GB /// [DllImport("shlwapi.dll", CharSet=CharSet.Ansi)] public static extern IntPtr StrFormatByteSize64A(Int64 nSize, byte[] pBuffer, uint nBufSize); //--------------------------------------------------------------------- private const int _EncodingShift = 8; private const int _checkNetworkFrequency = 10000; // milliseconds private static int _lastCheckNetworkTicks = 0; private static bool _isNetworkConnected = true; private static bool _wasNetworkConnected = false; /// /// Creates an image source from a byte stream, a raster or vector one. /// // TODO: support vector images. /// Throws on errors. /// [NotNull] public static ImageSource LoadImage([NotNull] byte[] imagedata) { if(imagedata == null) throw new ArgumentNullException("imagedata"); if(imagedata.Length == 0) throw new ArgumentException("The image data is empty.", "imagedata"); var result = (ImageSource)TypeDescriptor.GetConverter(typeof(ImageSource)).ConvertFrom(imagedata); if(result == null) throw new InvalidOperationException(string.Format("Could not load an image from the data stream.")); return result; } } public class StringStrictComparer : IComparer { private readonly CompareInfo info = CultureInfo.InvariantCulture.CompareInfo; #region IComparer Members public int Compare( object x, object y ) { // Do you think this works??? Huj !!! Fuck!!! - not enough info... // return String.Compare( x_, y_, false, System.Globalization.CultureInfo.InvariantCulture ); return info.Compare( (string)x, (string)y, CompareOptions.Ordinal ); } #endregion } }