gdkselection-win32.c

Go to the documentation of this file.
00001 /* GDK - The GIMP Drawing Kit
00002  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Library General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Library General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Library General Public
00015  * License along with this library; if not, write to the
00016  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
00017  * Boston, MA 02111-1307, USA.
00018  */
00019 
00020 /*
00021  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
00022  * file for a list of people on the GTK+ Team.  See the ChangeLog
00023  * files for a list of changes.  These files are distributed with
00024  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
00025  */
00026 
00027 #include "config.h"
00028 
00029 #include <string.h>
00030 
00031 #include <gdk/gdk.h>
00032 #include "gdkwin32.h"
00033 
00034 /* We emulate the GDK_SELECTION window properties by storing
00035  * it's data in a per-window hashtable.
00036  */
00037 
00038 typedef struct {
00039    guchar *data;
00040    gint length;
00041    gint format;
00042    GdkAtom type;
00043 } GdkSelProp;
00044 
00045 static GHashTable *sel_prop_table = NULL;
00046 
00047 void gdk_win32_selection_init(void)
00048 {
00049    if (sel_prop_table == NULL)
00050       sel_prop_table = g_hash_table_new(g_int_hash, g_int_equal);
00051 }
00052 
00053 void
00054 gdk_sel_prop_store(GdkWindow * owner,
00055                    GdkAtom type, gint format, guchar * data, gint length)
00056 {
00057    GdkSelProp *prop;
00058 
00059    prop = g_hash_table_lookup(sel_prop_table, &GDK_DRAWABLE_XID(owner));
00060    if (prop != NULL) {
00061       g_free(prop->data);
00062       g_hash_table_remove(sel_prop_table, &GDK_DRAWABLE_XID(owner));
00063    }
00064    prop = g_new(GdkSelProp, 1);
00065    prop->data = data;
00066    prop->length = length;
00067    prop->format = format;
00068    prop->type = type;
00069    g_hash_table_insert(sel_prop_table, &GDK_DRAWABLE_XID(owner), prop);
00070 }
00071 
00072 gint
00073 gdk_selection_owner_set(GdkWindow * owner,
00074                         GdkAtom selection, guint32 time, gint send_event)
00075 {
00076    gchar *sel_name;
00077    HWND xwindow;
00078 
00079    GDK_NOTE(DND,
00080             (sel_name = gdk_atom_name(selection),
00081              g_print("gdk_selection_owner_set: %#x %#x (%s)\n",
00082                      (owner ? GDK_DRAWABLE_XID(owner) : 0),
00083                      selection, sel_name), g_free(sel_name)));
00084 
00085    if (selection != gdk_clipboard_atom)
00086       return FALSE;
00087 
00088    if (owner != NULL)
00089       xwindow = GDK_DRAWABLE_XID(owner);
00090    else
00091       xwindow = NULL;
00092 
00093    GDK_NOTE(DND, g_print("...OpenClipboard(%#x)\n", xwindow));
00094    if (!OpenClipboard(xwindow)) {
00095       WIN32_API_FAILED("OpenClipboard");
00096       return FALSE;
00097    }
00098    GDK_NOTE(DND, g_print("...EmptyClipboard()\n"));
00099    if (!EmptyClipboard()) {
00100       WIN32_API_FAILED("EmptyClipboard");
00101       CloseClipboard();
00102       return FALSE;
00103    }
00104 #if 0
00105    /* No delayed rendering */
00106    if (xwindow != NULL)
00107       SetClipboardData(CF_TEXT, NULL);
00108 #endif
00109    GDK_NOTE(DND, g_print("...CloseClipboard()\n"));
00110    if (!CloseClipboard()) {
00111       WIN32_API_FAILED("CloseClipboard");
00112       return FALSE;
00113    }
00114    if (owner != NULL) {
00115       /* Send ourselves an ersatz selection request message so that
00116        * gdk_property_change will be called to store the clipboard data.
00117        */
00118       SendMessage(xwindow, gdk_selection_request_msg, selection, 0);
00119    }
00120 
00121    return TRUE;
00122 }
00123 
00124 GdkWindow *gdk_selection_owner_get(GdkAtom selection)
00125 {
00126    GdkWindow *window;
00127    gchar *sel_name;
00128 
00129 #if 0
00130    /* XXX Hmm, gtk selections seem to work best with this. This causes
00131     * gtk to always get the clipboard contents from Windows, and not
00132     * from the editable's own stashed-away copy.
00133     */
00134    return NULL;
00135 #else
00136    if (selection != gdk_clipboard_atom)
00137       window = NULL;
00138    else {
00139       window = gdk_window_lookup(GetClipboardOwner());
00140       if (window == NULL)
00141          window = (GdkWindow *)GetClipboardOwner();
00142    }
00143 
00144 #endif
00145 
00146    GDK_NOTE(DND,
00147             (sel_name = gdk_atom_name(selection),
00148              g_print("gdk_selection_owner_get: %#x (%s) = %#x\n",
00149                      selection, sel_name,
00150                      (window ? GDK_DRAWABLE_XID(window) : 0)),
00151              g_free(sel_name)));
00152 
00153    return window;
00154 }
00155 
00156 void
00157 gdk_selection_convert(GdkWindow * requestor,
00158                       GdkAtom selection, GdkAtom target, guint32 time)
00159 {
00160    HGLOBAL hdata;
00161    GdkSelProp *prop;
00162    guchar *ptr, *data, *datap, *p;
00163    guint i, length, slength;
00164    gchar *sel_name, *tgt_name;
00165 
00166    g_return_if_fail(requestor != NULL);
00167    if (GDK_DRAWABLE_DESTROYED(requestor))
00168       return;
00169 
00170    GDK_NOTE(DND,
00171             (sel_name = gdk_atom_name(selection),
00172              tgt_name = gdk_atom_name(target),
00173              g_print("gdk_selection_convert: %#x %#x (%s) %#x (%s)\n",
00174                      GDK_DRAWABLE_XID(requestor), selection, sel_name,
00175                      target, tgt_name), g_free(sel_name),
00176              g_free(tgt_name)));
00177 
00178    if (selection == gdk_clipboard_atom) {
00179       /* Converting the CLIPBOARD selection means he wants the
00180        * contents of the clipboard. Get the clipboard data,
00181        * and store it for later.
00182        */
00183       GDK_NOTE(DND, g_print("...OpenClipboard(%#x)\n",
00184                             GDK_DRAWABLE_XID(requestor)));
00185       if (!OpenClipboard(GDK_DRAWABLE_XID(requestor))) {
00186          WIN32_API_FAILED("OpenClipboard");
00187          return;
00188       }
00189 
00190       GDK_NOTE(DND, g_print("...GetClipboardData(CF_TEXT)\n"));
00191       if ((hdata = GetClipboardData(CF_TEXT)) != NULL) {
00192          if ((ptr = GlobalLock(hdata)) != NULL) {
00193             length = GlobalSize(hdata);
00194 
00195             GDK_NOTE(DND, g_print("...got data: %d bytes: %.10s\n",
00196                                   length, ptr));
00197 
00198             slength = 0;
00199             p = ptr;
00200             for (i = 0; i < length; i++) {
00201                if (*p == '\0')
00202                   break;
00203                else if (*p != '\r')
00204                   slength++;
00205                p++;
00206             }
00207 
00208             data = datap = g_malloc(slength + 1);
00209             p = ptr;
00210             for (i = 0; i < length; i++) {
00211                if (*p == '\0')
00212                   break;
00213                else if (*p != '\r')
00214                   *datap++ = *p;
00215                p++;
00216             }
00217             *datap++ = '\0';
00218             gdk_sel_prop_store(requestor, GDK_TARGET_STRING, 8,
00219                                data, strlen(data) + 1);
00220 
00221             GlobalUnlock(hdata);
00222          }
00223       }
00224       GDK_NOTE(DND, g_print("...CloseClipboard()\n"));
00225       CloseClipboard();
00226 
00227 
00228       /* Send ourselves an ersatz selection notify message so that we actually
00229        * fetch the data.
00230        */
00231       SendMessage(GDK_DRAWABLE_XID(requestor), gdk_selection_notify_msg,
00232                   selection, target);
00233    } else if (selection == gdk_win32_dropfiles_atom) {
00234       /* This means he wants the names of the dropped files.
00235        * gdk_dropfiles_filter already has stored the text/uri-list
00236        * data, tempoarily on gdk_root_parent's selection "property".
00237        */
00238       GdkSelProp *prop;
00239 
00240       prop = g_hash_table_lookup(sel_prop_table,
00241                                  &GDK_DRAWABLE_XID(gdk_parent_root));
00242 
00243       if (prop != NULL) {
00244          g_hash_table_remove(sel_prop_table,
00245                              &GDK_DRAWABLE_XID(gdk_parent_root));
00246          gdk_sel_prop_store(requestor, prop->type, prop->format,
00247                             prop->data, prop->length);
00248          g_free(prop);
00249          SendMessage(GDK_DRAWABLE_XID(requestor), gdk_selection_notify_msg,
00250                      selection, target);
00251       }
00252    } else {
00253       g_warning("gdk_selection_convert: General case not implemented");
00254    }
00255 }
00256 
00257 gint
00258 gdk_selection_property_get(GdkWindow * requestor,
00259                            guchar ** data,
00260                            GdkAtom * ret_type, gint * ret_format)
00261 {
00262    GdkSelProp *prop;
00263 
00264    g_return_val_if_fail(requestor != NULL, 0);
00265    g_return_val_if_fail(GDK_IS_WINDOW(requestor), 0);
00266 
00267    if (GDK_DRAWABLE_DESTROYED(requestor))
00268       return 0;
00269 
00270    GDK_NOTE(DND, g_print("gdk_selection_property_get: %#x",
00271                          GDK_DRAWABLE_XID(requestor)));
00272 
00273    prop =
00274        g_hash_table_lookup(sel_prop_table, &GDK_DRAWABLE_XID(requestor));
00275 
00276    if (prop == NULL) {
00277       GDK_NOTE(DND, g_print(": NULL\n"));
00278       *data = NULL;
00279       return 0;
00280    }
00281    GDK_NOTE(DND, g_print(": %d bytes\n", prop->length));
00282    *data = g_malloc(prop->length);
00283    if (prop->length > 0)
00284       memmove(*data, prop->data, prop->length);
00285    if (ret_type)
00286       *ret_type = prop->type;
00287    if (ret_format)
00288       *ret_format = prop->format;
00289 
00290    return prop->length;
00291 }
00292 
00293 void gdk_selection_property_delete(GdkWindow * window)
00294 {
00295    GdkSelProp *prop;
00296 
00297    GDK_NOTE(DND, g_print("gdk_selection_property_delete: %#x",
00298                          GDK_DRAWABLE_XID(window)));
00299 
00300    prop = g_hash_table_lookup(sel_prop_table, &GDK_DRAWABLE_XID(window));
00301    if (prop != NULL) {
00302       g_free(prop->data);
00303       g_hash_table_remove(sel_prop_table, &GDK_DRAWABLE_XID(window));
00304    } else
00305       g_warning("gdk_selection_property_delete: not found");
00306 }
00307 
00308 void
00309 gdk_selection_send_notify(guint32 requestor,
00310                           GdkAtom selection,
00311                           GdkAtom target, GdkAtom property, guint32 time)
00312 {
00313    gchar *sel_name, *tgt_name, *prop_name;
00314 
00315    GDK_NOTE(DND,
00316             (sel_name = gdk_atom_name(selection),
00317              tgt_name = gdk_atom_name(target),
00318              prop_name = gdk_atom_name(property),
00319              g_print
00320              ("gdk_selection_send_notify: %#x %#x (%s) %#x (%s) %#x (%s)\n",
00321               requestor, selection, sel_name, target, tgt_name, property,
00322               prop_name), g_free(sel_name), g_free(tgt_name),
00323              g_free(prop_name)));
00324 
00325    /* Send ourselves a selection clear message so that gtk thinks we don't
00326     * have the selection, and will claim it anew when needed, and
00327     * we thus get a chance to store data in the Windows clipboard.
00328     * Otherwise, if a gtkeditable does a copy to clipboard several times
00329     * only the first one actually gets copied to the Windows clipboard,
00330     * as only he first one causes a call to gdk_property_change.
00331     *
00332     * Hmm, there is something fishy with this. Cut and paste inside the
00333     * same app didn't work, the gtkeditable immediately forgot the
00334     * clipboard contents in gtk_editable_selection_clear as a result of
00335     * this message. OTOH, when I changed gdk_selection_owner_get to
00336     * always return NULL, it works. Sigh.
00337     */
00338 
00339    SendMessage((HWND) requestor, gdk_selection_clear_msg, selection, 0);
00340 }
00341 
00342 gint
00343 gdk_text_property_to_text_list(GdkAtom encoding,
00344                                gint format,
00345                                const guchar * text,
00346                                gint length, gchar *** list)
00347 {
00348    GDK_NOTE(DND,
00349             g_print("gdk_text_property_to_text_list not implemented\n"));
00350 
00351    return 0;
00352 }
00353 
00354 void gdk_free_text_list(gchar ** list)
00355 {
00356    g_return_if_fail(list != NULL);
00357 
00358    /* ??? */
00359 }
00360 
00361 gint
00362 gdk_string_to_compound_text(const gchar * str,
00363                             GdkAtom * encoding,
00364                             gint * format, guchar ** ctext, gint * length)
00365 {
00366    g_warning("gdk_string_to_compound_text: Not implemented");
00367 
00368    return 0;
00369 }
00370 
00371 void gdk_free_compound_text(guchar * ctext)
00372 {
00373    g_warning("gdk_free_compound_text: Not implemented");
00374 }

Generated on Tue Jul 5 14:14:40 2011 for ROOT_528-00b_version by  doxygen 1.5.1