/[rdesktop]/sourceforge.net/trunk/rdesktop/orders.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /sourceforge.net/trunk/rdesktop/orders.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1474 - (show annotations)
Fri Jul 11 03:35:24 2008 UTC (15 years, 9 months ago) by jsorg71
File MIME type: text/plain
File size: 30570 byte(s)
added brush cache

1 /* -*- c-basic-offset: 8 -*-
2 rdesktop: A Remote Desktop Protocol client.
3 RDP order processing
4 Copyright (C) Matthew Chapman 1999-2007
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 RD_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, RD_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 /* Parse a delta co-ordinate in polyline/polygon order form */
74 static int
75 parse_delta(uint8 * buffer, int *offset)
76 {
77 int value = buffer[(*offset)++];
78 int two_byte = value & 0x80;
79
80 if (value & 0x40) /* sign bit */
81 value |= ~0x3f;
82 else
83 value &= 0x3f;
84
85 if (two_byte)
86 value = (value << 8) | buffer[(*offset)++];
87
88 return value;
89 }
90
91 /* Read a colour entry */
92 static void
93 rdp_in_colour(STREAM s, uint32 * colour)
94 {
95 uint32 i;
96 in_uint8(s, i);
97 *colour = i;
98 in_uint8(s, i);
99 *colour |= i << 8;
100 in_uint8(s, i);
101 *colour |= i << 16;
102 }
103
104 /* Parse bounds information */
105 static RD_BOOL
106 rdp_parse_bounds(STREAM s, BOUNDS * bounds)
107 {
108 uint8 present;
109
110 in_uint8(s, present);
111
112 if (present & 1)
113 rdp_in_coord(s, &bounds->left, False);
114 else if (present & 16)
115 rdp_in_coord(s, &bounds->left, True);
116
117 if (present & 2)
118 rdp_in_coord(s, &bounds->top, False);
119 else if (present & 32)
120 rdp_in_coord(s, &bounds->top, True);
121
122 if (present & 4)
123 rdp_in_coord(s, &bounds->right, False);
124 else if (present & 64)
125 rdp_in_coord(s, &bounds->right, True);
126
127 if (present & 8)
128 rdp_in_coord(s, &bounds->bottom, False);
129 else if (present & 128)
130 rdp_in_coord(s, &bounds->bottom, True);
131
132 return s_check(s);
133 }
134
135 /* Parse a pen */
136 static RD_BOOL
137 rdp_parse_pen(STREAM s, PEN * pen, uint32 present)
138 {
139 if (present & 1)
140 in_uint8(s, pen->style);
141
142 if (present & 2)
143 in_uint8(s, pen->width);
144
145 if (present & 4)
146 rdp_in_colour(s, &pen->colour);
147
148 return s_check(s);
149 }
150
151 static void
152 setup_brush(BRUSH * out_brush, BRUSH * in_brush)
153 {
154 BRUSHDATA * brush_data;
155 uint16 cache_idx;
156 uint8 brush_bpp;
157
158 memcpy(out_brush, in_brush, sizeof(BRUSH));
159 if (out_brush->style & 0x80)
160 {
161 brush_bpp = out_brush->style & 0x0f;
162 if (brush_bpp == 1) /* 1 bpp */
163 {
164 cache_idx = out_brush->pattern[0];
165 brush_data = cache_get_brush_data(cache_idx);
166 if (brush_data == NULL)
167 {
168 error("error getting brush data, style %x\n", out_brush->style);
169 }
170 else
171 {
172 memcpy(out_brush->pattern, brush_data->pattern,
173 sizeof(out_brush->pattern));
174 }
175 }
176 else
177 {
178 error("bad brush bpp %d\n", brush_bpp);
179 }
180 out_brush->style = 3;
181 }
182 }
183
184 /* Parse a brush */
185 static RD_BOOL
186 rdp_parse_brush(STREAM s, BRUSH * brush, uint32 present)
187 {
188 if (present & 1)
189 in_uint8(s, brush->xorigin);
190
191 if (present & 2)
192 in_uint8(s, brush->yorigin);
193
194 if (present & 4)
195 in_uint8(s, brush->style);
196
197 if (present & 8)
198 in_uint8(s, brush->pattern[0]);
199
200 if (present & 16)
201 in_uint8a(s, &brush->pattern[1], 7);
202
203 return s_check(s);
204 }
205
206 /* Process a destination blt order */
207 static void
208 process_destblt(STREAM s, DESTBLT_ORDER * os, uint32 present, RD_BOOL delta)
209 {
210 if (present & 0x01)
211 rdp_in_coord(s, &os->x, delta);
212
213 if (present & 0x02)
214 rdp_in_coord(s, &os->y, delta);
215
216 if (present & 0x04)
217 rdp_in_coord(s, &os->cx, delta);
218
219 if (present & 0x08)
220 rdp_in_coord(s, &os->cy, delta);
221
222 if (present & 0x10)
223 in_uint8(s, os->opcode);
224
225 DEBUG(("DESTBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d)\n",
226 os->opcode, os->x, os->y, os->cx, os->cy));
227
228 ui_destblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy);
229 }
230
231 /* Process a pattern blt order */
232 static void
233 process_patblt(STREAM s, PATBLT_ORDER * os, uint32 present, RD_BOOL delta)
234 {
235 BRUSH brush;
236
237 if (present & 0x0001)
238 rdp_in_coord(s, &os->x, delta);
239
240 if (present & 0x0002)
241 rdp_in_coord(s, &os->y, delta);
242
243 if (present & 0x0004)
244 rdp_in_coord(s, &os->cx, delta);
245
246 if (present & 0x0008)
247 rdp_in_coord(s, &os->cy, delta);
248
249 if (present & 0x0010)
250 in_uint8(s, os->opcode);
251
252 if (present & 0x0020)
253 rdp_in_colour(s, &os->bgcolour);
254
255 if (present & 0x0040)
256 rdp_in_colour(s, &os->fgcolour);
257
258 rdp_parse_brush(s, &os->brush, present >> 7);
259
260 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,
261 os->y, os->cx, os->cy, os->brush.style, os->bgcolour, os->fgcolour));
262
263 setup_brush(&brush, &os->brush);
264
265 ui_patblt(ROP2_P(os->opcode), os->x, os->y, os->cx, os->cy,
266 &brush, os->bgcolour, os->fgcolour);
267 }
268
269 /* Process a screen blt order */
270 static void
271 process_screenblt(STREAM s, SCREENBLT_ORDER * os, uint32 present, RD_BOOL delta)
272 {
273 if (present & 0x0001)
274 rdp_in_coord(s, &os->x, delta);
275
276 if (present & 0x0002)
277 rdp_in_coord(s, &os->y, delta);
278
279 if (present & 0x0004)
280 rdp_in_coord(s, &os->cx, delta);
281
282 if (present & 0x0008)
283 rdp_in_coord(s, &os->cy, delta);
284
285 if (present & 0x0010)
286 in_uint8(s, os->opcode);
287
288 if (present & 0x0020)
289 rdp_in_coord(s, &os->srcx, delta);
290
291 if (present & 0x0040)
292 rdp_in_coord(s, &os->srcy, delta);
293
294 DEBUG(("SCREENBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,srcx=%d,srcy=%d)\n",
295 os->opcode, os->x, os->y, os->cx, os->cy, os->srcx, os->srcy));
296
297 ui_screenblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, os->srcx, os->srcy);
298 }
299
300 /* Process a line order */
301 static void
302 process_line(STREAM s, LINE_ORDER * os, uint32 present, RD_BOOL delta)
303 {
304 if (present & 0x0001)
305 in_uint16_le(s, os->mixmode);
306
307 if (present & 0x0002)
308 rdp_in_coord(s, &os->startx, delta);
309
310 if (present & 0x0004)
311 rdp_in_coord(s, &os->starty, delta);
312
313 if (present & 0x0008)
314 rdp_in_coord(s, &os->endx, delta);
315
316 if (present & 0x0010)
317 rdp_in_coord(s, &os->endy, delta);
318
319 if (present & 0x0020)
320 rdp_in_colour(s, &os->bgcolour);
321
322 if (present & 0x0040)
323 in_uint8(s, os->opcode);
324
325 rdp_parse_pen(s, &os->pen, present >> 7);
326
327 DEBUG(("LINE(op=0x%x,sx=%d,sy=%d,dx=%d,dy=%d,fg=0x%x)\n",
328 os->opcode, os->startx, os->starty, os->endx, os->endy, os->pen.colour));
329
330 if (os->opcode < 0x01 || os->opcode > 0x10)
331 {
332 error("bad ROP2 0x%x\n", os->opcode);
333 return;
334 }
335
336 ui_line(os->opcode - 1, os->startx, os->starty, os->endx, os->endy, &os->pen);
337 }
338
339 /* Process an opaque rectangle order */
340 static void
341 process_rect(STREAM s, RECT_ORDER * os, uint32 present, RD_BOOL delta)
342 {
343 uint32 i;
344 if (present & 0x01)
345 rdp_in_coord(s, &os->x, delta);
346
347 if (present & 0x02)
348 rdp_in_coord(s, &os->y, delta);
349
350 if (present & 0x04)
351 rdp_in_coord(s, &os->cx, delta);
352
353 if (present & 0x08)
354 rdp_in_coord(s, &os->cy, delta);
355
356 if (present & 0x10)
357 {
358 in_uint8(s, i);
359 os->colour = (os->colour & 0xffffff00) | i;
360 }
361
362 if (present & 0x20)
363 {
364 in_uint8(s, i);
365 os->colour = (os->colour & 0xffff00ff) | (i << 8);
366 }
367
368 if (present & 0x40)
369 {
370 in_uint8(s, i);
371 os->colour = (os->colour & 0xff00ffff) | (i << 16);
372 }
373
374 DEBUG(("RECT(x=%d,y=%d,cx=%d,cy=%d,fg=0x%x)\n", os->x, os->y, os->cx, os->cy, os->colour));
375
376 ui_rect(os->x, os->y, os->cx, os->cy, os->colour);
377 }
378
379 /* Process a desktop save order */
380 static void
381 process_desksave(STREAM s, DESKSAVE_ORDER * os, uint32 present, RD_BOOL delta)
382 {
383 int width, height;
384
385 if (present & 0x01)
386 in_uint32_le(s, os->offset);
387
388 if (present & 0x02)
389 rdp_in_coord(s, &os->left, delta);
390
391 if (present & 0x04)
392 rdp_in_coord(s, &os->top, delta);
393
394 if (present & 0x08)
395 rdp_in_coord(s, &os->right, delta);
396
397 if (present & 0x10)
398 rdp_in_coord(s, &os->bottom, delta);
399
400 if (present & 0x20)
401 in_uint8(s, os->action);
402
403 DEBUG(("DESKSAVE(l=%d,t=%d,r=%d,b=%d,off=%d,op=%d)\n",
404 os->left, os->top, os->right, os->bottom, os->offset, os->action));
405
406 width = os->right - os->left + 1;
407 height = os->bottom - os->top + 1;
408
409 if (os->action == 0)
410 ui_desktop_save(os->offset, os->left, os->top, width, height);
411 else
412 ui_desktop_restore(os->offset, os->left, os->top, width, height);
413 }
414
415 /* Process a memory blt order */
416 static void
417 process_memblt(STREAM s, MEMBLT_ORDER * os, uint32 present, RD_BOOL delta)
418 {
419 RD_HBITMAP bitmap;
420
421 if (present & 0x0001)
422 {
423 in_uint8(s, os->cache_id);
424 in_uint8(s, os->colour_table);
425 }
426
427 if (present & 0x0002)
428 rdp_in_coord(s, &os->x, delta);
429
430 if (present & 0x0004)
431 rdp_in_coord(s, &os->y, delta);
432
433 if (present & 0x0008)
434 rdp_in_coord(s, &os->cx, delta);
435
436 if (present & 0x0010)
437 rdp_in_coord(s, &os->cy, delta);
438
439 if (present & 0x0020)
440 in_uint8(s, os->opcode);
441
442 if (present & 0x0040)
443 rdp_in_coord(s, &os->srcx, delta);
444
445 if (present & 0x0080)
446 rdp_in_coord(s, &os->srcy, delta);
447
448 if (present & 0x0100)
449 in_uint16_le(s, os->cache_idx);
450
451 DEBUG(("MEMBLT(op=0x%x,x=%d,y=%d,cx=%d,cy=%d,id=%d,idx=%d)\n",
452 os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx));
453
454 bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
455 if (bitmap == NULL)
456 return;
457
458 ui_memblt(ROP2_S(os->opcode), os->x, os->y, os->cx, os->cy, bitmap, os->srcx, os->srcy);
459 }
460
461 /* Process a 3-way blt order */
462 static void
463 process_triblt(STREAM s, TRIBLT_ORDER * os, uint32 present, RD_BOOL delta)
464 {
465 RD_HBITMAP bitmap;
466 BRUSH brush;
467
468 if (present & 0x000001)
469 {
470 in_uint8(s, os->cache_id);
471 in_uint8(s, os->colour_table);
472 }
473
474 if (present & 0x000002)
475 rdp_in_coord(s, &os->x, delta);
476
477 if (present & 0x000004)
478 rdp_in_coord(s, &os->y, delta);
479
480 if (present & 0x000008)
481 rdp_in_coord(s, &os->cx, delta);
482
483 if (present & 0x000010)
484 rdp_in_coord(s, &os->cy, delta);
485
486 if (present & 0x000020)
487 in_uint8(s, os->opcode);
488
489 if (present & 0x000040)
490 rdp_in_coord(s, &os->srcx, delta);
491
492 if (present & 0x000080)
493 rdp_in_coord(s, &os->srcy, delta);
494
495 if (present & 0x000100)
496 rdp_in_colour(s, &os->bgcolour);
497
498 if (present & 0x000200)
499 rdp_in_colour(s, &os->fgcolour);
500
501 rdp_parse_brush(s, &os->brush, present >> 10);
502
503 if (present & 0x008000)
504 in_uint16_le(s, os->cache_idx);
505
506 if (present & 0x010000)
507 in_uint16_le(s, os->unknown);
508
509 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",
510 os->opcode, os->x, os->y, os->cx, os->cy, os->cache_id, os->cache_idx,
511 os->brush.style, os->bgcolour, os->fgcolour));
512
513 bitmap = cache_get_bitmap(os->cache_id, os->cache_idx);
514 if (bitmap == NULL)
515 return;
516
517 setup_brush(&brush, &os->brush);
518
519 ui_triblt(os->opcode, os->x, os->y, os->cx, os->cy,
520 bitmap, os->srcx, os->srcy, &brush, os->bgcolour, os->fgcolour);
521 }
522
523 /* Process a polygon order */
524 static void
525 process_polygon(STREAM s, POLYGON_ORDER * os, uint32 present, RD_BOOL delta)
526 {
527 int index, data, next;
528 uint8 flags = 0;
529 RD_POINT *points;
530
531 if (present & 0x01)
532 rdp_in_coord(s, &os->x, delta);
533
534 if (present & 0x02)
535 rdp_in_coord(s, &os->y, delta);
536
537 if (present & 0x04)
538 in_uint8(s, os->opcode);
539
540 if (present & 0x08)
541 in_uint8(s, os->fillmode);
542
543 if (present & 0x10)
544 rdp_in_colour(s, &os->fgcolour);
545
546 if (present & 0x20)
547 in_uint8(s, os->npoints);
548
549 if (present & 0x40)
550 {
551 in_uint8(s, os->datasize);
552 in_uint8a(s, os->data, os->datasize);
553 }
554
555 DEBUG(("POLYGON(x=%d,y=%d,op=0x%x,fm=%d,fg=0x%x,n=%d,sz=%d)\n",
556 os->x, os->y, os->opcode, os->fillmode, os->fgcolour, os->npoints, os->datasize));
557
558 DEBUG(("Data: "));
559
560 for (index = 0; index < os->datasize; index++)
561 DEBUG(("%02x ", os->data[index]));
562
563 DEBUG(("\n"));
564
565 if (os->opcode < 0x01 || os->opcode > 0x10)
566 {
567 error("bad ROP2 0x%x\n", os->opcode);
568 return;
569 }
570
571 points = (RD_POINT *) xmalloc((os->npoints + 1) * sizeof(RD_POINT));
572 memset(points, 0, (os->npoints + 1) * sizeof(RD_POINT));
573
574 points[0].x = os->x;
575 points[0].y = os->y;
576
577 index = 0;
578 data = ((os->npoints - 1) / 4) + 1;
579 for (next = 1; (next <= os->npoints) && (next < 256) && (data < os->datasize); next++)
580 {
581 if ((next - 1) % 4 == 0)
582 flags = os->data[index++];
583
584 if (~flags & 0x80)
585 points[next].x = parse_delta(os->data, &data);
586
587 if (~flags & 0x40)
588 points[next].y = parse_delta(os->data, &data);
589
590 flags <<= 2;
591 }
592
593 if (next - 1 == os->npoints)
594 ui_polygon(os->opcode - 1, os->fillmode, points, os->npoints + 1, NULL, 0,
595 os->fgcolour);
596 else
597 error("polygon parse error\n");
598
599 xfree(points);
600 }
601
602 /* Process a polygon2 order */
603 static void
604 process_polygon2(STREAM s, POLYGON2_ORDER * os, uint32 present, RD_BOOL delta)
605 {
606 int index, data, next;
607 uint8 flags = 0;
608 RD_POINT *points;
609 BRUSH brush;
610
611 if (present & 0x0001)
612 rdp_in_coord(s, &os->x, delta);
613
614 if (present & 0x0002)
615 rdp_in_coord(s, &os->y, delta);
616
617 if (present & 0x0004)
618 in_uint8(s, os->opcode);
619
620 if (present & 0x0008)
621 in_uint8(s, os->fillmode);
622
623 if (present & 0x0010)
624 rdp_in_colour(s, &os->bgcolour);
625
626 if (present & 0x0020)
627 rdp_in_colour(s, &os->fgcolour);
628
629 rdp_parse_brush(s, &os->brush, present >> 6);
630
631 if (present & 0x0800)
632 in_uint8(s, os->npoints);
633
634 if (present & 0x1000)
635 {
636 in_uint8(s, os->datasize);
637 in_uint8a(s, os->data, os->datasize);
638 }
639
640 DEBUG(("POLYGON2(x=%d,y=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x,n=%d,sz=%d)\n",
641 os->x, os->y, os->opcode, os->fillmode, os->brush.style, os->bgcolour, os->fgcolour,
642 os->npoints, os->datasize));
643
644 DEBUG(("Data: "));
645
646 for (index = 0; index < os->datasize; index++)
647 DEBUG(("%02x ", os->data[index]));
648
649 DEBUG(("\n"));
650
651 if (os->opcode < 0x01 || os->opcode > 0x10)
652 {
653 error("bad ROP2 0x%x\n", os->opcode);
654 return;
655 }
656
657 setup_brush(&brush, &os->brush);
658
659 points = (RD_POINT *) xmalloc((os->npoints + 1) * sizeof(RD_POINT));
660 memset(points, 0, (os->npoints + 1) * sizeof(RD_POINT));
661
662 points[0].x = os->x;
663 points[0].y = os->y;
664
665 index = 0;
666 data = ((os->npoints - 1) / 4) + 1;
667 for (next = 1; (next <= os->npoints) && (next < 256) && (data < os->datasize); next++)
668 {
669 if ((next - 1) % 4 == 0)
670 flags = os->data[index++];
671
672 if (~flags & 0x80)
673 points[next].x = parse_delta(os->data, &data);
674
675 if (~flags & 0x40)
676 points[next].y = parse_delta(os->data, &data);
677
678 flags <<= 2;
679 }
680
681 if (next - 1 == os->npoints)
682 ui_polygon(os->opcode - 1, os->fillmode, points, os->npoints + 1,
683 &brush, os->bgcolour, os->fgcolour);
684 else
685 error("polygon2 parse error\n");
686
687 xfree(points);
688 }
689
690 /* Process a polyline order */
691 static void
692 process_polyline(STREAM s, POLYLINE_ORDER * os, uint32 present, RD_BOOL delta)
693 {
694 int index, next, data;
695 uint8 flags = 0;
696 PEN pen;
697 RD_POINT *points;
698
699 if (present & 0x01)
700 rdp_in_coord(s, &os->x, delta);
701
702 if (present & 0x02)
703 rdp_in_coord(s, &os->y, delta);
704
705 if (present & 0x04)
706 in_uint8(s, os->opcode);
707
708 if (present & 0x10)
709 rdp_in_colour(s, &os->fgcolour);
710
711 if (present & 0x20)
712 in_uint8(s, os->lines);
713
714 if (present & 0x40)
715 {
716 in_uint8(s, os->datasize);
717 in_uint8a(s, os->data, os->datasize);
718 }
719
720 DEBUG(("POLYLINE(x=%d,y=%d,op=0x%x,fg=0x%x,n=%d,sz=%d)\n",
721 os->x, os->y, os->opcode, os->fgcolour, os->lines, os->datasize));
722
723 DEBUG(("Data: "));
724
725 for (index = 0; index < os->datasize; index++)
726 DEBUG(("%02x ", os->data[index]));
727
728 DEBUG(("\n"));
729
730 if (os->opcode < 0x01 || os->opcode > 0x10)
731 {
732 error("bad ROP2 0x%x\n", os->opcode);
733 return;
734 }
735
736 points = (RD_POINT *) xmalloc((os->lines + 1) * sizeof(RD_POINT));
737 memset(points, 0, (os->lines + 1) * sizeof(RD_POINT));
738
739 points[0].x = os->x;
740 points[0].y = os->y;
741 pen.style = pen.width = 0;
742 pen.colour = os->fgcolour;
743
744 index = 0;
745 data = ((os->lines - 1) / 4) + 1;
746 for (next = 1; (next <= os->lines) && (data < os->datasize); next++)
747 {
748 if ((next - 1) % 4 == 0)
749 flags = os->data[index++];
750
751 if (~flags & 0x80)
752 points[next].x = parse_delta(os->data, &data);
753
754 if (~flags & 0x40)
755 points[next].y = parse_delta(os->data, &data);
756
757 flags <<= 2;
758 }
759
760 if (next - 1 == os->lines)
761 ui_polyline(os->opcode - 1, points, os->lines + 1, &pen);
762 else
763 error("polyline parse error\n");
764
765 xfree(points);
766 }
767
768 /* Process an ellipse order */
769 static void
770 process_ellipse(STREAM s, ELLIPSE_ORDER * os, uint32 present, RD_BOOL delta)
771 {
772 if (present & 0x01)
773 rdp_in_coord(s, &os->left, delta);
774
775 if (present & 0x02)
776 rdp_in_coord(s, &os->top, delta);
777
778 if (present & 0x04)
779 rdp_in_coord(s, &os->right, delta);
780
781 if (present & 0x08)
782 rdp_in_coord(s, &os->bottom, delta);
783
784 if (present & 0x10)
785 in_uint8(s, os->opcode);
786
787 if (present & 0x20)
788 in_uint8(s, os->fillmode);
789
790 if (present & 0x40)
791 rdp_in_colour(s, &os->fgcolour);
792
793 DEBUG(("ELLIPSE(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,fg=0x%x)\n", os->left, os->top,
794 os->right, os->bottom, os->opcode, os->fillmode, os->fgcolour));
795
796 ui_ellipse(os->opcode - 1, os->fillmode, os->left, os->top, os->right - os->left,
797 os->bottom - os->top, NULL, 0, os->fgcolour);
798 }
799
800 /* Process an ellipse2 order */
801 static void
802 process_ellipse2(STREAM s, ELLIPSE2_ORDER * os, uint32 present, RD_BOOL delta)
803 {
804 BRUSH brush;
805
806 if (present & 0x0001)
807 rdp_in_coord(s, &os->left, delta);
808
809 if (present & 0x0002)
810 rdp_in_coord(s, &os->top, delta);
811
812 if (present & 0x0004)
813 rdp_in_coord(s, &os->right, delta);
814
815 if (present & 0x0008)
816 rdp_in_coord(s, &os->bottom, delta);
817
818 if (present & 0x0010)
819 in_uint8(s, os->opcode);
820
821 if (present & 0x0020)
822 in_uint8(s, os->fillmode);
823
824 if (present & 0x0040)
825 rdp_in_colour(s, &os->bgcolour);
826
827 if (present & 0x0080)
828 rdp_in_colour(s, &os->fgcolour);
829
830 rdp_parse_brush(s, &os->brush, present >> 8);
831
832 DEBUG(("ELLIPSE2(l=%d,t=%d,r=%d,b=%d,op=0x%x,fm=%d,bs=%d,bg=0x%x,fg=0x%x)\n",
833 os->left, os->top, os->right, os->bottom, os->opcode, os->fillmode, os->brush.style,
834 os->bgcolour, os->fgcolour));
835
836 setup_brush(&brush, &os->brush);
837
838 ui_ellipse(os->opcode - 1, os->fillmode, os->left, os->top, os->right - os->left,
839 os->bottom - os->top, &brush, os->bgcolour, os->fgcolour);
840 }
841
842 /* Process a text order */
843 static void
844 process_text2(STREAM s, TEXT2_ORDER * os, uint32 present, RD_BOOL delta)
845 {
846 int i;
847 BRUSH brush;
848
849 if (present & 0x000001)
850 in_uint8(s, os->font);
851
852 if (present & 0x000002)
853 in_uint8(s, os->flags);
854
855 if (present & 0x000004)
856 in_uint8(s, os->opcode);
857
858 if (present & 0x000008)
859 in_uint8(s, os->mixmode);
860
861 if (present & 0x000010)
862 rdp_in_colour(s, &os->fgcolour);
863
864 if (present & 0x000020)
865 rdp_in_colour(s, &os->bgcolour);
866
867 if (present & 0x000040)
868 in_uint16_le(s, os->clipleft);
869
870 if (present & 0x000080)
871 in_uint16_le(s, os->cliptop);
872
873 if (present & 0x000100)
874 in_uint16_le(s, os->clipright);
875
876 if (present & 0x000200)
877 in_uint16_le(s, os->clipbottom);
878
879 if (present & 0x000400)
880 in_uint16_le(s, os->boxleft);
881
882 if (present & 0x000800)
883 in_uint16_le(s, os->boxtop);
884
885 if (present & 0x001000)
886 in_uint16_le(s, os->boxright);
887
888 if (present & 0x002000)
889 in_uint16_le(s, os->boxbottom);
890
891 rdp_parse_brush(s, &os->brush, present >> 14);
892
893 if (present & 0x080000)
894 in_uint16_le(s, os->x);
895
896 if (present & 0x100000)
897 in_uint16_le(s, os->y);
898
899 if (present & 0x200000)
900 {
901 in_uint8(s, os->length);
902 in_uint8a(s, os->text, os->length);
903 }
904
905 DEBUG(("TEXT2(x=%d,y=%d,cl=%d,ct=%d,cr=%d,cb=%d,bl=%d,bt=%d,br=%d,bb=%d,bs=%d,bg=0x%x,fg=0x%x,font=%d,fl=0x%x,op=0x%x,mix=%d,n=%d)\n", os->x, os->y, os->clipleft, os->cliptop, os->clipright, os->clipbottom, os->boxleft, os->boxtop, os->boxright, os->boxbottom, os->brush.style, os->bgcolour, os->fgcolour, os->font, os->flags, os->opcode, os->mixmode, os->length));
906
907 DEBUG(("Text: "));
908
909 for (i = 0; i < os->length; i++)
910 DEBUG(("%02x ", os->text[i]));
911
912 DEBUG(("\n"));
913
914 setup_brush(&brush, &os->brush);
915
916 ui_draw_text(os->font, os->flags, os->opcode - 1, os->mixmode, os->x, os->y,
917 os->clipleft, os->cliptop, os->clipright - os->clipleft,
918 os->clipbottom - os->cliptop, os->boxleft, os->boxtop,
919 os->boxright - os->boxleft, os->boxbottom - os->boxtop,
920 &brush, os->bgcolour, os->fgcolour, os->text, os->length);
921 }
922
923 /* Process a raw bitmap cache order */
924 static void
925 process_raw_bmpcache(STREAM s)
926 {
927 RD_HBITMAP bitmap;
928 uint16 cache_idx, bufsize;
929 uint8 cache_id, width, height, bpp, Bpp;
930 uint8 *data, *inverted;
931 int y;
932
933 in_uint8(s, cache_id);
934 in_uint8s(s, 1); /* pad */
935 in_uint8(s, width);
936 in_uint8(s, height);
937 in_uint8(s, bpp);
938 Bpp = (bpp + 7) / 8;
939 in_uint16_le(s, bufsize);
940 in_uint16_le(s, cache_idx);
941 in_uint8p(s, data, bufsize);
942
943 DEBUG(("RAW_BMPCACHE(cx=%d,cy=%d,id=%d,idx=%d)\n", width, height, cache_id, cache_idx));
944 inverted = (uint8 *) xmalloc(width * height * Bpp);
945 for (y = 0; y < height; y++)
946 {
947 memcpy(&inverted[(height - y - 1) * (width * Bpp)], &data[y * (width * Bpp)],
948 width * Bpp);
949 }
950
951 bitmap = ui_create_bitmap(width, height, inverted);
952 xfree(inverted);
953 cache_put_bitmap(cache_id, cache_idx, bitmap);
954 }
955
956 /* Process a bitmap cache order */
957 static void
958 process_bmpcache(STREAM s)
959 {
960 RD_HBITMAP bitmap;
961 uint16 cache_idx, size;
962 uint8 cache_id, width, height, bpp, Bpp;
963 uint8 *data, *bmpdata;
964 uint16 bufsize, pad2, row_size, final_size;
965 uint8 pad1;
966
967 pad2 = row_size = final_size = 0xffff; /* Shut the compiler up */
968
969 in_uint8(s, cache_id);
970 in_uint8(s, pad1); /* pad */
971 in_uint8(s, width);
972 in_uint8(s, height);
973 in_uint8(s, bpp);
974 Bpp = (bpp + 7) / 8;
975 in_uint16_le(s, bufsize); /* bufsize */
976 in_uint16_le(s, cache_idx);
977
978 if (g_use_rdp5)
979 {
980 size = bufsize;
981 }
982 else
983 {
984
985 /* Begin compressedBitmapData */
986 in_uint16_le(s, pad2); /* pad */
987 in_uint16_le(s, size);
988 /* in_uint8s(s, 4); *//* row_size, final_size */
989 in_uint16_le(s, row_size);
990 in_uint16_le(s, final_size);
991
992 }
993 in_uint8p(s, data, size);
994
995 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));
996
997 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
998
999 if (bitmap_decompress(bmpdata, width, height, data, size, Bpp))
1000 {
1001 bitmap = ui_create_bitmap(width, height, bmpdata);
1002 cache_put_bitmap(cache_id, cache_idx, bitmap);
1003 }
1004 else
1005 {
1006 DEBUG(("Failed to decompress bitmap data\n"));
1007 }
1008
1009 xfree(bmpdata);
1010 }
1011
1012 /* Process a bitmap cache v2 order */
1013 static void
1014 process_bmpcache2(STREAM s, uint16 flags, RD_BOOL compressed)
1015 {
1016 RD_HBITMAP bitmap;
1017 int y;
1018 uint8 cache_id, cache_idx_low, width, height, Bpp;
1019 uint16 cache_idx, bufsize;
1020 uint8 *data, *bmpdata, *bitmap_id;
1021
1022 bitmap_id = NULL; /* prevent compiler warning */
1023 cache_id = flags & ID_MASK;
1024 Bpp = ((flags & MODE_MASK) >> MODE_SHIFT) - 2;
1025
1026 if (flags & PERSIST)
1027 {
1028 in_uint8p(s, bitmap_id, 8);
1029 }
1030
1031 if (flags & SQUARE)
1032 {
1033 in_uint8(s, width);
1034 height = width;
1035 }
1036 else
1037 {
1038 in_uint8(s, width);
1039 in_uint8(s, height);
1040 }
1041
1042 in_uint16_be(s, bufsize);
1043 bufsize &= BUFSIZE_MASK;
1044 in_uint8(s, cache_idx);
1045
1046 if (cache_idx & LONG_FORMAT)
1047 {
1048 in_uint8(s, cache_idx_low);
1049 cache_idx = ((cache_idx ^ LONG_FORMAT) << 8) + cache_idx_low;
1050 }
1051
1052 in_uint8p(s, data, bufsize);
1053
1054 DEBUG(("BMPCACHE2(compr=%d,flags=%x,cx=%d,cy=%d,id=%d,idx=%d,Bpp=%d,bs=%d)\n",
1055 compressed, flags, width, height, cache_id, cache_idx, Bpp, bufsize));
1056
1057 bmpdata = (uint8 *) xmalloc(width * height * Bpp);
1058
1059 if (compressed)
1060 {
1061 if (!bitmap_decompress(bmpdata, width, height, data, bufsize, Bpp))
1062 {
1063 DEBUG(("Failed to decompress bitmap data\n"));
1064 xfree(bmpdata);
1065 return;
1066 }
1067 }
1068 else
1069 {
1070 for (y = 0; y < height; y++)
1071 memcpy(&bmpdata[(height - y - 1) * (width * Bpp)],
1072 &data[y * (width * Bpp)], width * Bpp);
1073 }
1074
1075 bitmap = ui_create_bitmap(width, height, bmpdata);
1076
1077 if (bitmap)
1078 {
1079 cache_put_bitmap(cache_id, cache_idx, bitmap);
1080 if (flags & PERSIST)
1081 pstcache_save_bitmap(cache_id, cache_idx, bitmap_id, width, height,
1082 width * height * Bpp, bmpdata);
1083 }
1084 else
1085 {
1086 DEBUG(("process_bmpcache2: ui_create_bitmap failed\n"));
1087 }
1088
1089 xfree(bmpdata);
1090 }
1091
1092 /* Process a colourmap cache order */
1093 static void
1094 process_colcache(STREAM s)
1095 {
1096 COLOURENTRY *entry;
1097 COLOURMAP map;
1098 RD_HCOLOURMAP hmap;
1099 uint8 cache_id;
1100 int i;
1101
1102 in_uint8(s, cache_id);
1103 in_uint16_le(s, map.ncolours);
1104
1105 map.colours = (COLOURENTRY *) xmalloc(sizeof(COLOURENTRY) * map.ncolours);
1106
1107 for (i = 0; i < map.ncolours; i++)
1108 {
1109 entry = &map.colours[i];
1110 in_uint8(s, entry->blue);
1111 in_uint8(s, entry->green);
1112 in_uint8(s, entry->red);
1113 in_uint8s(s, 1); /* pad */
1114 }
1115
1116 DEBUG(("COLCACHE(id=%d,n=%d)\n", cache_id, map.ncolours));
1117
1118 hmap = ui_create_colourmap(&map);
1119
1120 if (cache_id)
1121 ui_set_colourmap(hmap);
1122
1123 xfree(map.colours);
1124 }
1125
1126 /* Process a font cache order */
1127 static void
1128 process_fontcache(STREAM s)
1129 {
1130 RD_HGLYPH bitmap;
1131 uint8 font, nglyphs;
1132 uint16 character, offset, baseline, width, height;
1133 int i, datasize;
1134 uint8 *data;
1135
1136 in_uint8(s, font);
1137 in_uint8(s, nglyphs);
1138
1139 DEBUG(("FONTCACHE(font=%d,n=%d)\n", font, nglyphs));
1140
1141 for (i = 0; i < nglyphs; i++)
1142 {
1143 in_uint16_le(s, character);
1144 in_uint16_le(s, offset);
1145 in_uint16_le(s, baseline);
1146 in_uint16_le(s, width);
1147 in_uint16_le(s, height);
1148
1149 datasize = (height * ((width + 7) / 8) + 3) & ~3;
1150 in_uint8p(s, data, datasize);
1151
1152 bitmap = ui_create_glyph(width, height, data);
1153 cache_put_font(font, character, offset, baseline, width, height, bitmap);
1154 }
1155 }
1156
1157 /* Process a brush cache order */
1158 static void
1159 process_brushcache(STREAM s, uint16 flags)
1160 {
1161 BRUSHDATA brush_data;
1162 uint8 cache_idx, depth, width, height, size;
1163
1164 in_uint8(s, cache_idx);
1165 in_uint8(s, depth);
1166 in_uint8(s, width);
1167 in_uint8(s, height);
1168 in_uint8s(s, 1); /* type, 0x80 = cached */
1169 in_uint8(s, size);
1170
1171 DEBUG(("BRUSHCACHE(idx=%d,dp=%d,wd=%d,ht=%d,sz=%d)\n", cache_idx, depth,
1172 width, height, size));
1173
1174 if ((depth == 1) && (width == 8) && (height == 8) && (size == 8))
1175 {
1176 in_uint8a(s, brush_data.pattern, sizeof(brush_data.pattern));
1177 cache_put_brush_data(cache_idx, &brush_data);
1178 }
1179 else
1180 {
1181 warning("ignoring incompatible brush type. display may be incorrect\n");
1182 }
1183 }
1184
1185 /* Process a secondary order */
1186 static void
1187 process_secondary_order(STREAM s)
1188 {
1189 /* The length isn't calculated correctly by the server.
1190 * For very compact orders the length becomes negative
1191 * so a signed integer must be used. */
1192 uint16 length;
1193 uint16 flags;
1194 uint8 type;
1195 uint8 *next_order;
1196
1197 in_uint16_le(s, length);
1198 in_uint16_le(s, flags); /* used by bmpcache2 */
1199 in_uint8(s, type);
1200
1201 next_order = s->p + (sint16) length + 7;
1202
1203 switch (type)
1204 {
1205 case RDP_ORDER_RAW_BMPCACHE:
1206 process_raw_bmpcache(s);
1207 break;
1208
1209 case RDP_ORDER_COLCACHE:
1210 process_colcache(s);
1211 break;
1212
1213 case RDP_ORDER_BMPCACHE:
1214 process_bmpcache(s);
1215 break;
1216
1217 case RDP_ORDER_FONTCACHE:
1218 process_fontcache(s);
1219 break;
1220
1221 case RDP_ORDER_RAW_BMPCACHE2:
1222 process_bmpcache2(s, flags, False); /* uncompressed */
1223 break;
1224
1225 case RDP_ORDER_BMPCACHE2:
1226 process_bmpcache2(s, flags, True); /* compressed */
1227 break;
1228
1229 case RDP_ORDER_BRUSHCACHE:
1230 process_brushcache(s, flags);
1231 break;
1232
1233 default:
1234 unimpl("secondary order %d\n", type);
1235 }
1236
1237 s->p = next_order;
1238 }
1239
1240 /* Process an order PDU */
1241 void
1242 process_orders(STREAM s, uint16 num_orders)
1243 {
1244 RDP_ORDER_STATE *os = &g_order_state;
1245 uint32 present;
1246 uint8 order_flags;
1247 int size, processed = 0;
1248 RD_BOOL delta;
1249
1250 while (processed < num_orders)
1251 {
1252 in_uint8(s, order_flags);
1253
1254 if (!(order_flags & RDP_ORDER_STANDARD))
1255 {
1256 error("order parsing failed\n");
1257 break;
1258 }
1259
1260 if (order_flags & RDP_ORDER_SECONDARY)
1261 {
1262 process_secondary_order(s);
1263 }
1264 else
1265 {
1266 if (order_flags & RDP_ORDER_CHANGE)
1267 {
1268 in_uint8(s, os->order_type);
1269 }
1270
1271 switch (os->order_type)
1272 {
1273 case RDP_ORDER_TRIBLT:
1274 case RDP_ORDER_TEXT2:
1275 size = 3;
1276 break;
1277
1278 case RDP_ORDER_PATBLT:
1279 case RDP_ORDER_MEMBLT:
1280 case RDP_ORDER_LINE:
1281 case RDP_ORDER_POLYGON2:
1282 case RDP_ORDER_ELLIPSE2:
1283 size = 2;
1284 break;
1285
1286 default:
1287 size = 1;
1288 }
1289
1290 rdp_in_present(s, &present, order_flags, size);
1291
1292 if (order_flags & RDP_ORDER_BOUNDS)
1293 {
1294 if (!(order_flags & RDP_ORDER_LASTBOUNDS))
1295 rdp_parse_bounds(s, &os->bounds);
1296
1297 ui_set_clip(os->bounds.left,
1298 os->bounds.top,
1299 os->bounds.right -
1300 os->bounds.left + 1,
1301 os->bounds.bottom - os->bounds.top + 1);
1302 }
1303
1304 delta = order_flags & RDP_ORDER_DELTA;
1305
1306 switch (os->order_type)
1307 {
1308 case RDP_ORDER_DESTBLT:
1309 process_destblt(s, &os->destblt, present, delta);
1310 break;
1311
1312 case RDP_ORDER_PATBLT:
1313 process_patblt(s, &os->patblt, present, delta);
1314 break;
1315
1316 case RDP_ORDER_SCREENBLT:
1317 process_screenblt(s, &os->screenblt, present, delta);
1318 break;
1319
1320 case RDP_ORDER_LINE:
1321 process_line(s, &os->line, present, delta);
1322 break;
1323
1324 case RDP_ORDER_RECT:
1325 process_rect(s, &os->rect, present, delta);
1326 break;
1327
1328 case RDP_ORDER_DESKSAVE:
1329 process_desksave(s, &os->desksave, present, delta);
1330 break;
1331
1332 case RDP_ORDER_MEMBLT:
1333 process_memblt(s, &os->memblt, present, delta);
1334 break;
1335
1336 case RDP_ORDER_TRIBLT:
1337 process_triblt(s, &os->triblt, present, delta);
1338 break;
1339
1340 case RDP_ORDER_POLYGON:
1341 process_polygon(s, &os->polygon, present, delta);
1342 break;
1343
1344 case RDP_ORDER_POLYGON2:
1345 process_polygon2(s, &os->polygon2, present, delta);
1346 break;
1347
1348 case RDP_ORDER_POLYLINE:
1349 process_polyline(s, &os->polyline, present, delta);
1350 break;
1351
1352 case RDP_ORDER_ELLIPSE:
1353 process_ellipse(s, &os->ellipse, present, delta);
1354 break;
1355
1356 case RDP_ORDER_ELLIPSE2:
1357 process_ellipse2(s, &os->ellipse2, present, delta);
1358 break;
1359
1360 case RDP_ORDER_TEXT2:
1361 process_text2(s, &os->text2, present, delta);
1362 break;
1363
1364 default:
1365 unimpl("order %d\n", os->order_type);
1366 return;
1367 }
1368
1369 if (order_flags & RDP_ORDER_BOUNDS)
1370 ui_reset_clip();
1371 }
1372
1373 processed++;
1374 }
1375 #if 0
1376 /* not true when RDP_COMPRESSION is set */
1377 if (s->p != g_next_packet)
1378 error("%d bytes remaining\n", (int) (g_next_packet - s->p));
1379 #endif
1380
1381 }
1382
1383 /* Reset order state */
1384 void
1385 reset_order_state(void)
1386 {
1387 memset(&g_order_state, 0, sizeof(g_order_state));
1388 g_order_state.order_type = RDP_ORDER_PATBLT;
1389 }

  ViewVC Help
Powered by ViewVC 1.1.26