src/windows/classes/sun/awt/windows/WDataTransferer.java

Print this page




 169     }
 170 
 171     public SortedMap getFormatsForFlavors(DataFlavor[] flavors, FlavorTable map) {
 172         SortedMap retval = super.getFormatsForFlavors(flavors, map);
 173 
 174         // The Win32 native code does not support exporting LOCALE data, nor
 175         // should it.
 176         retval.remove(L_CF_LOCALE);
 177 
 178         return retval;
 179     }
 180 
 181     public String getDefaultUnicodeEncoding() {
 182         return "utf-16le";
 183     }
 184 
 185     public byte[] translateTransferable(Transferable contents,
 186                                         DataFlavor flavor,
 187                                         long format) throws IOException
 188     {
 189         byte[] bytes = super.translateTransferable(contents, flavor, format);
 190 
 191         if (format == CF_HTML) {
 192             bytes = HTMLCodec.convertToHTMLFormat(bytes);

























 193         }
 194         return bytes;
 195     }
 196 
 197     protected Object translateBytesOrStream(InputStream str, byte[] bytes,

 198                                             DataFlavor flavor, long format,
 199                                             Transferable localeTransferable)
 200         throws IOException
 201     {
 202         if (format == CF_HTML && flavor.isFlavorTextType()) {
 203             if (str == null) {
 204                 str = new ByteArrayInputStream(bytes);
 205                 bytes = null;
 206             }
 207 
 208             str = new HTMLCodec(str,  EHTMLReadMode.HTML_READ_ALL);
 209         }






 210 
 211         if (format == CF_FILEGROUPDESCRIPTORA || format == CF_FILEGROUPDESCRIPTORW) {
 212             if (null != str ) {
 213                 str.close();
 214             }
 215             if (bytes == null || !DataFlavor.javaFileListFlavor.equals(flavor)) {
 216                 throw new IOException("data translation failed");
 217             }
 218             String st = new String(bytes, 0, bytes.length, "UTF-16LE");
 219             String[] filenames = st.split("\0");
 220             if( 0 == filenames.length ){
 221                 return null;
 222             }
 223 
 224             // Convert the strings to File objects
 225             File[] files = new File[filenames.length];
 226             for (int i = 0; i < filenames.length; ++i) {
 227                 files[i] = new File(filenames[i]);
 228                 //They are temp-files from memory Stream, so they have to be removed on exit
 229                 files[i].deleteOnExit();
 230             }
 231             // Turn the list of Files into a List and return
 232             return Arrays.asList(files);
 233         }
 234 
 235         if (format == CFSTR_INETURL &&
 236             URL.class.equals(flavor.getRepresentationClass()))
 237         {
 238             if (bytes == null) {
 239                 bytes = inputStreamToByteArray(str);
 240                 str = null;
 241             }
 242             String charset = getDefaultTextCharset();
 243             if (localeTransferable != null && localeTransferable.
 244                 isDataFlavorSupported(javaTextEncodingFlavor))
 245             {
 246                 try {
 247                     charset = new String((byte[])localeTransferable.
 248                                    getTransferData(javaTextEncodingFlavor),
 249                                    "UTF-8");
 250                 } catch (UnsupportedFlavorException cannotHappen) {
 251                 }
 252             }
 253             return new URL(new String(bytes, charset));
 254         }
 255 
 256         return super.translateBytesOrStream(str, bytes, flavor, format,
 257                                             localeTransferable);

 258     }
 259 
 260     public boolean isLocaleDependentTextFormat(long format) {
 261         return format == CF_TEXT || format == CFSTR_INETURL;
 262     }
 263 
 264     public boolean isFileFormat(long format) {
 265         return format == CF_HDROP || format == CF_FILEGROUPDESCRIPTORA || format == CF_FILEGROUPDESCRIPTORW;
 266     }
 267 
 268     protected Long getFormatForNativeAsLong(String str) {
 269         Long format = (Long)predefinedClipboardNameMap.get(str);
 270         if (format == null) {
 271             format = Long.valueOf(registerClipboardFormat(str));
 272         }
 273         return format;
 274     }
 275 
 276     protected String getNativeForFormat(long format) {
 277         return (format < predefinedClipboardNames.length)


 397         // According to MSDN the byte array have to be double NULL-terminated.
 398         // The array contains Unicode characters, so each NULL-terminator is
 399         // a pair of bytes
 400 
 401         bos.write(UNICODE_NULL_TERMINATOR);
 402         return bos;
 403     }
 404 
 405    /**
 406     * Returns a byte array which contains data special for the given format
 407     * and for the given image data.
 408     */
 409     private native byte[] imageDataToPlatformImageBytes(byte[] imageData,
 410                                                         int width, int height,
 411                                                         long format);
 412 
 413     /**
 414      * Translates either a byte array or an input stream which contain
 415      * platform-specific image data in the given format into an Image.
 416      */
 417     protected Image platformImageBytesOrStreamToImage(InputStream str,
 418                                                       byte[] bytes,
 419                                                       long format)
 420       throws IOException {
 421         String mimeType = null;
 422         if (format == CF_PNG) {
 423             mimeType = "image/png";
 424         } else if (format == CF_JFIF) {
 425             mimeType = "image/jpeg";
 426         }
 427         if (mimeType != null) {
 428             return standardImageBytesOrStreamToImage(str, bytes, mimeType);
 429         }
 430 
 431         if (bytes == null) {
 432             bytes = inputStreamToByteArray(str);
 433         }
 434 
 435         int[] imageData = platformImageBytesToImageData(bytes, format);
 436         if (imageData == null) {
 437             throw new IOException("data translation failed");
 438         }
 439 
 440         int len = imageData.length - 2;
 441         int width = imageData[len];
 442         int height = imageData[len + 1];
 443 
 444         DataBufferInt buffer = new DataBufferInt(imageData, len);
 445         WritableRaster raster = Raster.createPackedRaster(buffer, width,
 446                                                           height, width,
 447                                                           bandmasks, null);
 448 
 449         return new BufferedImage(directColorModel, raster, false, null);
 450     }
 451 
 452     /**


 470             throw new IllegalMonitorStateException();
 471         }
 472         unlock();
 473         startSecondaryEventLoop();
 474         lock();
 475     }
 476 
 477     public void exit() {
 478         if (!isOwned()) {
 479             throw new IllegalMonitorStateException();
 480         }
 481         WToolkit.quitSecondaryEventLoop();
 482     }
 483 
 484     private native void startSecondaryEventLoop();
 485 }
 486 
 487 enum EHTMLReadMode {
 488     HTML_READ_ALL,
 489     HTML_READ_FRAGMENT,
 490     HTML_READ_SELECTION















 491 }
 492 
 493 /**
 494  * on decode: This stream takes an InputStream which provides data in CF_HTML format,
 495  * strips off the description and context to extract the original HTML data.
 496  *
 497  * on encode: static convertToHTMLFormat is responsible for HTML clipboard header creation
 498  */
 499 class HTMLCodec extends InputStream {
 500     //static section
 501     public static final String ENCODING = "UTF-8";
 502 
 503     public static final String VERSION = "Version:";
 504     public static final String START_HTML = "StartHTML:";
 505     public static final String END_HTML = "EndHTML:";
 506     public static final String START_FRAGMENT = "StartFragment:";
 507     public static final String END_FRAGMENT = "EndFragment:";
 508     public static final String START_SELECTION = "StartSelection:"; //optional
 509     public static final String END_SELECTION = "EndSelection:"; //optional
 510 


 559      *<HTML>...<!--StartFragment-->...<BODY>...</BODY><!--EndFragment--><HTML>
 560      * are vailid too.
 561      */
 562     public static byte[] convertToHTMLFormat(byte[] bytes) {
 563         // Calculate section offsets
 564         String htmlPrefix = "";
 565         String htmlSuffix = "";
 566         {
 567             //we have extend the fragment to full HTML document correctly
 568             //to avoid HTML and BODY tags doubling
 569             String stContext = new String(bytes);
 570             String stUpContext = stContext.toUpperCase();
 571             if( -1 == stUpContext.indexOf("<HTML") ) {
 572                 htmlPrefix = "<HTML>";
 573                 htmlSuffix = "</HTML>";
 574                 if( -1 == stUpContext.indexOf("<BODY") ) {
 575                     htmlPrefix = htmlPrefix +"<BODY>";
 576                     htmlSuffix = "</BODY>" + htmlSuffix;
 577                 };
 578             };
 579             htmlPrefix = htmlPrefix + START_FRAGMENT_CMT;
 580             htmlSuffix = END_FRAGMENT_CMT + htmlSuffix;
 581         }
 582 
 583         String stBaseUrl = DEF_SOURCE_URL;
 584         int nStartHTML =
 585             VERSION.length() + VERSION_NUM.length() + EOLN.length()
 586             + START_HTML.length() + PADDED_WIDTH + EOLN.length()
 587             + END_HTML.length() + PADDED_WIDTH + EOLN.length()
 588             + START_FRAGMENT.length() + PADDED_WIDTH + EOLN.length()
 589             + END_FRAGMENT.length() + PADDED_WIDTH + EOLN.length()
 590             + SOURCE_URL.length() + stBaseUrl.length() + EOLN.length()
 591             ;
 592         int nStartFragment = nStartHTML + htmlPrefix.length();
 593         int nEndFragment = nStartFragment + bytes.length - 1;
 594         int nEndHTML = nEndFragment + htmlSuffix.length();
 595 
 596         StringBuilder header = new StringBuilder(
 597             nStartFragment
 598             + START_FRAGMENT_CMT.length()
 599         );
 600         //header




 169     }
 170 
 171     public SortedMap getFormatsForFlavors(DataFlavor[] flavors, FlavorTable map) {
 172         SortedMap retval = super.getFormatsForFlavors(flavors, map);
 173 
 174         // The Win32 native code does not support exporting LOCALE data, nor
 175         // should it.
 176         retval.remove(L_CF_LOCALE);
 177 
 178         return retval;
 179     }
 180 
 181     public String getDefaultUnicodeEncoding() {
 182         return "utf-16le";
 183     }
 184 
 185     public byte[] translateTransferable(Transferable contents,
 186                                         DataFlavor flavor,
 187                                         long format) throws IOException
 188     {
 189         byte[] bytes = null;

 190         if (format == CF_HTML) {
 191             if (contents.isDataFlavorSupported(DataFlavor.selectionHtmlFlavor)) {
 192                 // if a user provides data represented by
 193                 // DataFlavor.selectionHtmlFlavor format, we use this
 194                 // type to store the data in the native clipboard
 195                 bytes = super.translateTransferable(contents,
 196                         DataFlavor.selectionHtmlFlavor,
 197                         format);
 198             } else if (contents.isDataFlavorSupported(DataFlavor.allHtmlFlavor)) {
 199                 // if we cannot get data represented by the
 200                 // DataFlavor.selectionHtmlFlavor format
 201                 // but the DataFlavor.allHtmlFlavor format is avialable
 202                 // we belive that the user knows how to represent
 203                 // the data and how to mark up selection in a
 204                 // system specific manner. Therefor, we use this data
 205                 bytes = super.translateTransferable(contents,
 206                         DataFlavor.allHtmlFlavor,
 207                         format);
 208             } else {
 209                 // handle other html flavor types, including custom and
 210                 // fragment ones
 211                 bytes = HTMLCodec.convertToHTMLFormat(super.translateTransferable(contents, flavor, format));
 212             }
 213         } else {
 214             // we handle non-html types basing on  their
 215             // flavors
 216             bytes = super.translateTransferable(contents, flavor, format);
 217         }
 218         return bytes;
 219     }
 220 
 221     // The stream is closed as a closable object
 222     public Object translateStream(InputStream str,
 223                                   DataFlavor flavor, long format,
 224                                   Transferable localeTransferable)
 225         throws IOException {

 226         if (format == CF_HTML && flavor.isFlavorTextType()) {
 227             str = new HTMLCodec(str,
 228                     EHTMLReadMode.getEHTMLReadMode(flavor));


 229 

 230         }
 231         return super.translateStream(str, flavor, format,
 232                 localeTransferable);
 233     }
 234 
 235     public Object translateBytes(byte[] bytes, DataFlavor flavor, long format,
 236         Transferable localeTransferable) throws IOException {
 237 
 238         if (format == CF_FILEGROUPDESCRIPTORA || format == CF_FILEGROUPDESCRIPTORW) {



 239             if (bytes == null || !DataFlavor.javaFileListFlavor.equals(flavor)) {
 240                 throw new IOException("data translation failed");
 241             }
 242             String st = new String(bytes, 0, bytes.length, "UTF-16LE");
 243             String[] filenames = st.split("\0");
 244             if( 0 == filenames.length ){
 245                 return null;
 246             }
 247 
 248             // Convert the strings to File objects
 249             File[] files = new File[filenames.length];
 250             for (int i = 0; i < filenames.length; ++i) {
 251                 files[i] = new File(filenames[i]);
 252                 //They are temp-files from memory Stream, so they have to be removed on exit
 253                 files[i].deleteOnExit();
 254             }
 255             // Turn the list of Files into a List and return
 256             return Arrays.asList(files);
 257         }
 258 
 259         if (format == CFSTR_INETURL &&
 260                 URL.class.equals(flavor.getRepresentationClass()))
 261         {




 262             String charset = getDefaultTextCharset();
 263             if (localeTransferable != null && localeTransferable.isDataFlavorSupported(javaTextEncodingFlavor))

 264             {
 265                 try {
 266                     charset = new String((byte[])localeTransferable.
 267                         getTransferData(javaTextEncodingFlavor), "UTF-8");

 268                 } catch (UnsupportedFlavorException cannotHappen) {
 269                 }
 270             }
 271             return new URL(new String(bytes, charset));
 272         }
 273 
 274         return super.translateBytes(bytes , flavor, format,
 275                                         localeTransferable);
 276 
 277     }
 278 
 279     public boolean isLocaleDependentTextFormat(long format) {
 280         return format == CF_TEXT || format == CFSTR_INETURL;
 281     }
 282 
 283     public boolean isFileFormat(long format) {
 284         return format == CF_HDROP || format == CF_FILEGROUPDESCRIPTORA || format == CF_FILEGROUPDESCRIPTORW;
 285     }
 286 
 287     protected Long getFormatForNativeAsLong(String str) {
 288         Long format = (Long)predefinedClipboardNameMap.get(str);
 289         if (format == null) {
 290             format = Long.valueOf(registerClipboardFormat(str));
 291         }
 292         return format;
 293     }
 294 
 295     protected String getNativeForFormat(long format) {
 296         return (format < predefinedClipboardNames.length)


 416         // According to MSDN the byte array have to be double NULL-terminated.
 417         // The array contains Unicode characters, so each NULL-terminator is
 418         // a pair of bytes
 419 
 420         bos.write(UNICODE_NULL_TERMINATOR);
 421         return bos;
 422     }
 423 
 424     /**
 425      * Returns a byte array which contains data special for the given format
 426      * and for the given image data.
 427      */
 428     private native byte[] imageDataToPlatformImageBytes(byte[] imageData,
 429                                                         int width, int height,
 430                                                         long format);
 431 
 432     /**
 433      * Translates either a byte array or an input stream which contain
 434      * platform-specific image data in the given format into an Image.
 435      */
 436     protected Image platformImageBytesToImage(byte[] bytes, long format)


 437             throws IOException {
 438         String mimeType = null;
 439         if (format == CF_PNG) {
 440             mimeType = "image/png";
 441         } else if (format == CF_JFIF) {
 442             mimeType = "image/jpeg";
 443         }
 444         if (mimeType != null) {
 445             return standardImageBytesToImage(bytes, mimeType);




 446         }
 447 
 448         int[] imageData = platformImageBytesToImageData(bytes, format);
 449         if (imageData == null) {
 450             throw new IOException("data translation failed");
 451         }
 452 
 453         int len = imageData.length - 2;
 454         int width = imageData[len];
 455         int height = imageData[len + 1];
 456 
 457         DataBufferInt buffer = new DataBufferInt(imageData, len);
 458         WritableRaster raster = Raster.createPackedRaster(buffer, width,
 459                 height, width,
 460                 bandmasks, null);
 461 
 462         return new BufferedImage(directColorModel, raster, false, null);
 463     }
 464 
 465     /**


 483             throw new IllegalMonitorStateException();
 484         }
 485         unlock();
 486         startSecondaryEventLoop();
 487         lock();
 488     }
 489 
 490     public void exit() {
 491         if (!isOwned()) {
 492             throw new IllegalMonitorStateException();
 493         }
 494         WToolkit.quitSecondaryEventLoop();
 495     }
 496 
 497     private native void startSecondaryEventLoop();
 498 }
 499 
 500 enum EHTMLReadMode {
 501     HTML_READ_ALL,
 502     HTML_READ_FRAGMENT,
 503     HTML_READ_SELECTION;
 504 
 505     public static EHTMLReadMode getEHTMLReadMode (DataFlavor df) {
 506 
 507         EHTMLReadMode mode = HTML_READ_SELECTION;
 508 
 509         String parameter = df.getParameter("document");
 510 
 511         if ("all".equals(parameter)) {
 512             mode = HTML_READ_ALL;
 513         } else if ("fragment".equals(parameter)) {
 514             mode = HTML_READ_FRAGMENT;
 515         }
 516 
 517         return mode;
 518     }
 519 }
 520 
 521 /**
 522  * on decode: This stream takes an InputStream which provides data in CF_HTML format,
 523  * strips off the description and context to extract the original HTML data.
 524  *
 525  * on encode: static convertToHTMLFormat is responsible for HTML clipboard header creation
 526  */
 527 class HTMLCodec extends InputStream {
 528     //static section
 529     public static final String ENCODING = "UTF-8";
 530 
 531     public static final String VERSION = "Version:";
 532     public static final String START_HTML = "StartHTML:";
 533     public static final String END_HTML = "EndHTML:";
 534     public static final String START_FRAGMENT = "StartFragment:";
 535     public static final String END_FRAGMENT = "EndFragment:";
 536     public static final String START_SELECTION = "StartSelection:"; //optional
 537     public static final String END_SELECTION = "EndSelection:"; //optional
 538 


 587      *<HTML>...<!--StartFragment-->...<BODY>...</BODY><!--EndFragment--><HTML>
 588      * are vailid too.
 589      */
 590     public static byte[] convertToHTMLFormat(byte[] bytes) {
 591         // Calculate section offsets
 592         String htmlPrefix = "";
 593         String htmlSuffix = "";
 594         {
 595             //we have extend the fragment to full HTML document correctly
 596             //to avoid HTML and BODY tags doubling
 597             String stContext = new String(bytes);
 598             String stUpContext = stContext.toUpperCase();
 599             if( -1 == stUpContext.indexOf("<HTML") ) {
 600                 htmlPrefix = "<HTML>";
 601                 htmlSuffix = "</HTML>";
 602                 if( -1 == stUpContext.indexOf("<BODY") ) {
 603                     htmlPrefix = htmlPrefix +"<BODY>";
 604                     htmlSuffix = "</BODY>" + htmlSuffix;
 605                 };
 606             };


 607         }
 608 
 609         String stBaseUrl = DEF_SOURCE_URL;
 610         int nStartHTML =
 611                 VERSION.length() + VERSION_NUM.length() + EOLN.length()
 612                         + START_HTML.length() + PADDED_WIDTH + EOLN.length()
 613                         + END_HTML.length() + PADDED_WIDTH + EOLN.length()
 614                         + START_FRAGMENT.length() + PADDED_WIDTH + EOLN.length()
 615                         + END_FRAGMENT.length() + PADDED_WIDTH + EOLN.length()
 616                         + SOURCE_URL.length() + stBaseUrl.length() + EOLN.length()
 617                 ;
 618         int nStartFragment = nStartHTML + htmlPrefix.length();
 619         int nEndFragment = nStartFragment + bytes.length - 1;
 620         int nEndHTML = nEndFragment + htmlSuffix.length();
 621 
 622         StringBuilder header = new StringBuilder(
 623                 nStartFragment
 624                         + START_FRAGMENT_CMT.length()
 625         );
 626         //header