home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / BBS_UTIL / BGFAX121.ZIP / SOURCE.ZIP / VIEW.PAS < prev   
Pascal/Delphi Source File  |  1994-03-25  |  22KB  |  800 lines

  1. program
  2.   view;
  3. {.R+}   (* active range checking only while debuging program, decodes about
  4.            three times faster with range checking turned off *)
  5. uses
  6.   dos, crt;
  7.  
  8. {$i faxtree.pas}
  9. const
  10.   mrcoding = false;
  11.   maxfaxbuf = 8192;
  12.   maxoutbuf = 65534; { keep at this value, so doesn't wrap to 0 when INC'ed }
  13.   maxlinelen = 215; { 0..215, i.e., 216 bytes }
  14.   base2 : array[1..8] of word = (1, 2, 4, 8, 16, 32, 64, 128);
  15.   base2r : array[1..8] of word = (128, 64, 32, 16, 8, 4, 2, 1);
  16.   maxscanlinerec = 2560;
  17.   gfx : array[0..2] of array[0..2] of word = (
  18.     ($11,464{480},$a000){VGA}, ($0f,334{350},$a000){EGA}, ($6,200,$b800){CGA});
  19.   gmode : byte = 0;
  20.   shownpage : boolean = false;
  21.   revbitord : boolean = false;
  22.   displaybad : boolean = false;
  23.  
  24. type
  25.   scanlinerec = record
  26.     scanline : array[0..maxlinelen] of byte;
  27.   end;
  28.   scanlinearray = array[1..maxscanlinerec] of ^scanlinerec;
  29.   outbuftype = array[1..maxoutbuf] of byte;
  30.   pcxrec = record
  31.     zsoft    : byte;
  32.     version  : byte;
  33.     encoding : byte;
  34.     bitpix   : byte;
  35.     dimens   : array[1..4] of word;
  36.     hres     : word;
  37.     vres     : word;
  38.     palette  : array[1..48] of byte;
  39.     reserved : byte;
  40.     planes   : byte;
  41.     byteline : word;
  42.     paltype  : word;
  43.     xssize   : word;
  44.     yssize   : word;
  45.     filler   : array[1..54] of byte;
  46.   end;
  47.   zfaxhead = record
  48.     header   : array[1..5] of char;
  49.     offset   : byte;
  50.     version  : word;
  51.     reserved : word;
  52.     pgwidth  : word;
  53.     pgcount  : word;
  54.     coding   : word;
  55.   end;
  56.   qfaxhead = record
  57.     header   : array[1..8] of char;
  58.     pgcount  : word;
  59.     lastscan : word;
  60.     totscan  : longint;
  61.     hscale   : word;
  62.     vscale   : word;
  63.     filler   : array[1..12] of char;
  64.     pgpoint  : array[1..376] of longint;
  65.   end;
  66.  
  67. var
  68.   faxfile, outfile : file;
  69.   pcx : pcxrec; zfax : zfaxhead; qfax : qfaxhead;
  70.   page, maxpages, lines, badlines, bytesread, bufbit, bufbyte,
  71.     outbufp, padlines : word;
  72.   startclock : real;
  73.   faxbuf : array[1..maxfaxbuf] of byte;
  74.   outbuf : ^outbuftype;
  75.   scanlinebuf : array[0..maxlinelen] of byte;
  76.   fillbits, faxsize, faxpos : longint;
  77.   endoffile, mhline, endofpage : boolean;
  78.   regs : registers;
  79.   scanlinep : ^scanlinearray;
  80.   scanline : scanlinerec;
  81.   fopen : string[79];
  82.   ofn : string[8];
  83.   pagepos : array[1..128] of longint;
  84.   sqzary : array[1..80] of byte;
  85.  
  86. function dosclock : real;
  87. var
  88.   regs : registers;
  89. begin
  90.   regs.ah := $2c;
  91.   msdos(regs);
  92.   dosclock := regs.ch*3600+regs.cl*60.0+regs.dh+regs.dl/100.0;
  93. end;
  94.  
  95. procedure fatal(s : string);
  96. begin
  97.   if shownpage then
  98.     textmode(3);
  99.   writeln;
  100.   writeln;
  101.   writeln(#7'Fatal Error: '+s);
  102.   halt(1);
  103. end;
  104.  
  105. function bswap(code : byte) : byte; assembler;
  106. asm
  107.   mov dl,code
  108.   xor ax,ax
  109.   mov cx,8
  110.  @loop: shr dl,1
  111.   rcl al,1
  112.   loop @loop
  113. end;
  114.  
  115. procedure flipfax;
  116. var
  117.   i : word;
  118.   j, t, p : byte;
  119. begin
  120.   for i := 1 to (lines div 2) do begin
  121.     move(scanlinep^[i]^.scanline, scanlinebuf, sizeof(scanlinebuf));
  122.     move(scanlinep^[lines-i+1]^.scanline, scanlinep^[i]^.scanline,
  123.       sizeof(scanlinebuf));
  124.     move(scanlinebuf, scanlinep^[lines-i+1]^.scanline, sizeof(scanlinebuf));
  125.   end;
  126.   for i := 1 to lines do begin
  127.     if i mod 64 = 0 then
  128.       sound(100);
  129.     for j := 0 to 107 do begin
  130.       p := 215-j;
  131.       t := bswap(scanlinep^[i]^.scanline[j]);
  132.       scanlinep^[i]^.scanline[j] := bswap(scanlinep^[i]^.scanline[p]);
  133.       scanlinep^[i]^.scanline[p] := t;
  134.     end;
  135.     if i mod 64 = 0 then
  136.       nosound;
  137.   end;
  138. end;
  139.  
  140. procedure invertfax;
  141. var
  142.   i, j : word;
  143. begin
  144.   for i := 1 to lines do begin
  145.     if i mod 128 = 0 then
  146.       sound(100);
  147.     for j := 0 to maxlinelen do
  148.       scanlinep^[i]^.scanline[j] := scanlinep^[i]^.scanline[j] xor 255;
  149.     if i mod 128 = 0 then
  150.       nosound;
  151.   end;
  152. end;
  153.  
  154. function is(l : longint) : string;
  155. var
  156.   s : string;
  157. begin
  158.   str(l, s);
  159.   is := s;
  160. end;
  161.  
  162. function rp(s : string; l : byte) : string;
  163. var
  164.   ss : string;
  165. begin
  166.   fillchar(ss[1], l, #32);
  167.   move(s[1], ss[1], length(s));
  168.   ss[0] := chr(l);
  169.   rp := ss;
  170. end;
  171.  
  172.  
  173. function viewfax(partial : boolean) : char;
  174. var
  175.   x, y, ymost : word;
  176.   gk, ge : char;
  177.  
  178.   procedure movefax;
  179.   var
  180.     i, dx, dy, ymax : word;
  181.   begin
  182.     dx := x*8;
  183.     dy := y*32;
  184.     if gmode = 2 then begin { cga, interlaced mode }
  185.       ymax := (gfx[gmode][1] div 2)-1;
  186.       for i := 4 to ymax do begin
  187.         inc(dy, 2);
  188.         move(scanlinep^[dy]^.scanline[dx], mem[gfx[gmode][2]:80*i], 80);
  189.       end;
  190.       dy := y*32+1;
  191.       ymax := (gfx[gmode][1])-1;
  192.       for i := 4+(gfx[gmode][1] div 2) to ymax do begin
  193.        inc(dy, 2);
  194.        move(scanlinep^[dy]^.scanline[dx], mem[gfx[gmode][2]:192+80*i], 80);
  195.       end;
  196.     end else begin { ega/vga }
  197.       ymax := gfx[gmode][1]-1 + 16;
  198.       for i := 16{0} to ymax do begin
  199.         inc(dy);
  200.         move(scanlinep^[dy]^.scanline[dx], mem[gfx[gmode][2]:80*i], 80);
  201.       end;
  202.     end;
  203.   end;
  204.  
  205.   procedure shrinkfax;
  206.   var
  207.     i, dx, dy, ymax : word;
  208.    procedure makesqz(y : word);
  209.    var a : byte;
  210.    begin
  211.      for a := 1 to 72 do begin
  212.        sqzary[a] :=
  213.          (scanlinep^[dy]^.scanline[a*3-3] and 128){1} +
  214.          (scanlinep^[dy]^.scanline[a*3-2] and 8){16};
  215.        if (scanlinep^[dy]^.scanline[a*3-3] and 16){2} = 16 then
  216.          sqzary[a] := sqzary[a] xor 64;
  217.        if (scanlinep^[dy]^.scanline[a*3-3] and 2){4} = 2 then
  218.          sqzary[a] := sqzary[a] xor 32;
  219.        if (scanlinep^[dy]^.scanline[a*3-2] and 64){8} = 64 then
  220.          sqzary[a] := sqzary[a] xor 16;
  221.        if (scanlinep^[dy]^.scanline[a*3-2] and 1){32} = 1 then
  222.          sqzary[a] := sqzary[a] xor 4;
  223.        if (scanlinep^[dy]^.scanline[a*3-1] and 32){64} = 32 then
  224.          sqzary[a] := sqzary[a] xor 2;
  225.        if (scanlinep^[dy]^.scanline[a*3-1] and 4){128} = 4 then
  226.          sqzary[a] := sqzary[a] xor 1;
  227.        end;
  228.      move(sqzary, mem[gfx[gmode][2]:y], 80)
  229.    end;
  230.   begin
  231.     dx := x*8;
  232.     dy := y*32;
  233.     if gmode = 2 then begin { cga, interlaced mode }
  234.       ymax := (gfx[gmode][1] div 2)-1;
  235.       for i := 4 to ymax do begin
  236.         inc(dy, 2);
  237.         makesqz(80*i);
  238.       end;
  239.       dy := y*32+1;
  240.       ymax := (gfx[gmode][1])-1;
  241.       for i := 4+(gfx[gmode][1] div 2) to ymax do begin
  242.        inc(dy, 2);
  243.        makesqz(192+80*i);
  244.       end;
  245.     end else begin { ega/vga }
  246.       ymax := gfx[gmode][1]-1 + 16;
  247.       for i := 16{0} to ymax do begin
  248.         inc(dy);
  249.         makesqz(80*i);
  250.       end;
  251.     end;
  252.   end;
  253.  
  254. begin
  255.   if not partial then begin
  256.     if gmode >= 200 then begin
  257.       inc(faxpos, bufbyte);
  258.       blockwrite(outfile, outbuf^, outbufp, x);
  259.       close(outfile);
  260.       reset(outfile, 1);
  261.       writeln;
  262.       writeln('PCX File Size [', filesize(outfile) div 1024, 'K]');
  263.       blockread(outfile, outbuf^, sizeof(pcxrec), x);
  264.       move(outbuf^, pcx, sizeof(pcxrec));
  265.       pcx.dimens[4] := lines-1; { updating number of lines }
  266.       move(pcx, outbuf^, sizeof(pcxrec));
  267.       seek(outfile, 0);
  268.       blockwrite(outfile, outbuf^, sizeof(pcxrec), x);
  269.       close(outfile);
  270.       viewfax := #81;
  271.       exit;
  272.     end;
  273.     if lines = 0 then
  274.       fatal('no valid scan lines detected');
  275.     fillchar(scanlinebuf, sizeof(scanlinebuf), 85);
  276.     if lines < gfx[gmode][1] then begin
  277.       ymost := 0;
  278.       for y := lines+1 to gfx[gmode][1] do begin
  279.         if memavail > sizeof(scanlinerec) then begin
  280.           inc(padlines);
  281.           new(scanlinep^[y]);
  282.           move(scanlinebuf, scanlinep^[y]^, sizeof(scanlinebuf));
  283.         end;
  284.       end;
  285.     end else begin
  286.       y := lines-gfx[gmode][1];
  287.       x := lines;
  288.       repeat { fill boundries }
  289.         inc(y);
  290.         inc(x);
  291.         if memavail > sizeof(scanlinerec) then begin
  292.           inc(padlines);
  293.           new(scanlinep^[x]);
  294.           move(scanlinebuf, scanlinep^[x]^, sizeof(scanlinebuf));
  295.         end;
  296.       until(y mod 32 = 0);
  297.       ymost := y div 32;
  298.     end;
  299.   end;
  300.   x := 0;
  301.   y := 0;
  302.   if (partial) or (not shownpage) then begin
  303.     shownpage := true;
  304.     directvideo := false;
  305.     gotoxy(1,1);
  306.     regs.ax := gfx[gmode][0]; { switch to graphics mode }
  307.     intr($10, regs);
  308.     movefax;
  309.     write('[WAIT]'#13);
  310.     if partial then
  311.       exit;
  312.   end;
  313.   inc(faxpos, bufbyte);
  314.   write(rp('Page '+is(page)+'/'+is(maxpages)+'... '+is(lines)+' scan lines, '+
  315.     is(badlines)+' bad lines', 79)+#13);
  316.   sound(2000);
  317.   delay(100);
  318.   nosound;
  319.   repeat
  320.     repeat
  321.     until(keypressed);
  322.     gk := readkey;
  323.     if gk = #0 then begin
  324.       ge := readkey;
  325.       case ge of
  326.         #23 : begin {alt-i}
  327.           invertfax;
  328.           movefax;
  329.         end;
  330.         #31 : begin {alt-s}
  331.           shrinkfax;
  332.         end;
  333.         #33 : begin {alt-f}
  334.           flipfax;
  335.           movefax;
  336.         end;
  337.         #75 : begin {left}
  338.           if x > 0 then begin
  339.             dec(x);
  340.             movefax;
  341.           end;
  342.         end;
  343.         #77 : begin {right}
  344.           if x < 17 then begin
  345.             inc(x);
  346.             movefax;
  347.           end;
  348.         end;
  349.         #72 : begin {up}
  350.           if y > 0 then begin
  351.             dec(y);
  352.             movefax;
  353.           end;
  354.         end;
  355.         #80 : begin {down}
  356.           if y < ymost then begin
  357.             inc(y);
  358.             movefax;
  359.           end;
  360.         end;
  361.         #73 : begin
  362.           viewfax := #73;
  363.           exit;
  364.         end;
  365.         #81 : begin {pgdn}
  366.           viewfax := #81;
  367.           exit;
  368.         end;
  369.       end;
  370.     end;
  371.   until(gk=#27);
  372.   viewfax := #0;
  373. end;
  374.  
  375. procedure loadingblock;
  376. begin
  377.   clreol;
  378.   write(rp('Loading... '+is(filepos(faxfile) div 1024)+'K read, '+
  379.     is(lines)+' scan lines, '+is(badlines)+' bad lines, '+
  380.     is(memavail div 1024)+'K mem free', 79)+#13);
  381.   {write('[', filepos(faxfile) div 1024, 'K]  Memory [',
  382.     memavail div 1024, 'K]  Scan Lines [', lines, ']  Bad [',
  383.     badlines, ']  Fill Bytes [', fillbits div 8, ']'#13);}
  384. end;
  385.  
  386. function readbit : byte;
  387. begin
  388.   if bufbit = 7 then begin
  389.     bufbit := 0;
  390.     inc(bufbyte);
  391.     if bufbyte > bytesread then begin
  392.       inc(faxpos, bufbyte);
  393.       bufbyte := 1;
  394.       if not endoffile then begin
  395.         blockread(faxfile, faxbuf, sizeof(faxbuf), bytesread);
  396.         loadingblock;
  397.         if filepos(faxfile) >= faxsize then
  398.           endoffile := true;
  399.       end else begin
  400.         write(#7+rp('WARNING: fax file terminates without RTC', 79)+#13);
  401.         delay(1000);
  402.         endofpage := true;
  403.         maxpages := page;
  404.         faxbuf[1] := 0;
  405.         faxbuf[2] := 128; { dummy EOL }
  406.         bytesread := 2;
  407.       end;
  408.     end;
  409.     if revbitord then
  410.       faxbuf[bufbyte] := bswap(faxbuf[bufbyte]);
  411.     readbit := faxbuf[bufbyte] and 1;
  412.   end else begin
  413.     inc(bufbit);
  414.     readbit := (faxbuf[bufbyte] shr bufbit) and 1;
  415.   end;
  416. end;
  417.  
  418. function findrun(color : boolean) : integer;
  419. var
  420.   k, j, value : integer;
  421.   bit : byte;
  422.   ch : char;
  423. begin
  424.   if keypressed then begin
  425.     ch := readkey;
  426.     if ch = #27 then begin
  427.       if shownpage then
  428.         textmode(3);
  429.       close(faxfile);
  430.       writeln;
  431.       writeln('Fax load terminated by user.');
  432.       halt;
  433.     end else begin
  434.       sound(100);
  435.       delay(100);
  436.       nosound;
  437.       write(rp('The facsimile image has not yet finished loading.', 79)+#13);
  438.     end;
  439.   end;
  440.   value := 0;
  441.   repeat
  442.     k := 0;
  443.     if color then begin {white}
  444.       repeat
  445.         bit := readbit;
  446.         k := whiteh[k][bit];
  447.       until(whiteh[k][2] > -9); { read until hit tree root }
  448.       j := whiteh[k][2];
  449.     end else begin
  450.       repeat
  451.         bit := readbit;
  452.         k := blackh[k][bit];
  453.       until(blackh[k][2] > -9);
  454.       j := blackh[k][2];
  455.     end;
  456.     inc(value, j);
  457.   until(j < 64);
  458.   if j = -2 then begin { fill }
  459.     while readbit=0 do
  460.       inc(fillbits);
  461.     value := -1;
  462.   end;
  463.   findrun := value;
  464. end;
  465.  
  466. procedure putoutbuf(b : byte);
  467. var
  468.   zz : word;
  469. begin
  470.   inc(outbufp);
  471.   if outbufp > maxoutbuf then begin
  472.     blockwrite(outfile, outbuf^, maxoutbuf, zz);
  473.     outbufp := 1;
  474.   end;
  475.   outbuf^[outbufp] := b;
  476. end;
  477.  
  478. function zp(s : string; l : byte) : string;
  479. begin
  480.   while length(s) < l do
  481.     s := '0'+s;
  482.   zp := s;
  483. end;
  484.  
  485. procedure decodeblock;
  486. var
  487.   bit, slbit, r, v, ceol : byte;
  488.   k, j, run : integer;
  489.   io, runlen, i, slbyte : word;
  490.   color : boolean;
  491. begin
  492.   if gmode >= 200 then begin
  493.     fopen := ofn+'.P'+zp(is(page), 2);
  494.     writeln('Writing ['+fopen+']');
  495.     assign(outfile, fopen);
  496.     rewrite(outfile, 1);
  497.     fillchar(pcx, sizeof(pcx), #0);
  498.     pcx.zsoft := 10;
  499.     pcx.version := 5;
  500.     pcx.encoding := 1;
  501.     pcx.bitpix := 1;
  502.     pcx.dimens[1] := 0;
  503.     pcx.dimens[2] := 0;
  504.     pcx.dimens[3] := 1727;
  505.     pcx.dimens[4] := 0; { this needs to be updated after conversion }
  506.     pcx.hres := 640;
  507.     pcx.vres := 480;
  508.     pcx.planes := 1;
  509.     pcx.byteline := 216;
  510.     pcx.paltype := 1;
  511.     pcx.xssize := 640;
  512.     pcx.yssize := 480;
  513.     move(pcx, outbuf^, sizeof(pcxrec));
  514.     blockwrite(outfile, outbuf^, sizeof(pcxrec), io);
  515.     outbufp := 0; { keep at zero }
  516.   end;
  517.   endoffile := false;
  518.   endofpage := false;
  519.   bytesread := 0;
  520.   bufbit := 7;
  521.   bufbyte := 1;
  522.   lines := 0;
  523.   padlines := 0;
  524.   badlines := 0;
  525.   fillbits := 0;
  526.   ceol := 0;
  527.   repeat
  528.     run := findrun(true);
  529.   until(run=-1); { faxes always start with an EOL }
  530.   if mrcoding then begin { if two dimensional }
  531.     bit := readbit; { first bit after FIRST EOL should always be 1 }
  532.     if bit = 0 then { MR-coding }
  533.       fatal('file probably not 2D-MR encoding');
  534.   end;
  535.   mhline := true; { first scan line is 1d coding, all fax types }
  536.   repeat
  537.     if mhline then begin { 1d-scan line, modified huffman coding }
  538.       runlen := 0;
  539.       color := true;
  540.       fillchar(scanlinebuf, sizeof(scanlinebuf), #255); { default white }
  541.       repeat
  542.         run := findrun(color);
  543.         if run > 0 then begin
  544.           if not color then begin
  545.             slbyte := (runlen) div 8;
  546.             slbit := ((runlen) mod 8)+1;
  547.             inc(runlen, run);
  548.             if slbyte + (run+slbit-2) div 8 <= maxlinelen then begin {rangechk}
  549.               for i := 1 to run do begin
  550.                 scanlinebuf[slbyte] := scanlinebuf[slbyte] xor base2r[slbit];
  551.                 if slbit = 8 then begin
  552.                   inc(slbyte);
  553.                   slbit := 1;
  554.                 end else
  555.                   inc(slbit);
  556.               end;
  557.             end;
  558.           end else
  559.             inc(runlen, run);
  560.         end;
  561.         color := not color;
  562.       until(run=-1);
  563.       if (runlen = 1728) or ((runlen > 0) and (displaybad)) then begin
  564.         if runlen <> 1728 then
  565.           inc(badlines);
  566.         ceol := 0;
  567.         inc(lines);
  568.         if gmode < 200 then begin
  569.           if ((lines>maxscanlinerec) or (memavail<sizeof(scanlinerec))) then begin
  570.             dec(lines);
  571.             loadingblock;
  572.             if pagepos[page+1] = 0 then begin { don't add already processed pages }
  573.               write(#7+rp('WARNING: not enough memory to view entire fax page', 79)+#13);
  574.               delay(1000);
  575.               inc(maxpages); { add "fake" extra page so can see all }
  576.             end;
  577.             exit;
  578.           end;
  579.           new(scanlinep^[lines]);
  580.           move(scanlinebuf, scanlinep^[lines]^, sizeof(scanlinebuf));
  581.           if lines = gfx[gmode][1] then
  582.             viewfax(true);
  583.         end else begin
  584.           i := 0; { pcx conversion routines }
  585.           while i <= maxlinelen do begin
  586.             if (i < maxlinelen) and (scanlinebuf[i] = scanlinebuf[i+1]) then begin { RLE encoding }
  587.               if i + 63 > maxlinelen then
  588.                 v := maxlinelen - i + 1
  589.               else
  590.                 v := 63;
  591.               r := 2;
  592.               while (r < v) and (scanlinebuf[i]=scanlinebuf[i+r]) do
  593.                 inc(r);
  594.               putoutbuf(r+192); { 1st 2 bits indicate compression }
  595.               putoutbuf(scanlinebuf[i]);
  596.               inc(i, r);
  597.             end else begin
  598.               if (scanlinebuf[i] and 192) = 192 then begin
  599.                 putoutbuf(193); { repetion, one count }
  600.                 putoutbuf(scanlinebuf[i]);
  601.               end else
  602.                 putoutbuf(scanlinebuf[i]);
  603.               inc(i);
  604.             end;
  605.           end;
  606.         end;
  607.       end else if runlen > 0 then begin
  608.         inc(badlines);
  609.         if (gmode < 200) and (memavail > sizeof(scanlinerec)) then begin
  610.           fillchar(scanlinebuf, sizeof(scanlinebuf), 238);
  611.           inc(lines);
  612.           new(scanlinep^[lines]);
  613.           move(scanlinebuf, scanlinep^[lines]^, sizeof(scanlinebuf));
  614.         end;
  615.       end else begin
  616.         inc(ceol);
  617.         if ceol = 5 then
  618.           endofpage := true; { encountered RTC }
  619.       end;
  620.     end else begin { 2d-line, modified read coding NOT FUNCTIONAL!!! }
  621.       writeln;
  622.       writeln('2d line follows');
  623.       repeat
  624.         k := 0;
  625.         repeat
  626.           bit := readbit;
  627.           k := twodr[k][bit];
  628.         until(twodr[k][2] > -9); { read until hit tree root }
  629.         j := twodr[k][2];
  630.         writeln(j);
  631.         if j = 8999 then
  632.           writeln(#7, 'need MH coding');
  633.       until(j > 9000);
  634.       if j = 9002 then begin { fill }
  635.         while readbit=0 do
  636.           inc(fillbits);
  637.       end;
  638.       writeln('END OF 2D LINE');
  639.       halt;
  640.     end;
  641.     if mrcoding then begin
  642.       if readbit = 1 then { check bit following EOL }
  643.         mhline := true { 1d }
  644.       else
  645.         mhline := false; { 2d }
  646.     end;
  647.   until(endofpage);
  648.   loadingblock;
  649.   exit;
  650. end;
  651.  
  652. function ucase(s : string) : string;
  653. var
  654.   i : byte;
  655. begin
  656.   for i := 1 to length(s) do
  657.     s[i] := upcase(s[i]);
  658.   ucase := s;
  659. end;
  660.  
  661. procedure mainloop;
  662. var
  663.   fn : string[79];
  664.   s : string;
  665.   io : word;
  666.   ge : char;
  667. begin
  668.   writeln('VIEW 1.21, BGFAX fax viewer/PCX converter utility.');
  669.   writeln('Copyright (C) 1994 B.J. Guillot.  All Rights Reserved.');
  670.   writeln;
  671.   if paramcount = 0 then begin
  672.     writeln('VIEW filename [/VGA|/EGA|/CGA|/PCX]');
  673.     halt;
  674.   end;
  675.   fn := ucase(paramstr(1));
  676.   if paramcount > 1 then begin
  677.     for io := 2 to paramcount do begin
  678.       s := ucase(paramstr(io));
  679.       if s[1] = '/' then begin
  680.         delete(s, 1, 1);
  681.         if s = 'VGA' then
  682.           gmode := 0
  683.         else if s = 'EGA' then
  684.           gmode := 1
  685.         else if s = 'CGA' then
  686.           gmode := 2
  687.         else if s = 'PCX' then
  688.           gmode := 200
  689.         else if s = 'DB' then
  690.           displaybad := true
  691.         else if s = 'BO' then
  692.           revbitord := true;
  693.       end;
  694.     end;
  695.   end;
  696.   fillchar(sqzary, sizeof(sqzary), #0);
  697.   startclock := dosclock;
  698.   if pos('.', fn) = 0 then
  699.     fn := fn+'.FAX';
  700.   write('Memory [', memavail div 1024, 'K]  File ['+fn+']  ');
  701.   assign(faxfile, fn);
  702.   {$i-}
  703.     reset(faxfile, 1);
  704.     io := ioresult;
  705.     if io > 0 then begin
  706.       writeln('I/O error [', io, ']');
  707.       fatal('cannot open input file');
  708.     end;
  709.   {$i+}
  710.   faxsize := filesize(faxfile);
  711.   writeln('Size [', faxsize div 1024, 'K]');
  712.   writeln;
  713.   if displaybad then
  714.     writeln('Display bad scan line mode.');
  715.   if gmode < 200 then begin
  716.     if memavail < sizeof(scanlinearray) then
  717.       fatal('not enough memory to initialize scanline table');
  718.     new(scanlinep);
  719.   end else begin
  720.     fopen := fn;
  721.     io := pos(':', fopen);
  722.     delete(fopen, 1, io);
  723.     repeat
  724.       io := pos('\', fopen);
  725.       if io > 0 then
  726.         delete(fopen, 1, io);
  727.     until(io=0);
  728.     io := pos('.', fopen);
  729.     if io > 0 then
  730.       delete(fopen, io, length(fopen)-io+1);
  731.     ofn := fopen;
  732.     writeln('FAX -> PCX conversion mode.');
  733.     writeln;
  734.     if memavail < sizeof(outbuf) then
  735.       fatal('not enough memory to initialize output buffer');
  736.     new(outbuf);
  737.   end;
  738.   page := 1;
  739.   blockread(faxfile, faxbuf, sizeof(zfax), bytesread);
  740.   move(faxbuf, zfax, sizeof(zfax));
  741.   if zfax.header <> 'ZyXEL' then begin
  742.     reset(faxfile, 1);
  743.     blockread(faxfile, faxbuf, sizeof(qfax), bytesread);
  744.     move(faxbuf, qfax, sizeof(qfax));
  745.     if qfax.header <> 'QLIIFAX ' then begin
  746.       writeln('Cannot identify fax format, assuming Binkley raw fax page...');
  747.       maxpages := 1;
  748.       faxpos := -1;
  749.       reset(faxfile, 1);
  750.     end else begin
  751.       maxpages := qfax.pgcount;
  752.       faxpos := sizeof(qfax);
  753.     end;
  754.   end else begin
  755.     maxpages := zfax.pgcount;
  756.     faxpos := sizeof(zfax);
  757.   end;
  758.   fillchar(pagepos, sizeof(pagepos), #0);
  759.   pagepos[page] := faxpos+1;
  760.   repeat
  761.     shownpage := false;
  762.     decodeblock;
  763.     ge := viewfax(false);
  764.     if pagepos[page+1] = 0 then
  765.       pagepos[page+1] := faxpos;
  766.     if gmode < 200 then begin
  767.       for io := 1 to lines+padlines do
  768.         dispose(scanlinep^[io]);
  769.     end;
  770.     if ge = #81 then begin {pgdn}
  771.       if page = maxpages then begin
  772.         if shownpage then
  773.           textmode(3);
  774.         close(faxfile);
  775.         writeln('No more pages.');
  776.         halt;
  777.       end;
  778.       inc(page);
  779.     end else if ge = #73 then begin {pgup}
  780.       if page = 1 then begin
  781.         if shownpage then
  782.           textmode(3);
  783.         close(faxfile);
  784.         writeln('That was the first page.');
  785.         halt;
  786.       end;
  787.       dec(page);
  788.     end;
  789.     seek(faxfile, pagepos[page]);
  790.     faxpos := pagepos[page];
  791.   until(ge=#0);
  792.   textmode(3);
  793.   close(faxfile);
  794. end;
  795.  
  796. begin
  797.   clrscr;
  798.   mainloop;
  799. end.
  800.