rdesktop/orders.c
Erik Forsberg 1bc2511c0b Got bitmap decompression to work. It turned out Microsoft doesn't care about sending the compressed
bitmap header any longer, instead the size of the compressed bitmap data is sent in the bitmapLength
field of the cache bitmap order. Of course this doesn't concur with T.128.

Added more detailed debugging which helped in finding this.


git-svn-id: svn://svn.code.sf.net/p/rdesktop/code/trunk/rdesktop@354 423420c4-83ab-492f-b58f-81f9feb106b5
2003-03-28 09:09:17 +00:00

961 lines
20 KiB
C

/* -*- c-basic-offset: 8 -*-
rdesktop: A Remote Desktop Protocol client.
RDP order processing
Copyright (C) Matthew Chapman 1999-2002
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "rdesktop.h"
#include "orders.h"
extern uint8 *next_packet;
static RDP_ORDER_STATE order_state;
extern BOOL use_rdp5;
/* Read field indicating which parameters are present */
static void
rdp_in_present(STREAM s, uint32 * present, uint8 flags, int size)
{
uint8 bits;
int i;
if (flags & RDP_ORDER_SMALL)
{
size--;
}
if (flags & RDP_ORDER_TINY)
{
if (size < 2)
size = 0;
else
size -= 2;
}
*present = 0;
for (i = 0; i < size; i++)
{
in_uint8(s, bits);
*present |= bits << (i * 8);
}
}
/* Read a co-ordinate (16-bit, or 8-bit delta) */
static void
rdp_in_coord(STREAM s, uint16 * coord, BOOL delta)
{
sint8 change;
if (delta)
{
in_uint8(s, change);
*coord += change;
}
else
{
in_uint16_le(s, *coord);
}
}
/* Read a colour entry */
static void
rdp_in_colour(STREAM s, uint32 * colour)
{
uint32 i;
in_uint8(s, i);
*colour = i;
in_uint8(s, i);
*colour |= i << 8;
in_uint8(s, i);
*colour |= i << 16;
}
/* Parse bounds information */
static BOOL
rdp_parse_bounds(STREAM s, BOUNDS * bounds)
{
uint8 present;
in_uint8(s, present);
if (present & 1)
rdp_in_coord(s, &bounds->left, False);
else if (present & 16)
rdp_in_coord(s, &bounds->left, True);
if (present & 2)
rdp_in_coord(s, &bounds->top, False);
else if (present & 32)
rdp_in_coord(s, &bounds->top, True);
if (present & 4)
rdp_in_coord(s, &bounds->right, False);
else if (present & 64)
rdp_in_coord(s, &bounds->right, True);
if (present & 8)
rdp_in_coord(s, &bounds->bottom, False);
else if (present & 128)
rdp_in_coord(s, &bounds->bottom, True);
return s_check(s);
}
/* Parse a pen */
static BOOL
rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
{
if (present & 1)
in_uint8(s, pen->style);
if (present & 2)
in_uint8(s, pen->width);
if (present & 4)
rdp_in_colour(s, &pen->colour);
return s_check(s);
}
/* Parse a brush */
static BOOL
rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
{
if (present & 1)
in_uint8(s, brush->xorigin);
if (present & 2)
in_uint8(s, brush->yorigin);
if (present & 4)
in_uint8(s, brush->style);
if (present & 8)
in_uint8(s, brush->pattern[0]);
if (present & 16)
in_uint8a(s, &brush->pattern[1], 7);
return s_check(s);
}
/* Process a destination blt order */
static void
process_destblt(STREAM s, DESTBLT_ORDER * os, uint32 present, BOOL delta)
{
if (present & 0x01)
rdp_in_coord(s, &os->x, delta);
if (present & 0x02)
rdp_in_coord(s, &os->y, delta);
if (present & 0x04)
rdp_in_coord(s, &os->cx, delta);
if (present & 0x08)
rdp_in_coord(s, &os->cy, delta);
if (present & 0x10)
in_uint8(s, os->opcode);
DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n",
os->opcode, os->x, os->y, os->cx, os->cy));
ui_destblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy);
}
/* Process a pattern blt order */
static void
process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, BOOL delta)
{
if (present & 0x0001)
rdp_in_coord(s, &os->x, delta);
if (present & 0x0002)
rdp_in_coord(s, &os->y, delta);
if (present & 0x0004)
rdp_in_coord(s, &os->cx, delta);
if (present & 0x0008)
rdp_in_coord(s, &os->cy, delta);
if (present & 0x0010)
in_uint8(s, os->opcode);
if (present & 0x0020)
rdp_in_colour(s, &os->bgcolour);
if (present & 0x0040)
rdp_in_colour(s, &os->fgcolour);
rdp_parse_brush(s, &os->brush, present >> 7);
DEBUG(("PATBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,bs=%d,bg=0x%x,fg=0x%x)\n", os->opcode, os->x,
os->y, os->cx, os->cy, os->brush.style, os->bgcolour, os->fgcolour));
ui_patblt(ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy,
&os->brush, os->bgcolour, os->fgcolour);
}
/* Process a screen blt order */
static void
process_screenblt(STREAM s, SCREENBLT_ORDER * os, uint32 present, BOOL delta)
{
if (present & 0x0001)
rdp_in_coord(s, &os->x, delta);
if (present & 0x0002)
rdp_in_coord(s, &os->y, delta);
if (present & 0x0004)
rdp_in_coord(s, &os->cx, delta);
if (present & 0x0008)
rdp_in_coord(s, &os->cy, delta);
if (present & 0x0010)
in_uint8(s, os->opcode);
if (present & 0x0020)
rdp_in_coord(s, &os->srcx, delta);
if (present & 0x0040)
rdp_in_coord(s, &os->srcy, delta);
DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n",
os->opcode, os->x, os->y, os->cx, os->cy, os->srcx, os->srcy));
ui_screenblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, os->srcx, os->srcy);
}
/* Process a line order */
static void
process_line(STREAM s, LINE_ORDER * os, uint32 present, BOOL delta)
{
if (present & 0x0001)
in_uint16_le(s, os->mixmode);
if (present & 0x0002)
rdp_in_coord(s, &os->startx, delta);
if (present & 0x0004)
rdp_in_coord(s, &os->starty, delta);
if (present & 0x0008)
rdp_in_coord(s, &os->endx, delta);
if (present & 0x0010)
rdp_in_coord(s, &os->endy, delta);
if (present & 0x0020)
rdp_in_colour(s, &os->bgcolour);
if (present & 0x0040)
in_uint8(s, os->opcode);
rdp_parse_pen(s, &os->pen, present >> 7);
DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dx=%d,fg=0x%x)\n",
os->opcode, os->startx, os->starty, os->endx, os->endy, os->pen.colour));
if (os->opcode < 0x01 || os->opcode > 0x10)
{
error("bad ROP2 0x%x\n", os->opcode);
return;
}
ui_line(os->opcode - 1, os->startx, os->starty, os->endx, os->endy, &os->pen);
}
/* Process an opaque rectangle order */
static void
process_rect(STREAM s, RECT_ORDER * os, uint32 present, BOOL delta)
{
uint32 i;
if (present & 0x01)
rdp_in_coord(s, &os->x, delta);
if (present & 0x02)
rdp_in_coord(s, &os->y, delta);
if (present & 0x04)
rdp_in_coord(s, &os->cx, delta);
if (present & 0x08)
rdp_in_coord(s, &os->cy, delta);
if (present & 0x10)
{
in_uint8(s, i);
os->colour = (os->colour & 0xffffff00) | i;
}
if (present & 0x20)
{
in_uint8(s, i);
os->colour = (os->colour & 0xffff00ff) | (i << 8);
}
if (present & 0x40)
{
in_uint8(s, i);
os->colour = (os->colour & 0xff00ffff) | (i << 16);
}
DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os->x, os->y, os->cx, os->cy, os->colour));
ui_rect(os->x, os->y, os->cx, os->cy, os->colour);
}
/* Process a desktop save order */
static void
process_desksave(STREAM s, DESKSAVE_ORDER * os, uint32 present, BOOL delta)
{
int width, height;
if (present & 0x01)
in_uint32_le(s, os->offset);
if (present & 0x02)
rdp_in_coord(s, &os->left, delta);
if (present & 0x04)
rdp_in_coord(s, &os->top, delta);
if (present & 0x08)
rdp_in_coord(s, &os->right, delta);
if (present & 0x10)
rdp_in_coord(s, &os->bottom, delta);
if (present & 0x20)
in_uint8(s, os->action);
DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n",
os->left, os->top, os->right, os->bottom, os->offset, os->action));
width = os->right - os->left + 1;
height = os->bottom - os->top + 1;
if (os->action == 0)
ui_desktop_save(os->offset, os->left, os->top, width, height);
else
ui_desktop_restore(os->offset, os->left, os->top, width, height);
}
/* Process a memory blt order */
static void
process_memblt(STREAM s, MEMBLT_ORDER * os, uint32 present, BOOL delta)
{
HBITMAP bitmap;
if (present & 0x0001)
{
in_uint8(s, os->cache_id);
in_uint8(s, os->colour_table);
}
if (present & 0x0002)
rdp_in_coord(s, &os->x, delta);
if (present & 0x0004)
rdp_in_coord(s, &os->y, delta);
if (present & 0x0008)
rdp_in_coord(s, &os->cx, delta);
if (present & 0x0010)
rdp_in_coord(s, &os->cy, delta);
if (present & 0x0020)
in_uint8(s, os->opcode);
if (present & 0x0040)
rdp_in_coord(s, &os->srcx, delta);
if (present & 0x0080)
rdp_in_coord(s, &os->srcy, delta);
if (present & 0x0100)
in_uint16_le(s, os->cache_idx);
DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n",
os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx));
bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
if (bitmap == NULL)
return;
ui_memblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, bitmap, os->srcx, os->srcy);
}
/* Process a 3-way blt order */
static void
process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, BOOL delta)
{
HBITMAP bitmap;
if (present & 0x000001)
{
in_uint8(s, os->cache_id);
in_uint8(s, os->colour_table);
}
if (present & 0x000002)
rdp_in_coord(s, &os->x, delta);
if (present & 0x000004)
rdp_in_coord(s, &os->y, delta);
if (present & 0x000008)
rdp_in_coord(s, &os->cx, delta);
if (present & 0x000010)
rdp_in_coord(s, &os->cy, delta);
if (present & 0x000020)
in_uint8(s, os->opcode);
if (present & 0x000040)
rdp_in_coord(s, &os->srcx, delta);
if (present & 0x000080)
rdp_in_coord(s, &os->srcy, delta);
if (present & 0x000100)
rdp_in_colour(s, &os->bgcolour);
if (present & 0x000200)
rdp_in_colour(s, &os->fgcolour);
rdp_parse_brush(s, &os->brush, present >> 10);
if (present & 0x008000)
in_uint16_le(s, os->cache_idx);
if (present & 0x010000)
in_uint16_le(s, os->unknown);
DEBUG(("TRIBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx,
os->brush.style, os->bgcolour, os->fgcolour));
bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
if (bitmap == NULL)
return;
ui_triblt(os->opcode, os->x, os->y, os->cx, os->cy,
bitmap, os->srcx, os->srcy, &os->brush, os->bgcolour, os->fgcolour);
}
/* Parse a delta co-ordinate in polyline order form */
static int
parse_delta(uint8 * buffer, int *offset)
{
int value = buffer[(*offset)++];
int two_byte = value & 0x80;
if (value & 0x40) /* sign bit */
value |= ~0x3f;
else
value &= 0x3f;
if (two_byte)
value = (value << 8) | buffer[(*offset)++];
return value;
}
/* Process a polyline order */
static void
process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, BOOL delta)
{
int index, line, data;
int x, y, xfrom, yfrom;
uint8 flags = 0;
PEN pen;
uint8 opcode;
if (present & 0x01)
rdp_in_coord(s, &os->x, delta);
if (present & 0x02)
rdp_in_coord(s, &os->y, delta);
if (present & 0x04)
in_uint8(s, os->opcode);
if (present & 0x10)
rdp_in_colour(s, &os->fgcolour);
if (present & 0x20)
in_uint8(s, os->lines);
if (present & 0x40)
{
in_uint8(s, os->datasize);
in_uint8a(s, os->data, os->datasize);
}
DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n",
os->x, os->y, os->opcode, os->fgcolour, os->lines, os->datasize));
DEBUG(("Data: "));
for (index = 0; index < os->datasize; index++)
DEBUG(("%02x ", os->data[index]));
DEBUG(("\n"));
if (os->opcode < 0x01 || os->opcode > 0x10)
{
error("bad ROP2 0x%x\n", os->opcode);
return;
}
opcode = os->opcode - 1;
x = os->x;
y = os->y;
pen.style = pen.width = 0;
pen.colour = os->fgcolour;
index = 0;
data = ((os->lines - 1) / 4) + 1;
for (line = 0; (line < os->lines) && (data < os->datasize); line++)
{
xfrom = x;
yfrom = y;
if (line % 4 == 0)
flags = os->data[index++];
if ((flags & 0xc0) == 0)
flags |= 0xc0; /* none = both */
if (flags & 0x40)
x += parse_delta(os->data, &data);
if (flags & 0x80)
y += parse_delta(os->data, &data);
ui_line(opcode, xfrom, yfrom, x, y, &pen);
flags <<= 2;
}
}
/* Process a text order */
static void
process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, BOOL delta)
{
int i;
if (present & 0x000001)
in_uint8(s, os->font);
if (present & 0x000002)
in_uint8(s, os->flags);
if (present & 0x000004)
in_uint8(s, os->unknown);
if (present & 0x000008)
in_uint8(s, os->mixmode);
if (present & 0x000010)
rdp_in_colour(s, &os->fgcolour);
if (present & 0x000020)
rdp_in_colour(s, &os->bgcolour);
if (present & 0x000040)
in_uint16_le(s, os->clipleft);
if (present & 0x000080)
in_uint16_le(s, os->cliptop);
if (present & 0x000100)
in_uint16_le(s, os->clipright);
if (present & 0x000200)
in_uint16_le(s, os->clipbottom);
if (present & 0x000400)
in_uint16_le(s, os->boxleft);
if (present & 0x000800)
in_uint16_le(s, os->boxtop);
if (present & 0x001000)
in_uint16_le(s, os->boxright);
if (present & 0x002000)
in_uint16_le(s, os->boxbottom);
if (present & 0x004000) /* fix for connecting to a server that */
in_uint8s(s, 10); /* was disconnected with mstsc.exe */
/* 0x008000, 0x020000, and 0x040000 are present too ??? */
if (present & 0x080000)
in_uint16_le(s, os->x);
if (present & 0x100000)
in_uint16_le(s, os->y);
if (present & 0x200000)
{
in_uint8(s, os->length);
in_uint8a(s, os->text, os->length);
}
DEBUG(("TEXT2(x=%d,y=%d,cl=%d,ct=%d,cr=%d,cb=%d,bl=%d,bt=%d,bb=%d,br=%d,fg=0x%x,bg=0x%x,font=%d,fl=0x%x,mix=%d,unk=0x%x,n=%d)\n", os->x, os->y, os->clipleft, os->cliptop, os->clipright, os->clipbottom, os->boxleft, os->boxtop, os->boxright, os->boxbottom, os->fgcolour, os->bgcolour, os->font, os->flags, os->mixmode, os->unknown, os->length));
DEBUG(("Text: "));
for (i = 0; i < os->length; i++)
DEBUG(("%02x ", os->text[i]));
DEBUG(("\n"));
ui_draw_text(os->font, os->flags, os->mixmode, os->x, os->y,
os->clipleft, os->cliptop,
os->clipright - os->clipleft,
os->clipbottom - os->cliptop,
os->boxleft, os->boxtop,
os->boxright - os->boxleft,
os->boxbottom - os->boxtop, os->bgcolour, os->fgcolour, os->text, os->length);
}
/* Process a raw bitmap cache order */
static void
process_raw_bmpcache(STREAM s)
{
HBITMAP bitmap;
uint16 cache_idx, bufsize;
uint8 cache_id, width, height, bpp, Bpp;
uint8 *data, *inverted;
int y;
in_uint8(s, cache_id);
in_uint8s(s, 1); /* pad */
in_uint8(s, width);
in_uint8(s, height);
in_uint8(s, bpp);
Bpp = (bpp + 7) / 8;
in_uint16_le(s, bufsize);
in_uint16_le(s, cache_idx);
in_uint8p(s, data, bufsize);
DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx));
inverted = xmalloc(width * height * Bpp);
for (y = 0; y < height; y++)
{
memcpy(&inverted[(height - y - 1) * (width * Bpp)], &data[y * (width * Bpp)],
width * Bpp);
}
bitmap = ui_create_bitmap(width, height, inverted);
xfree(inverted);
cache_put_bitmap(cache_id, cache_idx, bitmap);
}
/* Process a bitmap cache order */
static void
process_bmpcache(STREAM s)
{
HBITMAP bitmap;
uint16 cache_idx, size;
uint8 cache_id, width, height, bpp, Bpp;
uint8 *data, *bmpdata;
uint16 bufsize, pad2, row_size, final_size;
uint8 pad1;
in_uint8(s, cache_id);
in_uint8(s, pad1); /* pad */
in_uint8(s, width);
in_uint8(s, height);
in_uint8(s, bpp);
Bpp = (bpp + 7) / 8;
in_uint16_le(s, bufsize); /* bufsize */
in_uint16_le(s, cache_idx);
if (!use_rdp5) {
/* Begin compressedBitmapData */
in_uint16_le(s, pad2); /* pad */
in_uint16_le(s, size);
// in_uint8s(s, 4); /* row_size, final_size */
in_uint16_le(s, row_size);
in_uint16_le(s, final_size);
} else {
size = bufsize;
}
in_uint8p(s, data, size);
DEBUG(("BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d,bpp=%d,size=%d,pad1=%d,bufsize=%d,pad2=%d,rs=%d,fs=%d)\n",
width, height,
cache_id, cache_idx,
bpp, size, pad1, bufsize, pad2, row_size, final_size));
bmpdata = xmalloc(width * height * Bpp);
if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
{
bitmap = ui_create_bitmap(width, height, bmpdata);
cache_put_bitmap(cache_id, cache_idx, bitmap);
}
else
{
DEBUG(("Failed to decompress bitmap data\n"));
}
xfree(bmpdata);
}
/* Process a colourmap cache order */
static void
process_colcache(STREAM s)
{
COLOURENTRY *entry;
COLOURMAP map;
HCOLOURMAP hmap;
uint8 cache_id;
int i;
in_uint8(s, cache_id);
in_uint16_le(s, map.ncolours);
map.colours = xmalloc(3 * map.ncolours);
for (i = 0; i < map.ncolours; i++)
{
entry = &map.colours[i];
in_uint8(s, entry->blue);
in_uint8(s, entry->green);
in_uint8(s, entry->red);
in_uint8s(s, 1); /* pad */
}
DEBUG(("COLCACHE(id=%d,n=%d)\n", cache_id, map.ncolours));
hmap = ui_create_colourmap(&map);
ui_set_colourmap(hmap);
xfree(map.colours);
}
/* Process a font cache order */
static void
process_fontcache(STREAM s)
{
HGLYPH bitmap;
uint8 font, nglyphs;
uint16 character, offset, baseline, width, height;
int i, datasize;
uint8 *data;
in_uint8(s, font);
in_uint8(s, nglyphs);
DEBUG(("FONTCACHE(font=%d,n=%d)\n", font, nglyphs));
for (i = 0; i < nglyphs; i++)
{
in_uint16_le(s, character);
in_uint16_le(s, offset);
in_uint16_le(s, baseline);
in_uint16_le(s, width);
in_uint16_le(s, height);
datasize = (height * ((width + 7) / 8) + 3) & ~3;
in_uint8p(s, data, datasize);
bitmap = ui_create_glyph(width, height, data);
cache_put_font(font, character, offset, baseline, width, height, bitmap);
}
}
/* Process a secondary order */
static void
process_secondary_order(STREAM s)
{
uint16 length;
uint8 type;
uint8 *next_order;
in_uint16_le(s, length);
in_uint8s(s, 2); /* flags */
in_uint8(s, type);
next_order = s->p + length + 7;
switch (type)
{
case RDP_ORDER_RAW_BMPCACHE:
process_raw_bmpcache(s);
break;
case RDP_ORDER_COLCACHE:
process_colcache(s);
break;
case RDP_ORDER_BMPCACHE:
process_bmpcache(s);
break;
case RDP_ORDER_FONTCACHE:
process_fontcache(s);
break;
default:
unimpl("secondary order %d\n", type);
}
s->p = next_order;
}
/* Process an order PDU */
void
process_orders(STREAM s, uint16 num_orders)
{
RDP_ORDER_STATE *os = &order_state;
uint32 present;
uint8 order_flags;
int size, processed = 0;
BOOL delta;
while (processed < num_orders)
{
in_uint8(s, order_flags);
if (!(order_flags & RDP_ORDER_STANDARD))
{
error("order parsing failed\n");
break;
}
if (order_flags & RDP_ORDER_SECONDARY)
{
process_secondary_order(s);
}
else
{
if (order_flags & RDP_ORDER_CHANGE)
{
in_uint8(s, os->order_type);
}
switch (os->order_type)
{
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;
}
rdp_in_present(s, &present, order_flags, size);
if (order_flags & RDP_ORDER_BOUNDS)
{
if (!(order_flags & RDP_ORDER_LASTBOUNDS))
rdp_parse_bounds(s, &os->bounds);
ui_set_clip(os->bounds.left,
os->bounds.top,
os->bounds.right -
os->bounds.left + 1,
os->bounds.bottom - os->bounds.top + 1);
}
delta = order_flags & RDP_ORDER_DELTA;
switch (os->order_type)
{
case RDP_ORDER_DESTBLT:
process_destblt(s, &os->destblt, present, delta);
break;
case RDP_ORDER_PATBLT:
process_patblt(s, &os->patblt, present, delta);
break;
case RDP_ORDER_SCREENBLT:
process_screenblt(s, &os->screenblt, present, delta);
break;
case RDP_ORDER_LINE:
process_line(s, &os->line, present, delta);
break;
case RDP_ORDER_RECT:
process_rect(s, &os->rect, present, delta);
break;
case RDP_ORDER_DESKSAVE:
process_desksave(s, &os->desksave, present, delta);
break;
case RDP_ORDER_MEMBLT:
process_memblt(s, &os->memblt, present, delta);
break;
case RDP_ORDER_TRIBLT:
process_triblt(s, &os->triblt, present, delta);
break;
case RDP_ORDER_POLYLINE:
process_polyline(s, &os->polyline, present, delta);
break;
case RDP_ORDER_TEXT2:
process_text2(s, &os->text2, present, delta);
break;
default:
unimpl("order %d\n", os->order_type);
return;
}
if (order_flags & RDP_ORDER_BOUNDS)
ui_reset_clip();
}
processed++;
}
if (s->p != next_packet)
error("%d bytes remaining\n", (int) (next_packet - s->p));
}
/* Reset order state */
void
reset_order_state(void)
{
memset(&order_state, 0, sizeof(order_state));
order_state.order_type = RDP_ORDER_PATBLT;
}