/*
 * Copyright (c) 2000, 2009, 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.windows;

import java.awt.Image;
import java.awt.Graphics2D;
import java.awt.Transparency;

import java.awt.color.ColorSpace;

import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.FlavorTable;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;

import java.awt.geom.AffineTransform;

import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.ComponentColorModel;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.DataBufferInt;
import java.awt.image.DirectColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.io.File;

import java.net.URL;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;

import sun.awt.Mutex;
import sun.awt.datatransfer.DataTransferer;
import sun.awt.datatransfer.ToolkitThreadBlockedHandler;

import sun.awt.image.ImageRepresentation;
import sun.awt.image.ToolkitImage;

import java.util.ArrayList;

import java.io.ByteArrayOutputStream;

/**
 * Platform-specific support for the data transfer subsystem.
 *
 * @author David Mendenhall
 * @author Danila Sinopalnikov
 *
 * @since 1.3.1
 */
public class WDataTransferer extends DataTransferer {
    private static final String[] predefinedClipboardNames = {
        "",
        "TEXT",
        "BITMAP",
        "METAFILEPICT",
        "SYLK",
        "DIF",
        "TIFF",
        "OEM TEXT",
        "DIB",
        "PALETTE",
        "PENDATA",
        "RIFF",
        "WAVE",
        "UNICODE TEXT",
        "ENHMETAFILE",
        "HDROP",
        "LOCALE",
        "DIBV5"
    };

    private static final Map predefinedClipboardNameMap;
    static {
        Map tempMap = new HashMap(predefinedClipboardNames.length, 1.0f);
        for (int i = 1; i < predefinedClipboardNames.length; i++) {
            tempMap.put(predefinedClipboardNames[i], Long.valueOf(i));
        }
        predefinedClipboardNameMap = Collections.synchronizedMap(tempMap);
    }

    /**
     * from winuser.h
     */
    public static final int CF_TEXT = 1;
    public static final int CF_METAFILEPICT = 3;
    public static final int CF_DIB = 8;
    public static final int CF_ENHMETAFILE = 14;
    public static final int CF_HDROP = 15;
    public static final int CF_LOCALE = 16;

    public static final long CF_HTML = registerClipboardFormat("HTML Format");
    public static final long CFSTR_INETURL = registerClipboardFormat("UniformResourceLocator");
    public static final long CF_PNG = registerClipboardFormat("PNG");
    public static final long CF_JFIF = registerClipboardFormat("JFIF");

    public static final long CF_FILEGROUPDESCRIPTORW = registerClipboardFormat("FileGroupDescriptorW");
    public static final long CF_FILEGROUPDESCRIPTORA = registerClipboardFormat("FileGroupDescriptor");
    //CF_FILECONTENTS supported as mandatory associated clipboard

    private static final Long L_CF_LOCALE = (Long)
      predefinedClipboardNameMap.get(predefinedClipboardNames[CF_LOCALE]);

    private static final DirectColorModel directColorModel =
        new DirectColorModel(24,
                             0x00FF0000,  /* red mask   */
                             0x0000FF00,  /* green mask */
                             0x000000FF); /* blue mask  */

    private static final int[] bandmasks = new int[] {
        directColorModel.getRedMask(),
        directColorModel.getGreenMask(),
        directColorModel.getBlueMask() };

    /**
     * Singleton constructor
     */
    private WDataTransferer() {
    }

    private static WDataTransferer transferer;

    public static WDataTransferer getInstanceImpl() {
        if (transferer == null) {
            synchronized (WDataTransferer.class) {
                if (transferer == null) {
                    transferer = new WDataTransferer();
                }
            }
        }
        return transferer;
    }

    public SortedMap getFormatsForFlavors(DataFlavor[] flavors, FlavorTable map) {
        SortedMap retval = super.getFormatsForFlavors(flavors, map);

        // The Win32 native code does not support exporting LOCALE data, nor
        // should it.
        retval.remove(L_CF_LOCALE);

        return retval;
    }

    public String getDefaultUnicodeEncoding() {
        return "utf-16le";
    }

    public byte[] translateTransferable(Transferable contents,
                                        DataFlavor flavor,
                                        long format) throws IOException
    {
        byte[] bytes = super.translateTransferable(contents, flavor, format);

        if (format == CF_HTML) {
            bytes = HTMLCodec.convertToHTMLFormat(bytes);
        }
        return bytes;
    }

    protected Object translateBytesOrStream(InputStream str, byte[] bytes,
                                            DataFlavor flavor, long format,
                                            Transferable localeTransferable)
        throws IOException
    {
        if (format == CF_HTML && flavor.isFlavorTextType()) {
            if (str == null) {
                str = new ByteArrayInputStream(bytes);
                bytes = null;
            }

            str = new HTMLCodec(str,  EHTMLReadMode.HTML_READ_SELECTION);
        }

        if (format == CF_FILEGROUPDESCRIPTORA || format == CF_FILEGROUPDESCRIPTORW) {
            if (null != str ) {
                str.close();
            }
            if (bytes == null || !DataFlavor.javaFileListFlavor.equals(flavor)) {
                throw new IOException("data translation failed");
            }
            String st = new String(bytes, 0, bytes.length, "UTF-16LE");
            String[] filenames = st.split("\0");
            if( 0 == filenames.length ){
                return null;
            }

            // Convert the strings to File objects
            File[] files = new File[filenames.length];
            for (int i = 0; i < filenames.length; ++i) {
                files[i] = new File(filenames[i]);
                //They are temp-files from memory Stream, so they have to be removed on exit
                files[i].deleteOnExit();
            }
            // Turn the list of Files into a List and return
            return Arrays.asList(files);
        }

        if (format == CFSTR_INETURL &&
            URL.class.equals(flavor.getRepresentationClass()))
        {
            if (bytes == null) {
                bytes = inputStreamToByteArray(str);
                str = null;
            }
            String charset = getDefaultTextCharset();
            if (localeTransferable != null && localeTransferable.
                isDataFlavorSupported(javaTextEncodingFlavor))
            {
                try {
                    charset = new String((byte[])localeTransferable.
                                   getTransferData(javaTextEncodingFlavor),
                                   "UTF-8");
                } catch (UnsupportedFlavorException cannotHappen) {
                }
            }
            return new URL(new String(bytes, charset));
        }

        return super.translateBytesOrStream(str, bytes, flavor, format,
                                            localeTransferable);
    }

    public boolean isLocaleDependentTextFormat(long format) {
        return format == CF_TEXT || format == CFSTR_INETURL;
    }

    public boolean isFileFormat(long format) {
        return format == CF_HDROP || format == CF_FILEGROUPDESCRIPTORA || format == CF_FILEGROUPDESCRIPTORW;
    }

    protected Long getFormatForNativeAsLong(String str) {
        Long format = (Long)predefinedClipboardNameMap.get(str);
        if (format == null) {
            format = Long.valueOf(registerClipboardFormat(str));
        }
        return format;
    }

    protected String getNativeForFormat(long format) {
        return (format < predefinedClipboardNames.length)
            ? predefinedClipboardNames[(int)format]
            : getClipboardFormatName(format);
    }

    private final ToolkitThreadBlockedHandler handler =
        new WToolkitThreadBlockedHandler();

    public ToolkitThreadBlockedHandler getToolkitThreadBlockedHandler() {
        return handler;
    }

   /**
     * Calls the Win32 RegisterClipboardFormat function to register
     * a non-standard format.
     */
    private static native long registerClipboardFormat(String str);

    /**
     * Calls the Win32 GetClipboardFormatName function which is
     * the reverse operation of RegisterClipboardFormat.
     */
    private static native String getClipboardFormatName(long format);

    public boolean isImageFormat(long format) {
        return format == CF_DIB || format == CF_ENHMETAFILE ||
               format == CF_METAFILEPICT || format == CF_PNG ||
               format == CF_JFIF;
    }

    protected byte[] imageToPlatformBytes(Image image, long format)
      throws IOException {
        String mimeType = null;
        if (format == CF_PNG) {
            mimeType = "image/png";
        } else if (format == CF_JFIF) {
            mimeType = "image/jpeg";
        }
        if (mimeType != null) {
            return imageToStandardBytes(image, mimeType);
        }

        int width = 0;
        int height = 0;

        if (image instanceof ToolkitImage) {
            ImageRepresentation ir = ((ToolkitImage)image).getImageRep();
            ir.reconstruct(ImageObserver.ALLBITS);
            width = ir.getWidth();
            height = ir.getHeight();
        } else {
            width = image.getWidth(null);
            height = image.getHeight(null);
        }

        // Fix for 4919639.
        // Some Windows native applications (e.g. clipbrd.exe) do not handle
        // 32-bpp DIBs correctly.
        // As a workaround we switched to 24-bpp DIBs.
        // MSDN prescribes that the bitmap array for a 24-bpp should consist of
        // 3-byte triplets representing blue, green and red components of a
        // pixel respectively. Additionally each scan line must be padded with
        // zeroes to end on a LONG data-type boundary. LONG is always 32-bit.
        // We render the given Image to a BufferedImage of type TYPE_3BYTE_BGR
        // with non-default scanline stride and pass the resulting data buffer
        // to the native code to fill the BITMAPINFO structure.
        int mod = (width * 3) % 4;
        int pad = mod > 0 ? 4 - mod : 0;

        ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
        int[] nBits = {8, 8, 8};
        int[] bOffs = {2, 1, 0};
        ColorModel colorModel =
            new ComponentColorModel(cs, nBits, false, false,
                                    Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
        WritableRaster raster =
            Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height,
                                           width * 3 + pad, 3, bOffs, null);

        BufferedImage bimage = new BufferedImage(colorModel, raster, false, null);

        // Some Windows native applications (e.g. clipbrd.exe) do not understand
        // top-down DIBs.
        // So we flip the image vertically and create a bottom-up DIB.
        AffineTransform imageFlipTransform =
            new AffineTransform(1, 0, 0, -1, 0, height);

        Graphics2D g2d = bimage.createGraphics();

        try {
            g2d.drawImage(image, imageFlipTransform, null);
        } finally {
            g2d.dispose();
        }

        DataBufferByte buffer = (DataBufferByte)raster.getDataBuffer();

        byte[] imageData = buffer.getData();
        return imageDataToPlatformImageBytes(imageData, width, height, format);
    }

    private static final byte [] UNICODE_NULL_TERMINATOR =  new byte [] {0,0};

    protected ByteArrayOutputStream convertFileListToBytes(ArrayList<String> fileList)
        throws IOException
    {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        if(fileList.isEmpty()) {
            //store empty unicode string (null terminator)
            bos.write(UNICODE_NULL_TERMINATOR);
        } else {
            for (int i = 0; i < fileList.size(); i++) {
                byte[] bytes = fileList.get(i).getBytes(getDefaultUnicodeEncoding());
                //store unicode string with null terminator
                bos.write(bytes, 0, bytes.length);
                bos.write(UNICODE_NULL_TERMINATOR);
            }
        }

        // According to MSDN the byte array have to be double NULL-terminated.
        // The array contains Unicode characters, so each NULL-terminator is
        // a pair of bytes

        bos.write(UNICODE_NULL_TERMINATOR);
        return bos;
    }

   /**
    * Returns a byte array which contains data special for the given format
    * and for the given image data.
    */
    private native byte[] imageDataToPlatformImageBytes(byte[] imageData,
                                                        int width, int height,
                                                        long format);

    /**
     * Translates either a byte array or an input stream which contain
     * platform-specific image data in the given format into an Image.
     */
    protected Image platformImageBytesOrStreamToImage(InputStream str,
                                                      byte[] bytes,
                                                      long format)
      throws IOException {
        String mimeType = null;
        if (format == CF_PNG) {
            mimeType = "image/png";
        } else if (format == CF_JFIF) {
            mimeType = "image/jpeg";
        }
        if (mimeType != null) {
            return standardImageBytesOrStreamToImage(str, bytes, mimeType);
        }

        if (bytes == null) {
            bytes = inputStreamToByteArray(str);
        }

        int[] imageData = platformImageBytesToImageData(bytes, format);
        if (imageData == null) {
            throw new IOException("data translation failed");
        }

        int len = imageData.length - 2;
        int width = imageData[len];
        int height = imageData[len + 1];

        DataBufferInt buffer = new DataBufferInt(imageData, len);
        WritableRaster raster = Raster.createPackedRaster(buffer, width,
                                                          height, width,
                                                          bandmasks, null);

        return new BufferedImage(directColorModel, raster, false, null);
    }

    /**
     * Translates a byte array which contains platform-specific image data in
     * the given format into an integer array which contains pixel values in
     * ARGB format. The two last elements in the array specify width and
     * height of the image respectively.
     */
    private native int[] platformImageBytesToImageData(byte[] bytes,
                                                       long format)
      throws IOException;

    protected native String[] dragQueryFile(byte[] bytes);
}

final class WToolkitThreadBlockedHandler extends Mutex
                       implements ToolkitThreadBlockedHandler {

    public void enter() {
        if (!isOwned()) {
            throw new IllegalMonitorStateException();
        }
        unlock();
        startSecondaryEventLoop();
        lock();
    }

    public void exit() {
        if (!isOwned()) {
            throw new IllegalMonitorStateException();
        }
        WToolkit.quitSecondaryEventLoop();
    }

    private native void startSecondaryEventLoop();
}

enum EHTMLReadMode {
    HTML_READ_ALL,
    HTML_READ_FRAGMENT,
    HTML_READ_SELECTION
}

/**
 * on decode: This stream takes an InputStream which provides data in CF_HTML format,
 * strips off the description and context to extract the original HTML data.
 *
 * on encode: static convertToHTMLFormat is responsible for HTML clipboard header creation
 */
class HTMLCodec extends InputStream {
    //static section
    public static final String ENCODING = "UTF-8";

    public static final String VERSION = "Version:";
    public static final String START_HTML = "StartHTML:";
    public static final String END_HTML = "EndHTML:";
    public static final String START_FRAGMENT = "StartFragment:";
    public static final String END_FRAGMENT = "EndFragment:";
    public static final String START_SELECTION = "StartSelection:"; //optional
    public static final String END_SELECTION = "EndSelection:"; //optional

    public static final String START_FRAGMENT_CMT = "<!--StartFragment-->";
    public static final String END_FRAGMENT_CMT = "<!--EndFragment-->";
    public static final String SOURCE_URL = "SourceURL:";
    public static final String DEF_SOURCE_URL = "about:blank";

    public static final String EOLN = "\r\n";

    private static final String VERSION_NUM = "1.0";
    private static final int PADDED_WIDTH = 10;

    private static String toPaddedString(int n, int width) {
        String string = "" + n;
        int len = string.length();
        if (n >= 0 && len < width) {
            char[] array = new char[width - len];
            Arrays.fill(array, '0');
            StringBuffer buffer = new StringBuffer(width);
            buffer.append(array);
            buffer.append(string);
            string = buffer.toString();
        }
        return string;
    }

    /**
     * convertToHTMLFormat adds the MS HTML clipboard header to byte array that
     * contains the parameters pairs.
     *
     * The consequence of parameters is fixed, but some or all of them could be
     * omitted. One parameter per one text line.
     * It looks like that:
     *
     * Version:1.0\r\n                -- current supported version
     * StartHTML:000000192\r\n        -- shift in array to the first byte after the header
     * EndHTML:000000757\r\n          -- shift in array of last byte for HTML syntax analysis
     * StartFragment:000000396\r\n    -- shift in array jast after <!--StartFragment-->
     * EndFragment:000000694\r\n      -- shift in array before start  <!--EndFragment-->
     * StartSelection:000000398\r\n   -- shift in array of the first char in copied selection
     * EndSelection:000000692\r\n     -- shift in array of the last char in copied selection
     * SourceURL:http://sun.com/\r\n  -- base URL for related referenses
     * <HTML>...<BODY>...<!--StartFragment-->.....................<!--EndFragment-->...</BODY><HTML>
     * ^                                     ^ ^                ^^                                 ^
     * \ StartHTML                           | \-StartSelection | \EndFragment              EndHTML/
     *                                       \-StartFragment    \EndSelection
     *
     *Combinations with tags sequence
     *<!--StartFragment--><HTML>...<BODY>...</BODY><HTML><!--EndFragment-->
     * or
     *<HTML>...<!--StartFragment-->...<BODY>...</BODY><!--EndFragment--><HTML>
     * are vailid too.
     */
    public static byte[] convertToHTMLFormat(byte[] bytes) {
        // Calculate section offsets
        String htmlPrefix = "";
        String htmlSuffix = "";
        {
            //we have extend the fragment to full HTML document correctly
            //to avoid HTML and BODY tags doubling
            String stContext = new String(bytes);
            String stUpContext = stContext.toUpperCase();
            if( -1 == stUpContext.indexOf("<HTML") ) {
                htmlPrefix = "<HTML>";
                htmlSuffix = "</HTML>";
                if( -1 == stUpContext.indexOf("<BODY") ) {
                    htmlPrefix = htmlPrefix +"<BODY>";
                    htmlSuffix = "</BODY>" + htmlSuffix;
                };
            };
            htmlPrefix = htmlPrefix + START_FRAGMENT_CMT;
            htmlSuffix = END_FRAGMENT_CMT + htmlSuffix;
        }

        String stBaseUrl = DEF_SOURCE_URL;
        int nStartHTML =
            VERSION.length() + VERSION_NUM.length() + EOLN.length()
            + START_HTML.length() + PADDED_WIDTH + EOLN.length()
            + END_HTML.length() + PADDED_WIDTH + EOLN.length()
            + START_FRAGMENT.length() + PADDED_WIDTH + EOLN.length()
            + END_FRAGMENT.length() + PADDED_WIDTH + EOLN.length()
            + SOURCE_URL.length() + stBaseUrl.length() + EOLN.length()
            ;
        int nStartFragment = nStartHTML + htmlPrefix.length();
        int nEndFragment = nStartFragment + bytes.length - 1;
        int nEndHTML = nEndFragment + htmlSuffix.length();

        StringBuilder header = new StringBuilder(
            nStartFragment
            + START_FRAGMENT_CMT.length()
        );
        //header
        header.append(VERSION);
        header.append(VERSION_NUM);
        header.append(EOLN);

        header.append(START_HTML);
        header.append(toPaddedString(nStartHTML, PADDED_WIDTH));
        header.append(EOLN);

        header.append(END_HTML);
        header.append(toPaddedString(nEndHTML, PADDED_WIDTH));
        header.append(EOLN);

        header.append(START_FRAGMENT);
        header.append(toPaddedString(nStartFragment, PADDED_WIDTH));
        header.append(EOLN);

        header.append(END_FRAGMENT);
        header.append(toPaddedString(nEndFragment, PADDED_WIDTH));
        header.append(EOLN);

        header.append(SOURCE_URL);
        header.append(stBaseUrl);
        header.append(EOLN);

        //HTML
        header.append(htmlPrefix);

        byte[] headerBytes = null, trailerBytes = null;

        try {
            headerBytes = header.toString().getBytes(ENCODING);
            trailerBytes = htmlSuffix.getBytes(ENCODING);
        } catch (UnsupportedEncodingException cannotHappen) {
        }

        byte[] retval = new byte[headerBytes.length + bytes.length +
                                 trailerBytes.length];

        System.arraycopy(headerBytes, 0, retval, 0, headerBytes.length);
        System.arraycopy(bytes, 0, retval, headerBytes.length,
                       bytes.length - 1);
        System.arraycopy(trailerBytes, 0, retval,
                         headerBytes.length + bytes.length - 1,
                         trailerBytes.length);
        retval[retval.length-1] = 0;

        return retval;
    }

    ////////////////////////////////////
    //decoder instance data and methods:

    private final BufferedInputStream bufferedStream;
    private boolean descriptionParsed = false;
    private boolean closed = false;

     // InputStreamReader uses an 8K buffer. The size is not customizable.
    public static final int BYTE_BUFFER_LEN = 8192;

    // CharToByteUTF8.getMaxBytesPerChar returns 3, so we should not buffer
    // more chars than 3 times the number of bytes we can buffer.
    public static final int CHAR_BUFFER_LEN = BYTE_BUFFER_LEN / 3;

    private static final String FAILURE_MSG =
        "Unable to parse HTML description: ";
    private static final String INVALID_MSG =
        " invalid";

    //HTML header mapping:
    private long   iHTMLStart,// StartHTML -- shift in array to the first byte after the header
                   iHTMLEnd,  // EndHTML -- shift in array of last byte for HTML syntax analysis
                   iFragStart,// StartFragment -- shift in array jast after <!--StartFragment-->
                   iFragEnd,  // EndFragment -- shift in array before start <!--EndFragment-->
                   iSelStart, // StartSelection -- shift in array of the first char in copied selection
                   iSelEnd;   // EndSelection -- shift in array of the last char in copied selection
    private String stBaseURL; // SourceURL -- base URL for related referenses
    private String stVersion; // Version -- current supported version

    //Stream reader markers:
    private long iStartOffset,
                 iEndOffset,
                 iReadCount;

    private EHTMLReadMode readMode;

    public HTMLCodec(
        InputStream _bytestream,
        EHTMLReadMode _readMode) throws IOException
    {
        bufferedStream = new BufferedInputStream(_bytestream, BYTE_BUFFER_LEN);
        readMode = _readMode;
    }

    public synchronized String getBaseURL() throws IOException
    {
        if( !descriptionParsed ) {
            parseDescription();
        }
        return stBaseURL;
    }
    public synchronized String getVersion() throws IOException
    {
        if( !descriptionParsed ) {
            parseDescription();
        }
        return stVersion;
    }

    /**
     * parseDescription parsing HTML clipboard header as it described in
     * comment to convertToHTMLFormat
     */
    private void parseDescription() throws IOException
    {
        stBaseURL = null;
        stVersion = null;

        // initialization of array offset pointers
        // to the same "uninitialized" state.
        iHTMLEnd =
            iHTMLStart =
                iFragEnd =
                    iFragStart =
                        iSelEnd =
                            iSelStart = -1;

        bufferedStream.mark(BYTE_BUFFER_LEN);
        String astEntries[] = new String[] {
            //common
            VERSION,
            START_HTML,
            END_HTML,
            START_FRAGMENT,
            END_FRAGMENT,
            //ver 1.0
            START_SELECTION,
            END_SELECTION,
            SOURCE_URL
        };
        BufferedReader bufferedReader = new BufferedReader(
            new InputStreamReader(
                bufferedStream,
                ENCODING
            ),
            CHAR_BUFFER_LEN
        );
        long iHeadSize = 0;
        long iCRSize = EOLN.length();
        int iEntCount = astEntries.length;
        boolean bContinue = true;

        for( int  iEntry = 0; iEntry < iEntCount; ++iEntry ){
            String stLine = bufferedReader.readLine();
            if( null==stLine ) {
                break;
            }
            //some header entries are optional, but the order is fixed.
            for( ; iEntry < iEntCount; ++iEntry ){
                if( !stLine.startsWith(astEntries[iEntry]) ) {
                    continue;
                }
                iHeadSize += stLine.length() + iCRSize;
                String stValue = stLine.substring(astEntries[iEntry].length()).trim();
                if( null!=stValue ) {
                    try{
                        switch( iEntry ){
                        case 0:
                            stVersion = stValue;
                            break;
                        case 1:
                            iHTMLStart = Integer.parseInt(stValue);
                            break;
                        case 2:
                            iHTMLEnd = Integer.parseInt(stValue);
                            break;
                        case 3:
                            iFragStart = Integer.parseInt(stValue);
                            break;
                        case 4:
                            iFragEnd = Integer.parseInt(stValue);
                            break;
                        case 5:
                            iSelStart = Integer.parseInt(stValue);
                            break;
                        case 6:
                            iSelEnd = Integer.parseInt(stValue);
                            break;
                        case 7:
                            stBaseURL = stValue;
                            break;
                        };
                    } catch ( NumberFormatException e ) {
                        throw new IOException(FAILURE_MSG + astEntries[iEntry]+ " value " + e + INVALID_MSG);
                    }
                }
                break;
            }
        }
        //some entries could absent in HTML header,
        //so we have find they by another way.
        if( -1 == iHTMLStart )
            iHTMLStart = iHeadSize;
        if( -1 == iFragStart )
            iFragStart = iHTMLStart;
        if( -1 == iFragEnd )
            iFragEnd = iHTMLEnd;
        if( -1 == iSelStart )
            iSelStart = iFragStart;
        if( -1 == iSelEnd )
            iSelEnd = iFragEnd;

        //one of possible modes
        switch( readMode ){
        case HTML_READ_ALL:
            iStartOffset = iHTMLStart;
            iEndOffset = iHTMLEnd;
            break;
        case HTML_READ_FRAGMENT:
            iStartOffset = iFragStart;
            iEndOffset = iFragEnd;
            break;
        case HTML_READ_SELECTION:
        default:
            iStartOffset = iSelStart;
            iEndOffset = iSelEnd;
            break;
        }

        bufferedStream.reset();
        if( -1 == iStartOffset ){
            throw new IOException(FAILURE_MSG + "invalid HTML format.");
        }
        iReadCount = bufferedStream.skip(iStartOffset);
        if( iStartOffset != iReadCount ){
            throw new IOException(FAILURE_MSG + "Byte stream ends in description.");
        }
        descriptionParsed = true;
    }

    public synchronized int read() throws IOException {
        if( closed ){
            throw new IOException("Stream closed");
        }

        if( !descriptionParsed ){
            parseDescription();
        }
        if( -1 != iEndOffset && iReadCount >= iEndOffset ) {
            return -1;
        }

        int retval = bufferedStream.read();
        if( retval == -1 ) {
            return -1;
        }
        ++iReadCount;
        return retval;
    }

    public synchronized void close() throws IOException {
        if( !closed ){
            closed = true;
            bufferedStream.close();
        }
    }
}
