egra: more asm microoptimisations; fixed bug in dashed translucent rects
[iv.d.git] / oldpakerz / hapack.d
blobb50317007aabad1058a5508c93cc256db4356882
1 /***********************************************************************
2 * This file is part of HA, a general purpose file archiver.
3 * Copyright (C) 1995 Harri Hirvola
4 * Modified by Ketmar // Invisible Vector
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.
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.
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 module iv.oldpakerz.hapack /*is aliced*/;
21 private:
22 import iv.alice;
25 // ////////////////////////////////////////////////////////////////////////// //
26 alias libha_read_fn = int delegate (void *buf, int buf_len); // return number of bytes read; 0: EOF; <0: error; can be less than buf_len
27 alias libha_write_fn = int delegate (const(void)* buf, int buf_len); // result != buf_len: error
30 // ////////////////////////////////////////////////////////////////////////// //
31 public alias libha_t = libha_s*;
34 // ////////////////////////////////////////////////////////////////////////// //
35 // some constants
36 // ////////////////////////////////////////////////////////////////////////// //
37 // ASC
38 enum POSCODES = 31200; // also, dictionary buffer len for SWD
39 enum SLCODES = 16;
40 enum LLCODES = 48;
41 enum LLLEN = 16;
42 enum LLBITS = 4;
43 enum LLMASK = LLLEN-1;
44 enum LENCODES = SLCODES+LLCODES*LLLEN;
45 enum LTCODES = SLCODES+LLCODES;
46 enum CTCODES = 256;
47 enum PTCODES = 16;
48 enum LTSTEP = 8;
49 enum MAXLT = 750*LTSTEP;
50 enum CTSTEP = 1;
51 enum MAXCT = 1000*CTSTEP;
52 enum PTSTEP = 24;
53 enum MAXPT = 250*PTSTEP;
54 enum TTSTEP = 40;
55 enum MAXTT = 150*TTSTEP;
56 enum TTORD = 4;
57 enum TTOMASK = TTORD-1;
58 enum LCUTOFF = 3*LTSTEP;
59 enum CCUTOFF = 3*CTSTEP;
60 enum CPLEN = 8;
61 enum LPLEN = 4;
62 enum MINLENLIM = 4096;
64 // SWD
65 // Minimum possible match lenght for this implementation
66 enum MINLEN = 3;
67 enum HSIZE = 16384;
68 enum HSHIFT = 3;
69 enum MAXCNT = 1024;
70 // derived
71 enum MAXFLEN = LENCODES+MINLEN-1; // max len to be found
72 enum MAXDLEN = POSCODES+MAXFLEN; // reserved bytes for dict; POSCODES+2*MAXFLEN-1<32768 !!!
74 enum HASH(string p) = "((swd.b["~p~"]^((swd.b["~p~"+1]^(swd.b["~p~"+2]<<HSHIFT))<<HSHIFT))&(HSIZE-1))";
77 // ////////////////////////////////////////////////////////////////////////// //
78 struct io_t {
79 libha_read_fn bread;
80 libha_write_fn bwrite;
81 // input buffer
82 ubyte *bufin;
83 int bufin_pos;
84 int bufin_max;
85 int bufin_size;
86 // output buffer
87 ubyte *bufout;
88 int bufout_pos;
89 int bufout_size;
93 // ////////////////////////////////////////////////////////////////////////// //
94 int get_byte (io_t *io) {
95 if (io.bufin_pos >= io.bufin_max) {
96 if (io.bufin_pos < io.bufin_size+1) {
97 io.bufin_pos = 0;
98 io.bufin_max = io.bread(io.bufin, io.bufin_size);
99 if (io.bufin_max < 0) throw new Exception("read error");
100 if (io.bufin_max == 0) { io.bufin_pos = io.bufin_size+42; return -1; } // EOF
101 } else {
102 return -1; // EOF
105 return io.bufin[io.bufin_pos++];
109 void put_byte (io_t *io, int c) {
110 if (io.bufout_pos >= io.bufout_size) {
111 int res = io.bwrite(io.bufout, io.bufout_pos);
112 if (res != io.bufout_pos) throw new Exception("write error");
113 io.bufout_pos = 0;
115 io.bufout[io.bufout_pos++] = c&0xff;
119 void flush (io_t *io) {
120 if (io.bufout_pos > 0) {
121 int res = io.bwrite(io.bufout, io.bufout_pos);
122 if (res != io.bufout_pos) throw new Exception("write error");
123 io.bufout_pos = 0;
128 // ////////////////////////////////////////////////////////////////////////// //
129 struct swd_t {
130 ushort swd_bpos, swd_mlf;
131 short swd_char;
132 ushort cblen, binb;
133 ushort bbf, bbl, inptr;
134 ushort[HSIZE] ccnt;
135 ushort[MAXDLEN] ll;
136 ushort[HSIZE] cr;
137 ushort[MAXDLEN] best;
138 ubyte[MAXDLEN+MAXFLEN] b; // was:-1
139 ushort blen, iblen;
140 io_t *io;
144 void swd_init (swd_t *swd) {
145 import core.stdc.string : memset;
146 memset(swd.ccnt.ptr, 0, swd.ccnt.sizeof);
147 memset(swd.ll.ptr, 0, swd.ll.sizeof);
148 memset(swd.cr.ptr, 0, swd.cr.sizeof);
149 memset(swd.best.ptr, 0, swd.best.sizeof);
150 memset(swd.b.ptr, 0, swd.b.sizeof);
151 swd.binb = swd.bbf = swd.bbl = swd.inptr = 0;
152 swd.swd_mlf = MINLEN-1;
156 // return -1 on EOF or 0
157 int swd_first_bytes (swd_t *swd) {
158 while (swd.bbl < MAXFLEN) {
159 int b = get_byte(swd.io);
160 if (b < 0) return -1;
161 swd.b[swd.inptr++] = cast(ubyte)b;
162 ++swd.bbl;
164 return 0;
168 void swd_accept (swd_t *swd) {
169 short j = cast(short)(swd.swd_mlf-2);
170 // relies on non changed swd.swd_mlf !!!
171 do {
172 short i;
173 if (swd.binb == POSCODES) --swd.ccnt[mixin(HASH!"swd.inptr")]; else ++swd.binb;
174 i = mixin(HASH!"swd.bbf");
175 swd.ll[swd.bbf] = swd.cr[i];
176 swd.cr[i] = swd.bbf;
177 swd.best[swd.bbf] = 30000;
178 ++swd.ccnt[i];
179 if (++swd.bbf == MAXDLEN) swd.bbf = 0;
180 if ((i = cast(short)get_byte(swd.io)) < 0) {
181 --swd.bbl;
182 if (++swd.inptr == MAXDLEN) swd.inptr = 0;
183 continue;
185 if (swd.inptr < MAXFLEN-1) {
186 swd.b[swd.inptr+MAXDLEN] = swd.b[swd.inptr] = cast(ubyte)i;
187 ++swd.inptr;
188 } else {
189 swd.b[swd.inptr] = cast(ubyte)i;
190 if (++swd.inptr == MAXDLEN) swd.inptr = 0;
192 } while (--j);
193 swd.swd_mlf = MINLEN-1;
197 void swd_findbest (swd_t *swd) {
198 ushort ref_, ptr, start_len;
199 int ch;
200 ushort i = mixin(HASH!"swd.bbf");
201 ushort cnt = swd.ccnt[i];
202 ++swd.ccnt[i];
203 if (cnt > MAXCNT) cnt = MAXCNT;
204 ptr = swd.ll[swd.bbf] = swd.cr[i];
205 swd.cr[i] = swd.bbf;
206 swd.swd_char = swd.b[swd.bbf];
207 if ((start_len = swd.swd_mlf) >= swd.bbl) {
208 if (swd.bbl == 0) swd.swd_char = -1;
209 swd.best[swd.bbf] = 30000;
210 } else {
211 for (ref_ = swd.b[swd.bbf+swd.swd_mlf-1]; cnt--; ptr = swd.ll[ptr]) {
212 if (swd.b[ptr+swd.swd_mlf-1] == ref_ && swd.b[ptr] == swd.b[swd.bbf] && swd.b[ptr+1] == swd.b[swd.bbf+1]) {
213 ubyte *p1 = swd.b.ptr+ptr+3;
214 ubyte *p2 = swd.b.ptr+swd.bbf+3;
215 for (i = 3; i < swd.bbl; ++i) if (*p1++ != *p2++) break;
216 if (i <= swd.swd_mlf) continue;
217 swd.swd_bpos = ptr;
218 if ((swd.swd_mlf = i) == swd.bbl || swd.best[ptr] < i) break;
219 ref_ = swd.b[swd.bbf+swd.swd_mlf-1];
222 swd.best[swd.bbf] = swd.swd_mlf;
223 if (swd.swd_mlf > start_len) {
224 if (swd.swd_bpos < swd.bbf) {
225 swd.swd_bpos = cast(ushort)(swd.bbf-swd.swd_bpos-1);
226 } else {
227 swd.swd_bpos = cast(ushort)(MAXDLEN-1-swd.swd_bpos+swd.bbf);
231 if (swd.binb == POSCODES) --swd.ccnt[mixin(HASH!"swd.inptr")]; else ++swd.binb;
232 if (++swd.bbf == MAXDLEN) swd.bbf = 0;
233 if ((ch = get_byte(swd.io)) < 0) {
234 --swd.bbl;
235 if (++swd.inptr == MAXDLEN) swd.inptr = 0;
236 return;
238 if (swd.inptr < MAXFLEN-1) {
239 swd.b[swd.inptr+MAXDLEN] = swd.b[swd.inptr] = cast(ubyte)ch;
240 ++swd.inptr;
241 } else {
242 swd.b[swd.inptr] = cast(ubyte)ch;
243 if (++swd.inptr == MAXDLEN) swd.inptr = 0;
248 // ////////////////////////////////////////////////////////////////////////// //
249 struct ari_t {
250 ushort h, l, v;
251 short s;
252 short gpat, ppat;
253 io_t *io;
257 // ////////////////////////////////////////////////////////////////////////// //
258 // Bit I/O
259 enum putbit(string b) = "{
260 ari.ppat <<= 1;
261 if ("~b~") ari.ppat |= 1;
262 if (ari.ppat&0x100) {
263 put_byte(ari.io, ari.ppat&0xff);
264 ari.ppat = 1;
269 // ////////////////////////////////////////////////////////////////////////// //
270 // Arithmetic encoding
271 void ac_out (ari_t *ari, ushort low, ushort high, ushort tot) {
272 uint r;
273 if (tot == 0) throw new Exception("data error");
274 r = cast(uint)(ari.h-ari.l)+1;
275 ari.h = cast(ushort)(cast(ushort)(r*high/tot-1)+ari.l);
276 ari.l += cast(ushort)(r*low/tot);
277 if (!((ari.h^ari.l)&0x8000)) {
278 mixin(putbit!"ari.l&0x8000");
279 while (ari.s) {
280 --ari.s;
281 mixin(putbit!"~ari.l&0x8000");
283 ari.l <<= 1;
284 ari.h <<= 1;
285 ari.h |= 1;
286 while (!((ari.h^ari.l)&0x8000)) {
287 mixin(putbit!"ari.l&0x8000");
288 ari.l <<= 1;
289 ari.h <<= 1;
290 ari.h |= 1;
293 while ((ari.l&0x4000) && !(ari.h&0x4000)) {
294 ++ari.s;
295 ari.l <<= 1;
296 ari.l &= 0x7fff;
297 ari.h <<= 1;
298 ari.h |= 0x8001;
303 void ac_init_encode (ari_t *ari) {
304 ari.h = 0xffff;
305 ari.l = ari.s = 0;
306 ari.ppat = 1;
310 void ac_end_encode (ari_t *ari) {
311 ++ari.s;
312 mixin(putbit!"ari.l&0x4000");
313 while (ari.s--) {
314 mixin(putbit!"~ari.l&0x4000");
316 if (ari.ppat == 1) {
317 flush(ari.io);
318 return;
320 while (!(ari.ppat&0x100)) ari.ppat <<= 1;
321 put_byte(ari.io, ari.ppat&0xff);
322 flush(ari.io);
326 // ////////////////////////////////////////////////////////////////////////// //
327 enum BUFIN_SIZE = 1024;
328 enum BUFOUT_SIZE = 1024;
331 struct libha_s {
332 ushort[2*LTCODES] ltab;
333 ushort[2*LTCODES] eltab;
334 ushort[2*PTCODES] ptab;
335 ushort[2*CTCODES] ctab;
336 ushort[2*CTCODES] ectab;
337 ushort[2][TTORD] ttab;
338 ushort accnt, pmax, npt;
339 ushort ces;
340 ushort les;
341 ushort ttcon;
342 swd_t swd;
343 ari_t ari;
344 io_t io;
345 ubyte[BUFIN_SIZE] bufin;
346 ubyte[BUFOUT_SIZE] bufout;
347 // step
348 short fldOc;
349 ushort fldOmlf, fldObpos;
350 int phase; // 0: not initialized; 1: in progress; <0: error
352 version(oldpack_sizes) pragma(msg, libha_s.sizeof); // ~200 KB, wow!
355 void setup_buffers (libha_t asc) {
356 asc.io.bufin = asc.bufin.ptr;
357 asc.io.bufin_size = asc.bufin.sizeof;
358 asc.io.bufin_pos = 0;
359 asc.io.bufin_max = 0;
360 asc.io.bufout = asc.bufout.ptr;
361 asc.io.bufout_size = asc.bufout.sizeof;
362 asc.io.bufout_pos = 0;
366 void tabinit (ushort[] t, ushort tl, ushort ival) {
367 uint i, j;
368 for (i = tl; i < 2*tl; ++i) t[i] = ival;
369 for (i = tl-1, j = (tl<<1)-2; i; --i, j -= 2) t[i] = cast(ushort)(t[j]+t[j+1]);
373 void tscale (ushort[] t, ushort tl) {
374 uint i, j;
375 for (i = (tl<<1)-1; i >= tl; --i) if (t[i] > 1) t[i] >>= 1;
376 for (i = tl-1, j = (tl<<1)-2; i; --i, j -= 2) t[i] = cast(ushort)(t[j]+t[j+1]);
380 void tupd (ushort[] t, ushort tl, ushort maxt, ushort step, ushort p) {
381 int i;
382 for (i = p+tl; i; i >>= 1) t[i] += step;
383 if (t[1] >= maxt) tscale(t, tl);
387 void tzero (ushort[] t, ushort tl, ushort p) {
388 int i;
389 short step;
390 for (i = p+tl, step = t[i]; i; i >>= 1) t[i] -= step;
394 void model_init (libha_t asc) {
395 short i;
396 asc.ces = CTSTEP;
397 asc.les = LTSTEP;
398 asc.accnt = 0;
399 asc.ttcon = 0;
400 asc.npt = asc.pmax = 1;
401 for (i = 0; i < TTORD; ++i) asc.ttab[i][0] = asc.ttab[i][1] = TTSTEP;
402 tabinit(asc.ltab, LTCODES, 0);
403 tabinit(asc.eltab, LTCODES, 1);
404 tabinit(asc.ctab, CTCODES, 0);
405 tabinit(asc.ectab, CTCODES, 1);
406 tabinit(asc.ptab, PTCODES, 0);
407 tupd(asc.ptab, PTCODES, MAXPT, PTSTEP, 0);
411 void pack_init (libha_t asc) {
412 model_init(asc);
413 ac_init_encode(&asc.ari);
417 void ttscale (libha_t asc, ushort con) {
418 asc.ttab[con][0] >>= 1;
419 if (asc.ttab[con][0] == 0) asc.ttab[con][0] = 1;
420 asc.ttab[con][1] >>= 1;
421 if (asc.ttab[con][1] == 0) asc.ttab[con][1] = 1;
425 void codepair (libha_t asc, short l, short p) {
426 ushort i, j, lt, k, cf, tot;
427 i = cast(ushort)(asc.ttab[asc.ttcon][0]+asc.ttab[asc.ttcon][1]);
428 ac_out(&asc.ari, asc.ttab[asc.ttcon][0], i, cast(ushort)(i+1)); // writes
429 asc.ttab[asc.ttcon][1] += TTSTEP;
430 if (i >= MAXTT) ttscale(asc, asc.ttcon);
431 asc.ttcon = ((asc.ttcon<<1)|1)&TTOMASK;
432 while (asc.accnt > asc.pmax) {
433 tupd(asc.ptab, PTCODES, MAXPT, PTSTEP, asc.npt++);
434 asc.pmax <<= 1;
436 for (i = p, j = 0; i; ++j, i >>= 1) {}
437 cf = asc.ptab[PTCODES+j];
438 tot = asc.ptab[1];
439 for (lt = 0, i = cast(ushort)(PTCODES+j); i; i >>= 1) {
440 if (i&1) lt += asc.ptab[i-1];
441 asc.ptab[i] += PTSTEP;
443 if (asc.ptab[1] >= MAXPT) tscale(asc.ptab, PTCODES);
444 ac_out(&asc.ari, lt, cast(ushort)(lt+cf), tot); // writes
445 if (p > 1) {
446 for (i = 0x8000U; !(p&i); i >>= 1) {}
447 j = p&~i;
448 if (i != (asc.pmax>>1)) {
449 ac_out(&asc.ari, j, cast(ushort)(j+1), i); // writes
450 } else {
451 ac_out(&asc.ari, j, cast(ushort)(j+1), cast(ushort)(asc.accnt-(asc.pmax>>1))); // writes
454 i = cast(ushort)(l-MINLEN);
455 if (i == LENCODES-1) {
456 i = SLCODES-1, j = 0xffff;
457 } else if (i < SLCODES-1) {
458 j = 0xffff;
459 } else {
460 j = (i-SLCODES+1)&LLMASK;
461 i = ((i-SLCODES+1)>>LLBITS)+SLCODES;
463 if ((cf = asc.ltab[LTCODES+i]) == 0) {
464 ac_out(&asc.ari, asc.ltab[1], cast(ushort)(asc.ltab[1]+asc.les), cast(ushort)(asc.ltab[1]+asc.les)); // writes
465 for (lt = 0, k = cast(ushort)(LTCODES+i); k; k >>= 1) {
466 if (k&1) lt += asc.eltab[k-1];
467 asc.ltab[k] += LTSTEP;
469 if (asc.ltab[1] >= MAXLT) tscale(asc.ltab, LTCODES);
470 ac_out(&asc.ari, lt, cast(ushort)(lt+asc.eltab[LTCODES+i]), asc.eltab[1]); // writes
471 tzero(asc.eltab, LTCODES, i);
472 if (asc.eltab[1] != 0) asc.les += LTSTEP; else asc.les = 0;
473 for (k = cast(ushort)(i <= LPLEN ? 0 : i-LPLEN); k < (i+LPLEN >= LTCODES-1 ? LTCODES-1 : i+LPLEN); ++k) {
474 if (asc.eltab[LTCODES+k]) tupd(asc.eltab, LTCODES, MAXLT, 1, k);
476 } else {
477 tot = cast(ushort)(asc.ltab[1]+asc.les);
478 for (lt = 0, k = cast(ushort)(LTCODES+i); k; k >>= 1) {
479 if (k&1) lt += asc.ltab[k-1];
480 asc.ltab[k] += LTSTEP;
482 if (asc.ltab[1] >= MAXLT) tscale(asc.ltab, LTCODES);
483 ac_out(&asc.ari, lt, cast(ushort)(lt+cf), tot); // writes
485 if (asc.ltab[LTCODES+i] == LCUTOFF) asc.les -= (LTSTEP < asc.les ? LTSTEP : asc.les-1);
486 if (j != 0xffff) ac_out(&asc.ari, j, cast(ushort)(j+1), LLLEN); // writes
487 if (asc.accnt < POSCODES) {
488 asc.accnt += l;
489 if (asc.accnt > POSCODES) asc.accnt = POSCODES;
494 void codechar (libha_t asc, short c) {
495 ushort i, lt, tot, cf;
496 i = cast(ushort)(asc.ttab[asc.ttcon][0]+asc.ttab[asc.ttcon][1]);
497 ac_out(&asc.ari, 0, asc.ttab[asc.ttcon][0], cast(ushort)(i+1)); // writes
498 asc.ttab[asc.ttcon][0] += TTSTEP;
499 if (i >= MAXTT) ttscale(asc, asc.ttcon);
500 asc.ttcon = (asc.ttcon<<1)&TTOMASK;
501 if ((cf = asc.ctab[CTCODES+c]) == 0) {
502 ac_out(&asc.ari, asc.ctab[1], cast(ushort)(asc.ctab[1]+asc.ces), cast(ushort)(asc.ctab[1]+asc.ces)); // writes
503 for (lt = 0, i = cast(ushort)(CTCODES+c); i; i >>= 1) {
504 if (i&1) lt += asc.ectab[i-1];
505 asc.ctab[i] += CTSTEP;
507 if (asc.ctab[1] >= MAXCT) tscale(asc.ctab, CTCODES);
508 ac_out(&asc.ari, lt, cast(ushort)(lt+asc.ectab[CTCODES+c]), asc.ectab[1]); // writes
509 tzero(asc.ectab, CTCODES, c);
510 if (asc.ectab[1] != 0) asc.ces += CTSTEP; else asc.ces = 0;
511 for (i = cast(ushort)(c <= CPLEN ? 0 : c-CPLEN); i < (c+CPLEN >= CTCODES-1 ? CTCODES-1 : c+CPLEN); ++i) {
512 if (asc.ectab[CTCODES+i]) tupd(asc.ectab, CTCODES, MAXCT, 1, i);
514 } else {
515 tot = cast(ushort)(asc.ctab[1]+asc.ces);
516 for (lt = 0, i = cast(ushort)(CTCODES+c); i; i >>= 1) {
517 if (i&1) lt += asc.ctab[i-1];
518 asc.ctab[i] += CTSTEP;
520 if (asc.ctab[1] >= MAXCT) tscale(asc.ctab, CTCODES);
521 ac_out(&asc.ari, lt, cast(ushort)(lt+cf), tot); // writes
523 if (asc.ctab[CTCODES+c] == CCUTOFF) asc.ces -= (CTSTEP < asc.ces ? CTSTEP : asc.ces-1);
524 if (asc.accnt < POSCODES) ++asc.accnt;
528 // ////////////////////////////////////////////////////////////////////////// //
529 public libha_t libha_create () {
530 import core.stdc.stdlib : calloc;
531 return cast(libha_t)calloc(1, libha_s.sizeof);
535 public void libha_free (libha_t asc) {
536 import core.stdc.stdlib : free;
537 if (asc != null) free(asc);
541 public void libha_reset (libha_t asc) {
542 if (asc !is null) {
543 import core.stdc.string : memset;
544 memset(asc, 0, (*asc).sizeof);
549 // return `false` when finished, or `true` if packer needs more steps
550 public bool libha_pack_step (libha_t asc, libha_read_fn rd, libha_write_fn wr) {
551 //swd_findbest(): reads
552 if (asc is null || asc.phase < 0 || rd is null || wr is null) throw new Exception("hapack error");
553 asc.io.bread = rd;
554 asc.io.bwrite = wr;
555 asc.swd.io = asc.ari.io = &asc.io;
556 scope(exit) {
557 asc.io.bread = null;
558 asc.io.bwrite = null;
559 asc.swd.io = asc.ari.io = null;
561 // init?
562 if (asc.phase == 0) {
563 asc.phase = -1; // so throw will end up in error
564 setup_buffers(asc);
565 swd_init(&asc.swd);
566 swd_first_bytes(&asc.swd); // reads MAXFLEN bytes
567 pack_init(asc);
568 swd_findbest(&asc.swd);
569 asc.phase = 1;
571 assert(asc.phase == 1);
572 if (asc.swd.swd_char < 0) {
573 // finish
574 asc.phase = -1; // so next call will end up in error
575 ac_out(&asc.ari, cast(ushort)(asc.ttab[asc.ttcon][0]+asc.ttab[asc.ttcon][1]), cast(ushort)(asc.ttab[asc.ttcon][0]+asc.ttab[asc.ttcon][1]+1), cast(ushort)(asc.ttab[asc.ttcon][0]+asc.ttab[asc.ttcon][1]+1));
576 ac_end_encode(&asc.ari);
577 return false;
579 if (asc.swd.swd_mlf > MINLEN || (asc.swd.swd_mlf == MINLEN && asc.swd.swd_bpos < MINLENLIM)) {
580 asc.fldOmlf = asc.swd.swd_mlf;
581 asc.fldObpos = asc.swd.swd_bpos;
582 asc.fldOc = asc.swd.swd_char;
583 swd_findbest(&asc.swd); // reads
584 if (asc.swd.swd_mlf > asc.fldOmlf) {
585 codechar(asc, asc.fldOc);
586 } else {
587 swd_accept(&asc.swd); // reads
588 codepair(asc, asc.fldOmlf, asc.fldObpos);
589 swd_findbest(&asc.swd); // reads
591 } else {
592 asc.swd.swd_mlf = MINLEN-1;
593 codechar(asc, asc.swd.swd_char);
594 swd_findbest(&asc.swd); // reads
596 asc.phase = 1; // go on
597 return true;