home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / grafik / vgakit / lbm / lbm.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1991-10-16  |  13.5 KB  |  576 lines

  1.  
  2. PROGRAM LBM;
  3. {
  4.   PROGRAMM ZUM ANZEIGEN VON DELUXE PAINT ENHANCED *.LBM UND *.BBM- FILES
  5.  
  6.   Paul Schubert, Rottweiler Str. 8, D6000 Frankfurt /M 1, 069 / 231145
  7.  
  8. }
  9. {$R-}
  10. {$S-}
  11.  
  12.  
  13. {.$DEFINE PAUL}
  14.  
  15.  
  16. USES  TPCRT,TPDOS,TPMOUSE,TPPICK
  17.       ,DIRUNIT,TPSTRING
  18.       ,SVGA
  19.       ;
  20.  
  21.  
  22. CONST LINLEN   = 2048;
  23.  
  24. CONST POWERSOF2 : ARRAY[0..8] OF WORD = (1,2,4,8,16,32,64,128,256);
  25.  
  26.  
  27. TYPE  IDTYPE        = ARRAY[1..4] OF CHAR;
  28.       CMAPTYP       = ARRAY[0..255,0..2] OF BYTE;
  29.  
  30. TYPE  CHUNKTYP = RECORD
  31.         KORR    : BOOLEAN;
  32.         ID      : IDTYPE;
  33.         CASE BOOLEAN OF
  34.           TRUE  : (LEN : LONGINT);
  35.           FALSE : (LBA : ARRAY[1..4] OF BYTE);
  36.       END;
  37.  
  38.       CRNGTYP = RECORD
  39.         FILL       : WORD;
  40.         RATE       : WORD;
  41.         FILL2      : BYTE;
  42.         FLAGS      : BYTE;
  43.         START,STOP : BYTE;
  44.       END;
  45.  
  46.  
  47. TYPE  HDRTYP = RECORD
  48.         WID,HIG   : WORD;
  49.         FILL0     : ARRAY[1..4] OF BYTE;
  50.         BPP       : BYTE;
  51.         AMI1      : BYTE;
  52.         COMPR     : BYTE;
  53.         FILL      : BYTE;
  54.         FGCOL     : BYTE;
  55.         BKCOL     : BYTE;
  56.         XRAT,YRAT : BYTE;
  57.         SCWID     : WORD;
  58.         SCHIG     : WORD;
  59.       END;
  60.  
  61.  
  62. VAR   I,J                  : INTEGER;
  63.       CH1,CH2              : CHAR;
  64.       PATH,FN,S            : STRING;
  65.       F                    : FILE;
  66.       CHUNK                : CHUNKTYP;
  67.       FTYP                 : IDTYPE;
  68.       FLEN,CHUNKPOS        : LONGINT;
  69.       CMAPSIZ              : WORD;
  70.       CMAP                 : CMAPTYP;
  71.       PAL                  : VGAPALETTETYP ABSOLUTE CMAP;
  72.       HDR                  : HDRTYP;
  73.       TW,TH                : WORD;
  74.       X,Y,XW               : WORD;
  75.       ILBM,CUT             : BOOLEAN;
  76.       LINBUF               : ARRAY[0..LINLEN] OF BYTE;
  77.       RDWID,DSPWID         : WORD;
  78.       CRNG                 : ARRAY[1..16] OF CRNGTYP;
  79.       CRNP                 : BYTE;
  80.  
  81.       FIRST,AUTO,ZINFO,
  82.       QUIET,ENDFILE,ENDE   : BOOLEAN;
  83.  
  84.  
  85.  
  86. PROCEDURE GRAPHEIN(VORGABE:BYTE);
  87. BEGIN { GRAPHEIN }
  88.   SET320X200;
  89.  
  90.   IF VORGABE = 0 THEN BEGIN
  91.     WITH HDR DO BEGIN
  92.       IF HIG > 200 THEN SET640X350;
  93.       IF HIG > 350 THEN SET640X400;
  94.       IF HIG > 400 THEN SET640X480;
  95.       IF HIG > 480 THEN SET800X600;
  96.       IF HIG > 600 THEN SET1024X768;
  97.  
  98.       IF WID > XWID THEN BEGIN
  99.         SET640X350;
  100.         IF WID > 640 THEN SET800X600;
  101.         IF WID > 800 THEN SET1024X768;
  102.       END;
  103.     END; { WITH HDR }
  104.   END ELSE BEGIN
  105.     CASE VORGABE OF
  106.       2 : SET640X350;
  107.       3 : SET640X400;
  108.       4 : SET640X480;
  109.       5 : SET800X600;
  110.       6 : SET1024X768;
  111.     END;
  112.   END;
  113.  
  114.   IF CHECKVGA(VMOD) < 0 THEN BEGIN
  115.     TEXTMODE(CO80);
  116.     WRITELN;
  117.     WRITELN('KEINE VGA- KARTE VORHANDEN, ODER DIE VGA UNTERSTÜTZT');
  118.     WRITELN('DEN GEWÜNSCHTEN VIDEO- MODUS NICHT');
  119.     HALT(1);
  120.   END;
  121.   MAXX := PRED(XWID);
  122.   MAXY := PRED(YWID);
  123.  
  124.   VGASETPALETTE(PAL,0,PRED(CMAPSIZ));
  125.  
  126.   DIRECTVIDEO := FALSE;
  127. END; { GRAPHEIN }
  128.  
  129.  
  130. FUNCTION READCHUNK:BOOLEAN;
  131. VAR   B  : BYTE;
  132.       W  : WORD;
  133. BEGIN
  134.   READCHUNK := FALSE;
  135.   IF EOF(F) THEN EXIT;
  136.   WITH CHUNK DO BEGIN
  137.     BLOCKREAD(F,ID,8,W);
  138.     IF W <> 8 THEN EXIT;
  139.     CHUNKPOS := FILEPOS(F);
  140.     B := LBA[4]; LBA[4] := LBA[1]; LBA[1] := B;
  141.     B := LBA[3]; LBA[3] := LBA[2]; LBA[2] := B;
  142.  
  143.     KORR := ODD(LEN);
  144.     IF KORR THEN INC(LEN);
  145.   END; { WITH CHUNK }
  146.   READCHUNK := TRUE;
  147. END; { READCHUNK }
  148.  
  149.  
  150. PROCEDURE NXTCHUNK;
  151. BEGIN
  152.   IF (CHUNKPOS+CHUNK.LEN) <= FILESIZE(F) THEN BEGIN
  153.     SEEK(F,CHUNKPOS+CHUNK.LEN);
  154.   END ELSE BEGIN
  155.     WRITE('CHUNK- Größe falsch : ',CHUNKPOS+CHUNK.LEN:8,FILESIZE(F):8);
  156.   END;
  157. END; { NXTCHUNK }
  158.  
  159.  
  160. PROCEDURE PUTLINE;
  161. VAR   I,J,K  : INTEGER;
  162.       W,IDX  : WORD;
  163.       B,MSK  : BYTE;
  164.       OTLN   : ARRAY[0..LINLEN] OF BYTE;
  165. BEGIN
  166.   IF HDR.BPP = 1 THEN BEGIN
  167.     I := PRED(XW SHL 3);
  168.     J := PRED(XW);
  169.     REPEAT
  170.       FOR K := 0 TO 7 DO BEGIN
  171.         IF ODD(LINBUF[J]) THEN LINBUF[I] := 1 ELSE LINBUF[I] := 0;
  172.         LINBUF[J] := LINBUF[J] SHR 1;
  173.         DEC(I);
  174.       END; { NEXT K }
  175.       DEC(J);
  176.     UNTIL I < 0;
  177.     RAMTOVGA(@LINBUF,LONGINT(Y) * LONGINT(XWID),DSPWID);
  178.   END ELSE BEGIN
  179.     IF ILBM THEN BEGIN
  180.       IF HDR.BPP = 4 THEN MSK := $F ELSE MSK := $FF;
  181.       W := XW DIV HDR.BPP;
  182.       X := 0;
  183.       I := 0;
  184.       REPEAT
  185.         FOR J := 0 TO 7 DO BEGIN
  186.           B := 0;
  187.           IDX := I;
  188.           FOR K := 0 TO 7 DO BEGIN
  189.             B := (B SHR 1) OR (LINBUF[IDX] AND $80);
  190.             LINBUF[IDX] := LINBUF[IDX] SHL 1;
  191.             INC(IDX,W);
  192.           END;
  193.           OTLN[X] := B AND MSK;
  194.           INC(X);
  195.         END; { NEXT J }
  196.         INC(I);
  197.       UNTIL I >= W;
  198.       RAMTOVGA(@OTLN,LONGINT(Y) * LONGINT(XWID),DSPWID);
  199.     END ELSE
  200.       RAMTOVGA(@LINBUF,LONGINT(Y) * LONGINT(XWID),DSPWID);
  201.   END;
  202.   INC(Y);
  203.   X := 0;
  204. END; { PUTLINE }
  205.  
  206.  
  207. PROCEDURE READLINE;
  208. VAR   B,B2 : BYTE;
  209. BEGIN
  210.   WITH HDR DO BEGIN
  211.     IF COMPR = 0 THEN BEGIN
  212.       BLOCKREAD(F,LINBUF,XW);
  213.       PUTLINE;
  214.     END ELSE BEGIN
  215.       BLOCKREAD(F,B,1);
  216.       IF B > $7F THEN BEGIN
  217.         BLOCKREAD(F,B2,1);
  218.         FILLCHAR(LINBUF[X],257 - B,B2);
  219.         INC(X,257); DEC(X,B);
  220.         IF X >= XW THEN PUTLINE;
  221.       END ELSE BEGIN
  222.         INC(B);
  223.         BLOCKREAD(F,LINBUF[X],B);
  224.         INC(X,B);
  225.         IF X >= XW THEN PUTLINE;
  226.       END;
  227.     END;
  228.   END; { WITH HDR }
  229. END; { READLINE }
  230.  
  231.  
  232. PROCEDURE DISPLAYTINY;
  233. VAR   MKB  : WORD;
  234. BEGIN { DISPLAYTINY }
  235.   MKB := READKEYORBUTTON;
  236.   IF (MKB <> MOUSERT) AND (LO(MKB) <> $20) THEN EXIT;
  237.   CASE HDR.BPP OF
  238.     1 : XW := TW SHR 3;
  239.     4 : XW := TW SHR 1;
  240.     8 : XW := TW;
  241.   ELSE
  242.     EXIT;
  243.   END;
  244.   GRAPHEIN(1);
  245.   DSPWID := TW;
  246.   X  := 0;
  247.   Y  := 0;
  248.   REPEAT READLINE UNTIL Y >= TH;
  249.   MKB := READKEYORBUTTON;
  250.   TEXTMODE(CO80);
  251. END; { DISPLAYTINY }
  252.  
  253.  
  254. PROCEDURE ZEIGINFO;
  255. CONST SS     = 65535;
  256. VAR   P      : ^BYTE;
  257.       TC,TB  : BYTE;
  258.       I,J,L  : WORD;
  259.       T      : LONGINT;
  260.       NP     : VGAPALETTETYP;
  261.       S,S1   : STRING;
  262. BEGIN
  263.   IF NOT ZINFO THEN EXIT;
  264.   IF MAXAVAIL < SS THEN BEGIN
  265.     WRITE(#7);
  266.     EXIT;
  267.   END;
  268.   GETMEM(P,SS);
  269.   SETSEG(0); { VORSICHTSHALBER }
  270.  
  271.   VGAGETPALETTE(NP);
  272.   TC := 0; TB := 0;
  273.   FOR I := 0 TO 255 DO BEGIN
  274.     IF (NP[I].R >= NP[TC].R) AND
  275.        (NP[I].G >= NP[TC].G) AND
  276.        (NP[I].B >= NP[TC].B) THEN TC := I;
  277.     IF (NP[I].R <= NP[TB].R) AND
  278.        (NP[I].G <= NP[TB].G) AND
  279.        (NP[I].B <= NP[TB].B) THEN TB := I;
  280.   END; { NEXT I }
  281.  
  282.   IF YWID > 200 THEN BEGIN
  283.     SETFONT(16);
  284.     L := 20;
  285.   END ELSE BEGIN
  286.     SETFONT(8);
  287.     L := 10;
  288.   END;
  289.   MOVE(MEM[$A000:0],P^,SS);
  290.  
  291.   FOR I := 0 TO L DO BEGIN
  292.     FOR J := 0 TO 255 DO BEGIN
  293.       IF XWID > 320 THEN BEGIN
  294.         MEM[$A000:I * XWID + (J SHL 1)] := J;
  295.         MEM[$A000:I * XWID + SUCC(J SHL 1)] := J;
  296.       END ELSE BEGIN
  297.         MEM[$A000:I * XWID + J] := J;
  298.       END;
  299.     END; { NEXT J }
  300.   END; { NEXT I }
  301.  
  302.   FGBGTEXT(2,L+5,TC,TB,FN);
  303.   S := '»'+FTYP+'« ';
  304.   STR(HDR.WID,S1); S := S + S1 + ' * ';
  305.   STR(HDR.HIG,S1); S := S + S1 + ' / ';
  306.   STR(POWERSOF2[HDR.BPP],S1);
  307.   FGBGTEXT(2,L+5+SUCC(CHRHIG),TC,TB,S+S1);
  308.  
  309.   T := TIMEMS;
  310.   REPEAT
  311.   UNTIL KEYPRESSED OR MOUSEPRESSED OR ((TIMEMS - T) > 10000);
  312.   IF KEYPRESSED OR MOUSEPRESSED THEN I := READKEYORBUTTON;
  313.  
  314.   MOVE(P^,MEM[$A000:0],SS);
  315.   FREEMEM(P,SS);
  316. END; { ZEIGINFO }
  317.  
  318.  
  319. PROCEDURE DISPLAYBODY;
  320. VAR   I,J   : INTEGER;
  321.       B,B2  : BYTE;
  322.       MKB   : WORD;
  323.       P     : VGAPALETTETYP;
  324.       C     : COLORVALUE;
  325.       Z     : ARRAY[1..16] OF WORD;
  326.       CY    : BOOLEAN;
  327. BEGIN
  328.   IF NOT AUTO THEN BEGIN
  329.     MKB := READKEYORBUTTON;
  330.     IF (MKB <> MOUSERT) AND (LO(MKB) <> $20) THEN EXIT;
  331.   END;
  332.   WITH HDR DO BEGIN
  333.     CASE BPP OF
  334.       1 : XW := RDWID SHR 3;
  335.       4 : XW := RDWID SHR 1;
  336.       8 : XW := RDWID;
  337.     ELSE
  338.       EXIT;
  339.     END;
  340.     GRAPHEIN(0);
  341.     DSPWID := WID;
  342.     IF DSPWID > XWID THEN DSPWID := XWID;
  343.     X  := 0;
  344.     Y  := 0;
  345.     REPEAT
  346.       READLINE;
  347.     UNTIL Y >= HIG;
  348.   END; { WITH HDR }
  349.   ZEIGINFO;
  350.  
  351.   CY := FALSE;
  352.   P  := PAL;
  353.   J  := 0;
  354.   REPEAT
  355.     REPEAT
  356.       IF CY THEN BEGIN
  357.         FOR I := 1 TO CRNP DO BEGIN
  358.           WITH CRNG[I] DO BEGIN
  359.             IF Z[I] > 0 THEN BEGIN
  360.               DEC(Z[I]);
  361.               IF Z[I] = 0 THEN BEGIN
  362.                 Z[I] := RATE DIV 76;
  363.                 IF (FLAGS AND 2) = 2 THEN BEGIN
  364.                   C := P[START];
  365.                   MOVE(P[SUCC(START)],P[START],(STOP-START) * 3);
  366.                   P[STOP] := C;
  367.                 END ELSE BEGIN
  368.                   C := P[STOP];
  369.                   MOVE(P[START],P[SUCC(START)],(STOP-START) * 3);
  370.                   P[START] := C;
  371.                 END;
  372.               END;
  373.             END;
  374.           END; { WITH }
  375.         END; { NEXT I }
  376.         INC(J);
  377.         IF J = 6 THEN BEGIN
  378.           VGASETPALETTE(P,0,127);
  379.           VGASETPALETTE(P,128,255);
  380.           J := 0;
  381.         END;
  382.       END;
  383.     UNTIL KEYPRESSED OR MOUSEPRESSED;
  384.     MKB := READKEYORBUTTON;
  385.     IF LO(MKB) = 9 THEN BEGIN
  386.       CY := NOT CY;
  387.       FOR I := 1 TO CRNP DO Z[I] := CRNG[I].RATE DIV 76;
  388.       VGASETPALETTE(PAL,0,255);
  389.     END;
  390.   UNTIL (LO(MKB) <> 9);
  391.   TEXTMODE(CO80);
  392. END; { DISPLAYBODY }
  393.  
  394.  
  395. FUNCTION DISPLAYCHUNK:BOOLEAN;
  396. VAR   I,J  : INTEGER;
  397. BEGIN
  398.   DISPLAYCHUNK := FALSE;
  399.  
  400.   IF FIRST AND (CHUNK.ID <> 'FORM') THEN BEGIN
  401.     WRITELN('Der 1. Chunk muß Typ ''FORM'' sein !');
  402.     EXIT;
  403.   END;
  404.   FIRST := FALSE;
  405.   DISPLAYCHUNK := TRUE;
  406.  
  407.   IF NOT QUIET THEN BEGIN
  408.     WRITE  (CHUNK.ID,CHUNK.LEN:8,' ');
  409.     IF CHUNK.KORR THEN WRITE('* ') ELSE WRITE('  ');
  410.   END;
  411.  
  412.   IF CHUNK.ID = 'CRNG' THEN BEGIN
  413.     INC(CRNP);
  414.     BLOCKREAD(F,CRNG[CRNP],SIZEOF(CRNGTYP));
  415.     CRNG[CRNP].RATE  := SWAP(CRNG[CRNP].RATE);
  416.     IF NOT QUIET THEN WRITE(' ');
  417.     NXTCHUNK;
  418.     EXIT;
  419.   END;
  420.  
  421.   IF CHUNK.ID = 'FORM' THEN BEGIN
  422.     FLEN := CHUNK.LEN;
  423.     BLOCKREAD(F,FTYP,4);
  424.     ILBM := (FTYP = 'ILBM');
  425.     IF NOT QUIET THEN BEGIN
  426.       WRITE  ('Filetyp >',FTYP,'<   ');
  427.       WRITE  ('Filegröße : ',FILESIZE(F):8,FLEN:8);
  428.       IF FILESIZE(F) <> (FLEN + 8) THEN WRITE(' !!!');
  429.       WRITELN;
  430.     END;
  431.     EXIT;
  432.   END;
  433.  
  434.   IF CHUNK.ID = 'TINY' THEN BEGIN
  435.     BLOCKREAD(F,TW,2); TW := SWAP(TW); WRITE(TW:6);
  436.     BLOCKREAD(F,TH,2); TH := SWAP(TH); WRITE(TH:6);
  437.     IF NOT QUIET THEN DISPLAYTINY;
  438.   END;
  439.  
  440.   IF CHUNK.ID = 'CMAP' THEN BEGIN
  441.     CMAPSIZ := CHUNK.LEN;
  442.     BLOCKREAD(F,CMAP,CMAPSIZ);
  443.     CMAPSIZ := CMAPSIZ DIV 3;
  444.     FOR I := 0 TO PRED(CMAPSIZ) DO BEGIN
  445.       FOR J := 0 TO 2 DO CMAP[I][J] := CMAP[I][J] SHR 2;
  446.     END;
  447.     IF NOT QUIET THEN WRITELN;
  448.     EXIT;
  449.   END;
  450.  
  451.   IF CHUNK.ID = 'BMHD' THEN BEGIN
  452.     BLOCKREAD(F,HDR,SIZEOF(HDR));
  453.     WITH HDR DO BEGIN
  454.       CUT := (WID < SCWID) OR (HIG < SCHIG);
  455.  
  456.       WID := SWAP(WID);
  457.       RDWID := WID;
  458.       IF ODD(RDWID) THEN INC(RDWID);
  459.       IF ILBM AND (BPP > 1) THEN BEGIN
  460.         IF ((RDWID AND 2) > 0) THEN INC(RDWID,2);
  461.         IF ((RDWID AND 4) > 0) THEN INC(RDWID,4);
  462.         IF ((RDWID AND 8) > 0) THEN INC(RDWID,8);
  463.       END;
  464.  
  465.       HIG := SWAP(HIG);
  466.       SCWID := SWAP(SCWID);
  467.       SCHIG := SWAP(SCHIG);
  468.  
  469.       IF NOT QUIET THEN BEGIN
  470.         WRITE('<',RDWID,'> ');
  471.         WRITE(WID,'*',HIG,' (',SCWID,'*',SCHIG,') ',BPP,' Bit/Pixel, ',COMPR);
  472.  
  473.         WRITELN;
  474.         FOR I := 1 TO 4 DO WRITE(HEXB(FILL0[I]),' ');
  475.         WRITE(HEXB(AMI1),' ',HEXB(FILL),' ');
  476.         WRITE('  ',HEXB(XRAT),' ',HEXB(YRAT));
  477.         WRITE('  FG = ',FGCOL,',  BK = ',BKCOL,',  CUT = ',CUT);
  478.       END;
  479.     END; { WITH HDR }
  480.   END;
  481.  
  482.   IF CHUNK.ID = 'BODY' THEN BEGIN
  483.     DISPLAYBODY;
  484.   END;
  485.  
  486.   NXTCHUNK;
  487.   IF NOT QUIET THEN WRITELN;
  488. END; { DISPLAYCHUNK }
  489.  
  490.  
  491. PROCEDURE AUS;
  492. BEGIN
  493.   TEXTMODE(CO80);
  494.   HALT(3);
  495. END; { AUS }
  496.  
  497.  
  498. BEGIN { MAIN }
  499.   INITIALIZEMOUSE;
  500.   ENABLEEVENTHANDLING;
  501.   ENABLEPICKMOUSE;
  502.  
  503.   AUTO  := FALSE;
  504.   QUIET := FALSE;
  505.   ZINFO := FALSE;
  506.   ENDE  := FALSE;
  507.   FN    := '*';
  508. {$IFDEF PAUL}
  509.   PATH  := 'C:\DPAINT\ARTWORK\';
  510. {$ELSE}
  511.   PATH  := '';
  512. {$ENDIF}
  513.  
  514.   FOR I := 1 TO PARAMCOUNT DO BEGIN
  515.     S := STUPCASE(PARAMSTR(I));
  516.     IF S[1] IN ['-','/'] THEN BEGIN
  517.       CASE S[2] OF
  518.         'A' : BEGIN
  519.                 AUTO := TRUE;
  520.                 QUIET := TRUE;
  521.               END;
  522.         'E' : ENDE := TRUE;
  523.         'I' : BEGIN
  524.                 AUTO := TRUE;
  525.                 QUIET := TRUE;
  526.                 ZINFO := TRUE;
  527.               END;
  528.         'Q' : QUIET := TRUE;
  529.       END; { CASE }
  530.     END ELSE BEGIN
  531.       PATH := S;
  532.       IF NOT (PATH[LENGTH(PATH)] IN [':','\']) THEN BEGIN
  533.         FN := PATH;
  534.         WHILE (LENGTH(PATH) > 0) AND (PATH[LENGTH(PATH)] <> '\') DO DELETE(PATH,LENGTH(PATH),1);
  535.       END;
  536.     END;
  537.     IF NOT (PATH[LENGTH(PATH)] IN ['\',':']) THEN PATH := PATH + '\';
  538.     IF PATH[2] <> ':' THEN PATH := DEFAULTDRIVE + ':' + PATH;
  539.   END; { NEXT I }
  540.   IF FN <> '*' THEN BEGIN
  541.     IF POS('.',FN) = 0 THEN FN := FN + '.LBM';
  542.   END;
  543.  
  544.   CLRSCR;
  545.   REPEAT
  546.     IF FN = '*' THEN BEGIN
  547.       FN := DIRECTORY(PATH+'*.?BM');
  548.       IF (FN <> '*') AND (FN <> '') THEN BEGIN
  549.         PATH := JUSTPATHNAME(FN);
  550.         IF NOT (PATH[LENGTH(PATH)] IN ['\',':']) THEN PATH := PATH + '\';
  551.       END;
  552.     END;
  553.     IF (FN <> '*') AND (FN <> '') THEN BEGIN
  554.       GOTOXY(1,25);
  555.       IF NOT QUIET THEN BEGIN
  556.         WRITELN;
  557.         WRITELN;
  558.         WRITELN('Filename : ',FN);
  559.       END;
  560.       ASSIGN(F,FN);
  561.       RESET(F,1);
  562.       FIRST := TRUE;
  563.       CRNP  := 0;
  564.       REPEAT
  565.         ENDFILE := NOT READCHUNK;
  566.         IF NOT ENDFILE THEN ENDFILE := NOT DISPLAYCHUNK;
  567.       UNTIL ENDFILE;
  568.       CLOSE(F);
  569.       FN := '*';
  570.     END;
  571.   UNTIL ENDE OR (FN = '');
  572.  
  573. END.
  574.  
  575.  
  576.