alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (awt_Clipboard.cpp)

This example Java source code file (awt_Clipboard.cpp) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

catch_bad_alloc, dassert, false, globalunlock, jnicall, jniexport, jnu_throwioexception, lpbyte, lpmetafilepict, lpvoid, null, true, try, verify

The awt_Clipboard.cpp Java example source code

/*
 * Copyright (c) 1996, 2011, 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.
 */

#include "awt_Clipboard.h"
#include "awt_DataTransferer.h"
#include "awt_Toolkit.h"
#include <shlobj.h>
#include <sun_awt_windows_WClipboard.h>


/************************************************************************
 * AwtClipboard fields
 */

jmethodID AwtClipboard::lostSelectionOwnershipMID;
jobject AwtClipboard::theCurrentClipboard;

/* This flag is set while we call EmptyClipboard to indicate to
   WM_DESTROYCLIPBOARD handler that we are not losing ownership */
BOOL AwtClipboard::isGettingOwnership = FALSE;

volatile jmethodID AwtClipboard::handleContentsChangedMID;
volatile BOOL AwtClipboard::skipInitialWmDrawClipboardMsg = TRUE;
volatile BOOL AwtClipboard::isClipboardViewerRegistered = FALSE;
volatile HWND AwtClipboard::hwndNextViewer = NULL;

#define GALLOCFLG (GMEM_DDESHARE | GMEM_MOVEABLE | GMEM_ZEROINIT)

/************************************************************************
 * AwtClipboard methods
 */

void AwtClipboard::LostOwnership(JNIEnv *env) {
    if (theCurrentClipboard != NULL) {
        env->CallVoidMethod(theCurrentClipboard, lostSelectionOwnershipMID);
        DASSERT(!safe_ExceptionOccurred(env));
    }
}

void AwtClipboard::WmChangeCbChain(WPARAM wParam, LPARAM lParam) {
    if ((HWND)wParam == hwndNextViewer) {
        hwndNextViewer = (HWND)lParam;
    } else if (hwndNextViewer != NULL) {
        ::SendMessage(hwndNextViewer, WM_CHANGECBCHAIN, wParam, lParam);
    }
}

void AwtClipboard::WmDrawClipboard(JNIEnv *env, WPARAM wParam, LPARAM lParam) {
    if (skipInitialWmDrawClipboardMsg) {
        // skipping the first contents change notification as it comes
        // immediately after registering the clipboard viewer window
        // and it is not caused by an actual contents change.
        skipInitialWmDrawClipboardMsg = FALSE;
        return;
    }
    if (theCurrentClipboard != NULL) {
        env->CallVoidMethod(theCurrentClipboard, handleContentsChangedMID);
        DASSERT(!safe_ExceptionOccurred(env));
    }
    ::SendMessage(hwndNextViewer, WM_DRAWCLIPBOARD, wParam, lParam);
}

void AwtClipboard::RegisterClipboardViewer(JNIEnv *env, jobject jclipboard) {
    if (isClipboardViewerRegistered) {
        return;
    }

    if (theCurrentClipboard == NULL) {
        theCurrentClipboard = env->NewGlobalRef(jclipboard);
    }

    jclass cls = env->GetObjectClass(jclipboard);
    AwtClipboard::handleContentsChangedMID =
            env->GetMethodID(cls, "handleContentsChanged", "()V");
    DASSERT(AwtClipboard::handleContentsChangedMID != NULL);

    hwndNextViewer = ::SetClipboardViewer(AwtToolkit::GetInstance().GetHWnd());
    isClipboardViewerRegistered = TRUE;
}

void AwtClipboard::UnregisterClipboardViewer(JNIEnv *env) {
    TRY;

    if (isClipboardViewerRegistered) {
        ::ChangeClipboardChain(AwtToolkit::GetInstance().GetHWnd(), AwtClipboard::hwndNextViewer);
        AwtClipboard::hwndNextViewer = NULL;
        isClipboardViewerRegistered = FALSE;
        skipInitialWmDrawClipboardMsg = TRUE;
    }

    CATCH_BAD_ALLOC;
}

extern "C" {

void awt_clipboard_uninitialize(JNIEnv *env) {
    AwtClipboard::UnregisterClipboardViewer(env);
    env->DeleteGlobalRef(AwtClipboard::theCurrentClipboard);
    AwtClipboard::theCurrentClipboard = NULL;
}

/************************************************************************
 * WClipboard native methods
 */

/*
 * Class:     sun_awt_windows_WClipboard
 * Method:    init
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WClipboard_init(JNIEnv *env, jclass cls)
{
    TRY;

    AwtClipboard::lostSelectionOwnershipMID =
        env->GetMethodID(cls, "lostSelectionOwnershipImpl", "()V");
    DASSERT(AwtClipboard::lostSelectionOwnershipMID != NULL);

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WClipboard
 * Method:    openClipboard
 * Signature: (Lsun/awt/windows/WClipboard;)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WClipboard_openClipboard(JNIEnv *env, jobject self,
                                              jobject newOwner)
{
    TRY;

    DASSERT(::GetOpenClipboardWindow() != AwtToolkit::GetInstance().GetHWnd());

    if (!::OpenClipboard(AwtToolkit::GetInstance().GetHWnd())) {
        JNU_ThrowByName(env, "java/lang/IllegalStateException",
                        "cannot open system clipboard");
        return;
    }
    if (newOwner != NULL) {
        AwtClipboard::GetOwnership();
        if (AwtClipboard::theCurrentClipboard != NULL) {
            env->DeleteGlobalRef(AwtClipboard::theCurrentClipboard);
        }
        AwtClipboard::theCurrentClipboard = env->NewGlobalRef(newOwner);
    }

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WClipboard
 * Method:    closeClipboard
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WClipboard_closeClipboard(JNIEnv *env, jobject self)
{
    TRY;

    if (::GetOpenClipboardWindow() == AwtToolkit::GetInstance().GetHWnd()) {
        VERIFY(::CloseClipboard());
    }

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WClipboard
 * Method:    registerClipboardViewer
 * Signature: ()V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WClipboard_registerClipboardViewer(JNIEnv *env, jobject self)
{
    TRY;

    AwtClipboard::RegisterClipboardViewer(env, self);

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WClipboard
 * Method:    publishClipboardData
 * Signature: (J[B)V
 */
JNIEXPORT void JNICALL
Java_sun_awt_windows_WClipboard_publishClipboardData(JNIEnv *env,
                                                     jobject self,
                                                     jlong format,
                                                     jbyteArray bytes)
{
    TRY;

    DASSERT(::GetOpenClipboardWindow() == AwtToolkit::GetInstance().GetHWnd());

    if (bytes == NULL) {
        return;
    }

    jint nBytes = env->GetArrayLength(bytes);

    if (format == CF_ENHMETAFILE) {
        LPBYTE lpbEmfBuffer =
            (LPBYTE)env->GetPrimitiveArrayCritical(bytes, NULL);
        if (lpbEmfBuffer == NULL) {
            env->PopLocalFrame(NULL);
            throw std::bad_alloc();
        }

        HENHMETAFILE hemf = ::SetEnhMetaFileBits(nBytes, lpbEmfBuffer);

        env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbEmfBuffer,
                                           JNI_ABORT);

        if (hemf != NULL) {
            VERIFY(::SetClipboardData((UINT)format, hemf));
        }
        return;
    } else if (format == CF_METAFILEPICT) {
        LPBYTE lpbMfpBuffer =
            (LPBYTE)env->GetPrimitiveArrayCritical(bytes, NULL);
        if (lpbMfpBuffer == NULL) {
            env->PopLocalFrame(NULL);
            throw std::bad_alloc();
        }

        HMETAFILE hmf = ::SetMetaFileBitsEx(nBytes - sizeof(METAFILEPICT),
                                         lpbMfpBuffer + sizeof(METAFILEPICT));
        if (hmf == NULL) {
            env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbMfpBuffer, JNI_ABORT);
            env->PopLocalFrame(NULL);
            return;
        }

        LPMETAFILEPICT lpMfpOld = (LPMETAFILEPICT)lpbMfpBuffer;

        HMETAFILEPICT hmfp = ::GlobalAlloc(GALLOCFLG, sizeof(METAFILEPICT));
        if (hmfp == NULL) {
            VERIFY(::DeleteMetaFile(hmf));
            env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbMfpBuffer, JNI_ABORT);
            env->PopLocalFrame(NULL);
            throw std::bad_alloc();
        }

        LPMETAFILEPICT lpMfp = (LPMETAFILEPICT)::GlobalLock(hmfp);
        lpMfp->mm = lpMfpOld->mm;
        lpMfp->xExt = lpMfpOld->xExt;
        lpMfp->yExt = lpMfpOld->yExt;
        lpMfp->hMF = hmf;
        ::GlobalUnlock(hmfp);

        env->ReleasePrimitiveArrayCritical(bytes, (LPVOID)lpbMfpBuffer, JNI_ABORT);

        VERIFY(::SetClipboardData((UINT)format, hmfp));

        return;
    }

    // We have to prepend the DROPFILES structure here because WDataTransferer
    // doesn't.
    HGLOBAL hglobal = ::GlobalAlloc(GALLOCFLG, nBytes + ((format == CF_HDROP)
                                                            ? sizeof(DROPFILES)
                                                            : 0));
    if (hglobal == NULL) {
        throw std::bad_alloc();
    }
    char *dataout = (char *)::GlobalLock(hglobal);

    if (format == CF_HDROP) {
        DROPFILES *dropfiles = (DROPFILES *)dataout;
        dropfiles->pFiles = sizeof(DROPFILES);
        dropfiles->fWide = TRUE; // we publish only Unicode
        dataout += sizeof(DROPFILES);
    }

    env->GetByteArrayRegion(bytes, 0, nBytes, (jbyte *)dataout);
    ::GlobalUnlock(hglobal);

    VERIFY(::SetClipboardData((UINT)format, hglobal));

    CATCH_BAD_ALLOC;
}

/*
 * Class:     sun_awt_windows_WClipboard
 * Method:    getClipboardFormats
 * Signature: ()[J
 */
JNIEXPORT jlongArray JNICALL
Java_sun_awt_windows_WClipboard_getClipboardFormats
    (JNIEnv *env, jobject self)
{
    TRY;

    DASSERT(::GetOpenClipboardWindow() == AwtToolkit::GetInstance().GetHWnd());

    jsize nFormats = ::CountClipboardFormats();
    jlongArray formats = env->NewLongArray(nFormats);
    if (formats == NULL) {
        throw std::bad_alloc();
    }
    if (nFormats == 0) {
        return formats;
    }
    jboolean isCopy;
    jlong *lFormats = env->GetLongArrayElements(formats, &isCopy),
        *saveFormats = lFormats;
    UINT num = 0;

    for (jsize i = 0; i < nFormats; i++, lFormats++) {
        *lFormats = num = ::EnumClipboardFormats(num);
    }

    env->ReleaseLongArrayElements(formats, saveFormats, 0);

    return formats;

    CATCH_BAD_ALLOC_RET(NULL);
}

/*
 * Class:     sun_awt_windows_WClipboard
 * Method:    getClipboardData
 * Signature: (J)[B
 */
JNIEXPORT jbyteArray JNICALL
Java_sun_awt_windows_WClipboard_getClipboardData
    (JNIEnv *env, jobject self, jlong format)
{
    TRY;

    DASSERT(::GetOpenClipboardWindow() == AwtToolkit::GetInstance().GetHWnd());

    HANDLE handle = ::GetClipboardData((UINT)format);
    if (handle == NULL) {
        JNU_ThrowIOException(env, "system clipboard data unavailable");
        return NULL;
    }

    jbyteArray bytes = NULL;
    jbyteArray paletteData = NULL;

    switch (format) {
    case CF_ENHMETAFILE:
    case CF_METAFILEPICT: {
        HENHMETAFILE hemf = NULL;

        if (format == CF_METAFILEPICT) {
            HMETAFILEPICT hMetaFilePict = (HMETAFILEPICT)handle;
            LPMETAFILEPICT lpMetaFilePict =
                (LPMETAFILEPICT)::GlobalLock(hMetaFilePict);
            UINT uSize = ::GetMetaFileBitsEx(lpMetaFilePict->hMF, 0, NULL);
            DASSERT(uSize != 0);

            try {
                LPBYTE lpMfBits = (LPBYTE)safe_Malloc(uSize);
                VERIFY(::GetMetaFileBitsEx(lpMetaFilePict->hMF, uSize,
                                           lpMfBits) == uSize);
                hemf = ::SetWinMetaFileBits(uSize, lpMfBits, NULL,
                                            lpMetaFilePict);
                free(lpMfBits);
                if (hemf == NULL) {
                    ::GlobalUnlock(hMetaFilePict);
                    JNU_ThrowIOException(env, "failed to get system clipboard data");
                    return NULL;
                }
            } catch (...) {
                ::GlobalUnlock(hMetaFilePict);
                throw;
            }
            ::GlobalUnlock(hMetaFilePict);
        } else {
            hemf = (HENHMETAFILE)handle;
        }

        UINT uEmfSize = ::GetEnhMetaFileBits(hemf, 0, NULL);
        if (uEmfSize == 0) {
            JNU_ThrowIOException(env, "cannot retrieve metafile bits");
            return NULL;
        }

        bytes = env->NewByteArray(uEmfSize);
        if (bytes == NULL) {
            throw std::bad_alloc();
        }

        LPBYTE lpbEmfBuffer =
            (LPBYTE)env->GetPrimitiveArrayCritical(bytes, NULL);
        if (lpbEmfBuffer == NULL) {
            env->DeleteLocalRef(bytes);
            throw std::bad_alloc();
        }
        VERIFY(::GetEnhMetaFileBits(hemf, uEmfSize, lpbEmfBuffer) == uEmfSize);
        env->ReleasePrimitiveArrayCritical(bytes, lpbEmfBuffer, 0);

        paletteData =
            AwtDataTransferer::GetPaletteBytes(hemf, OBJ_ENHMETAFILE, FALSE);
        break;
    }
    case CF_LOCALE: {
        LCID *lcid = (LCID *)::GlobalLock(handle);
        if (lcid == NULL) {
            JNU_ThrowIOException(env, "invalid LCID");
            return NULL;
        }
        try {
            bytes = AwtDataTransferer::LCIDToTextEncoding(env, *lcid);
        } catch (...) {
            ::GlobalUnlock(handle);
            throw;
        }
        ::GlobalUnlock(handle);
        break;
    }
    default: {
        ::SetLastError(0); // clear error
        // Warning C4244.
        // Cast SIZE_T (__int64 on 64-bit/unsigned int on 32-bit)
        // to jsize (long).
        SIZE_T globalSize = ::GlobalSize(handle);
        jsize size = (globalSize <= INT_MAX) ? (jsize)globalSize : INT_MAX;
        if (::GetLastError() != 0) {
            JNU_ThrowIOException(env, "invalid global memory block handle");
            return NULL;
        }

        bytes = env->NewByteArray(size);
        if (bytes == NULL) {
            throw std::bad_alloc();
        }

        if (size != 0) {
            LPVOID data = ::GlobalLock(handle);
            env->SetByteArrayRegion(bytes, 0, size, (jbyte *)data);
            ::GlobalUnlock(handle);
        }
        break;
    }
    }

    switch (format) {
    case CF_ENHMETAFILE:
    case CF_METAFILEPICT:
    case CF_DIB: {
        if (JNU_IsNull(env, paletteData)) {
            HPALETTE hPalette = (HPALETTE)::GetClipboardData(CF_PALETTE);
            paletteData =
                AwtDataTransferer::GetPaletteBytes(hPalette, OBJ_PAL, TRUE);
        }
        DASSERT(!JNU_IsNull(env, paletteData) &&
                !JNU_IsNull(env, bytes));

        jbyteArray concat =
            (jbyteArray)AwtDataTransferer::ConcatData(env, paletteData, bytes);

        if (!JNU_IsNull(env, safe_ExceptionOccurred(env))) {
            env->ExceptionDescribe();
            env->ExceptionClear();
            env->DeleteLocalRef(bytes);
            env->DeleteLocalRef(paletteData);
            return NULL;
        }

        env->DeleteLocalRef(bytes);
        env->DeleteLocalRef(paletteData);
        bytes = concat;
        break;
    }
    }

    return bytes;

    CATCH_BAD_ALLOC_RET(NULL);
}

} /* extern "C" */

Other Java examples (source code examples)

Here is a short list of links related to this Java awt_Clipboard.cpp source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.