(*---------------------------------------------------------------------------
    :Program.    MuchMore.mod
    :Author.     Fridtjof Siebert
    :Address.    Nobileweg 67, D-7-Stgt-40
    :Phone.      Please write a letter.
    :Shortcut.   [fbs]
    :Version.    1.1
    :Date.       24-Sep-88
    :Copyright.  PD
    :Language.   Modula-II
    :Translator. M2Amiga
    :Imports.    WarpText    [Bill Kelly, fbs]
    :Imports.    NTSC        [fbs]
    :UpDate.     none.
    :Contents.   A Soft-Scrolling ASCII-File Printer.
    :Remark.     Usage: MuchMore {FileName(s)}
---------------------------------------------------------------------------*)

MODULE MuchMore;


(*-----------------------------  IMPORTs:  --------------------------------*)


(*------  SYSTEM:  ------*)

FROM SYSTEM     IMPORT ADR, ADDRESS, SHIFT;

FROM Arguments  IMPORT NumArgs, GetArg;

FROM Arts       IMPORT TermProcedure, Terminate, CurrentLevel, BreakPoint,
                       Assert;

(*------  Libraries:  ------*)

FROM Dos        IMPORT Open, Close, oldFile, Read, FileHandlePtr;

FROM Exec       IMPORT GetMsg, ReplyMsg, MessagePtr, WaitPort, AllocMem,
                       FreeMem, MemReqSet, MemReqs;

FROM Graphics   IMPORT SetAPen, SetDrMd, jam1, jam2, DrawModes, DrawModeSet,
                       Text, Draw, ViewModes, ViewModeSet, FontStyles,
                       FontStyleSet, FontFlags, FontFlagSet, TextAttr,
                       RastPortPtr, Move, BltBitMap, WaitBOVP, WaitTOF,
                       BitMap, InitBitMap, BltClear, OpenFont, CloseFont,
                       TextFontPtr, WaitBlit;

FROM InputEvent IMPORT Qualifiers, QualifierSet;

FROM Intuition  IMPORT NewScreen, ScreenFlags, ScreenFlagSet, customScreen,
                       OpenScreen, CloseScreen, MakeScreen, RethinkDisplay,
                       ScreenPtr, NewWindow, WindowFlags, WindowFlagSet,
                       IDCMPFlags, IDCMPFlagSet, OpenWindow, CloseWindow,
                       WindowPtr, IntuiMessage, IntuiMessagePtr;

(*------  Standard:  ------*)

FROM Strings    IMPORT Length, Copy, first, last;

(*------  Other:  ------*)

FROM NTSC       IMPORT NTSC;

FROM WarpText   IMPORT SetUpFont, NewWarp, NewWarpInfo;


(*------------------------------  TYPES:  ---------------------------------*)


TYPE
  TextLinePtr = POINTER TO TextLine;
  TextLine = RECORD
               next: TextLinePtr;
               prev: TextLinePtr;
               text: ARRAY[0..81] OF CHAR;
             END;


(*-----------------------------  Variables:  ------------------------------*)


VAR
  NuScreen: NewScreen;
  Screen: ScreenPtr;           (* Screen that contains the Text     *)
  RP: RastPortPtr;             (* Screen's RastPort                 *)
  NuWindow: NewWindow;
  Window: WindowPtr;
  MyFont: TextAttr;
  retry: BOOLEAN;              (* used for Retry/Cancel-Requesters  *)
  MyFile: FileHandlePtr;       (* For loading Textfile              *)
  FirstLine: TextLinePtr;      (* Saved Text                        *)
  TopLine: TextLinePtr;        (* Points to topmost Line            *)
  BottomLine: TextLinePtr;     (* Last Line displayed on Screen     *)
  len: INTEGER;                (* Length of Text's name             *)
  Name: ARRAY[0..127] OF CHAR; (* Text's Name                       *)
  Buffer: POINTER TO ARRAY[0..511] OF CHAR; (* Buffer for Reading   *)
  RQPos: LONGINT;              (* Position within ReadBuffer        *)
  RQLen: LONGINT;              (* Number of CHARs in Buffer         *)
  EOF: BOOLEAN;                (* End of File ?                     *)
  CountFiles: INTEGER;         (* Counts TextFiles                  *)
  i: INTEGER;                  (* used in FOR-NEXT-loops            *)
  NumLines: INTEGER;           (* Number of Lines (32 PAL, 25 NTSC) *)
  BitMaps: ARRAY[0..1] OF BitMap; (* BitMaps for DoubleBuffering    *)
  DisplayedMap: [0..1];        (* actually displayed BitMap         *)
  AnzLines: INTEGER;           (* Length of Text in Lines           *)
  Scroll: BOOLEAN;             (* TRUE = Scroll, FALSE = Wait.      *)
  Down: BOOLEAN;               (* Scroll-Direction                  *)
  MyMsgPtr: IntuiMessagePtr;   (* For receiving Messages            *)
  MyMsg: IntuiMessage;         (* contains Message                  *)
  Shift: BOOLEAN;              (* Shifted Keystroke ?               *)
  Alt: BOOLEAN;                (* Altered Keystroke ?               *)
  RefreshDisplayCnt: CARDINAL; (* Lines to output after HELP        *)
  Font: TextFontPtr;           (* Font for WarpText                 *)
  nwinfo: NewWarpInfo;         (* Info for WarpText                 *)


(*------------------------  Open Display:  --------------------------------*)


PROCEDURE InitScreen();

BEGIN

(*------  Open Screen:  ------*)

  WITH MyFont DO
    name := ADR("topaz.font");
    ySize := 8;
    style := FontStyleSet{};
    flags := FontFlagSet{};
  END;
  WITH nwinfo DO
    fontData := AllocMem(2048,MemReqSet{memClear});
    IF fontData=NIL THEN Terminate(0) END;
  END;
  Font := OpenFont(ADR(MyFont));
  SetUpFont(ADR(nwinfo),Font);
  WITH NuScreen DO
    leftEdge     := 0;
    topEdge      := 0;
    width        := 640;
    IF NTSC() THEN
      height     := 216;
      NumLines   := 25;
    ELSE
      height     := 272;
      NumLines   := 32;
    END;
    depth        := 1;
    detailPen    := 0;
    blockPen     := 1;
    viewModes    := ViewModeSet{hires};
    font         := ADR(MyFont);
    defaultTitle := NIL;
    gadgets      := NIL;
    customBitMap := ADR(BitMaps[DisplayedMap]);
  END;
  NuScreen.type := customScreen + ScreenFlagSet{screenQuiet,customBitMap};
  DisplayedMap := 0;
  WITH NuScreen DO
    REPEAT
      InitBitMap(BitMaps[DisplayedMap],depth,width,height);
      WITH BitMaps[DisplayedMap] DO
        planes[0] := AllocMem(width DIV 8 * height,MemReqSet{chip,memClear});
        IF planes[0]=NIL THEN Terminate(0) END;
      END;
      DisplayedMap := 1 - DisplayedMap;
    UNTIL DisplayedMap = 0;
  END;
  Screen := OpenScreen(NuScreen);
  Assert(Screen#NIL,ADR("OpenScrn failed !!"));
  RP := ADR(Screen^.rastPort);
  RP^.bitMap := ADR(BitMaps[1-DisplayedMap]);
  DEC(Screen^.height,16);
  INC(Screen^.viewPort.rasInfo^.ryOffset,8);
  MakeScreen(Screen); RethinkDisplay();

(*------  Open Window:  ------*)

  WITH NuWindow DO
    leftEdge   := 0;
    topEdge    := 10;
    width      := 640;
    height     := Screen^.height-10;
    detailPen  := 0;
    blockPen   := 1;
    idcmpFlags := IDCMPFlagSet{rawKey};
    flags      := WindowFlagSet{borderless,activate};
    firstGadget:= NIL;
    checkMark  := NIL;
    title      := NIL;
    screen     := Screen;
    bitMap     := NIL;
    minWidth   := 0;
    minHeight  := 0;
    maxWidth   := -1;
    maxHeight  := -1;
    type       := customScreen;
  END;
  Window := OpenWindow(NuWindow);
  Assert(Window#NIL,ADR("OpenWindow failed!!!"));

END InitScreen;


(*------  Flip Buffers:  ------*)


PROCEDURE FlipBitMap();

BEGIN
  RP^.bitMap := ADR(BitMaps[DisplayedMap]);
  DisplayedMap := 1 - DisplayedMap;
  Screen^.viewPort.rasInfo^.bitMap := ADR(BitMaps[DisplayedMap]);
  MakeScreen(Screen); RethinkDisplay();
END FlipBitMap;


(*------  Read one TextLine into a Variable:  ------*)


PROCEDURE GetTextLine(Line: TextLinePtr): BOOLEAN;
(* returns TRUE if EOF *)

VAR
  Pos: CARDINAL;

BEGIN
  Pos := 0;
  WITH Line^ DO
    text := "                                                                                ";
    LOOP
      IF RQPos=RQLen THEN
        RQLen := Read(MyFile,Buffer,SIZE(Buffer^));
        RQPos := 0;
      END;
      text[Pos] := Buffer^[RQPos];
      INC(RQPos);
      IF text[Pos]<" " THEN
        CASE ORD(text[Pos]) OF
        09H: REPEAT
               text[Pos] := " ";
               INC(Pos);
             UNTIL (Pos=80) OR (SHIFT(SHIFT(Pos,-3),3)=Pos);
             DEC(Pos); |
        0AH,0DH,0: EXIT; |
        ELSE
          text[Pos] := " ";
        END;
      END;
      INC(Pos);
      IF Pos>=80 THEN EXIT END;
    END;
    IF Pos#80 THEN text[Pos] := " " END;
  END;
  RETURN RQLen=0;
END GetTextLine;


(*------  Type one Line of Text:  ------*)

PROCEDURE TypeLine(Line: TextLinePtr; PosY: INTEGER);

BEGIN
  WITH Line^ DO
    WITH nwinfo DO
      bitPlane := RP^.bitMap^.planes[0];
      xLoc := 0; yLoc := PosY;
      WaitBlit();
      NewWarp(ADR(nwinfo),ADR(text),80);
    END;
  END;
END TypeLine;


(*------  Write Line at Bottom of Text:  ------*)


PROCEDURE AddBottomLine(Line: TextLinePtr; Fast: BOOLEAN);

VAR
  Height: INTEGER;
  i: INTEGER;

BEGIN
  WITH Screen^ DO
    TypeLine(Line,NumLines);
    IF BltBitMap(ADR(BitMaps[1-DisplayedMap]),0,height,ADR(BitMaps[
         DisplayedMap]),0,height+8,640,8,0C0H,1,NIL) = 0 THEN END;
    WITH viewPort.rasInfo^ DO
      IF Fast THEN
        FlipBitMap();
        IF BltBitMap(ADR(BitMaps[1-DisplayedMap]),0,16,ADR(BitMaps[1-
          DisplayedMap]),0,0,width,height,0C0H,1,NIL) = 0 THEN END;
      ELSE
        DEC(ryOffset,7);
        FlipBitMap();
        Height := height DIV 4;
        FOR i:=0 TO 3 DO
          INC(ryOffset,1);
          MakeScreen(Screen); RethinkDisplay();
          IF BltBitMap(ADR(BitMaps[1-DisplayedMap]),0,16+i*Height,
                       ADR(BitMaps[1-DisplayedMap]),0,i*Height,
                       width,Height,0C0H,1,NIL) = 0 THEN END;
        END;
        FOR i:=4 TO 6 DO
          INC(ryOffset,1);
          MakeScreen(Screen); RethinkDisplay();
        END;
      END;
    END;
  END;
END AddBottomLine;


(*------  Write String to Screen:  ------*)


PROCEDURE Write(String: ARRAY OF CHAR);

VAR
  text: TextLine;

BEGIN
  text.next := NIL;
  text.prev := NIL;
  text.text := "                                                                                ";
  Copy(text.text,String,0,Length(String));
  text.text[Length(String)] := " ";
  AddBottomLine(ADR(text),FALSE);
END Write;


(*------  Deallocate Text:  ------*)


PROCEDURE FreeText(Text: TextLinePtr);
(* This was recursiv, but caused Stack overflow with 4K Stack *)

VAR
  text: TextLinePtr;

BEGIN
  IF Text#NIL THEN
    WHILE Text^.next#NIL DO Text := Text^.next END;
    WHILE Text^.prev#NIL DO
      text := Text;
      Text := Text^.prev;
      FreeMem(text,SIZE(TextLine));
    END;
    FreeMem(Text,SIZE(TextLine));
  END;
END FreeText;


(*------  Scroll down one Line:  ------*)


PROCEDURE ScrollDown(Fast: BOOLEAN; Read: BOOLEAN): BOOLEAN;
(* Returns TRUE if EOF *)

VAR
  EOF: BOOLEAN;
  NewDisplay: BOOLEAN;

BEGIN
  NewDisplay := TRUE;
  IF (FirstLine=NIL) AND Read THEN
    FirstLine := AllocMem(SIZE(TextLine),MemReqSet{memClear});
    IF FirstLine=NIL THEN Terminate(0) END;
    TopLine := FirstLine; BottomLine := FirstLine;
    EOF := GetTextLine(BottomLine);
    IF EOF THEN
      FreeMem(FirstLine,SIZE(TextLine));
      FirstLine := NIL;
      NewDisplay := FALSE;
    ELSE
      INC(AnzLines);
    END;
  ELSIF (BottomLine^.next=NIL) AND Read THEN
    BottomLine^.next := AllocMem(SIZE(TextLine),MemReqSet{memClear});
    IF BottomLine^.next=NIL THEN Terminate(0) END;
    BottomLine^.next^.prev := BottomLine;
    BottomLine := BottomLine^.next;
    EOF := GetTextLine(BottomLine);
    IF EOF THEN
      BottomLine := BottomLine^.prev;
      FreeMem(BottomLine^.next,SIZE(TextLine));
      BottomLine^.next := NIL;
      NewDisplay := FALSE;
    ELSE
      INC(AnzLines);
    END;
  ELSIF (BottomLine^.next#NIL) AND (BottomLine#NIL) THEN
    BottomLine := BottomLine^.next;
    EOF := FALSE;
  ELSE
    NewDisplay := FALSE;
  END;
  IF NewDisplay THEN
    IF (AnzLines>=NumLines) AND (RefreshDisplayCnt=0) THEN
      TopLine := TopLine^.next;
    END;
    AddBottomLine(BottomLine,Fast);
  END;
  RETURN EOF;
END ScrollDown;


(*------  Scroll Up one Line:  ------*)


PROCEDURE ScrollUp(Fast: BOOLEAN);

VAR
  Height: INTEGER;
  i: INTEGER;

BEGIN

  IF (TopLine^.prev#NIL) AND (TopLine^.prev^.prev#NIL) THEN
    TopLine := TopLine^.prev;
    BottomLine := BottomLine^.prev;
    WITH Screen^ DO
      RP^.bitMap := ADR(BitMaps[DisplayedMap]);
      WITH TopLine^ DO
        TypeLine(prev,0);
        IF Fast THEN
          IF BltBitMap(ADR(BitMaps[1-DisplayedMap]),0, 0,
                       ADR(BitMaps[1-DisplayedMap]),0,16,
                       width,height-8,0C0H,1,NIL) = 0 THEN END;
        ELSE
          Height := (height-8) DIV 4;
          WITH viewPort.rasInfo^ DO
            IF NOT(Fast) THEN
              FOR i:=1 TO 4 DO
                DEC(ryOffset,1);
                MakeScreen(Screen); RethinkDisplay(); (* WaitTOF(); *)
                IF BltBitMap(ADR(BitMaps[1-DisplayedMap]),0,height-8-i*Height,
                             ADR(BitMaps[1-DisplayedMap]),0,height+8-i*Height,
                             width,Height,0C0H,1,NIL) = 0 THEN END;
              END;
              FOR i:=4 TO 6 DO
                DEC(ryOffset,1);
                MakeScreen(Screen); RethinkDisplay(); (* WaitTOF(); *)
              END;
              INC(ryOffset,7);
            END;
          END;
        END;   (* IF FAST THEN ELSE *)
      END;   (* WITH TopLine^ DO *)
      IF BltBitMap(ADR(BitMaps[DisplayedMap]),0,0,
                   ADR(BitMaps[1-DisplayedMap]),0,8,
                   640,8,0C0H,1,NIL) = 0 THEN END;
      FlipBitMap();
    END;   (* WITH Screen^ DO *)
  END;   (* IF TopLine#NIL ... *)
END ScrollUp;


(*------  Clear Display:  ------*)


PROCEDURE ClearBitMaps();

BEGIN
  WITH BitMaps[0] DO
    BltClear(planes[0],bytesPerRow*rows,0);
  END;
  WITH BitMaps[1] DO
    BltClear(planes[0],bytesPerRow*rows,0);
  END;
END ClearBitMaps;


(*------  CleanUp:  ------*)


PROCEDURE CleanUp();

BEGIN
  IF Window#NIL THEN CloseWindow(Window) END;
  IF Screen#NIL THEN CloseScreen(Screen) END;
  WITH NuScreen DO
    WITH BitMaps[0] DO
      IF planes[0]#NIL THEN FreeMem(planes[0],width DIV 8 * height) END;
    END;
    WITH BitMaps[1] DO
      IF planes[0]#NIL THEN FreeMem(planes[0],width DIV 8 * height) END;
    END;
  END;
  IF Buffer#NIL THEN FreeMem(Buffer,SIZE(Buffer^)) END;
  IF MyFile#NIL THEN Close(MyFile) END;
  FreeText(FirstLine);
  WITH nwinfo DO
    IF fontData#NIL THEN FreeMem(fontData,2048) END;
  END;
END CleanUp;


(*------------------------------  MAIN:  ----------------------------------*)


BEGIN

(*------  Init:  ------*)

  Screen := NIL; Window := NIL; FirstLine := NIL; Buffer := NIL;
  TopLine := NIL; BottomLine := NIL; MyFile := NIL; AnzLines := 0;
  Scroll := TRUE; Down := TRUE; nwinfo.fontData := NIL;
  TermProcedure(CleanUp);
  InitScreen();
  Buffer := AllocMem(SIZE(Buffer^),MemReqSet{chip,memClear});
  IF Buffer=NIL THEN Terminate(0) END;

(*------  Open File(s):  ------*)

  IF NumArgs()=0 THEN

    Write("                          MuchMore");
    Write("                       =============="); Write("");
    Write("   A Soft-Scrolling ASCII-File-Printer."); Write("");
    Write("   Usage: "); Write("");
    Write("     MuchMore {FileName(s)}"); Write("");
    Write("   To Start from Workbench Shift-click Texts to Print before"); Write("");
    Write("   doubleclicking MuchMore. "); Write("");
    Write("   Texts whose Default Tool is MuchMore just need to be doubleclicked"); Write("");
    Write("   This should work on NTSC as well as on PAL Amigas."); Write("");
    Write("   © 1988 Fridtjof Siebert, Nobileweg 67, D-7000-Stuttgart-40");
    Write("     Thanx to Bill Kelly for his WarpText-routines!"); Write("");
    Write("     This is free to be spread on PD or Shareware Disks, as long as");
    Write("     you leave my name in.");
    Write("     It's illegal to make any profit of this without my permission !");
    IF NOT(NTSC()) THEN
      FOR i:=0 TO 6 DO Write(""); END;
    END;

    LOOP
      WaitPort(Window^.userPort);
      MyMsgPtr := ADDRESS(GetMsg(Window^.userPort));
      IF MyMsgPtr^.code<128 THEN EXIT END;
      ReplyMsg(MyMsgPtr);
    END;
    ReplyMsg(MyMsgPtr);

  ELSE

    CountFiles := 1;
    LOOP

      WHILE (CountFiles<=NumArgs()) AND (MyFile=NIL) DO
        GetArg(CountFiles,Name,len);
        MyFile := Open(ADR(Name),oldFile);
        RQPos := -1; RQLen := -1;
        INC(CountFiles);
      END;

(*------  Type Text:  ------*)

      IF Scroll THEN
        IF Down THEN
          IF ScrollDown(FALSE,MyFile#NIL) THEN
            Close(MyFile);
            MyFile := NIL;
          END;
          IF RefreshDisplayCnt#0 THEN DEC(RefreshDisplayCnt) END;
        ELSE
          ScrollUp(FALSE);
        END;
      ELSE
        WaitPort(Window^.userPort);
      END;

      MyMsgPtr := ADDRESS(GetMsg(Window^.userPort));

      IF MyMsgPtr#NIL THEN

        MyMsg := MyMsgPtr^;
        ReplyMsg(MessagePtr(MyMsgPtr));

        WITH MyMsg DO

          IF class=IDCMPFlagSet{rawKey} THEN

            Shift := (lShift   IN QualifierSet(qualifier)) OR
                     (rShift   IN QualifierSet(qualifier)) OR
                     (capsLock IN QualifierSet(qualifier));

            Alt   := (lAlt     IN QualifierSet(qualifier)) OR
                     (rAlt     IN QualifierSet(qualifier));

            CASE code OF

            40H:  IF Down THEN                      (* Space *)
                    Scroll := NOT(Scroll);
                    IF (BottomLine^.next=NIL) AND (MyFile=NIL) THEN
                      EXIT;
                    END;
                  ELSE
                    Down := TRUE;
                    Scroll := TRUE;
                  END; |

            41H:  IF RefreshDisplayCnt=0 THEN         (* BackSpace *)
                    IF Down THEN
                     Down := FALSE;
                      Scroll := TRUE;
                    ELSE
                      Scroll := NOT(Scroll);
                    END;
                  END; |

            4DH:  i:=1; IF Alt THEN i:=NumLines END;         (* Down *)
                  WHILE i#0 DO
                    IF ScrollDown(NOT(Shift),MyFile#NIL) THEN
                      Close(MyFile);
                      MyFile := NIL;
                    END;
                    IF RefreshDisplayCnt#0 THEN DEC(RefreshDisplayCnt) END;
                    DEC(i);
                  END;
                  Scroll := FALSE; |

            4CH:  i:=1; IF Alt THEN i:=NumLines END;         (* Up *)
                  WHILE i#0 DO
                    IF RefreshDisplayCnt=0 THEN
                      ScrollUp(NOT(Shift));
                      Scroll := FALSE;
                    END;
                    DEC(i);
                  END; |

            44H:  IF ScrollDown(FALSE,MyFile#NIL) THEN       (* CR *)
                    Close(MyFile);
                    MyFile := NIL;
                  END;
                  IF RefreshDisplayCnt#0 THEN DEC(RefreshDisplayCnt) END;
                  Scroll := FALSE; |

            23H:  TopLine := FirstLine;                      (* F *)
                  BottomLine := FirstLine;
                  ClearBitMaps();
                  RefreshDisplayCnt := NumLines-2;
                  AddBottomLine(BottomLine,FALSE);
                  Scroll := TRUE;
                  Down := TRUE; |

            28H:  WHILE BottomLine^.next#NIL DO              (* L *)
                    BottomLine := BottomLine^.next;
                  END;
                  i:=1;
                  WHILE (i<NumLines) AND (BottomLine^.prev#NIL) DO
                    BottomLine := BottomLine^.prev;
                    INC(i);
                  END;
                  RefreshDisplayCnt := NumLines-2;
                  TopLine := BottomLine;
                  ClearBitMaps();
                  AddBottomLine(BottomLine,FALSE);
                  Scroll := TRUE; Down := TRUE; |

            5FH,25H: ClearBitMaps();
                  Write("                          MuchMore");
                  Write("                       =============="); Write("");
                  Write("    Available Commands:"); Write("");
                  Write("      Space:           Start / Stop Scrolling. Quit at end of File."); Write("");
                  Write("      BackSpace:       Start / Stop Scrolling backwards."); Write("");
                  Write("      Up/Down:         Scroll quick one Line up or down."); Write("");
                  Write("      Shift & Up/Down: Scroll one Line up or down."); Write("");
                  Write("      Alt & Up/Down:   Scroll one Page up or down."); Write("");
                  Write("      F:               Jump to first Page."); Write("");
                  Write("      L:               Jump to last (loaded) Page."); Write("");
                  Write("      HELP, H:         Show Commands."); Write("");
                  Write("      ESC, Q, X:       Quit."); Write("");
                  Write("   © 1988 Fridtjof Siebert, Nobileweg 67, D-7000-Stuttgart-40");
                  IF NOT(NTSC()) THEN
                    FOR i:=0 TO 6 DO Write(""); END;
                  END;
                  LOOP
                    WaitPort(Window^.userPort);
                    MyMsgPtr := ADDRESS(GetMsg(Window^.userPort));
                    IF MyMsgPtr^.code<128 THEN EXIT END;
                    ReplyMsg(MyMsgPtr);
                  END;
                  ReplyMsg(MyMsgPtr);
                  BottomLine := TopLine;
                  RefreshDisplayCnt := NumLines - 2;
                  ClearBitMaps();
                  AddBottomLine(BottomLine,FALSE);
                  Scroll := TRUE; Down := TRUE; |

            10H,45H,32H: EXIT; |                        (* ESC, Q, X *)

            ELSE

            END;   (* CASE code OF *)

          END;   (* IF class=IDCMPFlagSet{rawKey} THEN *)

        END;   (* WITH MyMsg DO *)

      END;   (* IF MyMsgPtr#NIl THEN *)

    END;   (* LOOP *)

  END;   (* IF NumArgs()=0 THEN ELSE *)

END MuchMore.
