/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/orders.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26