Jo Shields a575963da9 Imported Upstream version 3.6.0
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
2014-08-13 10:39:27 +01:00

433 lines
12 KiB
C#

// 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) 2005 Novell, Inc. (http://www.novell.com)
//
// Authors:
// Peter Bartok (pbartok@novell.com)
//
//
// COMPLETE
using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
namespace System.Windows.Forms {
public sealed class Clipboard {
#region Local Variables
#endregion // Local Variables
#region Constructors
private Clipboard() {
}
#endregion // Constructors
#region Private Methods
private static bool ConvertToClipboardData(ref int type, object obj, out byte[] data) {
data = null;
return false;
}
private static bool ConvertFromClipboardData(int type, IntPtr data, out object obj) {
obj = null;
if (data == IntPtr.Zero) {
return false;
}
return false;
}
#endregion // Private Methods
#region Public Static Methods
public static void Clear ()
{
IntPtr clipboard_handle;
clipboard_handle = XplatUI.ClipboardOpen (false);
XplatUI.ClipboardStore (clipboard_handle, null, 0, null, false);
}
public static bool ContainsAudio ()
{
return ClipboardContainsFormat (DataFormats.WaveAudio);
}
public static bool ContainsData (string format)
{
return ClipboardContainsFormat (format);
}
public static bool ContainsFileDropList ()
{
return ClipboardContainsFormat (DataFormats.FileDrop);
}
public static bool ContainsImage ()
{
return ClipboardContainsFormat (DataFormats.Bitmap);
}
public static bool ContainsText ()
{
return ClipboardContainsFormat (DataFormats.Text, DataFormats.UnicodeText);
}
public static bool ContainsText (TextDataFormat format)
{
switch (format) {
case TextDataFormat.Text:
return ClipboardContainsFormat (DataFormats.Text);
case TextDataFormat.UnicodeText:
return ClipboardContainsFormat (DataFormats.UnicodeText);
case TextDataFormat.Rtf:
return ClipboardContainsFormat (DataFormats.Rtf);
case TextDataFormat.Html:
return ClipboardContainsFormat (DataFormats.Html);
case TextDataFormat.CommaSeparatedValue:
return ClipboardContainsFormat (DataFormats.CommaSeparatedValue);
}
return false;
}
public static Stream GetAudioStream ()
{
IDataObject data = GetDataObject ();
if (data == null)
return null;
return (Stream)data.GetData (DataFormats.WaveAudio, true);
}
public static Object GetData (string format)
{
IDataObject data = GetDataObject ();
if (data == null)
return null;
return data.GetData (format, true);
}
public static IDataObject GetDataObject ()
{
return GetDataObject (false);
}
public static StringCollection GetFileDropList ()
{
IDataObject data = GetDataObject ();
if (data == null)
return null;
return (StringCollection)data.GetData (DataFormats.FileDrop, true);
}
public static Image GetImage ()
{
IDataObject data = GetDataObject ();
if (data == null)
return null;
return (Image)data.GetData (DataFormats.Bitmap, true);
}
public static string GetText ()
{
return GetText (TextDataFormat.UnicodeText);
}
public static string GetText (TextDataFormat format)
{
if (!Enum.IsDefined (typeof (TextDataFormat), format))
throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for TextDataFormat", format));
IDataObject data = GetDataObject ();
if (data == null)
return string.Empty;
string retval;
switch (format) {
case TextDataFormat.Text:
default:
retval = (string)data.GetData (DataFormats.Text, true);
break;
case TextDataFormat.UnicodeText:
retval = (string)data.GetData (DataFormats.UnicodeText, true);
break;
case TextDataFormat.Rtf:
retval = (string)data.GetData (DataFormats.Rtf, true);
break;
case TextDataFormat.Html:
retval = (string)data.GetData (DataFormats.Html, true);
break;
case TextDataFormat.CommaSeparatedValue:
retval = (string)data.GetData (DataFormats.CommaSeparatedValue, true);
break;
}
return retval == null ? string.Empty : retval;
}
public static void SetAudio (byte[] audioBytes)
{
if (audioBytes == null)
throw new ArgumentNullException ("audioBytes");
MemoryStream ms = new MemoryStream (audioBytes);
SetAudio (ms);
}
public static void SetAudio (Stream audioStream)
{
if (audioStream == null)
throw new ArgumentNullException ("audioStream");
SetData (DataFormats.WaveAudio, audioStream);
}
public static void SetData (string format, Object data)
{
if (data == null)
throw new ArgumentNullException ("data");
DataObject data_object = new DataObject (format, data);
SetDataObject (data_object);
}
public static void SetDataObject(object data) {
SetDataObject(data, false); // MSDN says default behavior is to place non-persistent data to clipboard
}
public static void SetDataObject(object data, bool copy) {
SetDataObject(data, copy, 10, 100); // MSDN says default behavior is to try 10 times with 100 ms delay
}
internal static void SetDataObjectImpl(object data, bool copy) {
IntPtr clipboard_handle;
XplatUI.ObjectToClipboard converter;
int native_format;
DataFormats.Format item_format;
converter = new XplatUI.ObjectToClipboard(ConvertToClipboardData);
clipboard_handle = XplatUI.ClipboardOpen(false);
XplatUI.ClipboardStore(clipboard_handle, null, 0, null, copy); // Empty clipboard
native_format = -1;
if (data is IDataObject) {
string[] formats;
IDataObject data_object = data as IDataObject;
formats = data_object.GetFormats();
for (int i = 0; i < formats.Length; i++) {
item_format = DataFormats.GetFormat(formats[i]);
if ((item_format != null) && (item_format.Name != DataFormats.StringFormat)) {
native_format = item_format.Id;
}
object obj = data_object.GetData (formats [i]);
// this is used only by custom formats
if (IsDataSerializable (obj))
item_format.is_serializable = true;
XplatUI.ClipboardStore(clipboard_handle, obj, native_format, converter, copy);
}
} else {
item_format = DataFormats.Format.Find(data.GetType().FullName);
if ((item_format != null) && (item_format.Name != DataFormats.StringFormat)) {
native_format = item_format.Id;
}
XplatUI.ClipboardStore(clipboard_handle, data, native_format, converter, copy);
}
XplatUI.ClipboardClose(clipboard_handle);
}
static bool IsDataSerializable (object obj)
{
if (obj is ISerializable)
return true;
AttributeCollection attrs = TypeDescriptor.GetAttributes (obj);
return attrs [typeof (SerializableAttribute)] != null;
}
public static void SetDataObject(object data, bool copy, int retryTimes, int retryDelay)
{
if (data == null)
throw new ArgumentNullException("data");
if (retryTimes < 0)
throw new ArgumentOutOfRangeException("retryTimes");
if (retryDelay < 0)
throw new ArgumentOutOfRangeException("retryDelay");
// MS implementation actually puts data to clipboard even when retryTimes == 0
bool retry = true;
do
{
retry = false;
--retryTimes;
try
{
SetDataObjectImpl(data, copy);
} catch (ExternalException) {
if (retryTimes <= 0)
throw;
retry = true;
Threading.Thread.Sleep(retryDelay);
}
} while (retry && retryTimes > 0);
}
[MonoInternalNote ("Needs additional checks for valid paths, see MSDN")]
public static void SetFileDropList (StringCollection filePaths)
{
if (filePaths == null)
throw new ArgumentNullException ("filePaths");
SetData (DataFormats.FileDrop, filePaths);
}
public static void SetImage (Image image)
{
if (image == null)
throw new ArgumentNullException ("image");
SetData (DataFormats.Bitmap, image);
}
public static void SetText (string text)
{
if (string.IsNullOrEmpty (text))
throw new ArgumentNullException ("text");
SetData (DataFormats.UnicodeText, text);
}
public static void SetText (string text, TextDataFormat format)
{
if (string.IsNullOrEmpty (text))
throw new ArgumentNullException ("text");
if (!Enum.IsDefined (typeof (TextDataFormat), format))
throw new InvalidEnumArgumentException (string.Format ("Enum argument value '{0}' is not valid for TextDataFormat", format));
switch (format) {
case TextDataFormat.Text:
SetData (DataFormats.Text, text);
break;
case TextDataFormat.UnicodeText:
SetData (DataFormats.UnicodeText, text);
break;
case TextDataFormat.Rtf:
SetData (DataFormats.Rtf, text);
break;
case TextDataFormat.Html:
SetData (DataFormats.Html, text);
break;
case TextDataFormat.CommaSeparatedValue:
SetData (DataFormats.CommaSeparatedValue, text);
break;
}
}
#endregion // Public Static Methods
#region Internal Static Methods
internal static IDataObject GetDataObject (bool primary_selection)
{
DataObject clipboard;
IntPtr clipboard_handle;
int[] native_formats;
DataFormats.Format item_format;
object managed_clipboard_item;
XplatUI.ClipboardToObject converter;
converter = new XplatUI.ClipboardToObject (ConvertFromClipboardData);
clipboard_handle = XplatUI.ClipboardOpen (primary_selection);
native_formats = XplatUI.ClipboardAvailableFormats (clipboard_handle);
if (native_formats == null) {
return null; // Clipboard empty
}
// Build the IDataObject
clipboard = new DataObject ();
for (int i = 0; i < native_formats.Length; i++) {
// We might get a format we don't understand or know
item_format = DataFormats.GetFormat (native_formats[i]);
if (item_format != null) {
managed_clipboard_item = XplatUI.ClipboardRetrieve (clipboard_handle, native_formats[i], converter);
if (managed_clipboard_item != null) {
clipboard.SetData (item_format.Name, managed_clipboard_item);
// We don't handle 'bitmap' since it involves handles, so we'll equate it to dib
if (item_format.Name == DataFormats.Dib) {
clipboard.SetData (DataFormats.Bitmap, managed_clipboard_item);
}
}
}
}
XplatUI.ClipboardClose (clipboard_handle);
return clipboard;
}
internal static bool ClipboardContainsFormat (params string[] formats)
{
IntPtr clipboard_handle;
int[] native_formats;
DataFormats.Format item_format;
clipboard_handle = XplatUI.ClipboardOpen (false);
native_formats = XplatUI.ClipboardAvailableFormats (clipboard_handle);
if (native_formats == null)
return false;
foreach (int i in native_formats) {
// We might get a format we don't understand or know
item_format = DataFormats.GetFormat (i);
if (item_format != null)
if (((IList)formats).Contains (item_format.Name))
return true;
}
return false;
}
#endregion
}
}