]> git.sesse.net Git - rdpsrv/blob - Xserver/lib/font/fontfile/decompress.c
Support RDP5 logon packets.
[rdpsrv] / Xserver / lib / font / fontfile / decompress.c
1 /* $XConsortium: decompress.c,v 1.6 94/04/17 20:17:00 gildea Exp $ */
2 /*
3  * Copyright (c) 1985, 1986 The Regents of the University of California.
4  * All rights reserved.
5  *
6  * This code is derived from software contributed to Berkeley by
7  * James A. Woods, derived from original work by Spencer Thomas
8  * and Joseph Orost.
9  *
10  * Redistribution and use in source and binary forms are permitted
11  * provided that the above copyright notice and this paragraph are
12  * duplicated in all such forms and that any documentation,
13  * advertising materials, and other materials related to such
14  * distribution and use acknowledge that the software was developed
15  * by the University of California, Berkeley.  The name of the
16  * University may not be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21  */
22
23 /*
24
25 Copyright (c) 1993  X Consortium
26
27 Permission is hereby granted, free of charge, to any person obtaining a copy
28 of this software and associated documentation files (the "Software"), to deal
29 in the Software without restriction, including without limitation the rights
30 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
31 copies of the Software, and to permit persons to whom the Software is
32 furnished to do so, subject to the following conditions:
33
34 The above copyright notice and this permission notice shall be included in
35 all copies or substantial portions of the Software.
36
37 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
39 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
40 X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
41 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
42 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
43
44 Except as contained in this notice, the name of the X Consortium shall not be
45 used in advertising or otherwise to promote the sale, use or other dealings
46 in this Software without prior written authorization from the X Consortium.
47
48 */
49 /* 
50  * decompress - cat a compressed file
51  */
52
53 #include "fontmisc.h"
54 #include <bufio.h>
55
56 #define BITS    16
57
58 /*
59  * a code_int must be able to hold 2**BITS values of type int, and also -1
60  */
61 #if BITS > 15
62 typedef long int        code_int;
63 #else
64 typedef int             code_int;
65 #endif
66
67 typedef long int          count_int;
68
69 #ifdef NO_UCHAR
70  typedef char   char_type;
71 #else
72  typedef        unsigned char   char_type;
73 #endif /* UCHAR */
74
75 static char_type magic_header[] = { "\037\235" };       /* 1F 9D */
76
77 /* Defines for third byte of header */
78 #define BIT_MASK        0x1f
79 #define BLOCK_MASK      0x80
80 /* Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is
81    a fourth header byte (for expansion).
82 */
83
84 #define INIT_BITS 9                     /* initial number of bits/code */
85
86 #ifdef COMPATIBLE               /* But wrong! */
87 # define MAXCODE(n_bits)        (1 << (n_bits) - 1)
88 #else
89 # define MAXCODE(n_bits)        ((1 << (n_bits)) - 1)
90 #endif /* COMPATIBLE */
91
92 static code_int getcode();
93
94 /*
95  * the next two codes should not be changed lightly, as they must not
96  * lie within the contiguous general code space.
97  */ 
98 #define FIRST   257     /* first free entry */
99 #define CLEAR   256     /* table clear output code */
100
101 #define STACK_SIZE  8192
102
103 typedef struct _compressedFILE {
104     BufFilePtr      file;
105
106     char_type       *stackp;
107     code_int        oldcode;
108     char_type       finchar;
109
110     int         block_compress;
111     int         maxbits;
112     code_int    maxcode, maxmaxcode;
113
114     code_int    free_ent;
115     int         clear_flg;
116     int         n_bits;
117
118     /* bit buffer */
119     int         offset, size;
120     char_type   buf[BITS];
121
122     char_type       de_stack[STACK_SIZE];
123     char_type       *tab_suffix;
124     unsigned short  *tab_prefix;
125 } CompressedFile;
126
127
128 static int hsize_table[] = {
129     5003,       /* 12 bits - 80% occupancy */
130     9001,       /* 13 bits - 91% occupancy */
131     18013,      /* 14 bits - 91% occupancy */
132     35023,      /* 15 bits - 94% occupancy */
133     69001       /* 16 bits - 95% occupancy */
134 };
135
136 static int  BufCompressedFill(), BufCompressedSkip(), BufCompressedClose();
137
138 BufFilePtr
139 BufFilePushCompressed (f)
140     BufFilePtr  f;
141 {
142     int             code;
143     int             maxbits;
144     int             hsize;
145     CompressedFile  *file;
146     int             extra;
147
148     if ((BufFileGet(f) != (magic_header[0] & 0xFF)) ||
149         (BufFileGet(f) != (magic_header[1] & 0xFF)))
150     {
151         return 0;
152     }
153     code = BufFileGet (f);
154     maxbits = code & BIT_MASK;
155     if (maxbits > BITS || maxbits < 12)
156         return 0;
157     hsize = hsize_table[maxbits - 12];
158     extra = (1 << maxbits) * sizeof (char_type) +
159             hsize * sizeof (unsigned short);
160     file = (CompressedFile *) xalloc (sizeof (CompressedFile) + extra);
161     if (!file)
162         return 0;
163     file->file = f;
164     file->maxbits = maxbits;
165     file->block_compress = code & BLOCK_MASK;
166     file->maxmaxcode = 1 << file->maxbits;
167     file->tab_suffix = (char_type *) &file[1];
168     file->tab_prefix = (unsigned short *) (file->tab_suffix + file->maxmaxcode);
169     /*
170      * As above, initialize the first 256 entries in the table.
171      */
172     file->maxcode = MAXCODE(file->n_bits = INIT_BITS);
173     for ( code = 255; code >= 0; code-- ) {
174         file->tab_prefix[code] = 0;
175         file->tab_suffix[code] = (char_type) code;
176     }
177     file->free_ent = ((file->block_compress) ? FIRST : 256 );
178     file->clear_flg = 0;
179     file->offset = 0;
180     file->size = 0;
181     file->stackp = file->de_stack;
182     file->finchar = file->oldcode = getcode (file);
183     if (file->oldcode != -1)
184         *file->stackp++ = file->finchar;
185     return BufFileCreate ((char *) file,
186                           BufCompressedFill,
187                           BufCompressedSkip,
188                           BufCompressedClose);
189 }
190
191 static int
192 BufCompressedClose (f, doClose)
193     BufFilePtr  f;
194 {
195     CompressedFile  *file;
196     BufFilePtr      raw;
197
198     file = (CompressedFile *) f->private;
199     raw = file->file;
200     xfree (file);
201     BufFileClose (raw, doClose);
202     return 1;
203 }
204
205 static int
206 BufCompressedFill (f)
207     BufFilePtr      f;
208 {
209     CompressedFile  *file;
210     register char_type *stackp, *de_stack;
211     register char_type finchar;
212     register code_int code, oldcode, incode;
213     BufChar         *buf, *bufend;
214
215     file = (CompressedFile *) f->private;
216
217     buf = f->buffer;
218     bufend = buf + BUFFILESIZE;
219     stackp = file->stackp;
220     de_stack = file->de_stack;
221     finchar = file->finchar;
222     oldcode = file->oldcode;
223     while (buf < bufend) {
224         while (stackp > de_stack && buf < bufend)
225             *buf++ = *--stackp;
226
227         if (buf == bufend)
228             break;
229
230         if (oldcode == -1)
231             break;
232
233         code = getcode (file);
234         if (code == -1)
235             break;
236     
237         if ( (code == CLEAR) && file->block_compress ) {
238             for ( code = 255; code >= 0; code-- )
239                 file->tab_prefix[code] = 0;
240             file->clear_flg = 1;
241             file->free_ent = FIRST - 1;
242             if ( (code = getcode (file)) == -1 )        /* O, untimely death! */
243                 break;
244         }
245         incode = code;
246         /*
247          * Special case for KwKwK string.
248          */
249         if ( code >= file->free_ent ) {
250             *stackp++ = finchar;
251             code = oldcode;
252         }
253     
254         /*
255          * Generate output characters in reverse order
256          */
257         while ( code >= 256 )
258         {
259             *stackp++ = file->tab_suffix[code];
260             code = file->tab_prefix[code];
261         }
262         finchar = file->tab_suffix[code];
263         *stackp++ = finchar;
264     
265         /*
266          * Generate the new entry.
267          */
268         if ( (code=file->free_ent) < file->maxmaxcode ) {
269             file->tab_prefix[code] = (unsigned short)oldcode;
270             file->tab_suffix[code] = finchar;
271             file->free_ent = code+1;
272         } 
273         /*
274          * Remember previous code.
275          */
276         oldcode = incode;
277     }
278     file->oldcode = oldcode;
279     file->stackp = stackp;
280     file->finchar = finchar;
281     if (buf == f->buffer) {
282         f->left = 0;
283         return BUFFILEEOF;
284     }
285     f->bufp = f->buffer + 1;
286     f->left = (buf - f->buffer) - 1;
287     return f->buffer[0];
288 }
289
290 /*****************************************************************
291  * TAG( getcode )
292  *
293  * Read one code from the standard input.  If BUFFILEEOF, return -1.
294  * Inputs:
295  *      stdin
296  * Outputs:
297  *      code or -1 is returned.
298  */
299
300 static char_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
301
302 static code_int
303 getcode(file)
304     CompressedFile  *file;
305 {
306     register code_int code;
307     register int r_off, bits;
308     register char_type *bp = file->buf;
309     register BufFilePtr raw;
310
311     if ( file->clear_flg > 0 || file->offset >= file->size ||
312         file->free_ent > file->maxcode )
313     {
314         /*
315          * If the next entry will be too big for the current code
316          * size, then we must increase the size.  This implies reading
317          * a new buffer full, too.
318          */
319         if ( file->free_ent > file->maxcode ) {
320             file->n_bits++;
321             if ( file->n_bits == file->maxbits )
322                 file->maxcode = file->maxmaxcode;       /* won't get any bigger now */
323             else
324                 file->maxcode = MAXCODE(file->n_bits);
325         }
326         if ( file->clear_flg > 0) {
327             file->maxcode = MAXCODE (file->n_bits = INIT_BITS);
328             file->clear_flg = 0;
329         }
330         bits = file->n_bits;
331         raw = file->file;
332         while (bits > 0 && (code = BufFileGet (raw)) != BUFFILEEOF)
333         {
334             *bp++ = code;
335             --bits;
336         }
337         bp = file->buf;
338         if (bits == file->n_bits)
339             return -1;                  /* end of file */
340         file->size = file->n_bits - bits;
341         file->offset = 0;
342         /* Round size down to integral number of codes */
343         file->size = (file->size << 3) - (file->n_bits - 1);
344     }
345     r_off = file->offset;
346     bits = file->n_bits;
347     /*
348      * Get to the first byte.
349      */
350     bp += (r_off >> 3);
351     r_off &= 7;
352     /* Get first part (low order bits) */
353 #ifdef NO_UCHAR
354     code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
355 #else
356     code = (*bp++ >> r_off);
357 #endif /* NO_UCHAR */
358     bits -= (8 - r_off);
359     r_off = 8 - r_off;          /* now, offset into code word */
360     /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
361     if ( bits >= 8 ) {
362 #ifdef NO_UCHAR
363         code |= (*bp++ & 0xff) << r_off;
364 #else
365         code |= *bp++ << r_off;
366 #endif /* NO_UCHAR */
367         r_off += 8;
368         bits -= 8;
369     }
370     /* high order bits. */
371     code |= (*bp & rmask[bits]) << r_off;
372     file->offset += file->n_bits;
373
374     return code;
375 }
376
377 static int
378 BufCompressedSkip (f, bytes)
379     BufFilePtr  f;
380     int         bytes;
381 {
382     int             c;
383     while (bytes--) 
384     {
385         c = BufFileGet(f);
386         if (c == BUFFILEEOF)
387             return BUFFILEEOF;
388     }
389     return 0;
390 }
391
392 #ifdef TEST
393 main (argc, argv)
394     int     argc;
395     char    **argv;
396 {
397     BufFilePtr      inputraw, input, output;
398     int             c;
399     
400     inputraw = BufFileOpenRead (0);
401     input = BufFilePushCompressed (inputraw);
402     output = BufFileOpenWrite (1);
403     while ((c = BufFileGet (input)) != -1)
404         BufFilePut (c, output);
405     BufFileClose (input, FALSE);
406     BufFileClose (output, FALSE);
407 }
408 #endif