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

Annotation of /jpeg/rdesktop/trunk/bitmap.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1417 - (hide annotations)
Thu Aug 30 04:47:36 2007 UTC (16 years, 9 months ago) by jsorg71
Original Path: sourceforge.net/trunk/rdesktop/bitmap.c
File MIME type: text/plain
File size: 17850 byte(s)
32 bit color

1 astrand 963 /* -*- c-basic-offset: 8 -*-
2 matty 3 rdesktop: A Remote Desktop Protocol client.
3     Bitmap decompression routines
4 jsorg71 1365 Copyright (C) Matthew Chapman 1999-2007
5 jsorg71 309
6 matty 3 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 jsorg71 309
11 matty 3 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 jsorg71 309
16 matty 3 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 jsorg71 1371 /* three seperate function for speed when decompressing the bitmaps
22     when modifing one function make the change in the others
23     jay.sorg@gmail.com */
24 jsorg71 649
25     /* indent is confused by this file */
26     /* *INDENT-OFF* */
27    
28 matty 10 #include "rdesktop.h"
29 matty 3
30 matty 7 #define CVAL(p) (*(p++))
31 stargo 693 #ifdef NEED_ALIGN
32     #ifdef L_ENDIAN
33     #define CVAL2(p, v) { v = (*(p++)); v |= (*(p++)) << 8; }
34     #else
35     #define CVAL2(p, v) { v = (*(p++)) << 8; v |= (*(p++)); }
36     #endif /* L_ENDIAN */
37     #else
38 stargo 695 #define CVAL2(p, v) { v = (*((uint16*)p)); p += 2; }
39 stargo 693 #endif /* NEED_ALIGN */
40 matty 3
41 jsorg71 649 #define UNROLL8(exp) { exp exp exp exp exp exp exp exp }
42    
43     #define REPEAT(statement) \
44     { \
45     while((count & ~0x7) && ((x+8) < width)) \
46     UNROLL8( statement; count--; x++; ); \
47     \
48     while((count > 0) && (x < width)) \
49     { \
50     statement; \
51     count--; \
52     x++; \
53     } \
54     }
55    
56     #define MASK_UPDATE() \
57     { \
58     mixmask <<= 1; \
59     if (mixmask == 0) \
60     { \
61     mask = fom_mask ? fom_mask : CVAL(input); \
62     mixmask = 1; \
63     } \
64     }
65    
66     /* 1 byte bitmap decompress */
67 jsorg71 1372 static RD_BOOL
68 jsorg71 649 bitmap_decompress1(uint8 * output, int width, int height, uint8 * input, int size)
69     {
70     uint8 *end = input + size;
71     uint8 *prevline = NULL, *line = NULL;
72     int opcode, count, offset, isfillormix, x = width;
73     int lastopcode = -1, insertmix = False, bicolour = False;
74     uint8 code;
75     uint8 colour1 = 0, colour2 = 0;
76     uint8 mixmask, mask = 0;
77     uint8 mix = 0xff;
78     int fom_mask = 0;
79    
80     while (input < end)
81     {
82     fom_mask = 0;
83     code = CVAL(input);
84     opcode = code >> 4;
85     /* Handle different opcode forms */
86     switch (opcode)
87     {
88     case 0xc:
89     case 0xd:
90     case 0xe:
91     opcode -= 6;
92     count = code & 0xf;
93     offset = 16;
94     break;
95     case 0xf:
96     opcode = code & 0xf;
97     if (opcode < 9)
98     {
99     count = CVAL(input);
100     count |= CVAL(input) << 8;
101     }
102     else
103     {
104     count = (opcode < 0xb) ? 8 : 1;
105     }
106     offset = 0;
107     break;
108     default:
109     opcode >>= 1;
110     count = code & 0x1f;
111     offset = 32;
112     break;
113     }
114     /* Handle strange cases for counts */
115     if (offset != 0)
116     {
117     isfillormix = ((opcode == 2) || (opcode == 7));
118     if (count == 0)
119     {
120     if (isfillormix)
121     count = CVAL(input) + 1;
122     else
123     count = CVAL(input) + offset;
124     }
125     else if (isfillormix)
126     {
127     count <<= 3;
128     }
129     }
130     /* Read preliminary data */
131     switch (opcode)
132     {
133     case 0: /* Fill */
134     if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
135     insertmix = True;
136     break;
137     case 8: /* Bicolour */
138     colour1 = CVAL(input);
139     case 3: /* Colour */
140     colour2 = CVAL(input);
141     break;
142     case 6: /* SetMix/Mix */
143     case 7: /* SetMix/FillOrMix */
144     mix = CVAL(input);
145     opcode -= 5;
146     break;
147     case 9: /* FillOrMix_1 */
148     mask = 0x03;
149     opcode = 0x02;
150     fom_mask = 3;
151     break;
152     case 0x0a: /* FillOrMix_2 */
153     mask = 0x05;
154     opcode = 0x02;
155     fom_mask = 5;
156     break;
157     }
158     lastopcode = opcode;
159     mixmask = 0;
160     /* Output body */
161     while (count > 0)
162     {
163     if (x >= width)
164     {
165     if (height <= 0)
166     return False;
167     x = 0;
168     height--;
169     prevline = line;
170     line = output + height * width;
171     }
172     switch (opcode)
173     {
174     case 0: /* Fill */
175     if (insertmix)
176     {
177     if (prevline == NULL)
178     line[x] = mix;
179     else
180     line[x] = prevline[x] ^ mix;
181     insertmix = False;
182     count--;
183     x++;
184     }
185     if (prevline == NULL)
186     {
187     REPEAT(line[x] = 0)
188     }
189     else
190     {
191     REPEAT(line[x] = prevline[x])
192     }
193     break;
194     case 1: /* Mix */
195     if (prevline == NULL)
196     {
197     REPEAT(line[x] = mix)
198     }
199     else
200     {
201     REPEAT(line[x] = prevline[x] ^ mix)
202     }
203     break;
204     case 2: /* Fill or Mix */
205     if (prevline == NULL)
206     {
207     REPEAT
208     (
209     MASK_UPDATE();
210     if (mask & mixmask)
211     line[x] = mix;
212     else
213     line[x] = 0;
214     )
215     }
216     else
217     {
218     REPEAT
219     (
220     MASK_UPDATE();
221     if (mask & mixmask)
222     line[x] = prevline[x] ^ mix;
223     else
224     line[x] = prevline[x];
225     )
226     }
227     break;
228     case 3: /* Colour */
229     REPEAT(line[x] = colour2)
230     break;
231     case 4: /* Copy */
232     REPEAT(line[x] = CVAL(input))
233     break;
234     case 8: /* Bicolour */
235     REPEAT
236     (
237     if (bicolour)
238     {
239     line[x] = colour2;
240     bicolour = False;
241     }
242     else
243     {
244     line[x] = colour1;
245     bicolour = True; count++;
246     }
247     )
248     break;
249     case 0xd: /* White */
250     REPEAT(line[x] = 0xff)
251     break;
252     case 0xe: /* Black */
253     REPEAT(line[x] = 0)
254     break;
255     default:
256     unimpl("bitmap opcode 0x%x\n", opcode);
257     return False;
258     }
259     }
260     }
261     return True;
262     }
263    
264     /* 2 byte bitmap decompress */
265 jsorg71 1372 static RD_BOOL
266 jsorg71 649 bitmap_decompress2(uint8 * output, int width, int height, uint8 * input, int size)
267     {
268     uint8 *end = input + size;
269     uint16 *prevline = NULL, *line = NULL;
270     int opcode, count, offset, isfillormix, x = width;
271     int lastopcode = -1, insertmix = False, bicolour = False;
272     uint8 code;
273     uint16 colour1 = 0, colour2 = 0;
274     uint8 mixmask, mask = 0;
275     uint16 mix = 0xffff;
276     int fom_mask = 0;
277    
278     while (input < end)
279     {
280     fom_mask = 0;
281     code = CVAL(input);
282     opcode = code >> 4;
283     /* Handle different opcode forms */
284     switch (opcode)
285     {
286     case 0xc:
287     case 0xd:
288     case 0xe:
289     opcode -= 6;
290     count = code & 0xf;
291     offset = 16;
292     break;
293     case 0xf:
294     opcode = code & 0xf;
295     if (opcode < 9)
296     {
297     count = CVAL(input);
298     count |= CVAL(input) << 8;
299     }
300     else
301     {
302     count = (opcode < 0xb) ? 8 : 1;
303     }
304     offset = 0;
305     break;
306     default:
307     opcode >>= 1;
308     count = code & 0x1f;
309     offset = 32;
310     break;
311     }
312     /* Handle strange cases for counts */
313     if (offset != 0)
314     {
315     isfillormix = ((opcode == 2) || (opcode == 7));
316     if (count == 0)
317     {
318     if (isfillormix)
319     count = CVAL(input) + 1;
320     else
321     count = CVAL(input) + offset;
322     }
323     else if (isfillormix)
324     {
325     count <<= 3;
326     }
327     }
328     /* Read preliminary data */
329     switch (opcode)
330     {
331     case 0: /* Fill */
332     if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
333     insertmix = True;
334     break;
335     case 8: /* Bicolour */
336 stargo 693 CVAL2(input, colour1);
337 jsorg71 649 case 3: /* Colour */
338 stargo 693 CVAL2(input, colour2);
339 jsorg71 649 break;
340     case 6: /* SetMix/Mix */
341     case 7: /* SetMix/FillOrMix */
342 stargo 693 CVAL2(input, mix);
343 jsorg71 649 opcode -= 5;
344     break;
345     case 9: /* FillOrMix_1 */
346     mask = 0x03;
347     opcode = 0x02;
348     fom_mask = 3;
349     break;
350     case 0x0a: /* FillOrMix_2 */
351     mask = 0x05;
352     opcode = 0x02;
353     fom_mask = 5;
354     break;
355     }
356     lastopcode = opcode;
357     mixmask = 0;
358     /* Output body */
359     while (count > 0)
360     {
361     if (x >= width)
362     {
363     if (height <= 0)
364     return False;
365     x = 0;
366     height--;
367     prevline = line;
368     line = ((uint16 *) output) + height * width;
369     }
370     switch (opcode)
371     {
372     case 0: /* Fill */
373     if (insertmix)
374     {
375     if (prevline == NULL)
376     line[x] = mix;
377     else
378     line[x] = prevline[x] ^ mix;
379     insertmix = False;
380     count--;
381     x++;
382     }
383     if (prevline == NULL)
384     {
385     REPEAT(line[x] = 0)
386     }
387     else
388     {
389     REPEAT(line[x] = prevline[x])
390     }
391     break;
392     case 1: /* Mix */
393     if (prevline == NULL)
394     {
395     REPEAT(line[x] = mix)
396     }
397     else
398     {
399     REPEAT(line[x] = prevline[x] ^ mix)
400     }
401     break;
402     case 2: /* Fill or Mix */
403     if (prevline == NULL)
404     {
405     REPEAT
406     (
407     MASK_UPDATE();
408     if (mask & mixmask)
409     line[x] = mix;
410     else
411     line[x] = 0;
412     )
413     }
414     else
415     {
416     REPEAT
417     (
418     MASK_UPDATE();
419     if (mask & mixmask)
420     line[x] = prevline[x] ^ mix;
421     else
422     line[x] = prevline[x];
423     )
424     }
425     break;
426     case 3: /* Colour */
427     REPEAT(line[x] = colour2)
428     break;
429     case 4: /* Copy */
430 stargo 693 REPEAT(CVAL2(input, line[x]))
431 jsorg71 649 break;
432     case 8: /* Bicolour */
433     REPEAT
434     (
435     if (bicolour)
436     {
437     line[x] = colour2;
438     bicolour = False;
439     }
440     else
441     {
442     line[x] = colour1;
443     bicolour = True;
444     count++;
445     }
446     )
447     break;
448     case 0xd: /* White */
449     REPEAT(line[x] = 0xffff)
450     break;
451     case 0xe: /* Black */
452     REPEAT(line[x] = 0)
453     break;
454     default:
455     unimpl("bitmap opcode 0x%x\n", opcode);
456     return False;
457     }
458     }
459     }
460     return True;
461     }
462    
463     /* 3 byte bitmap decompress */
464 jsorg71 1372 static RD_BOOL
465 jsorg71 649 bitmap_decompress3(uint8 * output, int width, int height, uint8 * input, int size)
466     {
467     uint8 *end = input + size;
468     uint8 *prevline = NULL, *line = NULL;
469     int opcode, count, offset, isfillormix, x = width;
470     int lastopcode = -1, insertmix = False, bicolour = False;
471     uint8 code;
472     uint8 colour1[3] = {0, 0, 0}, colour2[3] = {0, 0, 0};
473     uint8 mixmask, mask = 0;
474     uint8 mix[3] = {0xff, 0xff, 0xff};
475     int fom_mask = 0;
476    
477     while (input < end)
478     {
479     fom_mask = 0;
480     code = CVAL(input);
481     opcode = code >> 4;
482     /* Handle different opcode forms */
483     switch (opcode)
484     {
485     case 0xc:
486     case 0xd:
487     case 0xe:
488     opcode -= 6;
489     count = code & 0xf;
490     offset = 16;
491     break;
492     case 0xf:
493     opcode = code & 0xf;
494     if (opcode < 9)
495     {
496     count = CVAL(input);
497     count |= CVAL(input) << 8;
498     }
499     else
500     {
501     count = (opcode <
502     0xb) ? 8 : 1;
503     }
504     offset = 0;
505     break;
506     default:
507     opcode >>= 1;
508     count = code & 0x1f;
509     offset = 32;
510     break;
511     }
512     /* Handle strange cases for counts */
513     if (offset != 0)
514     {
515     isfillormix = ((opcode == 2) || (opcode == 7));
516     if (count == 0)
517     {
518     if (isfillormix)
519     count = CVAL(input) + 1;
520     else
521     count = CVAL(input) + offset;
522     }
523     else if (isfillormix)
524     {
525     count <<= 3;
526     }
527     }
528     /* Read preliminary data */
529     switch (opcode)
530     {
531     case 0: /* Fill */
532     if ((lastopcode == opcode) && !((x == width) && (prevline == NULL)))
533     insertmix = True;
534     break;
535     case 8: /* Bicolour */
536     colour1[0] = CVAL(input);
537     colour1[1] = CVAL(input);
538     colour1[2] = CVAL(input);
539     case 3: /* Colour */
540     colour2[0] = CVAL(input);
541     colour2[1] = CVAL(input);
542     colour2[2] = CVAL(input);
543     break;
544     case 6: /* SetMix/Mix */
545     case 7: /* SetMix/FillOrMix */
546     mix[0] = CVAL(input);
547     mix[1] = CVAL(input);
548     mix[2] = CVAL(input);
549     opcode -= 5;
550     break;
551     case 9: /* FillOrMix_1 */
552     mask = 0x03;
553     opcode = 0x02;
554     fom_mask = 3;
555     break;
556     case 0x0a: /* FillOrMix_2 */
557     mask = 0x05;
558     opcode = 0x02;
559     fom_mask = 5;
560     break;
561     }
562     lastopcode = opcode;
563     mixmask = 0;
564     /* Output body */
565     while (count > 0)
566     {
567     if (x >= width)
568     {
569     if (height <= 0)
570     return False;
571     x = 0;
572     height--;
573     prevline = line;
574     line = output + height * (width * 3);
575     }
576     switch (opcode)
577     {
578     case 0: /* Fill */
579     if (insertmix)
580     {
581     if (prevline == NULL)
582     {
583     line[x * 3] = mix[0];
584     line[x * 3 + 1] = mix[1];
585     line[x * 3 + 2] = mix[2];
586     }
587     else
588     {
589     line[x * 3] =
590     prevline[x * 3] ^ mix[0];
591     line[x * 3 + 1] =
592     prevline[x * 3 + 1] ^ mix[1];
593     line[x * 3 + 2] =
594     prevline[x * 3 + 2] ^ mix[2];
595     }
596     insertmix = False;
597     count--;
598     x++;
599     }
600     if (prevline == NULL)
601     {
602     REPEAT
603     (
604     line[x * 3] = 0;
605     line[x * 3 + 1] = 0;
606     line[x * 3 + 2] = 0;
607     )
608     }
609     else
610     {
611     REPEAT
612     (
613     line[x * 3] = prevline[x * 3];
614     line[x * 3 + 1] = prevline[x * 3 + 1];
615     line[x * 3 + 2] = prevline[x * 3 + 2];
616     )
617     }
618     break;
619     case 1: /* Mix */
620     if (prevline == NULL)
621     {
622     REPEAT
623     (
624     line[x * 3] = mix[0];
625     line[x * 3 + 1] = mix[1];
626     line[x * 3 + 2] = mix[2];
627     )
628     }
629     else
630     {
631     REPEAT
632     (
633     line[x * 3] =
634     prevline[x * 3] ^ mix[0];
635     line[x * 3 + 1] =
636     prevline[x * 3 + 1] ^ mix[1];
637     line[x * 3 + 2] =
638     prevline[x * 3 + 2] ^ mix[2];
639     )
640     }
641     break;
642     case 2: /* Fill or Mix */
643     if (prevline == NULL)
644     {
645     REPEAT
646     (
647     MASK_UPDATE();
648     if (mask & mixmask)
649     {
650     line[x * 3] = mix[0];
651     line[x * 3 + 1] = mix[1];
652     line[x * 3 + 2] = mix[2];
653     }
654     else
655     {
656     line[x * 3] = 0;
657     line[x * 3 + 1] = 0;
658     line[x * 3 + 2] = 0;
659     }
660     )
661     }
662     else
663     {
664     REPEAT
665     (
666     MASK_UPDATE();
667     if (mask & mixmask)
668     {
669     line[x * 3] =
670     prevline[x * 3] ^ mix [0];
671     line[x * 3 + 1] =
672     prevline[x * 3 + 1] ^ mix [1];
673     line[x * 3 + 2] =
674     prevline[x * 3 + 2] ^ mix [2];
675     }
676     else
677     {
678     line[x * 3] =
679     prevline[x * 3];
680     line[x * 3 + 1] =
681     prevline[x * 3 + 1];
682     line[x * 3 + 2] =
683     prevline[x * 3 + 2];
684     }
685     )
686     }
687     break;
688     case 3: /* Colour */
689     REPEAT
690     (
691     line[x * 3] = colour2 [0];
692     line[x * 3 + 1] = colour2 [1];
693     line[x * 3 + 2] = colour2 [2];
694     )
695     break;
696     case 4: /* Copy */
697     REPEAT
698     (
699     line[x * 3] = CVAL(input);
700     line[x * 3 + 1] = CVAL(input);
701     line[x * 3 + 2] = CVAL(input);
702     )
703     break;
704     case 8: /* Bicolour */
705     REPEAT
706     (
707     if (bicolour)
708     {
709     line[x * 3] = colour2[0];
710     line[x * 3 + 1] = colour2[1];
711     line[x * 3 + 2] = colour2[2];
712     bicolour = False;
713     }
714     else
715     {
716     line[x * 3] = colour1[0];
717     line[x * 3 + 1] = colour1[1];
718     line[x * 3 + 2] = colour1[2];
719     bicolour = True;
720     count++;
721     }
722     )
723     break;
724     case 0xd: /* White */
725     REPEAT
726     (
727     line[x * 3] = 0xff;
728     line[x * 3 + 1] = 0xff;
729     line[x * 3 + 2] = 0xff;
730     )
731     break;
732     case 0xe: /* Black */
733     REPEAT
734     (
735     line[x * 3] = 0;
736     line[x * 3 + 1] = 0;
737     line[x * 3 + 2] = 0;
738     )
739     break;
740     default:
741     unimpl("bitmap opcode 0x%x\n", opcode);
742     return False;
743     }
744     }
745     }
746     return True;
747     }
748    
749 jsorg71 1417 /* decompress a colour plane */
750     static int
751     process_plane(uint8 * in, int width, int height, uint8 * out, int size)
752     {
753     int indexw;
754     int indexh;
755     int code;
756     int collen;
757     int replen;
758     int color;
759     int x;
760     int revcode;
761     uint8 * last_line;
762     uint8 * this_line;
763     uint8 * org_in;
764     uint8 * org_out;
765    
766     org_in = in;
767     org_out = out;
768     last_line = 0;
769     indexh = 0;
770     while (indexh < height)
771     {
772     out = (org_out + width * height * 4) - ((indexh + 1) * width * 4);
773     color = 0;
774     this_line = out;
775     indexw = 0;
776     if (last_line == 0)
777     {
778     while (indexw < width)
779     {
780     code = CVAL(in);
781     replen = code & 0xf;
782     collen = (code >> 4) & 0xf;
783     revcode = (replen << 4) | collen;
784     if ((revcode <= 47) && (revcode >= 16))
785     {
786     replen = revcode;
787     collen = 0;
788     }
789     while (collen > 0)
790     {
791     color = CVAL(in);
792     *out = color;
793     out += 4;
794     indexw++;
795     collen--;
796     }
797     while (replen > 0)
798     {
799     *out = color;
800     out += 4;
801     indexw++;
802     replen--;
803     }
804     }
805     }
806     else
807     {
808     while (indexw < width)
809     {
810     code = CVAL(in);
811     replen = code & 0xf;
812     collen = (code >> 4) & 0xf;
813     revcode = (replen << 4) | collen;
814     if ((revcode <= 47) && (revcode >= 16))
815     {
816     replen = revcode;
817     collen = 0;
818     }
819     while (collen > 0)
820     {
821     x = CVAL(in);
822     if (x & 1)
823     {
824     x = x >> 1;
825     x = x + 1;
826     color = -x;
827     }
828     else
829     {
830     x = x >> 1;
831     color = x;
832     }
833     x = last_line[indexw * 4] + color;
834     *out = x;
835     out += 4;
836     indexw++;
837     collen--;
838     }
839     while (replen > 0)
840     {
841     x = last_line[indexw * 4] + color;
842     *out = x;
843     out += 4;
844     indexw++;
845     replen--;
846     }
847     }
848     }
849     indexh++;
850     last_line = this_line;
851     }
852     return (int) (in - org_in);
853     }
854    
855     /* 4 byte bitmap decompress */
856     static RD_BOOL
857     bitmap_decompress4(uint8 * output, int width, int height, uint8 * input, int size)
858     {
859     int code;
860     int bytes_pro;
861     int total_pro;
862    
863     code = CVAL(input);
864     if (code != 0x10)
865     {
866     return False;
867     }
868     total_pro = 1;
869     bytes_pro = process_plane(input, width, height, output + 3, size - total_pro);
870     total_pro += bytes_pro;
871     input += bytes_pro;
872     bytes_pro = process_plane(input, width, height, output + 2, size - total_pro);
873     total_pro += bytes_pro;
874     input += bytes_pro;
875     bytes_pro = process_plane(input, width, height, output + 1, size - total_pro);
876     total_pro += bytes_pro;
877     input += bytes_pro;
878     bytes_pro = process_plane(input, width, height, output + 0, size - total_pro);
879     total_pro += bytes_pro;
880     return size == total_pro;
881     }
882    
883 jsorg71 649 /* main decompress function */
884 jsorg71 1372 RD_BOOL
885 jsorg71 649 bitmap_decompress(uint8 * output, int width, int height, uint8 * input, int size, int Bpp)
886     {
887 jsorg71 1372 RD_BOOL rv = False;
888 jsorg71 1371
889 jsorg71 649 switch (Bpp)
890     {
891     case 1:
892     rv = bitmap_decompress1(output, width, height, input, size);
893     break;
894     case 2:
895     rv = bitmap_decompress2(output, width, height, input, size);
896     break;
897     case 3:
898     rv = bitmap_decompress3(output, width, height, input, size);
899     break;
900 jsorg71 1417 case 4:
901     rv = bitmap_decompress4(output, width, height, input, size);
902     break;
903     default:
904     unimpl("Bpp %d\n", Bpp);
905     break;
906 jsorg71 649 }
907     return rv;
908     }
909    
910     /* *INDENT-ON* */

  ViewVC Help
Powered by ViewVC 1.1.26