Package com.lixia.rdp

Source Code of com.lixia.rdp.OrdersJPanel

/* Orders.java
* Component: ProperJavaRDP
*
* Revision: $Revision: 1.1.1.1 $
* Author: $Author: suvarov $
* Date: $Date: 2007/03/08 00:26:31 $
*
* Copyright (c) 2005 Propero Limited
*
* Purpose: Encapsulates an RDP order
*/
package com.lixia.rdp;

import com.alssoftrd.events.EventWakeUp;
import com.alssoftrd.utils.ManageBitmaps;
import com.alssoftrd.utils.RDPConnection;

import java.awt.image.IndexColorModel;
import java.io.IOException;

import com.lixia.rdp.orders.*;
import com.lixia.rdp.Package.RdpPackage;
import com.lixia.rdp.rdp5.ARDP5;

public class OrdersJPanel {

//    static Logger logger = Logger.getLogger(OrdersJPanel.class);
    private OrderState os = null;
    private Cache cache = null;
   
    public static ManageBitmaps mb;

    /* RDP_BMPCACHE2_ORDER */
    private static final int ID_MASK = 0x0007;
    private static final int MODE_MASK = 0x0038;
    private static final int SQUARE = 0x0080;
    private static final int PERSIST = 0x0100;
    private static final int FLAG_51_UNKNOWN = 0x0800;
    private static final int MODE_SHIFT = 3;
    private static final int LONG_FORMAT = 0x80;
    private static final int BUFSIZE_MASK = 0x3FFF; /* or 0x1FFF? */
   
    private static final int RDP_ORDER_STANDARD = 0x01;
    private static final int RDP_ORDER_SECONDARY = 0x02;
    private static final int RDP_ORDER_BOUNDS = 0x04;
    private static final int RDP_ORDER_CHANGE = 0x08;
    private static final int RDP_ORDER_DELTA = 0x10;
    private static final int RDP_ORDER_LASTBOUNDS = 0x20;
    private static final int RDP_ORDER_SMALL = 0x40;
    private static final int RDP_ORDER_TINY = 0x80;

    /* standard order types */
    private static final int RDP_ORDER_DESTBLT = 0;
    private static final int RDP_ORDER_PATBLT = 1;
    private static final int RDP_ORDER_SCREENBLT = 2;
    private static final int RDP_ORDER_LINE = 9;
    private static final int RDP_ORDER_RECT = 10;
    private static final int RDP_ORDER_DESKSAVE = 11;
    private static final int RDP_ORDER_MEMBLT = 13;
    private static final int RDP_ORDER_TRIBLT = 14;
    private static final int RDP_ORDER_POLYLINE = 22;
    private static final int RDP_ORDER_TEXT2 = 27;
    private int rect_colour;

    /* secondary order types */
    private static final int RDP_ORDER_RAW_BMPCACHE = 0;
    private static final int RDP_ORDER_COLCACHE = 1;
    private static final int RDP_ORDER_BMPCACHE = 2;
    private static final int RDP_ORDER_FONTCACHE = 3;
    private static final int RDP_ORDER_RAW_BMPCACHE2 = 4;
    private static final int RDP_ORDER_BMPCACHE2 = 5;
    private static final int MIX_TRANSPARENT = 0;
    private static final int MIX_OPAQUE = 1;
    private static final int TEXT2_VERTICAL = 0x04;
    private static final int TEXT2_IMPLICIT_X = 0x20;
   
    public OrdersJPanel() {
        os = new OrderState();
    }
   
    public void resetOrderState() {
        this.os.reset();
        os.setOrderType(RDP_ORDER_PATBLT);
    }
   
    private int inPresent(RdpPackage data, int flags, int size) {
        int present = 0;
        int bits;
        int i;
       
        if ((flags & RDP_ORDER_SMALL) != 0) {
            size--;
        }
       
        if ((flags & RDP_ORDER_TINY) != 0) {
           
            if (size < 2) {
                size = 0;
            } else {
                size -= 2;
            }
        }
       
        for (i = 0; i < size; i++) {
            bits = data.get8();
            present |= (bits << (i * 8));
        }
        return present;
    }

    /**
     * Process a set of orders sent by the server
     *
     * @param data Packet packet containing orders
     * @param next_packet Offset of end of this packet (start of next)
     * @param n_orders Number of orders sent in this packet
     * @throws OrderException
     * @throws RdesktopException
     */
    public void processOrders(RdpPackage data, int next_packet, int n_orders) throws OrderException, RdesktopException {
        int present;
        // int n_orders = 0;
        int order_flags, order_type = 0;
        int size, processed = 0;
        boolean delta;
       
        while (processed < n_orders) {
            order_flags = data.get8();
           
            if ((order_flags & RDP_ORDER_STANDARD) == 0) {
                throw new OrderException("Order parsing failed!");
            }
           
            if ((order_flags & RDP_ORDER_SECONDARY) != 0) {
                this.processSecondaryOrders(data);
            } else {
               
                if ((order_flags & RDP_ORDER_CHANGE) != 0) {
                    os.setOrderType(data.get8());
                }
               
                switch (os.getOrderType()) {
                    case RDP_ORDER_TRIBLT:
                    case RDP_ORDER_TEXT2:
                        size = 3;
                        break;
                    case RDP_ORDER_PATBLT:
                    case RDP_ORDER_MEMBLT:
                    case RDP_ORDER_LINE:
                        size = 2;
                        break;
                    default:
                        size = 1;
                }
               
                present = this.inPresent(data, order_flags, size);
               
                if ((order_flags & RDP_ORDER_BOUNDS) != 0) {
                    if ((order_flags & RDP_ORDER_LASTBOUNDS) == 0) {
                        this.parseBounds(data, os.getBounds());
                    }
                    mb.setClip(os.getBounds());
                }
               
                delta = ((order_flags & RDP_ORDER_DELTA) != 0);
               
                switch (os.getOrderType()) {
                    case RDP_ORDER_DESTBLT:
//                        logger.debug("DestBlt Order");
                        this.processDestBlt(data, os.getDestBlt(), present, delta);
                        break;
                    case RDP_ORDER_PATBLT:
//                        logger.debug("PatBlt Order");
                        this.processPatBlt(data, os.getPatBlt(), present, delta);
                        break;
                    case RDP_ORDER_SCREENBLT:
//                        logger.debug("ScreenBlt Order");
                        this.processScreenBlt(data, os.getScreenBlt(), present, delta);
                        break;
                    case RDP_ORDER_LINE:
//                        logger.debug("Line Order");
                        this.processLine(data, os.getLine(), present, delta);
                        break;
                    case RDP_ORDER_RECT:
//                        logger.debug("Rectangle Order");
                        this.processRectangle(data, os.getRectangle(), present, delta);
                        break;
                    case RDP_ORDER_DESKSAVE:
//                        logger.debug("Desksave!");
                        this.processDeskSave(data, os.getDeskSave(), present, delta);
                        break;
                    case RDP_ORDER_MEMBLT:
//                        logger.debug("MemBlt Order");
                        this.processMemBlt(data, os.getMemBlt(), present, delta);
                        break;
                    case RDP_ORDER_TRIBLT:
//                        logger.debug("TriBlt Order");
                        this.processTriBlt(data, os.getTriBlt(), present, delta);
                        break;
                    case RDP_ORDER_POLYLINE:
//                        logger.debug("Polyline Order");
                        this.processPolyLine(data, os.getPolyLine(), present, delta);
                        break;
                    case RDP_ORDER_TEXT2:
//                        logger.debug("Text2 Order");
                        this.processText2(data, os.getText2(), present, delta);
                        break;
                    default:
//                        logger.warn("Unimplemented Order type " + order_type);
                        return;
                }
                if ((order_flags & RDP_ORDER_BOUNDS) != 0) {
                    mb.resetClip();
//                    logger.debug("Reset clip");
                }
            }
            processed++;
        }
        if (data.getPosition() != next_packet) {
            throw new OrderException("End not reached!");
        }
        RDPConnection.sc.setImage(ARDP5.wi);
        EventWakeUp.getInstance().setImage(RDPConnection.sc);
    }
   
    private int ROP2_S(int rop3) {
        return (rop3 & 0x0f);
    }
   
    private int ROP2_P(int rop3) {
        return ((rop3 & 0x3) | ((rop3 & 0x30) >> 2));
    }

    /**
     * Register an RdesktopJPanel with this Orders object. This surface is where
     * all drawing orders will be carried out.
     *
     */
    public void registerDrawingSurface() {
    }

    /**
     * Handle secondary, or caching, orders
     *
     * @param data Packet containing secondary order
     * @throws OrderException
     * @throws RdesktopException
     */
    private void processSecondaryOrders(RdpPackage data) throws OrderException, RdesktopException {
        int length;
        int type;
        int flags;
        int next_order;
       
        length = data.getLittleEndian16();
        flags = data.getLittleEndian16();
        type = data.get8();
       
        next_order = data.getPosition() + length + 7;
       
        switch (type) {
            case RDP_ORDER_RAW_BMPCACHE:
//                logger.debug("Raw BitmapCache Order");
                this.processRawBitmapCache(data);
                break;
            case RDP_ORDER_COLCACHE:
//                logger.debug("Colorcache Order");
                this.processColorCache(data);
                break;
            case RDP_ORDER_BMPCACHE:
//                logger.debug("Bitmapcache Order");
                this.processBitmapCache(data);
                break;
            case RDP_ORDER_FONTCACHE:
//                logger.debug("Fontcache Order");
                this.processFontCache(data);
                break;
            case RDP_ORDER_RAW_BMPCACHE2:
                try {
                    this.process_bmpcache2(data, flags, false);
                } catch (IOException e) {
                    throw new RdesktopException(e.getMessage());
                } /* uncompressed */
               
                break;
            case RDP_ORDER_BMPCACHE2:
                try {
                    this.process_bmpcache2(data, flags, true);
                } catch (IOException e) {
                    throw new RdesktopException(e.getMessage());
                } /* compressed */
               
                break;
            default:
//                logger.warn("Unimplemented 2ry Order type " + type);
        }
       
        data.setPosition(next_order);
    }

    /**
     * Process a raw bitmap and store it in the bitmap cache
     *
     * @param data Packet containing raw bitmap data
     * @throws RdesktopException
     */
    private void processRawBitmapCache(RdpPackage data) throws RdesktopException {
        int cache_id = data.get8();
        data.incrementPosition(1); // pad
        int width = data.get8();
        int height = data.get8();
        int bpp = data.get8();
        int Bpp = (bpp + 7) / 8;
        int bufsize = data.getLittleEndian16();
        int cache_idx = data.getLittleEndian16();
        int pdata = data.getPosition();
        data.incrementPosition(bufsize);
       
        byte[] inverted = new byte[width * height * Bpp];
        int pinverted = (height - 1) * (width * Bpp);
        for (int y = 0; y < height; y++) {
            data.copyToByteArray(inverted, pinverted, pdata, width * Bpp);
            pinverted -= width * Bpp;
            pdata += width * Bpp;
        }
       
        cache.putBitmap(cache_id, cache_idx, new Bitmap(Bitmap.convertImage(inverted, Bpp), width, height, 0, 0), 0);
    }

    /**
     * Process and store details of a colour cache
     *
     * @param data Packet containing cache information
     * @throws RdesktopException
     */
    private void processColorCache(RdpPackage data) throws RdesktopException {
        byte[] palette;
       
        byte[] red;
        byte[] green;
        byte[] blue;
        int j = 0;
       
        int cache_id = data.get8();
        int n_colors = data.getLittleEndian16(); // Number of Colors in Palette

        palette = new byte[n_colors * 4];
        red = new byte[n_colors];
        green = new byte[n_colors];
        blue = new byte[n_colors];
        data.copyToByteArray(palette, 0, data.getPosition(), palette.length);
        data.incrementPosition(palette.length);
        for (int i = 0; i < n_colors; i++) {
            blue[i] = palette[j];
            green[i] = palette[j + 1];
            red[i] = palette[j + 2];
            j += 4;
        }
        IndexColorModel cm = new IndexColorModel(8, n_colors, red, green, blue);
        cache.put_colourmap(cache_id, cm);
    }

    /**
     * Process a compressed bitmap and store in the bitmap cache
     *
     * @param data Packet containing compressed bitmap
     * @throws RdesktopException
     */
    private void processBitmapCache(RdpPackage data) throws RdesktopException {
        int bufsize, pad2, row_size, final_size, size;
        int pad1;
       
        int cache_id = data.get8();
        pad1 = data.get8(); // pad
        int width = data.get8();
        int height = data.get8();
        int bpp = data.get8();
        int Bpp = (bpp + 7) / 8;
        bufsize = data.getLittleEndian16(); // bufsize
        int cache_idx = data.getLittleEndian16();
        if (RDPConnection.conf.use_rdp5) {
            /* Begin compressedBitmapData */
            pad2 = data.getLittleEndian16(); // in_uint16_le(s, pad2); pad
            size = data.getLittleEndian16(); // in_uint16_le(s, size);
            row_size = data.getLittleEndian16(); // in_uint16_le(s,row_size);
            final_size = data.getLittleEndian16(); // in_uint16_le(s,final_size);
        } else {
            data.incrementPosition(2); // pad
            size = data.getLittleEndian16();
            row_size = data.getLittleEndian16(); // in_uint16_le(s,row_size);
            final_size = data.getLittleEndian16(); // in_uint16_le(s,
        }
        if (Bpp == 1) {
            byte[] pixel = Bitmap.decompress(width, height, size, data, Bpp);
            if (pixel != null) {
                cache.putBitmap(cache_id, cache_idx, new Bitmap(Bitmap.convertImage(pixel, Bpp), width, height, 0, 0), 0);
            } else {
//                logger.warn("Failed to decompress bitmap");
            }
        } else {
            int[] pixel = Bitmap.decompressInt(width, height, size, data, Bpp);
            if (pixel != null) {
                cache.putBitmap(cache_id, cache_idx, new Bitmap(pixel, width, height, 0, 0), 0);
            } else {
//                logger.warn("Failed to decompress bitmap");
            }
        }
    }

    /* Process a bitmap cache v2 order */
    /**
     * Process a bitmap cache v2 order, storing a bitmap in the main cache, and
     * the persistant cache if so required
     *
     * @param data Packet containing order and bitmap data
     * @param flags Set of flags defining mode of order
     * @param compressed True if bitmap data is compressed
     * @throws RdesktopException
     * @throws IOException
     */
    private void process_bmpcache2(RdpPackage data, int flags, boolean compressed) throws RdesktopException, IOException {
        Bitmap bitmap;
        int y;
        int cache_id, cache_idx_low, width, height, Bpp;
        int cache_idx, bufsize;
        byte[] bmpdata, bitmap_id;
       
        bitmap_id = new byte[8]; /* prevent compiler warning */
       
        cache_id = flags & ID_MASK;
        Bpp = ((flags & MODE_MASK) >> MODE_SHIFT) - 2;
        if ((flags & PERSIST) != 0) {
            bitmap_id = new byte[8];
            data.copyToByteArray(bitmap_id, 0, data.getPosition(), 8);
        }
       
        if ((flags & SQUARE) != 0) {
            width = data.get8(); // in_uint8(s, width);
            height = width;
        } else {
            width = data.get8(); // in_uint8(s, width);
            height = data.get8(); // in_uint8(s, height);
        }
       
        bufsize = data.getBigEndian16(); // in_uint16_be(s, bufsize);
        bufsize &= BUFSIZE_MASK;
        cache_idx = data.get8(); // in_uint8(s, cache_idx);

        if ((cache_idx & LONG_FORMAT) != 0) {
            cache_idx_low = data.get8(); // in_uint8(s, cache_idx_low);
            cache_idx = ((cache_idx ^ LONG_FORMAT) << 8) + cache_idx_low;
        }
       
        bmpdata = new byte[width * height * Bpp];
        int[] bmpdataInt = new int[width * height];
       
        if (compressed) {
            if (Bpp == 1) {
                bmpdataInt = Bitmap.convertImage(Bitmap.decompress(width, height, bufsize, data, Bpp), Bpp);
            } else {
                bmpdataInt = Bitmap.decompressInt(width, height, bufsize, data, Bpp);
            }
            if (bmpdataInt == null) {
//                logger.debug("Failed to decompress bitmap data");
                return;
            }
            bitmap = new Bitmap(bmpdataInt, width, height, 0, 0);
        } else {
            for (y = 0; y < height; y++) {
                data.copyToByteArray(bmpdata, y * (width * Bpp), (height - y - 1) * (width * Bpp) + data.getPosition(), width * Bpp);
            }
            bitmap = new Bitmap(Bitmap.convertImage(bmpdata, Bpp), width, height, 0, 0);
        }
        if (bitmap != null) {
            cache.putBitmap(cache_id, cache_idx, bitmap, 0);
            if ((flags & PERSIST) != 0) {
                PstCache.pstcache_put_bitmap(cache_id, cache_idx, bitmap_id, width, height, width * height * Bpp, bmpdata);
            }
        } else {
//            logger.debug("process_bmpcache2: ui_create_bitmap failed");
        }
    }

    /**
     * Process a font caching order, and store font in the cache
     *
     * @param data Packet containing font cache order, with data for a series of
     * glyphs representing a font
     * @throws RdesktopException
     */
    private void processFontCache(RdpPackage data) throws RdesktopException {
        Glyph glyph;
       
        int font, nglyphs;
        int character, offset, baseline, width, height;
        int datasize;
        byte[] fontdata;
       
        font = data.get8();
        nglyphs = data.get8();
       
        for (int i = 0; i < nglyphs; i++) {
            character = data.getLittleEndian16();
            offset = data.getLittleEndian16();
            baseline = data.getLittleEndian16();
            width = data.getLittleEndian16();
            height = data.getLittleEndian16();
            datasize = (height * ((width + 7) / 8) + 3) & ~3;
            fontdata = new byte[datasize];
           
            data.copyToByteArray(fontdata, 0, data.getPosition(), datasize);
            data.incrementPosition(datasize);
            glyph = new Glyph(font, character, offset, baseline, width, height, fontdata);
            cache.putFont(glyph);
        }
    }

    /**
     * Process a dest blit order, and perform blit on drawing surface
     *
     * @param data Packet containing description of the order
     * @param destblt DestBltOrder object in which to store the blit description
     * @param present Flags defining the information available in the packet
     * @param delta True if the coordinates of the blit destination are
     * described as relative to the source
     */
    private void processDestBlt(RdpPackage data, DestBltOrder destblt, int present, boolean delta) {
        if ((present & 0x01) != 0) {
            destblt.setX(setCoordinate(data, destblt.getX(), delta));
        }
        if ((present & 0x02) != 0) {
            destblt.setY(setCoordinate(data, destblt.getY(), delta));
        }
        if ((present & 0x04) != 0) {
            destblt.setCX(setCoordinate(data, destblt.getCX(), delta));
        }
        if ((present & 0x08) != 0) {
            destblt.setCY(setCoordinate(data, destblt.getCY(), delta));
        }
        if ((present & 0x10) != 0) {
            destblt.setOpcode(ROP2_S(data.get8()));
        }
        mb.drawDestBltOrder(destblt);
    }

    /**
     * Parse data defining a brush and store brush information
     *
     * @param data Packet containing brush data
     * @param brush Brush object in which to store the brush description
     * @param present Flags defining the information available within the packet
     */
    private void parseBrush(RdpPackage data, Brush brush, int present) {
        if ((present & 0x01) != 0) {
            brush.setXOrigin(data.get8());
        }
        if ((present & 0x02) != 0) {
            brush.setXOrigin(data.get8());
        }
        if ((present & 0x04) != 0) {
            brush.setStyle(data.get8());
        }
        byte[] pat = brush.getPattern();
        if ((present & 0x08) != 0) {
            pat[0] = (byte) data.get8();
        }
        if ((present & 0x10) != 0) {
            for (int i = 1; i < 8; i++) {
                pat[i] = (byte) data.get8();
            }
        }
        brush.setPattern(pat);
    }

    /**
     * Parse data describing a pattern blit, and perform blit on drawing surface
     *
     * @param data Packet containing blit data
     * @param patblt PatBltOrder object in which to store the blit description
     * @param present Flags defining the information available within the packet
     * @param delta True if the coordinates of the blit destination are
     * described as relative to the source
     */
    private void processPatBlt(RdpPackage data, PatBltOrder patblt, int present, boolean delta) {
        if ((present & 0x01) != 0) {
            patblt.setX(setCoordinate(data, patblt.getX(), delta));
        }
        if ((present & 0x02) != 0) {
            patblt.setY(setCoordinate(data, patblt.getY(), delta));
        }
        if ((present & 0x04) != 0) {
            patblt.setCX(setCoordinate(data, patblt.getCX(), delta));
        }
        if ((present & 0x08) != 0) {
            patblt.setCY(setCoordinate(data, patblt.getCY(), delta));
        }
        if ((present & 0x10) != 0) {
            patblt.setOpcode(ROP2_P(data.get8()));
        }
        if ((present & 0x20) != 0) {
            patblt.setBackgroundColor(setColor(data));
        }
        if ((present & 0x40) != 0) {
            patblt.setForegroundColor(setColor(data));
        }
        parseBrush(data, patblt.getBrush(), present >> 7);
        mb.drawPatBltOrder(patblt);
    }

    /**
     * Parse data describing a screen blit, and perform blit on drawing surface
     *
     * @param data Packet containing blit data
     * @param screenblt ScreenBltOrder object in which to store blit description
     * @param present Flags defining the information available within the packet
     * @param delta True if the coordinates of the blit destination are
     * described as relative to the source
     */
    private void processScreenBlt(RdpPackage data, ScreenBltOrder screenblt, int present, boolean delta) {
        if ((present & 0x01) != 0) {
            screenblt.setX(setCoordinate(data, screenblt.getX(), delta));
        }
        if ((present & 0x02) != 0) {
            screenblt.setY(setCoordinate(data, screenblt.getY(), delta));
        }
        if ((present & 0x04) != 0) {
            screenblt.setCX(setCoordinate(data, screenblt.getCX(), delta));
        }
        if ((present & 0x08) != 0) {
            screenblt.setCY(setCoordinate(data, screenblt.getCY(), delta));
        }
        if ((present & 0x10) != 0) {
            screenblt.setOpcode(ROP2_S(data.get8()));
        }
        if ((present & 0x20) != 0) {
            screenblt.setSrcX(setCoordinate(data, screenblt.getSrcX(), delta));
        }
        if ((present & 0x40) != 0) {
            screenblt.setSrcY(setCoordinate(data, screenblt.getSrcY(), delta));
        }
        mb.drawScreenBltOrder(screenblt);
    }

    /**
     * Parse data describing a line order, and draw line on drawing surface
     *
     * @param data Packet containing line order data
     * @param line LineOrder object describing the line drawing operation
     * @param present Flags defining the information available within the packet
     * @param delta True if the coordinates of the end of the line are defined
     * as relative to the start
     */
    private void processLine(RdpPackage data, LineOrder line, int present, boolean delta) {
        if ((present & 0x01) != 0) {
            line.setMixmode(data.getLittleEndian16());
        }
        if ((present & 0x02) != 0) {
            line.setStartX(setCoordinate(data, line.getStartX(), delta));
        }
        if ((present & 0x04) != 0) {
            line.setStartY(setCoordinate(data, line.getStartY(), delta));
        }
        if ((present & 0x08) != 0) {
            line.setEndX(setCoordinate(data, line.getEndX(), delta));
        }
        if ((present & 0x10) != 0) {
            line.setEndY(setCoordinate(data, line.getEndY(), delta));
        }
        if ((present & 0x20) != 0) {
            line.setBackgroundColor(setColor(data));
        }
        if ((present & 0x40) != 0) {
            line.setOpcode(data.get8());
        }
        parsePen(data, line.getPen(), present >> 7);
        if (line.getOpcode() < 0x01 || line.getOpcode() > 0x10) {
//            logger.warn("bad ROP2 0x" + line.getOpcode());
            return;
        }
        mb.drawLineOrder(line);
    }

    /**
     * Parse data describing a rectangle order, and draw the rectangle to the
     * drawing surface
     *
     * @param data Packet containing rectangle order
     * @param rect RectangleOrder object in which to store order description
     * @param present Flags defining information available in packet
     * @param delta True if the rectangle is described as (x,y,width,height), as
     * opposed to (x1,y1,x2,y2)
     */
    private void processRectangle(RdpPackage data, RectangleOrder rect, int present, boolean delta) {
        if ((present & 0x01) != 0) {
            rect.setX(setCoordinate(data, rect.getX(), delta));
        }
        if ((present & 0x02) != 0) {
            rect.setY(setCoordinate(data, rect.getY(), delta));
        }
        if ((present & 0x04) != 0) {
            rect.setCX(setCoordinate(data, rect.getCX(), delta));
        }
        if ((present & 0x08) != 0) {
            rect.setCY(setCoordinate(data, rect.getCY(), delta));
        }
        if ((present & 0x10) != 0) {
            this.rect_colour = (this.rect_colour & 0xffffff00) | data.get8(); // rect.setColor(setColor(data));
        }
        if ((present & 0x20) != 0) {
            this.rect_colour = (this.rect_colour & 0xffff00ff)
                    | (data.get8() << 8); // rect.setColor(setColor(data));
        }
        if ((present & 0x40) != 0) {
            this.rect_colour = (this.rect_colour & 0xff00ffff)
                    | (data.get8() << 16);
        }
        rect.setColor(this.rect_colour);
        mb.drawRectangleOrder(rect);
    }

    /**
     * Parse data describing a desktop save order, either saving the desktop to
     * cache, or drawing a section to screen
     *
     * @param data Packet containing desktop save order
     * @param desksave DeskSaveOrder object in which to store order description
     * @param present Flags defining information available within the packet
     * @param delta True if destination coordinates are described as relative to
     * the source
     * @throws RdesktopException
     */
    private void processDeskSave(RdpPackage data, DeskSaveOrder desksave, int present, boolean delta) throws RdesktopException {
        int width, height;
       
        if ((present & 0x01) != 0) {
            desksave.setOffset(data.getLittleEndian32());
        }
        if ((present & 0x02) != 0) {
            desksave.setLeft(setCoordinate(data, desksave.getLeft(), delta));
        }
        if ((present & 0x04) != 0) {
            desksave.setTop(setCoordinate(data, desksave.getTop(), delta));
        }
        if ((present & 0x08) != 0) {
            desksave.setRight(setCoordinate(data, desksave.getRight(), delta));
        }
        if ((present & 0x10) != 0) {
            desksave.setBottom(setCoordinate(data, desksave.getBottom(), delta));
        }
        if ((present & 0x20) != 0) {
            desksave.setAction(data.get8());
        }
       
        width = desksave.getRight() - desksave.getLeft() + 1;
        height = desksave.getBottom() - desksave.getTop() + 1;
       
        if (desksave.getAction() == 0) {
            int[] pixel = mb.getImage(desksave.getLeft(), desksave.getTop(), width, height);
            cache.putDesktop((int) desksave.getOffset(), width, height, pixel);
        } else {
            int[] pixel = cache.getDesktopInt((int) desksave.getOffset(), width, height);
            mb.putImage(desksave.getLeft(), desksave.getTop(), width, height, pixel);
        }
    }

    /**
     * Process data describing a memory blit, and perform blit on drawing
     * surface
     *
     * @param data Packet containing mem blit order
     * @param memblt MemBltOrder object in which to store description of blit
     * @param present Flags defining information available in packet
     * @param delta True if destination coordinates are described as relative to
     * the source
     */
    private void processMemBlt(RdpPackage data, MemBltOrder memblt, int present, boolean delta) {
        if ((present & 0x01) != 0) {
            memblt.setCacheID(data.get8());
            memblt.setColorTable(data.get8());
        }
        if ((present & 0x02) != 0) {
            memblt.setX(setCoordinate(data, memblt.getX(), delta));
        }
        if ((present & 0x04) != 0) {
            memblt.setY(setCoordinate(data, memblt.getY(), delta));
        }
        if ((present & 0x08) != 0) {
            memblt.setCX(setCoordinate(data, memblt.getCX(), delta));
        }
        if ((present & 0x10) != 0) {
            memblt.setCY(setCoordinate(data, memblt.getCY(), delta));
        }
        if ((present & 0x20) != 0) {
            memblt.setOpcode(ROP2_S(data.get8()));
        }
        if ((present & 0x40) != 0) {
            memblt.setSrcX(setCoordinate(data, memblt.getSrcX(), delta));
        }
        if ((present & 0x80) != 0) {
            memblt.setSrcY(setCoordinate(data, memblt.getSrcY(), delta));
        }
        if ((present & 0x0100) != 0) {
            memblt.setCacheIDX(data.getLittleEndian16());
        }
        mb.drawMemBltOrder(memblt);
    }

    /**
     * Parse data describing a tri blit order, and perform blit on drawing
     * surface
     *
     * @param data Packet containing tri blit order
     * @param triblt TriBltOrder object in which to store blit description
     * @param present Flags defining information available in packet
     * @param delta True if destination coordinates are described as relative to
     * the source
     */
    private void processTriBlt(RdpPackage data, TriBltOrder triblt, int present, boolean delta) {
        if ((present & 0x01) != 0) {
            triblt.setCacheID(data.get8());
            triblt.setColorTable(data.get8());
        }
        if ((present & 0x02) != 0) {
            triblt.setX(setCoordinate(data, triblt.getX(), delta));
        }
        if ((present & 0x04) != 0) {
            triblt.setY(setCoordinate(data, triblt.getY(), delta));
        }
        if ((present & 0x08) != 0) {
            triblt.setCX(setCoordinate(data, triblt.getCX(), delta));
        }
        if ((present & 0x10) != 0) {
            triblt.setCY(setCoordinate(data, triblt.getCY(), delta));
        }
        if ((present & 0x20) != 0) {
            triblt.setOpcode(ROP2_S(data.get8()));
        }
        if ((present & 0x40) != 0) {
            triblt.setSrcX(setCoordinate(data, triblt.getSrcX(), delta));
        }
        if ((present & 0x80) != 0) {
            triblt.setSrcY(setCoordinate(data, triblt.getSrcY(), delta));
        }
        if ((present & 0x0100) != 0) {
            triblt.setBackgroundColor(setColor(data));
        }
        if ((present & 0x0200) != 0) {
            triblt.setForegroundColor(setColor(data));
        }
       
        parseBrush(data, triblt.getBrush(), present >> 10);
       
        if ((present & 0x8000) != 0) {
            triblt.setCacheIDX(data.getLittleEndian16());
        }
        if ((present & 0x10000) != 0) {
            triblt.setUnknown(data.getLittleEndian16());
        }
        mb.drawTriBltOrder(triblt);
    }

    /**
     * Parse data describing a multi-line order, and draw to registered surface
     *
     * @param data Packet containing polyline order
     * @param polyline PolyLineOrder object in which to store order description
     * @param present Flags defining information available in packet
     * @param delta True if each set of coordinates is described relative to
     * previous set
     */
    private void processPolyLine(RdpPackage data, PolyLineOrder polyline, int present, boolean delta) {
        if ((present & 0x01) != 0) {
            polyline.setX(setCoordinate(data, polyline.getX(), delta));
        }
        if ((present & 0x02) != 0) {
            polyline.setY(setCoordinate(data, polyline.getY(), delta));
        }
        if ((present & 0x04) != 0) {
            polyline.setOpcode(data.get8());
        }
        if ((present & 0x10) != 0) {
            polyline.setForegroundColor(setColor(data));
        }
        if ((present & 0x20) != 0) {
            polyline.setLines(data.get8());
        }
        if ((present & 0x40) != 0) {
            int datasize = data.get8();
            polyline.setDataSize(datasize);
            byte[] databytes = new byte[datasize];
            for (int i = 0; i < datasize; i++) {
                databytes[i] = (byte) data.get8();
            }
            polyline.setData(databytes);
        }
        mb.drawPolyLineOrder(polyline);
    }

    /**
     * Process a text2 order and output to drawing surface
     *
     * @param data Packet containing text2 order
     * @param text2 Text2Order object in which to store order description
     * @param present Flags defining information available in packet
     * @param delta Unused
     * @throws RdesktopException
     */
    private void processText2(RdpPackage data, Text2Order text2, int present, boolean delta) throws RdesktopException {
        if ((present & 0x000001) != 0) {
            text2.setFont(data.get8());
        }
        if ((present & 0x000002) != 0) {
            text2.setFlags(data.get8());
        }
        if ((present & 0x000004) != 0) {
            text2.setOpcode(data.get8()); // setUnknown(data.get8());
        }
        if ((present & 0x000008) != 0) {
            text2.setMixmode(data.get8());
        }
        if ((present & 0x000010) != 0) {
            text2.setForegroundColor(setColor(data));
        }
        if ((present & 0x000020) != 0) {
            text2.setBackgroundColor(setColor(data));
        }
        if ((present & 0x000040) != 0) {
            text2.setClipLeft(data.getLittleEndian16());
        }
        if ((present & 0x000080) != 0) {
            text2.setClipTop(data.getLittleEndian16());
        }
        if ((present & 0x000100) != 0) {
            text2.setClipRight(data.getLittleEndian16());
        }
        if ((present & 0x000200) != 0) {
            text2.setClipBottom(data.getLittleEndian16());
        }
        if ((present & 0x000400) != 0) {
            text2.setBoxLeft(data.getLittleEndian16());
        }
        if ((present & 0x000800) != 0) {
            text2.setBoxTop(data.getLittleEndian16());
        }
        if ((present & 0x001000) != 0) {
            text2.setBoxRight(data.getLittleEndian16());
        }
        if ((present & 0x002000) != 0) {
            text2.setBoxBottom(data.getLittleEndian16());
        }

        /*
         * Unknown members, seen when connecting to a session that was
         * disconnected with mstsc and with wintach's spreadsheet test.
         */
        if ((present & 0x004000) != 0) {
            data.incrementPosition(1);
        }
        if ((present & 0x008000) != 0) {
            data.incrementPosition(1);
        }
        if ((present & 0x010000) != 0) {
            data.incrementPosition(1); /* guessing the length here */

//            logger.warn("Unknown order state member (0x010000) in text2 order.\n");
        }
        if ((present & 0x020000) != 0) {
            data.incrementPosition(4);
        }
        if ((present & 0x040000) != 0) {
            data.incrementPosition(4);
        }
        if ((present & 0x080000) != 0) {
            text2.setX(data.getLittleEndian16());
        }
        if ((present & 0x100000) != 0) {
            text2.setY(data.getLittleEndian16());
        }
        if ((present & 0x200000) != 0) {
            text2.setLength(data.get8());
            byte[] text = new byte[text2.getLength()];
            data.copyToByteArray(text, 0, data.getPosition(), text.length);
            data.incrementPosition(text.length);
            text2.setText(text);
        }
        this.drawText(text2, text2.getClipRight() - text2.getClipLeft(), text2.getClipBottom()
                - text2.getClipTop(), text2.getBoxRight() - text2.getBoxLeft(),
                text2.getBoxBottom() - text2.getBoxTop());
    }

    /**
     * Parse a description for a bounding box
     *
     * @param data Packet containing order defining bounding box
     * @param bounds BoundsOrder object in which to store description of bounds
     * @throws OrderException
     */
    private void parseBounds(RdpPackage data, BoundsOrder bounds) throws OrderException {
        int present;
        present = data.get8();
       
        if ((present & 1) != 0) {
            bounds.setLeft(setCoordinate(data, bounds.getLeft(), false));
        } else if ((present & 16) != 0) {
            bounds.setLeft(setCoordinate(data, bounds.getLeft(), true));
        }
       
        if ((present & 2) != 0) {
            bounds.setTop(setCoordinate(data, bounds.getTop(), false));
        } else if ((present & 32) != 0) {
            bounds.setTop(setCoordinate(data, bounds.getTop(), true));
        }
       
        if ((present & 4) != 0) {
            bounds.setRight(setCoordinate(data, bounds.getRight(), false));
        } else if ((present & 64) != 0) {
            bounds.setRight(setCoordinate(data, bounds.getRight(), true));
        }
       
        if ((present & 8) != 0) {
            bounds.setBottom(setCoordinate(data, bounds.getBottom(), false));
        } else if ((present & 128) != 0) {
            bounds.setBottom(setCoordinate(data, bounds.getBottom(), true));
        }
       
        if (data.getPosition() > data.getEnd()) {
            throw new OrderException("Too far!");
        }
    }

    /**
     * Retrieve a coordinate from a packet and return as an absolute integer
     * coordinate
     *
     * @param data Packet containing coordinate at current read position
     * @param coordinate Offset coordinate
     * @param delta True if coordinate being read should be taken as relative to
     * offset coordinate, false if absolute
     * @return Integer value of coordinate stored in packet, in absolute form
     */
    private static int setCoordinate(RdpPackage data, int coordinate, boolean delta) {
        byte change;
        if (delta) {
            change = (byte) data.get8();
            coordinate += (int) change;
            return coordinate;
        } else {
            coordinate = data.getLittleEndian16();
            return coordinate;
        }
    }

    /**
     * Read a colour value from a packet
     *
     * @param data Packet containing colour value at current read position
     * @return Integer colour value read from packet
     */
    private static int setColor(RdpPackage data) {
        int color;
        int i;
       
        i = data.get8(); // in_uint8(s, i);
        color = i; // *colour = i;
        i = data.get8(); // in_uint8(s, i);
        color |= i << 8; // *colour |= i << 8;
        i = data.get8(); // in_uint8(s, i);
        color |= i << 16; // *colour |= i << 16;

        // color = data.get8();
        // data.incrementPosition(2);
        return color;
    }

    /**
     * Set current cache
     *
     * @param cache Cache object to set as current global cache
     */
    public void registerCache(Cache cache) {
        this.cache = cache;
        mb = new ManageBitmaps(cache);
        mb.setVisible(true);
    }

    /**
     * Parse a pen definition
     *
     * @param data Packet containing pen description at current read position
     * @param pen Pen object in which to store pen description
     * @param present Flags defining information available within packet
     * @return True if successful
     */
    private static boolean parsePen(RdpPackage data, Pen pen,
            int present) {
        if ((present & 0x01) != 0) {
            pen.setStyle(data.get8());
        }
        if ((present & 0x02) != 0) {
            pen.setWidth(data.get8());
        }
        if ((present & 0x04) != 0) {
            pen.setColor(setColor(data));
        }
       
        return true; // return s_check(s);
    }

    /**
     * Interpret an integer as a 16-bit two's complement number, based on its
     * binary representation
     *
     * @param val Integer interpretation of binary number
     * @return 16-bit two's complement value of input
     */
    private int twosComplement16(int val) {
        return ((val & 0x8000) != 0) ? -((~val & 0xFFFF) + 1) : val;
    }

    /**
     * Draw a text2 order to the drawing surface
     *
     * @param text2 Text2Order describing text to be drawn
     * @param clipcx Width of clipping area
     * @param clipcy Height of clipping area
     * @param boxcx Width of bounding box (to draw if > 1)
     * @param boxcy Height of bounding box (to draw if boxcx > 1)
     * @throws RdesktopException
     */
    private void drawText(Text2Order text2, int clipcx, int clipcy, int boxcx, int boxcy) throws RdesktopException {
        byte[] text = text2.getText();
        DataBlob entry;
        Glyph glyph;
        int offset;
        int ptext = 0;
        int length = text2.getLength();
        int x = text2.getX();
        int y = text2.getY();
       
        if (boxcx > 1) {
            mb.fillRectangle(text2.getBoxLeft(), text2.getBoxTop(), boxcx, boxcy, text2.getBackgroundColor());
        } else if (text2.getMixmode() == MIX_OPAQUE) {
            mb.fillRectangle(text2.getClipLeft(), text2.getClipTop(), clipcx, clipcy, text2.getBackgroundColor());
        }
        for (int i = 0; i < length;) {
            switch (text[ptext + i] & 0x000000ff) {
                case (0xff):
                    if (i + 2 < length) {
                        byte[] data = new byte[text[ptext + i + 2] & 0x000000ff];
                        System.arraycopy(text, ptext, data, 0, text[ptext + i + 2] & 0x000000ff);
                        DataBlob db = new DataBlob(text[ptext + i + 2] & 0x000000ff, data);
                        cache.putText(text[ptext + i + 1] & 0x000000ff, db);
                    } else {
                        throw new RdesktopException();
                    }
                    length -= i + 3;
                    ptext = i + 3;
                    i = 0;
                    break;
                case (0xfe):
                    entry = cache.getText(text[ptext + i + 1] & 0x000000ff);
                    if (entry != null) {
                        if ((entry.getData()[1] == 0) && ((text2.getFlags() & TEXT2_IMPLICIT_X) == 0)) {
                            if ((text2.getFlags() & 0x04) != 0) {
                                y += text[ptext + i + 2] & 0x000000ff;
                            } else {
                                x += text[ptext + i + 2] & 0x000000ff;
                            }
                        }
                    }
                    if (i + 2 < length) {
                        i += 3;
                    } else {
                        i += 2;
                    }
                    length -= i;
                    ptext = i;
                    i = 0;
                    byte[] data = entry.getData();
                    for (int j = 0; j < entry.getSize(); j++) {
                        glyph = cache.getFont(text2.getFont(), data[j] & 0x000000ff);
                        if ((text2.getFlags() & TEXT2_IMPLICIT_X) == 0) {
                            offset = data[++j] & 0x000000ff;
                            if ((offset & 0x80) != 0) {
                                if ((text2.getFlags() & TEXT2_VERTICAL) != 0) {
                                    int var = this.twosComplement16((data[j + 1] & 0xff) | ((data[j + 2] & 0xff) << 8));
                                    y += var;
                                    j += 2;
                                } else {
                                    int var = this.twosComplement16((data[j + 1] & 0xff) | ((data[j + 2] & 0xff) << 8));
                                    x += var;
                                    j += 2;
                                }
                            } else {
                                if ((text2.getFlags() & TEXT2_VERTICAL) != 0) {
                                    y += offset;
                                } else {
                                    x += offset;
                                }
                            }
                        }
                        if (glyph != null) {
                            mb.drawGlyph(text2.getMixmode(), x + (short) glyph.getOffset(),
                                    y + (short) glyph.getBaseLine(), glyph.getWidth(),
                                    glyph.getHeight(), glyph.getFontData(),
                                    text2.getBackgroundColor(), text2.getForegroundColor());
                           
                            if ((text2.getFlags() & TEXT2_IMPLICIT_X) != 0) {
                                x += glyph.getWidth();
                            }
                        }
                    }
                    break;
                default:
                    glyph = cache.getFont(text2.getFont(), text[ptext + i] & 0x000000ff);
                    if ((text2.getFlags() & TEXT2_IMPLICIT_X) == 0) {
                        offset = text[ptext + (++i)] & 0x000000ff;
                        if ((offset & 0x80) != 0) {
                            if ((text2.getFlags() & TEXT2_VERTICAL) != 0) {
                                int var = this.twosComplement16((text[ptext + i + 1] & 0x000000ff) | ((text[ptext + i + 2] & 0x000000ff) << 8));
                                y += var;
                                i += 2;
                            } else {
                                int var = this.twosComplement16((text[ptext + i + 1] & 0x000000ff) | ((text[ptext + i + 2] & 0x000000ff) << 8));
                                x += var;
                                i += 2;
                            }
                        } else {
                            if ((text2.getFlags() & TEXT2_VERTICAL) != 0) {
                                y += offset;
                            } else {
                                x += offset;
                            }
                        }
                    }
                    if (glyph != null) {
                        mb.drawGlyph(text2.getMixmode(), x + (short) glyph.getOffset(),
                                y + (short) glyph.getBaseLine(), glyph.getWidth(),
                                glyph.getHeight(), glyph.getFontData(),
                                text2.getBackgroundColor(), text2.getForegroundColor());
                       
                        if ((text2.getFlags() & TEXT2_IMPLICIT_X) != 0) {
                            x += glyph.getWidth();
                        }
                    }
                    i++;
                    break;
            }
        }
    }
}
TOP

Related Classes of com.lixia.rdp.OrdersJPanel

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.