view org.eclipse.swt.gtk.linux.x86/src/org/eclipse/swt/dnd/ClipboardProxy.d @ 120:536e43f63c81

Comprehensive update for Win32/Linux32 dmd-2.053/dmd-1.068+Tango-r5661 ===D2=== * added [Try]Immutable/Const/Shared templates to work with differenses in D1/D2 instead of version statements used these templates to work with strict type storage rules of dmd-2.053 * com.ibm.icu now also compilable with D2, but not tested yet * small fixes Snippet288 - shared data is in TLS ===Phobos=== * fixed critical bugs in Phobos implemention completely incorrect segfault prone fromStringz (Linux's port ruthless killer) terrible, incorrect StringBuffer realization (StyledText killer) * fixed small bugs as well Snippet72 - misprint in the snippet * implemented missed functionality for Phobos ByteArrayOutputStream implemented (image loading available) formatting correctly works for all DWT's cases As a result, folowing snippets now works with Phobos (Snippet### - what is fixed): Snippet24, 42, 111, 115, 130, 235, 276 - bad string formatting Snippet48, 282 - crash on image loading Snippet163, 189, 211, 213, 217, 218, 222 - crash on copy/cut in StyledText Snippet244 - hang-up ===Tango=== * few changes for the latest Tango trunc-r5661 * few small performance improvments ===General=== * implMissing-s for only one version changed to implMissingInTango/InPhobos * incorrect calls to Format in toString-s fixed * fixed loading \uXXXX characters in ResourceBundle * added good UTF-8 support for StyledText, TextLayout (Win32) and friends UTF functions revised and tested. It is now in java.nonstandard.*Utf modules StyledText and TextLayout (Win32) modules revised for UTF-8 support * removed small diferences in most identical files in *.swt.* folders *.swt.internal.image, *.swt.events and *.swt.custom are identical in Win32/Linux32 now 179 of 576 (~31%) files in *.swt.* folders are fully identical * Win32: snippets now have right subsystem, pretty icons and native system style controls * small fixes in snippets Snippet44 - it's not Snippet44 Snippet212 - functions work with different images and offsets arrays Win32: Snippet282 - crash on close if the button has an image Snippet293 - setGrayed is commented and others Win32: As a result, folowing snippets now works Snippet68 - color doesn't change Snippet163, 189, 211, 213, 217, 218, 222 - UTF-8 issues (see above) Snippet193 - no tabel headers
author Denis Shelomovskij <verylonglogin.reg@gmail.com>
date Sat, 09 Jul 2011 15:50:20 +0300
parents b397a43d66d1
children
line wrap: on
line source

/*******************************************************************************
 * Copyright (c) 2000, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 * Port to the D programming language:
 *     Frank Benoit <benoit@tionex.de>
 *******************************************************************************/
module org.eclipse.swt.dnd.ClipboardProxy;

import java.lang.all;



import org.eclipse.swt.SWT;
import org.eclipse.swt.internal.gtk.OS;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.TransferData;

version(Tango){
static import tango.stdc.string;
} else { // Phobos
}


class ClipboardProxy {
    /* Data is not flushed to the clipboard immediately.
     * This class will remember the data and provide it when requested.
     */
    Object[] clipboardData;
    Transfer[] clipboardDataTypes;
    Object[] primaryClipboardData;
    Transfer[] primaryClipboardDataTypes;

    Display display;
    Clipboard activeClipboard = null;
    Clipboard activePrimaryClipboard = null;

    static String ID = "CLIPBOARD PROXY OBJECT"; //$NON-NLS-1$

static ClipboardProxy _getInstance(Display display) {
    ClipboardProxy proxy = cast(ClipboardProxy) display.getData(ID);
    if (proxy !is null) return proxy;
    proxy = new ClipboardProxy(display);
    display.setData(ID, proxy);
    display.addListener(SWT.Dispose, new class( display ) Listener {
        Display disp;
        this( Display disp ){ this.disp = disp; }
        public void handleEvent(Event event) {
            ClipboardProxy clipbordProxy = cast(ClipboardProxy)disp.getData(ID);
            if (clipbordProxy is null) return;
            disp.setData(ID, null);
            clipbordProxy.dispose();
        }
    });
    return proxy;
}

this(Display display) {
    this.display = display;
}

void clear (Clipboard owner, int clipboards) {
    if ((clipboards & DND.CLIPBOARD) !is 0 && activeClipboard is owner) {
        OS.gtk_clipboard_clear(Clipboard.GTKCLIPBOARD);
    }
    if ((clipboards & DND.SELECTION_CLIPBOARD) !is 0 && activePrimaryClipboard is owner) {
        OS.gtk_clipboard_clear(Clipboard.GTKPRIMARYCLIPBOARD);
    }
}

private static extern(C) void clearFuncFunc(GtkClipboard *clipboard, void* user_data_or_owner){
    auto obj = cast(ClipboardProxy)user_data_or_owner;
    obj.clearFunc( clipboard );
}
void clearFunc(GtkClipboard *clipboard ){
    if (clipboard is Clipboard.GTKCLIPBOARD) {
        activeClipboard = null;
        clipboardData = null;
        clipboardDataTypes = null;
    }
    if (clipboard is Clipboard.GTKPRIMARYCLIPBOARD) {
        activePrimaryClipboard = null;
        primaryClipboardData = null;
        primaryClipboardDataTypes = null;
    }
}

void dispose () {
    if (display is null) return;
    if (activeClipboard !is null) OS.gtk_clipboard_clear(Clipboard.GTKCLIPBOARD);
    if (activePrimaryClipboard !is null) OS.gtk_clipboard_clear(Clipboard.GTKPRIMARYCLIPBOARD);
    display = null;
    clipboardData = null;
    clipboardDataTypes = null;
    primaryClipboardData = null;
    primaryClipboardDataTypes = null;
}

private static extern(C) void getFuncFunc(
    GtkClipboard *clipboard,
    GtkSelectionData *selection_data,
    uint info,
    void* user_data_or_owner)
{
    auto obj = cast(ClipboardProxy)user_data_or_owner;
    obj.getFunc( clipboard, selection_data, info );
}
/**
 * This function provides the data to the clipboard on request.
 * When this clipboard is disposed, the data will no longer be available.
 */
int getFunc(
    GtkClipboard *clipboard,
    GtkSelectionData *selectionData,
    uint info)
{
    if (selectionData is null) return 0;
    TransferData tdata = new TransferData();
    tdata.type = selectionData.target;
    Transfer[] types = (clipboard is Clipboard.GTKCLIPBOARD) ? clipboardDataTypes : primaryClipboardDataTypes;
    int index = -1;
    for (int i = 0; i < types.length; i++) {
        if (types[i].isSupportedType(tdata)) {
            index = i;
            break;
        }
    }
    if (index is -1) return 0;
    Object[] data = (clipboard is Clipboard.GTKCLIPBOARD) ? clipboardData : primaryClipboardData;
    types[index].javaToNative(data[index], tdata);
    if (tdata.format < 8 || tdata.format % 8 !is 0) {
        return 0;
    }
    OS.gtk_selection_data_set(selectionData, tdata.type, tdata.format, tdata.pValue, tdata.length);
    OS.g_free(tdata.pValue);
    return 1;
}

bool setData(Clipboard owner, Object[] data, Transfer[] dataTypes, int clipboards) { 
    GtkTargetEntry*[] entries;
    GtkTargetEntry* pTargetsList;
    try {
        for (int i = 0; i < dataTypes.length; i++) {
            Transfer transfer = dataTypes[i];
            int[] typeIds = transfer.getTypeIds();
            String[] typeNames = transfer.getTypeNames();
            for (int j = 0; j < typeIds.length; j++) {
                GtkTargetEntry*  entry = new GtkTargetEntry();
                entry.info = typeIds[j];
                char* pName = cast(char*)OS.g_malloc(typeNames[j].length+1);
                pName[ 0 .. typeNames[j].length ] = typeNames[j];
                pName[ typeNames[j].length ] = '\0';
                entry.target = pName;
                GtkTargetEntry*[] tmp = new GtkTargetEntry*[entries.length + 1];
                SimpleType!(GtkTargetEntry*).arraycopy(entries, 0, tmp, 0, entries.length);
                tmp[entries.length] = entry;
                entries = tmp;
            }
        }

        pTargetsList = cast(GtkTargetEntry*)OS.g_malloc(GtkTargetEntry.sizeof * entries.length);
        int offset = 0;
        for (int i = 0; i < entries.length; i++) {
            OS.memmove(pTargetsList + i, entries[i], GtkTargetEntry.sizeof);
            offset += GtkTargetEntry.sizeof;
        }
        if ((clipboards & DND.CLIPBOARD) !is 0) {
            if (activeClipboard !is null) OS.gtk_clipboard_clear(Clipboard.GTKCLIPBOARD);
            clipboardData = data;
            clipboardDataTypes = dataTypes;
            if (!OS.gtk_clipboard_set_with_data(Clipboard.GTKCLIPBOARD, pTargetsList, entries.length, &getFuncFunc, &clearFuncFunc, cast(void*)this )) {
                return false;
            }
            activeClipboard = owner;
        }
        if ((clipboards & DND.SELECTION_CLIPBOARD) !is 0) {
            if (activePrimaryClipboard !is null) OS.gtk_clipboard_clear(Clipboard.GTKPRIMARYCLIPBOARD);
            primaryClipboardData = data;
            primaryClipboardDataTypes = dataTypes;
            if (!OS.gtk_clipboard_set_with_data(Clipboard.GTKPRIMARYCLIPBOARD, pTargetsList, entries.length, &getFuncFunc, &clearFuncFunc, cast(void*)this )) {
                return false;
            }
            activePrimaryClipboard = owner;
        }
        return true;
    } finally {
        for (int i = 0; i < entries.length; i++) {
            GtkTargetEntry* entry = entries[i];
            if( entry.target !is null) OS.g_free(entry.target);
        }
        if (pTargetsList !is null) OS.g_free(pTargetsList);
    }
}
}