home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vipf.zip / ipfview.mod < prev    next >
Text File  |  1994-03-21  |  24KB  |  790 lines

  1. IMPLEMENTATION MODULE IPFView;
  2.  
  3.   FROM Storage  IMPORT ALLOCATE, DEALLOCATE;
  4.   FROM SYSTEM   IMPORT TSIZE;
  5.                 IMPORT IO, Str, Lib, IPF (*, IPFDump*);
  6.                 IMPORT Window;
  7.   FROM Window   IMPORT FullScreen;
  8.  
  9.  
  10.   CONST
  11.     OUT = FALSE;
  12.  
  13.   (*-------------------------------------------------- browser *)
  14.  
  15.   VAR
  16.     PopDef:             Window.WinDef;
  17.     PopWin:             Window.WinType;
  18.     SearchTxt:          IPF.aString;
  19.  
  20.   PROCEDURE PopUp (lines: CARDINAL);
  21.     BEGIN
  22.       PopDef.Y2:= PopDef.Y1 + lines + 2;
  23.       PopWin:= Window.Open( PopDef );
  24.       Window.Use( PopWin );
  25.     END PopUp;
  26.  
  27.   PROCEDURE PopDown;
  28.     BEGIN
  29.       Window.Use( Window.FullScreen );
  30.       Window.Close( PopWin );
  31.     END PopDown;
  32.  
  33.   PROCEDURE Yell (msg: ARRAY OF CHAR);
  34.     VAR
  35.       ch: CHAR;
  36.     BEGIN
  37.       PopUp( 5 );
  38.       IO.WrStr( "  " ); IO.WrStr( msg ); ch:= IO.RdKey();
  39.       PopDown;
  40.     END Yell;
  41.  
  42.   TYPE
  43.     aBuildHook =        PROCEDURE (): CARDINAL;
  44.     aLineHook =         PROCEDURE (CARDINAL);
  45.     aChooseHook =       PROCEDURE ((*key*) CHAR,
  46.                                    VAR (*beg*) CARDINAL,
  47.                                    VAR (*row*) CARDINAL,
  48.                                    VAR (*col*) CARDINAL): BOOLEAN;  (* continue? *)
  49.  
  50.   PROCEDURE Browse (Build: aBuildHook; Line: aLineHook; Choose: aChooseHook;
  51.                     begin, row, col: CARDINAL);
  52.     VAR
  53.       cnt:      IPF.anIndex;
  54.       i, j, k:  IPF.anIndex;
  55.       line:     CARDINAL;
  56.       done:     BOOLEAN;
  57.       move:     CHAR;
  58.       search:   ARRAY [0..79] OF CHAR;
  59.  
  60.     PROCEDURE Up;
  61.       BEGIN
  62.         IF row > 0 THEN
  63.           DEC(row);
  64.           IF row < begin THEN
  65.             DEC(begin);
  66.             Window.InsLine; Window.GotoXY( 1,1 );
  67.             Line( row );
  68.           END;
  69.           Window.GotoXY( 1, row - begin + 1 );
  70.         END;
  71.       END Up;
  72.  
  73.     PROCEDURE Down;
  74.       BEGIN
  75.         IF row < cnt-1 THEN
  76.           INC(row);
  77.           IF row = begin + Window.CurrentScreenDepth THEN
  78.             INC(begin);
  79.             IO.WrLn;
  80.             Line( row );
  81.           END;
  82.           Window.GotoXY( 1, row - begin + 1 );
  83.         END;
  84.       END Down;
  85.  
  86.     PROCEDURE Refresh;
  87.       BEGIN
  88.         Window.Clear;
  89.         Window.SetWrap( FALSE );
  90.         line:= 1; i:= begin;
  91.         WHILE (line <= Window.CurrentScreenDepth) AND (i < cnt) DO
  92.           Window.GotoXY( 1, i - begin + 1 ); Line( i );
  93.           INC(line); INC( i );
  94.         END;
  95.       END Refresh;
  96.  
  97.     PROCEDURE MovedUp;
  98.       BEGIN
  99.         IF begin > row THEN
  100.           begin:= row;
  101.           Refresh;
  102.         END;
  103.       END MovedUp;
  104.  
  105.     PROCEDURE MovedDown;
  106.       BEGIN
  107.         IF begin + Window.CurrentScreenDepth <= row THEN
  108.           IF row >= Window.CurrentScreenDepth THEN
  109.             begin:= row - Window.CurrentScreenDepth + 1;
  110.           ELSE
  111.             begin:= 0;
  112.           END;
  113.           Refresh;
  114.         END;
  115.       END MovedDown;
  116.  
  117.     BEGIN
  118.       done:= FALSE;
  119.       REPEAT
  120.         cnt:= Build();
  121.         IF (begin >= cnt) OR (row >= cnt) THEN begin:= 0; row:= 0 END;
  122.         Refresh;
  123.  
  124.         LOOP
  125.           Window.GotoXY( col + 1, row - begin + 1);
  126.           Window.CursorOn; move:= IO.RdKey(); Window.CursorOff;
  127.           CASE CAP(move) OF
  128.           | 0C:   (* extended *)
  129.             move:= IO.RdKey();
  130.             CASE move OF
  131.             | CHR(72):  (* up *)
  132.               Up;
  133.             | CHR(80):  (* down *)
  134.               Down;
  135.             | CHR(73):  (* page up *)
  136.               IF row > Window.CurrentScreenDepth THEN
  137.                 DEC( row, Window.CurrentScreenDepth );
  138.               ELSE
  139.                 row:= 0;
  140.               END;
  141.               MovedUp;
  142.             | CHR(81):  (* page down *)
  143.               IF row + Window.CurrentScreenDepth < cnt THEN
  144.                 INC( row, Window.CurrentScreenDepth );
  145.               ELSE
  146.                 row:= cnt-1;
  147.               END;
  148.               MovedDown;
  149.             | CHR(132): (* ctrl-page up *)
  150.               row:= 0; col:= 0; MovedUp;
  151.             | CHR(118): (* ctrl-page down *)
  152.               row:= cnt-1; col:= 0; MovedDown;
  153.             | CHR(75):  (* left *)
  154.               IF col > 0 THEN DEC(col) END;
  155.             | CHR(77):  (* right *)
  156.               IF col < 79 THEN INC(col) END;
  157.             | CHR(71):  (* home *)
  158.               col:= 0;
  159.             | CHR(79):  (* end *)
  160.               col:= 79;
  161.             END;
  162.           | CHR(27):  (* quit *)
  163.             done:= TRUE;
  164.             EXIT;
  165.           | "S":  (* search *)
  166.             PopUp( 3 );
  167.             IO.WrLn; IO.WrStr( "  Search: " ); IO.RdStr( SearchTxt );
  168.             PopDown;
  169.           | "?":  (* help *)
  170.             PopUp( Window.CurrentScreenDepth - 12 );
  171.             IO.WrLn; IO.WrStr( "  ESC                   quit" );
  172.             IO.WrLn; IO.WrStr( "  ENTER                 open text" );
  173.             IO.WrLn; IO.WrStr( "  SPACE                 unfold/fold" );
  174.             IO.WrLn; IO.WrStr( "  I                     index" );
  175.             IO.WrLn; IO.WrStr( "  S                     define search text" );
  176.             IO.WrLn; IO.WrStr( "  F                     find next occurrence" );
  177.             IO.WrLn; IO.WrStr( "  arrows                move cursor" );
  178.             IO.WrLn; IO.WrStr( "  pg up/dn              move pagewise" );
  179.             IO.WrLn; IO.WrStr( "  ctrl-pgup/dn          goto start/end" );
  180.             IO.WrLn; IO.WrStr( "  home/end              start/end of line" );
  181.             move:= IO.RdKey();
  182.             PopDown;
  183.           ELSE
  184.             done:= NOT Choose( CAP(move), begin, row, col );
  185.             MovedUp; MovedDown;
  186.             EXIT;
  187.           END;
  188.         END (*key loop*);
  189.  
  190.       UNTIL done;
  191.     END Browse;
  192.  
  193.  
  194.   (*-------------------------------------------------- table-of-contents *)
  195.  
  196.   CONST
  197.     Open =      4;
  198.   VAR
  199.     TocCnt:     IPF.anIndex;
  200.     Toc:        POINTER TO ARRAY IPF.anIndex OF IPF.anIndex;
  201.  
  202.   PROCEDURE BuildToc (): CARDINAL;
  203.     VAR
  204.       i: IPF.anIndex;
  205.       l: CARDINAL;
  206.     BEGIN
  207.       TocCnt:= 0; l:= 9;
  208.       FOR i:= 0 TO IPF.TocCnt-1 DO
  209.         WITH IPF.Toc^[i]^ DO
  210.           IF (nest # 0) AND NOT (IPF.Hidden IN flags)
  211.             AND
  212.              (nest <= l)
  213.           THEN
  214.             l:= nest;
  215.             Toc^[TocCnt]:= i; INC(TocCnt);
  216.             IF (IPF.HasChildren IN flags) AND (Open IN flags) THEN
  217.               INC(l);
  218.             END;
  219.           END;
  220.         END;
  221.       END;
  222.       RETURN TocCnt;
  223.     END BuildToc;
  224.  
  225.   PROCEDURE TocLine (i: CARDINAL);
  226.     BEGIN
  227.       WITH IPF.Toc^[Toc^[i]]^ DO
  228.         IF nest > 0 THEN
  229.           IO.WrCharRep( " ", (nest-1) * 4 );
  230.         END;
  231.         IF IPF.HasChildren IN flags THEN
  232.           IF Open IN flags THEN
  233.             IO.WrStr( "[-] " );
  234.           ELSE
  235.             IO.WrStr( "[+] " );
  236.           END;
  237.         END;
  238.         IO.WrStr( title^ );
  239.         IF OUT THEN IO.WrCard( Toc^[i], 5 ) END;
  240.       END;
  241.     END TocLine;
  242.  
  243.   PROCEDURE TocChoose (key: CHAR; VAR beg, row, col: CARDINAL): BOOLEAN;
  244.     VAR
  245.       r, p: CARDINAL;
  246.     BEGIN
  247.       CASE key OF
  248.       | 15C:  (* enter *)
  249.         IF IPF.Toc^[Toc^[row]]^.slotCnt > 0 THEN
  250.           BrowseText( Toc^[row] );
  251.         END;
  252.       | " ":  (* un/fold *)
  253.         WITH IPF.Toc^[Toc^[row]]^ DO
  254.           IF Open IN flags THEN
  255.             EXCL( flags, Open );
  256.           ELSE
  257.             INCL( flags, Open );
  258.           END;
  259.         END (*with slot*);
  260.       | "I":  (* index *)
  261.         BrowseIdx;
  262.       | "F":  (* find *)
  263.         r:= row+1;
  264.         WHILE r < TocCnt DO
  265.           WITH IPF.Toc^[Toc^[r]]^ DO
  266.             p:= Str.Pos( title^, SearchTxt );
  267.             IF p # MAX(CARDINAL) THEN
  268.               IF IPF.HasChildren IN flags THEN INC(p,4) END;
  269.               row:= r; col:= p + (nest-1)*4;
  270.               IF row >= beg + Window.CurrentScreenDepth THEN
  271.                 beg:= row - Window.CurrentScreenDepth + 1
  272.               END;
  273.               RETURN TRUE;
  274.             END;
  275.           END;
  276.           INC(r);
  277.         END;
  278.       | "O":  (* output *)
  279.         IF OUT THEN
  280.           PopUp( 5 );
  281.             IO.WrStr( "  Dump entry: " ); r:= IO.RdCard();
  282.           PopDown;
  283.           Window.Clear; Window.SetWrap( TRUE );
  284. (*          IPFDump.OutSlot( IPF.Toc^[r]^.slot^[0] );*)
  285.           IF IO.RdKey() = "a" THEN END;
  286.         END;
  287.       END;
  288.       RETURN TRUE;
  289.     END TocChoose;
  290.  
  291.   PROCEDURE BrowseToc;
  292.     BEGIN
  293.       ALLOCATE( Toc, IPF.TocCnt * TSIZE(IPF.anIndex) );
  294.       Browse( BuildToc, TocLine, TocChoose, 0,0,0 );
  295.       DEALLOCATE( Toc, IPF.TocCnt * TSIZE(IPF.anIndex) );
  296.     END BrowseToc;
  297.  
  298.  
  299.   (*-------------------------------------------------- index *)
  300.  
  301.   PROCEDURE BuildIdx (): CARDINAL;
  302.     BEGIN
  303.       RETURN IPF.IdxCnt;
  304.     END BuildIdx;
  305.  
  306.   PROCEDURE IdxLine (i: CARDINAL);
  307.     BEGIN
  308.       WITH IPF.Idx^[i]^ DO
  309.         IO.WrCharRep( " ", level * 4 );
  310.         IO.WrStr( name^ );
  311.       END;
  312.     END IdxLine;
  313.  
  314.   PROCEDURE IdxChoose (key: CHAR; VAR beg, row, col: CARDINAL): BOOLEAN;
  315.     VAR
  316.       r, p: CARDINAL;
  317.     BEGIN
  318.       CASE key OF
  319.       | 15C:  (* enter *)
  320.         BrowseText( IPF.Idx^[row]^.toc );
  321.       | "F":  (* find *)
  322.         r:= row+1;
  323.         WHILE r < IPF.IdxCnt DO
  324.           WITH IPF.Idx^[r]^ DO
  325.             p:= Str.Pos( name^, SearchTxt );
  326.             IF p # MAX(CARDINAL) THEN
  327.               row:= r; col:= p + level*4;
  328.               IF row >= beg + Window.CurrentScreenDepth THEN
  329.                 beg:= row - Window.CurrentScreenDepth + 1
  330.               END;
  331.               RETURN TRUE;
  332.             END;
  333.           END;
  334.           INC(r);
  335.         END;
  336.       END;
  337.       RETURN TRUE;
  338.     END IdxChoose;
  339.  
  340.   PROCEDURE BrowseIdx;
  341.     BEGIN
  342.       Browse( BuildIdx, IdxLine, IdxChoose, 0,0,0 );
  343.     END BrowseIdx;
  344.  
  345.  
  346.   (*-------------------------------------------------- slots *)
  347.  
  348.   CONST
  349.     MaxLines =  1000;
  350.     MaxRefs =   500;
  351.   TYPE
  352.     aLine =     POINTER TO IPF.aString;
  353.     aLineNo =   [1..MaxLines];
  354.     aRefNo =    [1..MaxRefs];
  355.   CONST
  356.     NoRef =     MAX(IPF.anIndex);
  357.   VAR
  358.     LineCnt:    CARDINAL;
  359.     Line:       ARRAY aLineNo OF aLine;
  360.     Indent:     ARRAY aLineNo OF CARDINAL;
  361.     Offset:     ARRAY aLineNo OF LONGCARD;
  362.     RefCnt:     CARDINAL;
  363.     Ref:        ARRAY aRefNo OF RECORD
  364.       start, end: LONGCARD;  (* offset *)
  365.       ref:        IPF.anIndex;
  366.                 END;
  367.     AutoStart:  CARDINAL;       (* where automatic refs start *)
  368.  
  369.   PROCEDURE BuildLines (i: IPF.anIndex);
  370.     VAR
  371.       row:      aLineNo;        (* current line *)
  372.       col:      CARDINAL;       (* current column *)
  373.       ofs:      LONGCARD;       (* current offset in chars (excl. CRLF) *)
  374.       cofs:     LONGCARD;       (* committed offset *)
  375.       line:     IPF.aString;    (* current line *)
  376.       part:     IPF.aString;    (* current unbreakable part of line *)
  377.       s:        IPF.anIndex;    (* index into slots *)
  378.       t:        IPF.anIndex;    (* index into slot text *)
  379.       w:        IPF.aWord;      (* current word *)
  380.       id:       IPF.aWord;      (* escape sequence *)
  381.       base,len: IPF.anIndex;    (* base index and length of escape sequence *)
  382.       word:     IPF.aString;    (* text of word *)
  383.       spc:      BOOLEAN;        (* spacing mode *)
  384.       monoSpc:  BOOLEAN;        (* monospace section? *)
  385.       nextleft: CARDINAL;       (* next left margin *)
  386.       left, right: CARDINAL;    (* margins *)
  387.       align:    BOOLEAN;        (* aligning? *)
  388.       alignment: CARDINAL;      (* alignment *)
  389.       style:    CARDINAL;       (* current style *)
  390.       ref:      IPF.anIndex;    (* of toc entry referenced *)
  391.       k:        IPF.anIndex;    (* temp *)
  392.       flag:     CARDINAL;       (* flags for reference *)
  393.  
  394.     PROCEDURE Reset;
  395.       BEGIN
  396.         spc:= TRUE; align:= FALSE;
  397.         style:= 0; ref:= NoRef;
  398.       END Reset;
  399.  
  400.     INLINE PROCEDURE RoomFor (l: CARDINAL): BOOLEAN;
  401.       BEGIN
  402.         RETURN (col + l) <= (Window.ScreenWidth - left - right);
  403.       END RoomFor;
  404.  
  405.     PROCEDURE CRCR;
  406.       VAR
  407.         l: CARDINAL;
  408.       BEGIN
  409.         IF line[0] = 0C  THEN
  410.           Line[row]:= NIL;
  411.         ELSE
  412.           l:= Str.Length(line);
  413.           ALLOCATE( Line[row], l + 1 );
  414.           Str.Assign( Line[row]^, line );
  415.           Indent[row]:= left;
  416.           Offset[row]:= cofs;  INC( cofs, VAL(LONGCARD,l) );
  417.           line:= "";
  418.         END;
  419.         IF row < HIGH(Line) THEN INC(row) END;
  420.         col:= 1; left:= nextleft;
  421.       END CRCR;
  422.  
  423.     PROCEDURE Spc;
  424.       VAR
  425.         l: CARDINAL;
  426.         s: CARDINAL;
  427.       BEGIN
  428.         IF part[0] # 0C THEN
  429.           l:= Str.Length( part );
  430.           IF NOT RoomFor( l ) THEN CRCR END;
  431.           Str.Append( line, part ); INC(col,l);
  432.           part:= "";
  433.         END;
  434.         IF (col > 1) AND RoomFor(1) THEN
  435.           Str.Append( line, " " ); INC(col); INC(ofs);
  436.         END;
  437.       END Spc;
  438.  
  439.     INLINE PROCEDURE CR;
  440.       BEGIN
  441.         IF part[0] # 0C THEN Spc END;
  442.         CRCR;
  443.       END CR;
  444.  
  445.     INLINE PROCEDURE OptCR;
  446.       BEGIN
  447.         IF (col # 1) OR (part[0] # 0C) THEN CR END;
  448.       END OptCR;
  449.  
  450.     INLINE PROCEDURE OptSecondCR;
  451.       BEGIN
  452.         IF (row < 2)
  453.           OR
  454.            (Line[row-1] # NIL)
  455.         THEN CR END;
  456.       END OptSecondCR;
  457.  
  458.     (*#save,call(o_a_copy=>off)*)
  459.  
  460.     INLINE PROCEDURE JustAdd (txt: ARRAY OF CHAR);
  461.       BEGIN
  462.         Str.Append( part, txt );  INC( ofs, VAL(LONGCARD,Str.Length(txt)) );
  463.       END JustAdd;
  464.  
  465.     INLINE PROCEDURE Add (txt: ARRAY OF CHAR);
  466.       BEGIN
  467.         JustAdd( txt );
  468.         IF spc AND NOT monoSpc THEN Spc END;
  469.       END Add;
  470.  
  471.     (*#restore*)
  472.  
  473.     BEGIN (*BuildLines*)
  474.       WITH IPF.Toc^[i]^ DO
  475.           (* init to known state *)
  476.         RefCnt:= 0; AutoStart:= 0;
  477.         nextleft:= 0; left:= 0; right:= 1;
  478.         monoSpc:= FALSE; spc:= TRUE; Reset;
  479.         line:= ""; part:= ""; row:= 1; col:= 1; ofs:= 0; cofs:= 0;
  480.         Add( title^ );
  481.           (* process slots *)
  482.         FOR s:= 0 TO slotCnt-1 DO WITH IPF.Slot^[slot^[s]]^ DO
  483.             (* process words *)
  484.           FOR t:= 0 TO textCnt-1 DO
  485.             w:= text^[t];
  486.             IF w >= localCnt THEN (* control word *)
  487.               CASE w OF
  488.  
  489.               | 0FAH: (* paragraph *)
  490.                 OptCR; Reset; OptSecondCR;
  491.  
  492.               | 0FCH: (* space control *)
  493.                 spc:= NOT spc;
  494.  
  495.               | 0FDH: (* line break *)
  496.                 OptCR; spc:= TRUE;
  497.  
  498.               | 0FEH: (* space *)
  499.                 Spc;
  500.  
  501.               | 0FFH: (* escape *)
  502.                 len:= VAL(IPF.anIndex, text^[t+1] );
  503.                 id:= text^[t+2];
  504.                 base:= t+3;
  505.                 INC( t, len ); DEC( len, 2 );
  506.                 CASE id OF
  507.  
  508.                 | 2, 17, 18:  (* set left margin *)
  509.                   nextleft:= VAL(CARDINAL, text^[base] );
  510.                   IF (id = 17) THEN
  511.                     CR;
  512.                   ELSIF (col = 1) AND (part[0] = 0C) THEN
  513.                     left:= nextleft;
  514.                   ELSE
  515.                     WHILE col + left <= nextleft DO Spc END;
  516.                   END;
  517.  
  518.                 | 3: (* set right margin *)
  519.                   right:= VAL(CARDINAL, text^[base] );
  520.  
  521.                 | 4: (* change style *)
  522.                   style:= VAL(CARDINAL, text^[base] );
  523.  
  524.                 | 5, 7, 15: (* reference, footnote, inlined-ref *)
  525.                   IF (id = 15) AND (len = 3) THEN k:= 1 ELSE k:= 0 END;
  526.                   ref:= VAL(IPF.anIndex,text^[base+k]) + 256 * VAL(IPF.anIndex,text^[base+k+1]);
  527.                   IF len > 2+k THEN
  528.                     flag:= VAL(CARDINAL, text^[base+k+2]);
  529.                   ELSE
  530.                     flag:= 0;
  531.                   END;
  532.                   IF RefCnt < HIGH(Ref) THEN
  533.                     INC( RefCnt );
  534.                     Ref[RefCnt].ref:= ref;
  535.                     Ref[RefCnt].start:= ofs;
  536.                     IF id = 15 THEN
  537.                       Str.Append( word, IPF.Toc^[ref]^.title^ );
  538.                       Ref[RefCnt].end:= ofs;
  539.                     END;
  540.                     IF RefCnt = HIGH(Ref) THEN
  541.                       Yell( "Out of reference memory. Discarding rest..." );
  542.                     END;
  543.                     IF (AutoStart = 0) AND (id = 5) AND (flag AND 40H # 0) THEN
  544.                       AutoStart:= RefCnt;
  545.                     END;
  546.                   END;
  547.  
  548.                 | 8: (* end of reference *)
  549.                   Ref[RefCnt].end:= ofs;
  550.  
  551.                 | 11: (* begin monospace example *)
  552.                   nextleft:= 4;
  553.                   OptCR; OptSecondCR; left:= 4;
  554.                   monoSpc:= TRUE;
  555.  
  556.                 | 12: (* end monospace example *)
  557.                   nextleft:= 0; OptCR; OptSecondCR; left:= 0;
  558.                   monoSpc:= FALSE;
  559.  
  560.                 | 13: (* special text colour *)
  561.                   (* do nothing *)
  562.  
  563.                 | 19, 20:  (* set fore/back colour *)
  564.                   (* do nothing *)
  565.  
  566.                 | 26: (* begin lines *)
  567.                   align:= TRUE; alignment:= VAL(CARDINAL,text^[base]);
  568.                   OptCR;
  569.  
  570.                 | 27: (* end lines *)
  571.                   align:= FALSE;
  572.  
  573.                 | 28: (* set left margin to current pos *)
  574.                   nextleft:= col-1;
  575.  
  576.                 ELSE
  577.                   Add( "{esc?}" );
  578.                 END;
  579.  
  580.               ELSE (*plain control*)
  581.                 Add( "{ctrl?}" );
  582.               END;
  583.  
  584.             ELSE (*plain word*)
  585.               Str.Assign( word, IPF.Dict^[local^[w]]^ );
  586.               Add( word );
  587.  
  588.             END (*if control or word*);
  589.  
  590.             IF row = HIGH(Line) THEN LineCnt:= row; RETURN END;
  591.  
  592.           END (*for words*);
  593.         END END (*with slot*);
  594.       END;
  595.       OptCR;
  596.       LineCnt:= row;
  597.     END BuildLines;
  598.  
  599.   PROCEDURE KillLines;
  600.     VAR
  601.       l: aLineNo;
  602.     BEGIN
  603.       FOR l:= 1 TO LineCnt DO
  604.         IF Line[l] # NIL THEN DEALLOCATE( Line[l], Str.Length(Line[l]^)+1 ) END;
  605.       END;
  606.     END KillLines;
  607.  
  608.  
  609.  
  610.   VAR
  611.     Goto: IPF.anIndex;
  612.     Beg,Row,Col: CARDINAL;
  613.  
  614.   PROCEDURE TextBuild (): CARDINAL;
  615.     BEGIN
  616.       RETURN LineCnt;
  617.     END TextBuild;
  618.  
  619.   PROCEDURE Invert (x,l: CARDINAL);
  620.     CONST
  621.       InvAtt = 07FH;
  622.     VAR
  623.       c:     CARDINAL;
  624.       line:  ARRAY [0..79] OF RECORD
  625.         ch:    CHAR;
  626.         att:   SHORTCARD;
  627.              END;
  628.     BEGIN
  629.       IF l = 0 THEN RETURN END;
  630.       Window.RdBufferLn( Window.FullScreen, 1, Window.WhereY(), ADR(line), 80 );
  631.       IF line[x].ch # " " THEN line[x].att:= InvAtt END;
  632.       FOR c:= x+1 TO x+l-2 DO
  633.         line[c].att:= InvAtt;
  634.       END;
  635.       IF line[x+l-1].ch # " " THEN line[x+l-1].att:= InvAtt END;
  636.       Window.WrBufferLn( Window.FullScreen, 1, Window.WhereY(), ADR(line), 80 );
  637.     END Invert;
  638.  
  639.   PROCEDURE TextLine (l: CARDINAL);
  640.     VAR
  641.       r:   CARDINAL;
  642.       s,e: LONGCARD;
  643.       at:  CARDINAL;
  644.     BEGIN
  645.       IF Line[l+1] # NIL THEN
  646.         IO.WrCharRep( " ", Indent[l+1] );
  647.         IO.WrStr( Line[l+1]^ );
  648.         s:= Offset[l+1];
  649.         e:= s + VAL(LONGCARD, Str.Length(Line[l+1]^));
  650.         FOR r:= 1 TO RefCnt DO
  651.           WITH Ref[r] DO
  652.             IF (start >= s) AND (start < e) THEN
  653.               at:= Indent[l+1] + VAL(CARDINAL, start - s);
  654.               IF end <= e THEN (*on same line*)
  655.                 Invert( at, VAL(CARDINAL, end - start ));
  656.               ELSE
  657.                 Invert( at, VAL(CARDINAL, e - s) - at );
  658.               END;
  659.             ELSIF (end > s) AND (end < e) THEN
  660.               Invert( Indent[l+1], VAL(CARDINAL,end - s) );
  661.             END;
  662.           END;
  663.         END;
  664.       END;
  665.     END TextLine;
  666.  
  667.   PROCEDURE TextChoose (key: CHAR; VAR beg,row,col: CARDINAL): BOOLEAN;
  668.     VAR
  669.       r:   aRefNo;
  670.       l,p: CARDINAL;
  671.       s:   LONGCARD;
  672.     BEGIN
  673.       CASE key OF
  674.       | CHR(13): (* choose *)
  675.         s:= Offset[row+1];
  676.         IF col > Indent[row+1] THEN INC( s, VAL(LONGCARD, col - Indent[row+1] )) END;
  677.         FOR r:= 1 TO RefCnt DO WITH Ref[r] DO
  678.           IF (s >= start) AND (s < end) THEN
  679.             IF ref < IPF.TocCnt THEN
  680.               Goto:= ref;
  681.               Beg:= beg; Row:= row; Col:= col;
  682.               RETURN FALSE;
  683.             ELSE
  684.               Yell( "The reference of out of range! Decoding error? ..." );
  685.             END;
  686.           END;
  687.         END END;
  688.       | "F":  (* find *)
  689.         l:= row+2;
  690.         WHILE l <= LineCnt DO
  691.           IF Line[l] # NIL THEN
  692.             p:= Str.Pos( Line[l]^, SearchTxt );
  693.             IF p # MAX(CARDINAL) THEN
  694.               row:= l-1; col:= p + Indent[l];
  695.               IF row >= beg + Window.CurrentScreenDepth THEN
  696.                 beg:= row - Window.CurrentScreenDepth + 1
  697.               END;
  698.               RETURN TRUE;
  699.             END;
  700.           END;
  701.           INC(l);
  702.         END;
  703.       END;
  704.       RETURN TRUE;
  705.     END TextChoose;
  706.  
  707.   PROCEDURE ViewLines;
  708.     VAR
  709.       l: aLineNo;
  710.       ch: CHAR;
  711.     BEGIN
  712.       Browse( TextBuild, TextLine, TextChoose, Beg,Row,Col );
  713.     END ViewLines;
  714.  
  715.   PROCEDURE BrowseText (i: IPF.anIndex);
  716.     CONST
  717.       Size =    16;
  718.     TYPE
  719.       aPos =    INTEGER [0..Size-1];
  720.     VAR
  721.       ch:       CHAR;
  722.       hist:     ARRAY aPos OF RECORD
  723.         ref:      IPF.anIndex;
  724.         beg,row,col: CARDINAL;
  725.                 END;
  726.       at:       aPos;
  727.       prev:     IPF.anIndex;
  728.       returned: BOOLEAN;
  729.     BEGIN
  730.       FOR at:= 0 TO 15 DO hist[at].ref:= NoRef END; at:= 0;
  731.       Goto:= i; Beg:= 0; Row:= 0; Col:= 0;
  732.       returned:= FALSE;
  733.       REPEAT
  734.         BuildLines( Goto ); prev:= Goto; Goto:= NoRef;
  735.         IF (AutoStart = 0) OR returned THEN
  736.           ViewLines;
  737.           KillLines;
  738.           returned:= (Goto = NoRef);
  739.           IF Goto # NoRef THEN
  740.             hist[at].ref:= prev;
  741.             hist[at].beg:= Beg;
  742.             hist[at].row:= Row;
  743.             hist[at].col:= Col;
  744.             at:= (at+1) MOD Size;
  745.             Beg:= 0; Row:= 0; Col:= 0;
  746.           ELSE
  747.             IF at = 0 THEN at:= Size-1 ELSE at:= at-1 END;
  748.             Goto:= hist[at].ref; hist[at].ref:= NoRef;
  749.             Beg:= hist[at].beg;
  750.             Row:= hist[at].row;
  751.             Col:= hist[at].col;
  752.           END;
  753.         ELSE (*autostart*)
  754.           KillLines;
  755.           IF AutoStart > 1 THEN
  756.             hist[at].ref:= prev;
  757.             hist[at].beg:= Beg;
  758.             hist[at].row:= Row;
  759.             hist[at].col:= Col;
  760.             at:= (at+1) MOD Size;
  761.           END;
  762.           Beg:= 0; Row:= 0; Col:= 0;
  763.           WHILE AutoStart < RefCnt DO
  764.             hist[at].ref:= Ref[AutoStart].ref;
  765.             hist[at].beg:= Beg;
  766.             hist[at].row:= Row;
  767.             hist[at].col:= Col;
  768.             at:= (at+1) MOD Size;
  769.             INC(AutoStart);
  770.           END;
  771.           Goto:= Ref[AutoStart].ref;
  772.           returned:= TRUE;
  773.         END;
  774.       UNTIL Goto = NoRef;
  775.     END BrowseText;
  776.  
  777.  
  778. BEGIN (*IPFView*)
  779.   Window.Use( FullScreen );
  780.   Window.Info( Window.FullScreen, PopDef );
  781.   WITH PopDef DO
  782.     X1:= 10; X2:= 70;
  783.     Y1:= 5; Y2:= 16;
  784.     CursorOn:= TRUE; WrapOn:= TRUE; Hidden:= FALSE; FrameOn:= TRUE;
  785.     FrameDef:= Window.SingleFrame;
  786.     FrameFore:= Foreground;
  787.     FrameBack:= Background;
  788.   END;
  789. END IPFView.
  790.