context: // Permission is hereby granted, free of charge, to any person obtaining
  // a copy of this software and associated documentation files (the
  // "Software"), to deal in the Software without restriction, including
  // without limitation the rights to use, copy, modify, merge, publish,
  // distribute, sublicense, and/or sell copies of the Software, and to
  // permit persons to whom the Software is furnished to do so, subject to
  // the following conditions:
  // 
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  // 
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  //
  // Copyright (c) 2004 - 2006 Novell, Inc.
  //
  // Authors:
  //	Peter Bartok	pbartok@novell.com
  //      Daniel Nauck    (dna(at)mono-project(dot)de)
  //
  
  // COMPLETE
  
  #undef DebugRunLoop
  
  using Microsoft.Win32;
  using System;
  using System.Drawing;
  using System.ComponentModel;
  using System.Collections;
  using System.Diagnostics;
  using System.Globalization;
  using System.IO;
  using System.Reflection;
  using System.Runtime.InteropServices;
  using System.Threading;
  using System.Text;
  using System.Windows.Forms.VisualStyles;
  
  namespace System.Windows.Forms
  {
  	public sealed class Application
  	{
  		internal class MWFThread
  		{
  			#region Fields
  
  			private ApplicationContext context;
  			private bool messageloop_started;
  			private bool handling_exception;
  			private int thread_id;
  
  			private static readonly Hashtable threads = new Hashtable();
  
  			#endregion	// Fields
  
  			#region Constructors
  
  			private MWFThread()
  			{
  			}
  
  			#endregion	// Constructors
  
  			#region Properties
  
  			public ApplicationContext Context {
  				get { return context; }
  				set { context = value; }
  			}
  
  			public bool MessageLoop {
  				get { return messageloop_started; }
  				set { messageloop_started = value; }
  			}
  
  			public bool HandlingException {
  				get { return handling_exception; }
  				set { handling_exception = value; }
  			}
  
  			public static int LoopCount {
  				get {
  					lock (threads) {
  						int loops = 0;
  
  						foreach (MWFThread thread in threads.Values) {
  							if (thread.messageloop_started)
  								loops++;
  						}
  
  						return loops;
  					}
  				}
  			}
  
  			public static MWFThread Current {
  				get {
  					MWFThread thread = null;
  
  					lock (threads) {
  						thread = (MWFThread) threads [Thread.CurrentThread.GetHashCode ()];
  						if (thread == null) {
  							thread = new MWFThread();
  							thread.thread_id = Thread.CurrentThread.GetHashCode ();
  							threads [thread.thread_id] = thread;
  						}
  					}
  
  					return thread;
  				}
  			}
  
  			#endregion	// Properties
  
  			#region Methods
  
  			public void Exit ()
  			{
  				if (context != null)
  					context.ExitThread();
  				context = null;
  
  				if (Application.ThreadExit != null)
  					Application.ThreadExit(null, EventArgs.Empty);
  
  				if (LoopCount == 0) {
  					if (Application.ApplicationExit != null)
  						Application.ApplicationExit (null, EventArgs.Empty);
  				}
  
  				((MWFThread) threads [thread_id]).MessageLoop = false;
  			}
  
  			#endregion	// Methods
  		}
  
  		private static bool browser_embedded;
  		private static InputLanguage input_language = InputLanguage.CurrentInputLanguage;
  		private static string safe_caption_format = "{1} - {0} - {2}";
  		private static readonly ArrayList message_filters = new ArrayList();
  		private static readonly FormCollection forms = new FormCollection ();
  
  		private static bool use_wait_cursor;
  		private static ToolStrip keyboard_capture;
  		private static VisualStyleState visual_style_state = VisualStyleState.ClientAndNonClientAreasEnabled;
  		static bool visual_styles_enabled;
  
  		private Application ()
  		{
  			browser_embedded = false;
  		}
  
  		static Application ()
  		{
  			// Attempt to load UIA support for winforms
  			// UIA support requires .NET 2.0
  			InitializeUIAutomation ();
  		}
  
  		#region Private Methods
  
  		private static void InitializeUIAutomation ()
  		{
  			// Initialize the UIAutomationWinforms Global class,
  			// which create some listeners which subscribe to internal
  			// MWF events so that it can provide a11y support for MWF
  			const string UIA_WINFORMS_ASSEMBLY = 
  			  "UIAutomationWinforms, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f4ceacb585d99812";
  			MethodInfo init_method;
  			Assembly mwf_providers = null;
  			try {
  				mwf_providers = Assembly.Load (UIA_WINFORMS_ASSEMBLY);
  			} catch { }
  			
  			if (mwf_providers == null)
  				return;
  
  			const string UIA_WINFORMS_TYPE     = "Mono.UIAutomation.Winforms.Global";
  			const string UIA_WINFORMS_METHOD   = "Initialize";
  			try {
  				Type global_type = mwf_providers.GetType (UIA_WINFORMS_TYPE, false);
  				if (global_type != null) {
  					init_method = global_type.GetMethod (UIA_WINFORMS_METHOD, 
  					                                     BindingFlags.Static | 
  					                                     BindingFlags.Public);
  					if (init_method != null)
  						init_method.Invoke (null, new object [] {});
  					else
  						throw new Exception (String.Format ("Method {0} not found in type {1}.",
  						                                    UIA_WINFORMS_METHOD, UIA_WINFORMS_TYPE));
  				}
  				else
  					throw new Exception (String.Format ("Type {0} not found in assembly {1}.",
  					                                    UIA_WINFORMS_TYPE, UIA_WINFORMS_ASSEMBLY));
  			} catch (Exception ex) {
  				Console.Error.WriteLine ("Error setting up UIA: " + ex);
  			}
  		}
  		
  		internal static void CloseForms (Thread thread)
  		{
  			#if DebugRunLoop
  				Console.WriteLine("   CloseForms({0}) called", thread);
  			#endif
  
  			ArrayList forms_to_close = new ArrayList ();
  
  			lock (forms) {
  				foreach (Form f in forms) {
  					if (thread == null || thread == f.creator_thread)
  						forms_to_close.Add (f);
  				}
  
  				foreach (Form f in forms_to_close) {
  					#if DebugRunLoop
  						Console.WriteLine("      Closing form {0}", f);
  					#endif
  					f.Dispose ();
  				}
  			}
  		}
  
  		#endregion	// Private methods
  
  		#region Public Static Properties
  
  		public static bool AllowQuit {
  			get {
  				return !browser_embedded;
  			}
  		}
  
  		public static string CommonAppDataPath {
  			get {
  				return CreateDataPath (Environment.GetFolderPath (Environment.SpecialFolder.CommonApplicationData));
  			}
  		}
  
  		public static RegistryKey CommonAppDataRegistry {
  			get {
  				string key = string.Format ("Software\\{0}\\{1}\\{2}", CompanyName, ProductName, ProductVersion);
  
  				return Registry.LocalMachine.CreateSubKey (key);
  			}
  		}
  
  		public static string CompanyName {
  			get {
  				string company = string.Empty;
  
  				Assembly assembly = Assembly.GetEntryAssembly ();
  				
  				if (assembly == null)
  					assembly = Assembly.GetCallingAssembly ();
  
  				AssemblyCompanyAttribute[] attrs = (AssemblyCompanyAttribute[])
  					assembly.GetCustomAttributes (typeof(AssemblyCompanyAttribute), true);
  				if (attrs != null && attrs.Length > 0)
  					company = attrs [0].Company;
  
  				// If there is no [AssemblyCompany], return the outermost namespace
  				// on Main ()
  				if (company == null || company.Length == 0)
  					if (assembly.EntryPoint != null) {
  						company = assembly.EntryPoint.DeclaringType.Namespace;
  
  						if (company != null) {
  							int firstDot = company.IndexOf ('.');
  							if (firstDot >= 0)
  								company = company.Substring (0, firstDot);
  						}
  					}
  
  				// If that doesn't work, return the name of class containing Main ()
  				if (company == null || company.Length == 0)
  					if (assembly.EntryPoint != null)
  						company = assembly.EntryPoint.DeclaringType.FullName;
  				
  				return company;
  			}
  		}
  
  		public static CultureInfo CurrentCulture {
  			get {
  				return Thread.CurrentThread.CurrentUICulture;
  			}
  			set {
  				Thread.CurrentThread.CurrentUICulture = value;
  			}
  		}
  
  		public static InputLanguage CurrentInputLanguage {
  			get {
  				return input_language;
  			}
  			set {
  				input_language=value;
  			}
  		}
  
  		public static string ExecutablePath {
  			get {
  				return Path.GetFullPath (Environment.GetCommandLineArgs ()[0]);
  			}
  		}
  
  		public static string LocalUserAppDataPath {
  			get {
  				return CreateDataPath (Environment.GetFolderPath (Environment.SpecialFolder.LocalApplicationData));
  			}
  		}
  
  		public static bool MessageLoop {
  			get {
  				return MWFThread.Current.MessageLoop;
  			}
  		}
  
  		public static string ProductName {
  			get {
  				string name = string.Empty;
  				
  				Assembly assembly = Assembly.GetEntryAssembly ();
  				
  				if (assembly == null)
  
gt: 					assembly = Assembly.GetCallingAssembly ();