~ubuntu-branches/ubuntu/feisty/rdesktop/feisty-proposed

« back to all changes in this revision

Viewing changes to orders.c

  • Committer: Bazaar Package Importer
  • Author(s): Sam Johnston
  • Date: 2004-02-04 17:52:26 UTC
  • Revision ID: james.westby@ubuntu.com-20040204175226-87kz4bzs1nimji68
Tags: upstream-1.3.1
ImportĀ upstreamĀ versionĀ 1.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- c-basic-offset: 8 -*-
 
2
   rdesktop: A Remote Desktop Protocol client.
 
3
   RDP order processing
 
4
   Copyright (C) Matthew Chapman 1999-2002
 
5
 
 
6
   This program is free software; you can redistribute it and/or modify
 
7
   it under the terms of the GNU General Public License as published by
 
8
   the Free Software Foundation; either version 2 of the License, or
 
9
   (at your option) any later version.
 
10
 
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program; if not, write to the Free Software
 
18
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
19
*/
 
20
 
 
21
#include "rdesktop.h"
 
22
#include "orders.h"
 
23
 
 
24
extern uint8 *g_next_packet;
 
25
static RDP_ORDER_STATE g_order_state;
 
26
extern BOOL g_use_rdp5;
 
27
 
 
28
/* Read field indicating which parameters are present */
 
29
static void
 
30
rdp_in_present(STREAM s, uint32 * present, uint8 flags, int size)
 
31
{
 
32
        uint8 bits;
 
33
        int i;
 
34
 
 
35
        if (flags & RDP_ORDER_SMALL)
 
36
        {
 
37
                size--;
 
38
        }
 
39
 
 
40
        if (flags & RDP_ORDER_TINY)
 
41
        {
 
42
                if (size < 2)
 
43
                        size = 0;
 
44
                else
 
45
                        size -= 2;
 
46
        }
 
47
 
 
48
        *present = 0;
 
49
        for (i = 0; i < size; i++)
 
50
        {
 
51
                in_uint8(s, bits);
 
52
                *present |= bits << (i * 8);
 
53
        }
 
54
}
 
55
 
 
56
/* Read a co-ordinate (16-bit, or 8-bit delta) */
 
57
static void
 
58
rdp_in_coord(STREAM s, sint16 * coord, BOOL delta)
 
59
{
 
60
        sint8 change;
 
61
 
 
62
        if (delta)
 
63
        {
 
64
                in_uint8(s, change);
 
65
                *coord += change;
 
66
        }
 
67
        else
 
68
        {
 
69
                in_uint16_le(s, *coord);
 
70
        }
 
71
}
 
72
 
 
73
/* Read a colour entry */
 
74
static void
 
75
rdp_in_colour(STREAM s, uint32 * colour)
 
76
{
 
77
        uint32 i;
 
78
        in_uint8(s, i);
 
79
        *colour = i;
 
80
        in_uint8(s, i);
 
81
        *colour |= i << 8;
 
82
        in_uint8(s, i);
 
83
        *colour |= i << 16;
 
84
}
 
85
 
 
86
/* Parse bounds information */
 
87
static BOOL
 
88
rdp_parse_bounds(STREAM s, BOUNDS * bounds)
 
89
{
 
90
        uint8 present;
 
91
 
 
92
        in_uint8(s, present);
 
93
 
 
94
        if (present & 1)
 
95
                rdp_in_coord(s, &bounds->left, False);
 
96
        else if (present & 16)
 
97
                rdp_in_coord(s, &bounds->left, True);
 
98
 
 
99
        if (present & 2)
 
100
                rdp_in_coord(s, &bounds->top, False);
 
101
        else if (present & 32)
 
102
                rdp_in_coord(s, &bounds->top, True);
 
103
 
 
104
        if (present & 4)
 
105
                rdp_in_coord(s, &bounds->right, False);
 
106
        else if (present & 64)
 
107
                rdp_in_coord(s, &bounds->right, True);
 
108
 
 
109
        if (present & 8)
 
110
                rdp_in_coord(s, &bounds->bottom, False);
 
111
        else if (present & 128)
 
112
                rdp_in_coord(s, &bounds->bottom, True);
 
113
 
 
114
        return s_check(s);
 
115
}
 
116
 
 
117
/* Parse a pen */
 
118
static BOOL
 
119
rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
 
120
{
 
121
        if (present & 1)
 
122
                in_uint8(s, pen->style);
 
123
 
 
124
        if (present & 2)
 
125
                in_uint8(s, pen->width);
 
126
 
 
127
        if (present & 4)
 
128
                rdp_in_colour(s, &pen->colour);
 
129
 
 
130
        return s_check(s);
 
131
}
 
132
 
 
133
/* Parse a brush */
 
134
static BOOL
 
135
rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
 
136
{
 
137
        if (present & 1)
 
138
                in_uint8(s, brush->xorigin);
 
139
 
 
140
        if (present & 2)
 
141
                in_uint8(s, brush->yorigin);
 
142
 
 
143
        if (present & 4)
 
144
                in_uint8(s, brush->style);
 
145
 
 
146
        if (present & 8)
 
147
                in_uint8(s, brush->pattern[0]);
 
148
 
 
149
        if (present & 16)
 
150
                in_uint8a(s, &brush->pattern[1], 7);
 
151
 
 
152
        return s_check(s);
 
153
}
 
154
 
 
155
/* Process a destination blt order */
 
156
static void
 
157
process_destblt(STREAM s, DESTBLT_ORDER * os, uint32 present, BOOL delta)
 
158
{
 
159
        if (present & 0x01)
 
160
                rdp_in_coord(s, &os->x, delta);
 
161
 
 
162
        if (present & 0x02)
 
163
                rdp_in_coord(s, &os->y, delta);
 
164
 
 
165
        if (present & 0x04)
 
166
                rdp_in_coord(s, &os->cx, delta);
 
167
 
 
168
        if (present & 0x08)
 
169
                rdp_in_coord(s, &os->cy, delta);
 
170
 
 
171
        if (present & 0x10)
 
172
                in_uint8(s, os->opcode);
 
173
 
 
174
        DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n",
 
175
               os->opcode, os->x, os->y, os->cx, os->cy));
 
176
 
 
177
        ui_destblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy);
 
178
}
 
179
 
 
180
/* Process a pattern blt order */
 
181
static void
 
182
process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, BOOL delta)
 
183
{
 
184
        if (present & 0x0001)
 
185
                rdp_in_coord(s, &os->x, delta);
 
186
 
 
187
        if (present & 0x0002)
 
188
                rdp_in_coord(s, &os->y, delta);
 
189
 
 
190
        if (present & 0x0004)
 
191
                rdp_in_coord(s, &os->cx, delta);
 
192
 
 
193
        if (present & 0x0008)
 
194
                rdp_in_coord(s, &os->cy, delta);
 
195
 
 
196
        if (present & 0x0010)
 
197
                in_uint8(s, os->opcode);
 
198
 
 
199
        if (present & 0x0020)
 
200
                rdp_in_colour(s, &os->bgcolour);
 
201
 
 
202
        if (present & 0x0040)
 
203
                rdp_in_colour(s, &os->fgcolour);
 
204
 
 
205
        rdp_parse_brush(s, &os->brush, present >> 7);
 
206
 
 
207
        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,
 
208
               os->y, os->cx, os->cy, os->brush.style, os->bgcolour, os->fgcolour));
 
209
 
 
210
        ui_patblt(ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy,
 
211
                  &os->brush, os->bgcolour, os->fgcolour);
 
212
}
 
213
 
 
214
/* Process a screen blt order */
 
215
static void
 
216
process_screenblt(STREAM s, SCREENBLT_ORDER * os, uint32 present, BOOL delta)
 
217
{
 
218
        if (present & 0x0001)
 
219
                rdp_in_coord(s, &os->x, delta);
 
220
 
 
221
        if (present & 0x0002)
 
222
                rdp_in_coord(s, &os->y, delta);
 
223
 
 
224
        if (present & 0x0004)
 
225
                rdp_in_coord(s, &os->cx, delta);
 
226
 
 
227
        if (present & 0x0008)
 
228
                rdp_in_coord(s, &os->cy, delta);
 
229
 
 
230
        if (present & 0x0010)
 
231
                in_uint8(s, os->opcode);
 
232
 
 
233
        if (present & 0x0020)
 
234
                rdp_in_coord(s, &os->srcx, delta);
 
235
 
 
236
        if (present & 0x0040)
 
237
                rdp_in_coord(s, &os->srcy, delta);
 
238
 
 
239
        DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n",
 
240
               os->opcode, os->x, os->y, os->cx, os->cy, os->srcx, os->srcy));
 
241
 
 
242
        ui_screenblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, os->srcx, os->srcy);
 
243
}
 
244
 
 
245
/* Process a line order */
 
246
static void
 
247
process_line(STREAM s, LINE_ORDER * os, uint32 present, BOOL delta)
 
248
{
 
249
        if (present & 0x0001)
 
250
                in_uint16_le(s, os->mixmode);
 
251
 
 
252
        if (present & 0x0002)
 
253
                rdp_in_coord(s, &os->startx, delta);
 
254
 
 
255
        if (present & 0x0004)
 
256
                rdp_in_coord(s, &os->starty, delta);
 
257
 
 
258
        if (present & 0x0008)
 
259
                rdp_in_coord(s, &os->endx, delta);
 
260
 
 
261
        if (present & 0x0010)
 
262
                rdp_in_coord(s, &os->endy, delta);
 
263
 
 
264
        if (present & 0x0020)
 
265
                rdp_in_colour(s, &os->bgcolour);
 
266
 
 
267
        if (present & 0x0040)
 
268
                in_uint8(s, os->opcode);
 
269
 
 
270
        rdp_parse_pen(s, &os->pen, present >> 7);
 
271
 
 
272
        DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dx=%d,fg=0x%x)\n",
 
273
               os->opcode, os->startx, os->starty, os->endx, os->endy, os->pen.colour));
 
274
 
 
275
        if (os->opcode < 0x01 || os->opcode > 0x10)
 
276
        {
 
277
                error("bad ROP2 0x%x\n", os->opcode);
 
278
                return;
 
279
        }
 
280
 
 
281
        ui_line(os->opcode - 1, os->startx, os->starty, os->endx, os->endy, &os->pen);
 
282
}
 
283
 
 
284
/* Process an opaque rectangle order */
 
285
static void
 
286
process_rect(STREAM s, RECT_ORDER * os, uint32 present, BOOL delta)
 
287
{
 
288
        uint32 i;
 
289
        if (present & 0x01)
 
290
                rdp_in_coord(s, &os->x, delta);
 
291
 
 
292
        if (present & 0x02)
 
293
                rdp_in_coord(s, &os->y, delta);
 
294
 
 
295
        if (present & 0x04)
 
296
                rdp_in_coord(s, &os->cx, delta);
 
297
 
 
298
        if (present & 0x08)
 
299
                rdp_in_coord(s, &os->cy, delta);
 
300
 
 
301
        if (present & 0x10)
 
302
        {
 
303
                in_uint8(s, i);
 
304
                os->colour = (os->colour & 0xffffff00) | i;
 
305
        }
 
306
 
 
307
        if (present & 0x20)
 
308
        {
 
309
                in_uint8(s, i);
 
310
                os->colour = (os->colour & 0xffff00ff) | (i << 8);
 
311
        }
 
312
 
 
313
        if (present & 0x40)
 
314
        {
 
315
                in_uint8(s, i);
 
316
                os->colour = (os->colour & 0xff00ffff) | (i << 16);
 
317
        }
 
318
 
 
319
        DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os->x, os->y, os->cx, os->cy, os->colour));
 
320
 
 
321
        ui_rect(os->x, os->y, os->cx, os->cy, os->colour);
 
322
}
 
323
 
 
324
/* Process a desktop save order */
 
325
static void
 
326
process_desksave(STREAM s, DESKSAVE_ORDER * os, uint32 present, BOOL delta)
 
327
{
 
328
        int width, height;
 
329
 
 
330
        if (present & 0x01)
 
331
                in_uint32_le(s, os->offset);
 
332
 
 
333
        if (present & 0x02)
 
334
                rdp_in_coord(s, &os->left, delta);
 
335
 
 
336
        if (present & 0x04)
 
337
                rdp_in_coord(s, &os->top, delta);
 
338
 
 
339
        if (present & 0x08)
 
340
                rdp_in_coord(s, &os->right, delta);
 
341
 
 
342
        if (present & 0x10)
 
343
                rdp_in_coord(s, &os->bottom, delta);
 
344
 
 
345
        if (present & 0x20)
 
346
                in_uint8(s, os->action);
 
347
 
 
348
        DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n",
 
349
               os->left, os->top, os->right, os->bottom, os->offset, os->action));
 
350
 
 
351
        width = os->right - os->left + 1;
 
352
        height = os->bottom - os->top + 1;
 
353
 
 
354
        if (os->action == 0)
 
355
                ui_desktop_save(os->offset, os->left, os->top, width, height);
 
356
        else
 
357
                ui_desktop_restore(os->offset, os->left, os->top, width, height);
 
358
}
 
359
 
 
360
/* Process a memory blt order */
 
361
static void
 
362
process_memblt(STREAM s, MEMBLT_ORDER * os, uint32 present, BOOL delta)
 
363
{
 
364
        HBITMAP bitmap;
 
365
 
 
366
        if (present & 0x0001)
 
367
        {
 
368
                in_uint8(s, os->cache_id);
 
369
                in_uint8(s, os->colour_table);
 
370
        }
 
371
 
 
372
        if (present & 0x0002)
 
373
                rdp_in_coord(s, &os->x, delta);
 
374
 
 
375
        if (present & 0x0004)
 
376
                rdp_in_coord(s, &os->y, delta);
 
377
 
 
378
        if (present & 0x0008)
 
379
                rdp_in_coord(s, &os->cx, delta);
 
380
 
 
381
        if (present & 0x0010)
 
382
                rdp_in_coord(s, &os->cy, delta);
 
383
 
 
384
        if (present & 0x0020)
 
385
                in_uint8(s, os->opcode);
 
386
 
 
387
        if (present & 0x0040)
 
388
                rdp_in_coord(s, &os->srcx, delta);
 
389
 
 
390
        if (present & 0x0080)
 
391
                rdp_in_coord(s, &os->srcy, delta);
 
392
 
 
393
        if (present & 0x0100)
 
394
                in_uint16_le(s, os->cache_idx);
 
395
 
 
396
        DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n",
 
397
               os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx));
 
398
 
 
399
        bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
 
400
        if (bitmap == NULL)
 
401
                return;
 
402
 
 
403
        ui_memblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, bitmap, os->srcx, os->srcy);
 
404
}
 
405
 
 
406
/* Process a 3-way blt order */
 
407
static void
 
408
process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, BOOL delta)
 
409
{
 
410
        HBITMAP bitmap;
 
411
 
 
412
        if (present & 0x000001)
 
413
        {
 
414
                in_uint8(s, os->cache_id);
 
415
                in_uint8(s, os->colour_table);
 
416
        }
 
417
 
 
418
        if (present & 0x000002)
 
419
                rdp_in_coord(s, &os->x, delta);
 
420
 
 
421
        if (present & 0x000004)
 
422
                rdp_in_coord(s, &os->y, delta);
 
423
 
 
424
        if (present & 0x000008)
 
425
                rdp_in_coord(s, &os->cx, delta);
 
426
 
 
427
        if (present & 0x000010)
 
428
                rdp_in_coord(s, &os->cy, delta);
 
429
 
 
430
        if (present & 0x000020)
 
431
                in_uint8(s, os->opcode);
 
432
 
 
433
        if (present & 0x000040)
 
434
                rdp_in_coord(s, &os->srcx, delta);
 
435
 
 
436
        if (present & 0x000080)
 
437
                rdp_in_coord(s, &os->srcy, delta);
 
438
 
 
439
        if (present & 0x000100)
 
440
                rdp_in_colour(s, &os->bgcolour);
 
441
 
 
442
        if (present & 0x000200)
 
443
                rdp_in_colour(s, &os->fgcolour);
 
444
 
 
445
        rdp_parse_brush(s, &os->brush, present >> 10);
 
446
 
 
447
        if (present & 0x008000)
 
448
                in_uint16_le(s, os->cache_idx);
 
449
 
 
450
        if (present & 0x010000)
 
451
                in_uint16_le(s, os->unknown);
 
452
 
 
453
        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",
 
454
               os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx,
 
455
               os->brush.style, os->bgcolour, os->fgcolour));
 
456
 
 
457
        bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
 
458
        if (bitmap == NULL)
 
459
                return;
 
460
 
 
461
        ui_triblt(os->opcode, os->x, os->y, os->cx, os->cy,
 
462
                  bitmap, os->srcx, os->srcy, &os->brush, os->bgcolour, os->fgcolour);
 
463
}
 
464
 
 
465
/* Parse a delta co-ordinate in polyline order form */
 
466
static int
 
467
parse_delta(uint8 * buffer, int *offset)
 
468
{
 
469
        int value = buffer[(*offset)++];
 
470
        int two_byte = value & 0x80;
 
471
 
 
472
        if (value & 0x40)       /* sign bit */
 
473
                value |= ~0x3f;
 
474
        else
 
475
                value &= 0x3f;
 
476
 
 
477
        if (two_byte)
 
478
                value = (value << 8) | buffer[(*offset)++];
 
479
 
 
480
        return value;
 
481
}
 
482
 
 
483
/* Process a polyline order */
 
484
static void
 
485
process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, BOOL delta)
 
486
{
 
487
        int index, line, data;
 
488
        int x, y, xfrom, yfrom;
 
489
        uint8 flags = 0;
 
490
        PEN pen;
 
491
        uint8 opcode;
 
492
 
 
493
        if (present & 0x01)
 
494
                rdp_in_coord(s, &os->x, delta);
 
495
 
 
496
        if (present & 0x02)
 
497
                rdp_in_coord(s, &os->y, delta);
 
498
 
 
499
        if (present & 0x04)
 
500
                in_uint8(s, os->opcode);
 
501
 
 
502
        if (present & 0x10)
 
503
                rdp_in_colour(s, &os->fgcolour);
 
504
 
 
505
        if (present & 0x20)
 
506
                in_uint8(s, os->lines);
 
507
 
 
508
        if (present & 0x40)
 
509
        {
 
510
                in_uint8(s, os->datasize);
 
511
                in_uint8a(s, os->data, os->datasize);
 
512
        }
 
513
 
 
514
        DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n",
 
515
               os->x, os->y, os->opcode, os->fgcolour, os->lines, os->datasize));
 
516
 
 
517
        DEBUG(("Data: "));
 
518
 
 
519
        for (index = 0; index < os->datasize; index++)
 
520
                DEBUG(("%02x ", os->data[index]));
 
521
 
 
522
        DEBUG(("\n"));
 
523
 
 
524
        if (os->opcode < 0x01 || os->opcode > 0x10)
 
525
        {
 
526
                error("bad ROP2 0x%x\n", os->opcode);
 
527
                return;
 
528
        }
 
529
 
 
530
        opcode = os->opcode - 1;
 
531
        x = os->x;
 
532
        y = os->y;
 
533
        pen.style = pen.width = 0;
 
534
        pen.colour = os->fgcolour;
 
535
 
 
536
        index = 0;
 
537
        data = ((os->lines - 1) / 4) + 1;
 
538
        for (line = 0; (line < os->lines) && (data < os->datasize); line++)
 
539
        {
 
540
                xfrom = x;
 
541
                yfrom = y;
 
542
 
 
543
                if (line % 4 == 0)
 
544
                        flags = os->data[index++];
 
545
 
 
546
                if ((flags & 0xc0) == 0)
 
547
                        flags |= 0xc0;  /* none = both */
 
548
 
 
549
                if (flags & 0x40)
 
550
                        x += parse_delta(os->data, &data);
 
551
 
 
552
                if (flags & 0x80)
 
553
                        y += parse_delta(os->data, &data);
 
554
 
 
555
                ui_line(opcode, xfrom, yfrom, x, y, &pen);
 
556
 
 
557
                flags <<= 2;
 
558
        }
 
559
}
 
560
 
 
561
/* Process a text order */
 
562
static void
 
563
process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, BOOL delta)
 
564
{
 
565
        int i;
 
566
 
 
567
        if (present & 0x000001)
 
568
                in_uint8(s, os->font);
 
569
 
 
570
        if (present & 0x000002)
 
571
                in_uint8(s, os->flags);
 
572
 
 
573
        if (present & 0x000004)
 
574
                in_uint8(s, os->unknown);
 
575
 
 
576
        if (present & 0x000008)
 
577
                in_uint8(s, os->mixmode);
 
578
 
 
579
        if (present & 0x000010)
 
580
                rdp_in_colour(s, &os->fgcolour);
 
581
 
 
582
        if (present & 0x000020)
 
583
                rdp_in_colour(s, &os->bgcolour);
 
584
 
 
585
        if (present & 0x000040)
 
586
                in_uint16_le(s, os->clipleft);
 
587
 
 
588
        if (present & 0x000080)
 
589
                in_uint16_le(s, os->cliptop);
 
590
 
 
591
        if (present & 0x000100)
 
592
                in_uint16_le(s, os->clipright);
 
593
 
 
594
        if (present & 0x000200)
 
595
                in_uint16_le(s, os->clipbottom);
 
596
 
 
597
        if (present & 0x000400)
 
598
                in_uint16_le(s, os->boxleft);
 
599
 
 
600
        if (present & 0x000800)
 
601
                in_uint16_le(s, os->boxtop);
 
602
 
 
603
        if (present & 0x001000)
 
604
                in_uint16_le(s, os->boxright);
 
605
 
 
606
        if (present & 0x002000)
 
607
                in_uint16_le(s, os->boxbottom);
 
608
 
 
609
        if (present & 0x004000) /* fix for connecting to a server that */
 
610
                in_uint8s(s, 10);       /* was disconnected with mstsc.exe */
 
611
        /* 0x008000, 0x020000, and 0x040000 are present too ??? */
 
612
 
 
613
        if (present & 0x080000)
 
614
                in_uint16_le(s, os->x);
 
615
 
 
616
        if (present & 0x100000)
 
617
                in_uint16_le(s, os->y);
 
618
 
 
619
        if (present & 0x200000)
 
620
        {
 
621
                in_uint8(s, os->length);
 
622
                in_uint8a(s, os->text, os->length);
 
623
        }
 
624
 
 
625
        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));
 
626
 
 
627
        DEBUG(("Text: "));
 
628
 
 
629
        for (i = 0; i < os->length; i++)
 
630
                DEBUG(("%02x ", os->text[i]));
 
631
 
 
632
        DEBUG(("\n"));
 
633
 
 
634
        ui_draw_text(os->font, os->flags, os->mixmode, os->x, os->y,
 
635
                     os->clipleft, os->cliptop,
 
636
                     os->clipright - os->clipleft,
 
637
                     os->clipbottom - os->cliptop,
 
638
                     os->boxleft, os->boxtop,
 
639
                     os->boxright - os->boxleft,
 
640
                     os->boxbottom - os->boxtop, os->bgcolour, os->fgcolour, os->text, os->length);
 
641
}
 
642
 
 
643
/* Process a raw bitmap cache order */
 
644
static void
 
645
process_raw_bmpcache(STREAM s)
 
646
{
 
647
        HBITMAP bitmap;
 
648
        uint16 cache_idx, bufsize;
 
649
        uint8 cache_id, width, height, bpp, Bpp;
 
650
        uint8 *data, *inverted;
 
651
        int y;
 
652
 
 
653
        in_uint8(s, cache_id);
 
654
        in_uint8s(s, 1);        /* pad */
 
655
        in_uint8(s, width);
 
656
        in_uint8(s, height);
 
657
        in_uint8(s, bpp);
 
658
        Bpp = (bpp + 7) / 8;
 
659
        in_uint16_le(s, bufsize);
 
660
        in_uint16_le(s, cache_idx);
 
661
        in_uint8p(s, data, bufsize);
 
662
 
 
663
        DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx));
 
664
        inverted = (uint8 *) xmalloc(width * height * Bpp);
 
665
        for (y = 0; y < height; y++)
 
666
        {
 
667
                memcpy(&inverted[(height - y - 1) * (width * Bpp)], &data[y * (width * Bpp)],
 
668
                       width * Bpp);
 
669
        }
 
670
 
 
671
        bitmap = ui_create_bitmap(width, height, inverted);
 
672
        xfree(inverted);
 
673
        cache_put_bitmap(cache_id, cache_idx, bitmap);
 
674
}
 
675
 
 
676
/* Process a bitmap cache order */
 
677
static void
 
678
process_bmpcache(STREAM s)
 
679
{
 
680
        HBITMAP bitmap;
 
681
        uint16 cache_idx, size;
 
682
        uint8 cache_id, width, height, bpp, Bpp;
 
683
        uint8 *data, *bmpdata;
 
684
        uint16 bufsize, pad2, row_size, final_size;
 
685
        uint8 pad1;
 
686
 
 
687
        pad2 = row_size = final_size = 0xffff;  /* Shut the compiler up */
 
688
 
 
689
        in_uint8(s, cache_id);
 
690
        in_uint8(s, pad1);      /* pad */
 
691
        in_uint8(s, width);
 
692
        in_uint8(s, height);
 
693
        in_uint8(s, bpp);
 
694
        Bpp = (bpp + 7) / 8;
 
695
        in_uint16_le(s, bufsize);       /* bufsize */
 
696
        in_uint16_le(s, cache_idx);
 
697
 
 
698
        if (!g_use_rdp5)
 
699
        {
 
700
 
 
701
                /* Begin compressedBitmapData */
 
702
                in_uint16_le(s, pad2);  /* pad */
 
703
                in_uint16_le(s, size);
 
704
                /*      in_uint8s(s, 4);  *//* row_size, final_size */
 
705
                in_uint16_le(s, row_size);
 
706
                in_uint16_le(s, final_size);
 
707
 
 
708
        }
 
709
        else
 
710
        {
 
711
                size = bufsize;
 
712
        }
 
713
        in_uint8p(s, data, size);
 
714
 
 
715
        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));
 
716
 
 
717
        bmpdata = (uint8 *) xmalloc(width * height * Bpp);
 
718
 
 
719
        if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
 
720
        {
 
721
                bitmap = ui_create_bitmap(width, height, bmpdata);
 
722
                cache_put_bitmap(cache_id, cache_idx, bitmap);
 
723
        }
 
724
        else
 
725
        {
 
726
                DEBUG(("Failed to decompress bitmap data\n"));
 
727
        }
 
728
 
 
729
        xfree(bmpdata);
 
730
}
 
731
 
 
732
/* Process a colourmap cache order */
 
733
static void
 
734
process_colcache(STREAM s)
 
735
{
 
736
        COLOURENTRY *entry;
 
737
        COLOURMAP map;
 
738
        HCOLOURMAP hmap;
 
739
        uint8 cache_id;
 
740
        int i;
 
741
 
 
742
        in_uint8(s, cache_id);
 
743
        in_uint16_le(s, map.ncolours);
 
744
 
 
745
        map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
 
746
 
 
747
        for (i = 0; i < map.ncolours; i++)
 
748
        {
 
749
                entry = &map.colours[i];
 
750
                in_uint8(s, entry->blue);
 
751
                in_uint8(s, entry->green);
 
752
                in_uint8(s, entry->red);
 
753
                in_uint8s(s, 1);        /* pad */
 
754
        }
 
755
 
 
756
        DEBUG(("COLCACHE(id=%d,n=%d)\n", cache_id, map.ncolours));
 
757
 
 
758
        hmap = ui_create_colourmap(&map);
 
759
        ui_set_colourmap(hmap);
 
760
 
 
761
        xfree(map.colours);
 
762
}
 
763
 
 
764
/* Process a font cache order */
 
765
static void
 
766
process_fontcache(STREAM s)
 
767
{
 
768
        HGLYPH bitmap;
 
769
        uint8 font, nglyphs;
 
770
        uint16 character, offset, baseline, width, height;
 
771
        int i, datasize;
 
772
        uint8 *data;
 
773
 
 
774
        in_uint8(s, font);
 
775
        in_uint8(s, nglyphs);
 
776
 
 
777
        DEBUG(("FONTCACHE(font=%d,n=%d)\n", font, nglyphs));
 
778
 
 
779
        for (i = 0; i < nglyphs; i++)
 
780
        {
 
781
                in_uint16_le(s, character);
 
782
                in_uint16_le(s, offset);
 
783
                in_uint16_le(s, baseline);
 
784
                in_uint16_le(s, width);
 
785
                in_uint16_le(s, height);
 
786
 
 
787
                datasize = (height * ((width + 7) / 8) + 3) & ~3;
 
788
                in_uint8p(s, data, datasize);
 
789
 
 
790
                bitmap = ui_create_glyph(width, height, data);
 
791
                cache_put_font(font, character, offset, baseline, width, height, bitmap);
 
792
        }
 
793
}
 
794
 
 
795
/* Process a secondary order */
 
796
static void
 
797
process_secondary_order(STREAM s)
 
798
{
 
799
        uint16 length;
 
800
        uint8 type;
 
801
        uint8 *next_order;
 
802
 
 
803
        in_uint16_le(s, length);
 
804
        in_uint8s(s, 2);        /* flags */
 
805
        in_uint8(s, type);
 
806
 
 
807
        next_order = s->p + length + 7;
 
808
 
 
809
        switch (type)
 
810
        {
 
811
                case RDP_ORDER_RAW_BMPCACHE:
 
812
                        process_raw_bmpcache(s);
 
813
                        break;
 
814
 
 
815
                case RDP_ORDER_COLCACHE:
 
816
                        process_colcache(s);
 
817
                        break;
 
818
 
 
819
                case RDP_ORDER_BMPCACHE:
 
820
                        process_bmpcache(s);
 
821
                        break;
 
822
 
 
823
                case RDP_ORDER_FONTCACHE:
 
824
                        process_fontcache(s);
 
825
                        break;
 
826
 
 
827
                default:
 
828
                        unimpl("secondary order %d\n", type);
 
829
        }
 
830
 
 
831
        s->p = next_order;
 
832
}
 
833
 
 
834
/* Process an order PDU */
 
835
void
 
836
process_orders(STREAM s, uint16 num_orders)
 
837
{
 
838
        RDP_ORDER_STATE *os = &g_order_state;
 
839
        uint32 present;
 
840
        uint8 order_flags;
 
841
        int size, processed = 0;
 
842
        BOOL delta;
 
843
 
 
844
        while (processed < num_orders)
 
845
        {
 
846
                in_uint8(s, order_flags);
 
847
 
 
848
                if (!(order_flags & RDP_ORDER_STANDARD))
 
849
                {
 
850
                        error("order parsing failed\n");
 
851
                        break;
 
852
                }
 
853
 
 
854
                if (order_flags & RDP_ORDER_SECONDARY)
 
855
                {
 
856
                        process_secondary_order(s);
 
857
                }
 
858
                else
 
859
                {
 
860
                        if (order_flags & RDP_ORDER_CHANGE)
 
861
                        {
 
862
                                in_uint8(s, os->order_type);
 
863
                        }
 
864
 
 
865
                        switch (os->order_type)
 
866
                        {
 
867
                                case RDP_ORDER_TRIBLT:
 
868
                                case RDP_ORDER_TEXT2:
 
869
                                        size = 3;
 
870
                                        break;
 
871
 
 
872
                                case RDP_ORDER_PATBLT:
 
873
                                case RDP_ORDER_MEMBLT:
 
874
                                case RDP_ORDER_LINE:
 
875
                                        size = 2;
 
876
                                        break;
 
877
 
 
878
                                default:
 
879
                                        size = 1;
 
880
                        }
 
881
 
 
882
                        rdp_in_present(s, &present, order_flags, size);
 
883
 
 
884
                        if (order_flags & RDP_ORDER_BOUNDS)
 
885
                        {
 
886
                                if (!(order_flags & RDP_ORDER_LASTBOUNDS))
 
887
                                        rdp_parse_bounds(s, &os->bounds);
 
888
 
 
889
                                ui_set_clip(os->bounds.left,
 
890
                                            os->bounds.top,
 
891
                                            os->bounds.right -
 
892
                                            os->bounds.left + 1,
 
893
                                            os->bounds.bottom - os->bounds.top + 1);
 
894
                        }
 
895
 
 
896
                        delta = order_flags & RDP_ORDER_DELTA;
 
897
 
 
898
                        switch (os->order_type)
 
899
                        {
 
900
                                case RDP_ORDER_DESTBLT:
 
901
                                        process_destblt(s, &os->destblt, present, delta);
 
902
                                        break;
 
903
 
 
904
                                case RDP_ORDER_PATBLT:
 
905
                                        process_patblt(s, &os->patblt, present, delta);
 
906
                                        break;
 
907
 
 
908
                                case RDP_ORDER_SCREENBLT:
 
909
                                        process_screenblt(s, &os->screenblt, present, delta);
 
910
                                        break;
 
911
 
 
912
                                case RDP_ORDER_LINE:
 
913
                                        process_line(s, &os->line, present, delta);
 
914
                                        break;
 
915
 
 
916
                                case RDP_ORDER_RECT:
 
917
                                        process_rect(s, &os->rect, present, delta);
 
918
                                        break;
 
919
 
 
920
                                case RDP_ORDER_DESKSAVE:
 
921
                                        process_desksave(s, &os->desksave, present, delta);
 
922
                                        break;
 
923
 
 
924
                                case RDP_ORDER_MEMBLT:
 
925
                                        process_memblt(s, &os->memblt, present, delta);
 
926
                                        break;
 
927
 
 
928
                                case RDP_ORDER_TRIBLT:
 
929
                                        process_triblt(s, &os->triblt, present, delta);
 
930
                                        break;
 
931
 
 
932
                                case RDP_ORDER_POLYLINE:
 
933
                                        process_polyline(s, &os->polyline, present, delta);
 
934
                                        break;
 
935
 
 
936
                                case RDP_ORDER_TEXT2:
 
937
                                        process_text2(s, &os->text2, present, delta);
 
938
                                        break;
 
939
 
 
940
                                default:
 
941
                                        unimpl("order %d\n", os->order_type);
 
942
                                        return;
 
943
                        }
 
944
 
 
945
                        if (order_flags & RDP_ORDER_BOUNDS)
 
946
                                ui_reset_clip();
 
947
                }
 
948
 
 
949
                processed++;
 
950
        }
 
951
 
 
952
        if (s->p != g_next_packet)
 
953
                error("%d bytes remaining\n", (int) (g_next_packet - s->p));
 
954
}
 
955
 
 
956
/* Reset order state */
 
957
void
 
958
reset_order_state(void)
 
959
{
 
960
        memset(&g_order_state, 0, sizeof(g_order_state));
 
961
        g_order_state.order_type = RDP_ORDER_PATBLT;
 
962
}