/*
 * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.awt.motif;

import java.awt.Toolkit;

import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.FlavorMap;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.SystemFlavorMap;

import java.util.Map;
import java.util.SortedMap;
import java.util.Vector;

import sun.awt.AppContext;
import sun.awt.SunToolkit;

import sun.awt.datatransfer.DataTransferer;

/*
 * Implements a general interface to the X11 selection mechanism.
 *
 * @author Amy Fowler
 * @author Roger Brinkley
 * @author Danila Sinopalnikov
 * @author Alexander Gerasimov
 *
 * @since JDK1.1
 */
public class X11Selection {

    static FlavorMap flavorMap = SystemFlavorMap.getDefaultFlavorMap();

    static Vector selections;

    long atom;

    private X11Clipboard clipboard;
    private X11SelectionHolder holder;
    private Transferable contents;

    private boolean disposed = false;
    private byte[] data = null;
    private boolean dataAvailable = false;
    private static final Object source = new Object();

    static {
        // 4154170:  Need to ensure the the toolkit is initialized prior
        // to executing this initializer
        Toolkit toolkit = Toolkit.getDefaultToolkit();

        selections = new Vector();

        initIDs();
        init();

    }

    private static native void initIDs();
    static native void init();

    public X11Selection(String name, X11Clipboard clipboard) {
        atom = ((MDataTransferer)DataTransferer.getInstance()).getAtomForTarget(name);
        selections.addElement(this);
        this.clipboard = clipboard;
    }

    private static Object[] getSelectionsArray() {
        return selections.toArray();
    }

   /*
    * methods for acting as selection provider
    */
    native boolean pGetSelectionOwnership(Object source,
                                          Transferable transferable,
                                          long[] formats,
                                          Map formatMap,
                                          X11SelectionHolder holder);

    boolean getSelectionOwnership(Transferable contents,
                                  X11SelectionHolder holder) {
        SortedMap formatMap =
            DataTransferer.getInstance().getFormatsForTransferable
                (contents, DataTransferer.adaptFlavorMap(flavorMap));
        long[] formats =
            DataTransferer.getInstance().keysToLongArray(formatMap);
        SunToolkit.insertTargetMapping(source, AppContext.getAppContext());

        /*
         * Update 'contents' and 'holder' fields in the native code under
         * AWTLock protection to prevent race with lostSelectionOwnership().
         */
        SunToolkit.awtLock();
        try {
            boolean isOwnerSet = pGetSelectionOwnership(source, contents, formats, formatMap,
                                                        holder);
            if (isOwnerSet) {
                clipboard.checkChangeHere(contents);
            }
            return isOwnerSet;
        } finally {
            SunToolkit.awtUnlock();
        }
    }

    // To be MT-safe this method should be called under awtLock.
    boolean isOwner() {
        return holder != null;
    }

    // NOTE: This method may be called by privileged threads.
    //       DO NOT INVOKE CLIENT CODE ON THIS THREAD!
    private void lostSelectionOwnership() {
        if (holder != null) {
            holder.lostSelectionOwnership();
            holder = null;
        }
        contents = null;
    }

    native void clearNativeContext();

    /*
     * Subclasses should override disposeImpl() instead of dispose(). Client
     * code should always invoke dispose(), never disposeImpl().
     */
    protected void disposeImpl() {
        selections.removeElement(this);
    }

    public final void dispose() {
        boolean call_disposeImpl = false;

        if (!disposed) {
            synchronized (this) {
                if (!disposed) {
                    disposed = call_disposeImpl = true;
                }
            }
        }

        if (call_disposeImpl) {
            disposeImpl();
        }
    }

    
Finds out all selections that have flavor listeners registered and returns their atoms. Upcall from native code.
Returns:an array of selection atoms
/** * Finds out all selections that have flavor listeners registered * and returns their atoms. * Upcall from native code. * * @return an array of selection atoms */
private static long[] getSelectionAtomsToCheckChange() { Object[] sels = getSelectionsArray(); long[] idArray = new long[sels.length]; int count = 0; for (int i = 0; i < sels.length; i++) { X11Clipboard clipboard = ((X11Selection)sels[i]).clipboard; if (clipboard.areFlavorListenersRegistered()) { idArray[count++] = clipboard.getID(); } } long[] atomArray = new long[count]; System.arraycopy(idArray, 0, atomArray, 0, atomArray.length); return atomArray; }
Upcall from native code.
/** * Upcall from native code. */
private void checkChange(long[] formats) { clipboard.checkChange(formats); } }