The Mozilla
Organization
Our Mission
Who We Are
Getting Involved
Community
Editorials
What's New
Newsbot
Development
Roadmap
Module Owners
Blue Sky
Projects
Status
Tools
Products
Source Code
Binaries
Documentation
License Terms
Bug Reports
Quality
Search
Feedback



XPToolkit Clipboard

Written by Rod Spears
4/19/99

Simple Use cases

  • User selects data, copies it to the clipboard
  • User pastes from the clipboard

NGLayout requirements

  • No direct requirement

High Level Design

This is a very preliminary design for clipboard support within NGLayout.

Design goals:

  1. Simplified, streamline API


Clipboard - Interface and Implementation

Description: 
Application-wide clipboard. It is a service that manages a single Transferable object and grants access to the native clipboard.
Interface:
nsIClipboard.h

ClipboardOwner - Interface only

Description: 
Objects implementing the ClipboardOwner interface "own" the transferable object on the application clipboard. When a new object is placed on the clipboard or the clipboard is cleared externally the owner is notified.
Interface:
nsIClipboardOwner.h

DataFlavor - Interface and Implementation (Cross platform impl.)

Description: 
A simple class that defines a MIME type and a human readable string for that MIME type. Transferable use this interface/object to identify the type of data that a Transferable contains or can emit.
Interface:
nsIDataFlavor.h

Transferable - Interface

Description: 
A transferable is a platform independent description and implemention of some piece of data. The data is described by a list of supported DataFlavor types.

The nsITransferable interface used as a "getter" interface. Transferable objects must support as a miminum this interface.
 

Interface:
nsITransferable.h

GenericTransferable - Interface and Implementation (Cross platform impl.)

Description: 
The GenericTransferable is a specific implementation of a transferable. It implements the nsITransferable interface enabling consumers accessof its internal data. It also, implements the nsIGenericTransferable interface that is used to set the data into the transferable. The nsIGenericTransferable interface also supports FormatConverters. The GenericTransferable is a multi-purpose transferable that can be used to set up mappings from one DataFlavor to another. This can be done directly through the class or through a object implementing the FormatConverter interface.

There may be several different types of transferables within any given system. The standard implementation is intended to handle Text, XIF, Unicode and HTML.

Interface:
nsIGenericTransferable.h

FormatConverter - Interface

Description: 
The FormatConverter provides a interface for converting from one type of DataFlavor to another. Implementations may be created to convert text to HTML. Image converters may convert from JPEG to PNG.
Interface:
nsIFormatConverter.h

XIFFormatConverter - Implementation (Cross platform impl.)

Description: 
The XIFFormatConverter class supports the conversion of  XIF data to Text, HTML, and AOL Mail formats. It currently does not suport the conversion of generic data to the XIF format.
Interface:
nsXIFFormatConverter.cpp

Implementation Considerations

Platform
Each platform will need to implement the Clipboard object to expose the native clipboard and its funcationality via the interfaces described above.
 

How to Place Items on the Clipboard

To place data on the clipboard you must first create an object that supports the nsITransferable interface, set data into the transferable and then set it into the clipboard.
 

How to Put Text onto the Clipboard

    // Get the Clipboard Service
    nsIClipboard* clipboard;
    nsresult rv = nsServiceManager::GetService(kCClipboardCID,
                                               kIClipboardIID,
                                               (nsISupports **)&clipboard);
    if (NS_OK == rv) {
      // Create a data flavor to tell the transferable
      // that it is about to receive Text
      nsCOMPtr<nsIDataFlavor> flavor;
      rv = nsComponentManager::CreateInstance(kCDataFlavorCID,
                                              nsnull,
                                              kIDataFlavorIID, (void**) getter_AddRefs(flavor));
      if (NS_OK == rv) {
        // Initialize data flavor to Text
        flavor->Init(kTextMime, "Text Format");

        // Create a generic transferable for putting data on the Clipboard
        nsCOMPtr<nsIGenericTransferable> genericTrans;
        rv = nsComponentManager::CreateInstance(kCGenericTransferableCID, nsnull,
                                                kIGenericTransferableIID, (void**) getter_AddRefs(genericTrans));
        if (NS_OK == rv) {
          // The data on the clipboard will be in "Text" format
          // add the DataFlavor to the generic transferable
          genericTrans->AddDataFlavor(flavor);

          // Now add the Text data into the transferable
          const char * data = "I am text Data";
          genericTrans->SetTransferData(flavor, data, strlen(data));

          // Get the nsITransferable interface from the GenericTransferable and
          // put the transferable on the clipboard, the clipboard owner is set to nsnull
          nsCOMPtr<nsITransferable> trans = do_QueryInterface(genericTrans);
          if (trans) {
            clipboard->SetData(trans, nsnull);
          }
        }
      }
    }
    nsServiceManager::ReleaseService(kCClipboardCID, clipboard);
 
 

How to Put Content onto the Clipboard

  // This code snipet comes from the Presentation Shell (nsPresShell.cpp)
  // it has access to the document, so start by getting the current document
  nsCOMPtr<nsIDocument> doc;
  GetDocument(getter_AddRefs(doc));
  if (doc) {
    // Create a buffer for holding the content converted to XIF
    nsString buffer;

    // Get the current selection in the PresShell
    nsIDOMSelection* sel = nsnull;
    GetSelection(&sel);

    // Ask the document to convert the selection to a XIF encoded string
    // This walks through the content nodes converting their contents to XIF
    // If there is no selection then the clipboard will hold what is basically
    // empty content
    if (sel != nsnull) {
      doc->CreateXIF(buffer,sel);
    NS_IF_RELEASE(sel);

    // Get the Clipboard Service
    nsIClipboard* clipboard;
    nsresult rv = nsServiceManager::GetService(kCClipboardCID,
                                               kIClipboardIID,
                                               (nsISupports **)&clipboard);
    if (NS_OK == rv) {
      // Create a data flavor to tell the transferable
      // that it is about to receive XIF
      nsCOMPtr<nsIDataFlavor> flavor;
      rv = nsComponentManager::CreateInstance(kCDataFlavorCID,
                                              nsnull,
                                              kIDataFlavorIID, (void**) getter_AddRefs(flavor));
      if (NS_OK == rv) {
        // Initialize data flavor to XIF
        flavor->Init(kXIFMime, "XIF");

        // Create a transferable for putting data on the Clipboard
        nsCOMPtr<nsIGenericTransferable> genericTrans;
        rv = nsComponentManager::CreateInstance(kCGenericTransferableCID, nsnull,
                                                kIGenericTransferableIID, (void**) getter_AddRefs(genericTrans));
        if (NS_OK == rv) {
          // The data on the clipboard will be in "XIF" format
          // so give the clipboard transferable a "XIFConverter" for
          // converting from XIF to other formats
          nsCOMPtr<nsIFormatConverter> xifConverter;
          rv = nsComponentManager::CreateInstance(kCXIFConverterCID, nsnull,
                                                  kIFormatConverterIID, (void**) getter_AddRefs(xifConverter));
          if (NS_OK == rv) {
            // Add the XIF DataFlavor to the transferable
            // this tells the transferable that it can handle receiving the XIF format
            genericTrans->AddDataFlavor(flavor);

            // Add the converter for going from XIF to other formats
            genericTrans->SetConverter(xifConverter);

            // Now add the XIF data to the transferable
            genericTrans->SetTransferData(flavor, buffer.ToNewCString(), buffer.Length());

            // put the transferable on the clipboard
            nsCOMPtr<nsITransferable> trans(do_QueryInterface(genericTrans));
            if (trans) {
              clipboard->SetData(trans, nsnull);
            }
          }
        }
      }
      nsServiceManager::ReleaseService(kCClipboardCID, clipboard);
    }
  }
 

Getting Items off of the Clipboard

How to Get Text off of the Clipboard

  // Get Clipboard Service
  nsIClipboard* clipboard;
  nsresult rv = nsServiceManager::GetService(kCClipboardCID,
                                             kIClipboardIID,
                                             (nsISupports **)&clipboard);

  // Create generic Transferable for getting the data
  nsCOMPtr<nsIGenericTransferable> genericTrans;
  rv = nsComponentManager::CreateInstance(kCGenericTransferableCID, nsnull,
                                          kIGenericTransferableIID, (void**) getter_AddRefs(genericTrans));
  if (NS_OK == rv) {
    // Get the nsITransferable interface for getting the data from the clipboard
    nsCOMPtr<nsITransferable> trans(do_QueryInterface(genericTrans));
    if (trans) {
      nsCOMPtr<nsIDataFlavor> flavor;

      // Create the desired DataFlavor for the type of data we want to get out of the transferable
      rv = nsComponentManager::CreateInstance(kCDataFlavorCID, nsnull, 
                                              kIDataFlavorIID, (void**) getter_AddRefs(flavor));
      if (NS_OK == rv) {
        // Initialize the DataFlavor and set it into the GenericTransferable
        flavor->Init(kTextMime, "Text");
        genericTrans->AddDataFlavor(flavor);

        // Get the Data from the clipboard
        clipboard->GetData(trans);

        // Now we ask the transferable for the data
        // it still owns the data, we just have a pointer to it.
        // If it can't support a "text" output of the data the call will fail
        char *str = 0;
        PRUint32 len;
        if (NS_OK == trans->GetTransferData(flavor, (void **)&str, &len)) {
          // Make adjustments for null terminated strings
          if (str && len > 0) {
            // stuffToPaste is ready for insertion into the content
            stuffToPaste.SetString(str, len);
          }
        }
      }
    }
  }
  nsServiceManager::ReleaseService(kCClipboardCID, clipboard);
 

Owners

NGLayout-only work (Tom Pixley)
XP classes & Win32 (Rod Spears)
MAC (Mike Pinkerton)
Unix (Chris McAfee)

Dependencies

TBD

Copyright © 1998 The Mozilla Organization.