home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 2: PC / frozenfish_august_1995.bin / bbs / d03xx / d0378.lha / MuchMore / txt / MuchMore.mod < prev    next >
Text File  |  1990-10-10  |  56KB  |  1,715 lines

  1. (*---------------------------------------------------------------------------
  2.  :Program.      MuchMore.mod
  3.  :Author.       Fridtjof Siebert
  4.  :Address.      Nobileweg 67, D-7000 Stuttgart 40
  5.  :Shortcut.     [fbs]
  6.  :Copyright.    PD
  7.  :Language.     OBERON
  8.  :Translator.   Amiga Oberon Compiler
  9.  :History. V1.0 summer-88: First very slow internal version              [fbs]
  10.  :History. V1.1 24-Sep-88: First published version                       [fbs]
  11.  :History. V1.2 26-Nov-88: Now displays Filelength & Percentage          [fbs]
  12.  :History.      27-Nov-88: Mouse can be used instead of Space / BackSpace[fbs]
  13.  :History. V1.3 29-Apr-89: Strong increase in speed, removed WarpText    [fbs]
  14.  :History.      29-Apr-89: Now supports Numeric Keys (Home,PgUp etc.)    [fbs]
  15.  :History.      29-Apr-89: Now opens Screen as big as gfx.normalDisplay  [fbs]
  16.  :History. V1.4 29/30-Apr-89: Asynchronus loading / displaying. Very nice[fbs]
  17.  :History.      30-Apr-89, 00:33: Removed bugs in Filelength & L-Command [fbs]
  18.  :History.      30-Apr-89, 02:21: Added Find-Command                     [fbs]
  19.  :History.      30-Apr-89, 10:30: Scrolling stops when window is inactive[fbs]
  20.  :History.      01-May-89: Allocates no more unneeded memory for text    [fbs]
  21.  :History.      07-May-89: Allocates even less memory now                [fbs]
  22.  :History.      14-May-89: Removed deadlock-bug with Find-Window         [fbs]
  23.  :History. V1.5 25-May-89: Added print feature                           [fbs]
  24.  :History.      25-May-89: Removed all imports (apart from Arts)         [fbs]
  25.  :History.      26-May-89: inspired by J. Kupfer, I added nk 5 to quit   [fbs]
  26.  :History.      26-May-89: Now handle BS correctly                       [fbs]
  27.  :History. V1.6 02-Jul-89: Now supports several fontstyles and colors    [fbs]
  28.  :History. V1.7 03-Jul-89: Is again as fast as it was with 2 colors      [fbs]
  29.  :History.      03-Jul-89: Now no more crashes when quitting while print [fbs]
  30.  :History.      07-Jul-89: removed bug with texts of length 0            [fbs]
  31.  :History. V1.8 10-Jul-89: small bug in find-command removed             [fbs]
  32.  :History.      10-Jul-89: now found strings are highlighted             [fbs]
  33.  :History.      14-Jul-89: nk0 to display fileinfo                       [fbs]
  34.  :History. V2.0 06-Aug-89: Ported this to OBERON                         [fbs]
  35.  :History.      06-Aug-89: Added ARP-FileRequester                       [fbs]
  36.  :History.      07-Aug-89: Added L - (load new file) Command             [fbs]
  37.  :History. V2.1 03-Sep-89: no more gurus if an r/w error occures         [fbs]
  38.  :History.      03-Sep-89: MM used to execute CSI-Codes backwards. fixed [fbs]
  39.  :History.      03-Sep-89: ping / pong with Shift+Fn / Fn                [fbs]
  40.  :History.      03-Sep-89: new command: goto                             [fbs]
  41.  :History. V2.2 05-Sep-89: will run with any keymapping now              [fbs]
  42.  :History. V2.3 17-Sep-89: New command: sleep & Pop-Up feature           [fbs]
  43.  :History.      17-Sep-89: "MuchMore -s" will go to sleep immediately    [fbs]
  44.  :History.      17-Sep-89: Interprets <CSI>m as <CSI>0m now              [fbs]
  45.  :History. V2.4 17-Sep-89: New command: write block "w"                  [fbs]
  46.  :History.      17-Sep-89: rewritten argument parser to allow quotes     [fbs]
  47.  :History. V2.5 18-Sep-89: now uses the 8x8 font set with SetFont        [fbs]
  48.  :History.      19-Sep-89: no more scatters memory. Allocates 4K Chunks  [fbs]
  49.  :History. V2.6 26-Jun-90: Made MuchMore reentrant                       [fbs]
  50.  :History.      26-Jun-90: Opens 1-Plane Screen if memory is rare        [fbs]
  51.  :History.      26-Jun-90: Asynchronus fast scrolling with Ctrl-Up/Down  [fbs]
  52.  :History.      26-Jun-90: Now supports interlaced screens               [fbs]
  53.  :History.      08-Aug-90: CLI-Option '-l' to toggle interlaced mode     [fbs]
  54.  :History. V2.7 09-Aug-90: no more RethinkDisplay()s,looks good with 2.0 [fbs]
  55.  :History.      10-Aug-90: Supports Kick2.0 ASL-FileRequester            [fbs]
  56.  :Contents.     A Soft-Scrolling ASCII-File Printer.
  57.  :Usage.        MuchMore {-s|-l} [Text]
  58.  :Remark.       Compile: 'Oberon -dm MuchMore'
  59.  :Remark.       Link:    'OLink -dm MuchMore OBJ MMQText.obj OBJ MMInput.obj'
  60. ---------------------------------------------------------------------------*)
  61.  
  62. MODULE MuchMore;
  63.  
  64. (* $StackChk- $OvflChk- $RangeChk- $StackChk- $NilChk- $ReturnChk- $CaseChk- *)
  65.  
  66. IMPORT ol: OberonLib,
  67.        d:  Dos,
  68.        e:  Exec,
  69.            Input,
  70.        ie: InputEvent,
  71.        I:  Intuition,
  72.        g:  Graphics,
  73.        wb: Workbench,
  74.        km: KeyMap,
  75.        sys:SYSTEM;
  76.  
  77. (*-------------------------------------------------------------------------*)
  78.  
  79. CONST
  80.   empty = "";
  81.   oom = "Out of memory!";
  82.   cof = "Can't open file!";
  83.   usage = "Usage: MuchMore {-s|-l} [Text]";
  84.   rwerr = "Read/Write Error";
  85.   noarp = "Need arp for FileReq";
  86.   conerr = "Console problem";
  87.   MuchText = "MuchMore V2.7 ⌐ 1990 AMOK";
  88.   MMissleeping = "MM is sleeping";
  89.   MMisawake = "MM is awake";
  90.   nil = "NIL:";
  91.   w = TRUE;
  92.   f = FALSE;
  93.   MaxLen = 256;
  94.  
  95. (* Control codes for QText: *)
  96.   plain    = CHR(17);
  97.   italic   = CHR(18);
  98.   bold     = CHR(19);
  99.   boldit   = CHR(20);
  100.   ulineon  = CHR(21);
  101.   ulineoff = CHR(22);
  102.  
  103.   Italic = 0;
  104.   Bold   = 1;
  105.   Ulin   = 2;
  106.   Inv    = 3;
  107.  
  108.  
  109. TYPE
  110.   TextLinePtr = POINTER TO TextLine;
  111.   TextLine = STRUCT
  112.                next: TextLinePtr;
  113.                prev: TextLinePtr;
  114.                len:  INTEGER;
  115.                size: INTEGER;
  116.                text: ARRAY MaxLen+1 OF CHAR;
  117.              END;
  118.   String = ARRAY 256 OF CHAR;
  119.   StringPtr = POINTER TO String;
  120.   FontData = ARRAY 8, 192, 8 OF CHAR;
  121.   FontDataPtr = POINTER TO FontData;
  122.  
  123.  
  124. CONST
  125. (* FileReqFlags *)
  126.   listFunc    = 0;
  127.   gEventFunc  = 1;
  128.   addGadFunc  = 2;
  129.   newWindFunc = 3;
  130.   newIDCMP    = 4;
  131.   doColor     = 5;
  132.   doMsgFunc   = 6;
  133.   doWildFunc  = 7;
  134.  
  135. TYPE
  136.   STRPTR = POINTER TO CHAR;
  137.  
  138.   FileRequesterPtr = POINTER TO FileRequester;
  139.   FileRequester = STRUCT
  140.     hail: STRPTR;                (* Hailing text                     *)
  141.     ddef: StringPtr;             (* Filename array (FCHARS+1)        *)
  142.     ddir: StringPtr;             (* Directory array (DSIZE+1)        *)
  143.     wind: I.WindowPtr;           (* Window requesting or NULL        *)
  144.     funcFlags: SHORTSET;         (* Control. See above.              *)
  145.     reserved1: SHORTINT;         (* Set this to 0                    *)
  146.     function: PROCEDURE;         (* Your function, see btdef's       *)
  147.     reserved2: LONGINT;          (* reserved                         *)
  148.   END;
  149.  
  150.  
  151. VAR
  152.   Screen: I.ScreenPtr;           (* Screen that contains the Text     *)
  153.   BM: g.BitMapPtr;               (* Screen's BitMap (external)        *)
  154.   Window: I.WindowPtr;           (* My window                         *)
  155.   MyFont: g.TextAttr;            (* Topaz 8                           *)
  156.   MyFile: d.FileHandlePtr;       (* For loading Textfile              *)
  157.   FirstLine: TextLinePtr;        (* Saved Text                        *)
  158.   TopLine: TextLinePtr;          (* Points to topmost Line            *)
  159.   BottomLine: TextLinePtr;       (* Last Line displayed on Screen     *)
  160.   LoadLine: TextLinePtr;         (* currently loaded Line             *)
  161.   LastLine: TextLinePtr;         (* Last element of LineList          *)
  162.   Name: String;                  (* Text's Name                       *)
  163.   lace: BOOLEAN;                 (* use interlaced screen?            *)
  164.   IStr,PStr: String;             (* differently used                  *)
  165.   Buffer: ARRAY 512 OF CHAR;     (* Buffer for Reading                *)
  166.   RQPos: LONGINT;                (* Position within ReadBuffer        *)
  167.   RQLen: LONGINT;                (* Number of CHARs in Buffer         *)
  168.   NumLines: INTEGER;             (* Number of Lines on Screen         *)
  169.   NumColumns: INTEGER;           (* Number of Columns on Screen       *)
  170.   PageSize: LONGINT;             (* 8*NumLines*NumColumns             *)
  171.   AnzLines: LONGINT;             (* Length of Text in Lines           *)
  172.   fontdata: FontData;            (* Fonts used by QText()             *)
  173.   MyLock,OldDir: d.FileLockPtr;  (* To Examine and Load File          *)
  174.   FileInfo: d.FileInfoBlockPtr;  (* to get File's length              *)
  175.   FileLength,TextLength: LONGINT;(* Length of File and of Displayed Text *)
  176.   ScreenPos: INTEGER;            (* actual position within bitmap     *)
  177.   ShowTask: e.Task;              (* the task that displays the text   *)
  178.   ShowStack: ARRAY 1000 OF LONGINT; (* it's stack                        *)
  179.   ShowTaskRunning: BOOLEAN;      (* is Showtask activated?            *)
  180.   mySigBit: INTEGER;             (* My SignalBit                      *)
  181.   mySig: LONGSET;                (* My SignalSet = LONGSET{mySigBit}  *)
  182.   SignalNewData: BOOLEAN;        (* Signal when new data is loaded    *)
  183.   SignalAllRead: BOOLEAN;        (* send signal at end of text        *)
  184.   Done: BOOLEAN;                 (* Quit                              *)
  185.   print: BOOLEAN;                (* print text                        *)
  186.   NewText: BOOLEAN;              (* load new text                     *)
  187.   Me: d.ProcessPtr;              (* my main task                      *)
  188.   Info: BOOLEAN;                 (* is info currently displayed ?     *)
  189.   MyMsgPtr: I.IntuiMessagePtr;   (* for receiving Messages            *)
  190.   i,j: INTEGER;                  (* count                             *)
  191.   Scroll: BOOLEAN;               (* scrolling or waiting?             *)
  192.   Fast: BOOLEAN;                 (* scrollquick?                      *)
  193.   Sync: BOOLEAN;                 (* scroll very quick?                *)
  194.   in,out: d.FileHandlePtr;       (* i/o for TYPE xxx TO PRT:          *)
  195.   fg,bg: INTEGER;                (* Text colors                       *)
  196.   style: SHORTSET;               (* Text style                        *)
  197.   CommLine: POINTER TO CHAR;     (* The CLI-commands                  *)
  198.   ArgPtr: POINTER TO String;     (* to get WBArg                      *)
  199.   wbm: wb.WBStartupPtr;          (* WBenchMessage                     *)
  200.   ri: g.RasInfoPtr;              (* Screen's ViewPort's RasInfo       *)
  201.   NuScreen: I.NewScreen;         (* to open screens                   *)
  202.   NuWindow: I.NewWindow;         (* to open window                    *)
  203.   Prefs: I.Preferences;          (* Preferences (need wbLace)         *)
  204.   StrGadget: I.Gadget;           (* Gadget for Find-Command           *)
  205.   StrInfo: I.StringInfo;         (* its special info                  *)
  206.   arp: LONGINT;                  (* ArpBase                           *)
  207.   asl: LONGINT;                  (* ASL-librarybase                   *)
  208.   body,text,ok: I.IntuiText;     (* IntuiTexts for AutoRequest        *)
  209.   FR: FileRequester;             (* The Requester                     *)
  210.   Filename: String;              (* The Filename (without path)       *)
  211.   Dirname: String;               (* its path                          *)
  212.   NewDisp: BOOLEAN;              (* need to rebuild Display ?         *)
  213.   TextMarkers: ARRAY 10 OF TextLinePtr; (* Marked Positions in text   *)
  214.   FindLine: TextLinePtr;         (* Last found line                   *)
  215.   KeyMap: ARRAY 40H OF CHAR;     (* console's KeyMap                  *)
  216.   wreq: e.IOStdReq;              (* Request to communicate with the console *)
  217.   console: e.DevicePtr;          (* the console.device                *)
  218.   ievent: ie.InputEvent;         (* InputEvent to convert keycodes    *)
  219.  
  220.   InputData: STRUCT
  221.     wakeUpSignal: SHORTINT;      (* Signal that's wakes us up*)
  222.     sigTask: e.TaskPtr;          (* MM's main task                    *)
  223.     sleeping: BOOLEAN;           (* TRUE while we sleep               *)
  224.   END;
  225.   InputDevPort: e.MsgPort;       (* Input.Device's Port               *)
  226.   InputRequestBlock: e.IOStdReq; (* its Requestblock                  *)
  227.   HandlerStuff: e.Interrupt;     (* contains data about Input Handler *)
  228.   InputOpen: BOOLEAN;            (* TRUE while input.device is open   *)
  229.   HandlerActive: BOOLEAN;        (* TRUE while InputHandler is active *)
  230.  
  231.   WriteName: String;             (* File to write Block               *)
  232.   savefrom,savesize: LONGINT;    (* How much to save?                 *)
  233.   save: BOOLEAN;                 (* save block                        *)
  234.   buffer: POINTER TO LONGINT;    (* buffer to save file               *)
  235.  
  236.   c: CHAR;                       (* \ used by GetTextLine();          *)
  237.   le: INTEGER;                   (* / global for speed                *)
  238.  
  239. (*------  Memory:  ------*)
  240.  
  241. CONST ChunkSize = 4096;          (* size of allocated chunks *)
  242.  
  243. TYPE
  244.   MemChunkPtr = POINTER TO MemChunk;  (* chunklist *)
  245.   MemChunk = STRUCT
  246.                prev: MemChunkPtr;     (* link *)
  247.                data: ARRAY ChunkSize OF BYTE; (* ChinkSize Bytes of memory *)
  248.              END;
  249.  
  250. VAR
  251.   MemIndex: INTEGER;      (* index in current Chunk *)
  252.   CurChunk: MemChunkPtr;  (* current chunk          *)
  253.  
  254. (*-----------------  External Assembler Procedures:  ----------------------*)
  255.  
  256.  
  257. (*------  The fastest textoutput-Procedure in the world (maybe):  ------*)
  258.  
  259. PROCEDURE QText{"QText"}(y{1}: INTEGER;
  260.                          str{8}: LONGINT;
  261.                          bm{9}: g.BitMapPtr;
  262.                          fd{10}: FontDataPtr);
  263.  
  264. (*------  Get Font:  ------*)
  265.  
  266. PROCEDURE GetFontData{"GetFontData"}(from{8},to{9}: LONGINT; linelen{7}: INTEGER);
  267.  
  268. (*------  Copy Line:  ------*)
  269.  
  270. PROCEDURE CopyLine1{"CopyLine1"}(bm{8}: g.BitMapPtr; w{0},h{1},pos{2}: INTEGER);
  271.  
  272. PROCEDURE CopyLine2{"CopyLine2"}(bm{8}: g.BitMapPtr; w{0},h{1},pos{2}: INTEGER);
  273.  
  274.  
  275. (*------  Input Handler:  ------*)
  276.  
  277. PROCEDURE * InputHandler{"MMInputHandler"};
  278.  
  279.  
  280. (*-------------------------------------------------------------------------*)
  281.  
  282. (*------  Console Procedure:  ------*)
  283.  
  284.  
  285. PROCEDURE RawKeyConvert{console,-48}(events{8}:ie.InputEventPtr;
  286.                                      buffer{9}:LONGINT;
  287.                                      length{1}:LONGINT;
  288.                                      keyMap{10}:LONGINT);
  289.  
  290.  
  291. (*-------------------------------------------------------------------------*)
  292.  
  293.  
  294. PROCEDURE Length(VAR s: String): INTEGER;
  295. VAR l: INTEGER;
  296. BEGIN l := -1; REPEAT INC(l) UNTIL (l>sys.SIZE(s)) OR (s[l]=0X); RETURN l;
  297. END Length;
  298.  
  299.  
  300. PROCEDURE Append(VAR s1: String; s2: StringPtr);
  301. (* appends s2 to s1 *)
  302. VAR p,q: INTEGER;
  303. BEGIN
  304.   p := Length(s1); q := 0;
  305.   WHILE (p<=sys.SIZE(s1)) AND (s2^[q]#0X) AND (p<NumColumns) DO
  306.     s1[p] := s2^[q]; INC(p); INC(q)
  307.   END;
  308.   IF p<=sys.SIZE(s1) THEN s1[p] := 0X END;
  309. END Append;
  310.  
  311.  
  312. (*-----------------------------  Requester:  ------------------------------*)
  313.  
  314.  
  315. PROCEDURE Request(Text: StringPtr);
  316.  
  317. VAR
  318.   out: d.FileHandlePtr;
  319.   c: CHAR;
  320.  
  321. BEGIN
  322.   IF ol.wbStarted THEN
  323.     body.frontPen := 0; body.backPen  := 1;  body.drawMode := g.jam2;
  324.     body.leftEdge := 12; body.topEdge  := 8;
  325.     text := body; ok := body;
  326.     body.iText    := sys.ADR(MuchText);
  327.     body.nextText := sys.ADR(text);
  328.     text.iText    := Text; text.topEdge := 22;
  329.     ok.leftEdge   := 6; ok.topEdge := 3; ok.iText := sys.ADR("  OK  ");
  330.     sys.SETREG(0,I.AutoRequest(NIL,sys.ADR(body),NIL,sys.ADR(ok),
  331.                            LONGSET{I.rawKey},LONGSET{},320,65));
  332.   ELSE
  333.     out := d.Output();
  334.     sys.SETREG(0,d.Write(out,Text^,Length(Text^)));
  335.     c := 0AX;
  336.     sys.SETREG(0,d.Write(out,c,1));
  337.   END;
  338.   HALT(0);
  339. END Request;
  340.  
  341.  
  342. (*-------------------------------------------------------------------------*)
  343.  
  344. PROCEDURE AllocLine(sz: INTEGER): TextLinePtr;
  345.  
  346. VAR
  347.   a: TextLinePtr;
  348.   newchunk: MemChunkPtr;
  349.  
  350. BEGIN
  351.   INC(sz,sys.SIZE(TextLine)-MaxLen); IF ODD(sz) THEN INC(sz) END;
  352.   IF MemIndex+sz<=ChunkSize THEN     (* does mem fit into current chunk ? *)
  353.     INC(MemIndex,sz);                (* increment index in current chunk  *)
  354.   ELSE
  355.     NEW(newchunk);                   (* allocate new chunk                *)
  356.     IF newchunk=NIL THEN Request(sys.ADR(oom)) END;
  357.     newchunk.prev := CurChunk;       (* link chunk into list              *)
  358.     CurChunk := newchunk;
  359.     MemIndex := sz;
  360.   END;
  361.   RETURN sys.ADR(CurChunk.data[MemIndex-sz]);
  362. END AllocLine;
  363.  
  364.  
  365. PROCEDURE DisposeLines();
  366.  
  367. VAR chunk: MemChunkPtr;
  368.  
  369. BEGIN
  370.   WHILE CurChunk#NIL DO
  371.     chunk := CurChunk.prev;
  372.     DISPOSE(CurChunk);
  373.     CurChunk := chunk;
  374.   END;
  375.   MemIndex := ChunkSize;
  376. END DisposeLines;
  377.  
  378. (*-------------------------------------------------------------------------*)
  379.  
  380.  
  381. PROCEDURE MakeThink(sync: BOOLEAN);
  382.  
  383. BEGIN
  384.   I.MakeScreen(Screen);
  385.   g.MrgCop(I.ViewAddress());
  386.   IF sync THEN g.WaitBOVP(sys.ADR(Screen.viewPort)) END;
  387. END MakeThink;
  388.  
  389.  
  390. (*------  Clear Display:  ------*)
  391.  
  392.  
  393. PROCEDURE ClearBitMaps();
  394.  
  395. BEGIN
  396.   g.BltClear(BM.planes[0],2*PageSize,LONGSET{});
  397.   g.BltClear(BM.planes[1],2*PageSize,LONGSET{});
  398.   ScreenPos := 0;
  399.   ri.ryOffset := 0;
  400. END ClearBitMaps;
  401.  
  402.  
  403. (*------------------------  Open Display:  --------------------------------*)
  404.  
  405.  
  406. PROCEDURE InitScreen();
  407.  
  408. VAR c: CHAR;
  409.  
  410. BEGIN
  411.  
  412. (*------  Open Screen:  ------*)
  413.  
  414.   NumColumns := g.gfx.normalDisplayColumns DIV 32 * 4;
  415.   IF NumColumns>MaxLen THEN NumColumns := MaxLen END;
  416.   NuScreen.viewModes := {g.hires};
  417.   NumLines := g.gfx.normalDisplayRows DIV 8;
  418.   IF lace THEN
  419.     INC(NumLines,NumLines);
  420.     INCL(NuScreen.viewModes,g.lace);
  421.   END;
  422.   NuScreen.width  := 8*NumColumns;
  423.   PageSize := 8*LONG(NumLines*NumColumns);
  424.   NuScreen.height := 16*NumLines;
  425.   NuScreen.depth  := 2;
  426.   MyFont.name := sys.ADR("topaz.font");
  427.   MyFont.ySize := 8;
  428.   NuScreen.font := sys.ADR(MyFont);
  429.   NuScreen.type := I.customScreen+{I.screenQuiet};
  430.   LOOP
  431.     Screen := I.OpenScreen(NuScreen);
  432.     IF Screen#NIL THEN EXIT END;
  433.     DEC(NuScreen.depth);
  434.     IF NuScreen.depth=0 THEN Request(sys.ADR(oom)) END;
  435.   END;
  436.   BM := Screen.rastPort.bitMap;
  437.   IF NuScreen.depth=1 THEN BM.planes[1] := BM.planes[0] END;
  438.   ri := Screen.viewPort.rasInfo;
  439.   ClearBitMaps;
  440.   ri.ryOffset := 32;
  441.   Screen.height := Screen.height DIV 2;
  442.   MakeThink(TRUE);
  443.   I.RethinkDisplay;
  444.  
  445. (*------  Get Font:  ------*)
  446.  
  447.   IStr[64] := 0X;
  448.   j := 0; c := 20X;
  449.   g.SetDrMd(sys.ADR(Screen.rastPort),g.jam1);
  450.   g.SetAPen(sys.ADR(Screen.rastPort),1);
  451.   WHILE j<32 DO
  452.     i := 0; WHILE i<48 DO IStr[i] := c; INC(i); INC(c) END;
  453.     IF c=80X THEN c := 0A0X END;
  454.     g.Move(sys.ADR(Screen.rastPort),0,Screen.rastPort.font.baseline+j);
  455.     g.Text(sys.ADR(Screen.rastPort),IStr,48);
  456.     INC(j,8);
  457.   END;
  458.   GetFontData(Screen.bitMap.planes[0],sys.ADR(fontdata),NumColumns);
  459.  
  460. (*------  Open Window:  ------*)
  461.  
  462.   NuWindow.flags  := LONGSET{I.rmbTrap,I.activate,I.borderless,I.reportMouse};
  463.   NuWindow.screen := Screen;
  464.   NuWindow.type   := I.customScreen;
  465.   NuWindow.topEdge:= 10;
  466.   NuWindow.width  := NuScreen.width;
  467.   NuWindow.height := Screen.height-10;
  468.   NuWindow.idcmpFlags := LONGSET{I.inactiveWindow,I.activeWindow,I.rawKey,
  469.                                  I.mouseButtons};
  470.   Window := I.OpenWindow(NuWindow);
  471.   IF Window=NIL THEN Request(sys.ADR(oom)) END;
  472.  
  473. END InitScreen;
  474.  
  475.  
  476. (*-------------------------------------------------------------------------*)
  477.  
  478. PROCEDURE CloseDisplay();
  479.  
  480. BEGIN
  481.   IF Window#NIL THEN I.CloseWindow(Window); Window := NIL END;
  482.   IF Screen#NIL THEN I.CloseScreen(Screen); Screen := NIL END;
  483. END CloseDisplay;
  484.  
  485. (*------  Read one TextLine into a Variable:  ------*)
  486.  
  487.  
  488. PROCEDURE GetTextLine(): TextLinePtr;
  489. (* returns NIL at EOF *)
  490.  
  491. VAR
  492.   l: TextLinePtr;
  493.   sz,wd,i,j: INTEGER;
  494.   txt: ARRAY MaxLen+1 OF CHAR;
  495.   num: ARRAY 10 OF INTEGER;
  496.   newcol: BOOLEAN;
  497.   oldstyle: SHORTSET;
  498.  
  499.   PROCEDURE GetCh();
  500.  
  501.   BEGIN
  502.     IF RQPos=RQLen THEN
  503.       RQLen := d.Read(MyFile,Buffer,sys.SIZE(Buffer));
  504.       IF RQLen<0 THEN Request(sys.ADR(rwerr)) END;
  505.       RQPos := 0;
  506.     END;
  507.     IF RQLen=0 THEN c := 0X ELSE
  508.       c := Buffer[RQPos]; IF c=0X THEN c:=1X END;
  509.       INC(RQPos); INC(le);
  510.     END;
  511.   END GetCh;
  512.  
  513. BEGIN
  514.   IF RQLen=0 THEN RETURN NIL END;
  515.   sz := 0; wd := 0; le := 0;
  516.   IF Italic IN style THEN IF Bold IN style THEN txt[sz] := boldit ELSE txt[sz] := italic END; INC(sz);
  517.                      ELSE IF Bold IN style THEN txt[sz] := bold; INC(sz) END;
  518.   END;
  519.   IF Ulin IN style THEN txt[sz] := ulineon; INC(sz) END;
  520.   IF    Inv IN style     THEN txt[sz] := CHR(fg+4*bg+1); INC(sz)
  521.   ELSIF (fg#1) OR (bg#0) THEN txt[sz] := CHR(bg+4*fg+1); INC(sz) END;
  522.   LOOP
  523.     LOOP
  524.       GetCh;
  525.       IF sys.VAL(CHAR,sys.VAL(SHORTSET,c)*SHORTSET{0..6})#1BX THEN EXIT END;
  526.       i := -1;
  527.       REPEAT
  528.         GetCh;
  529.         IF (c>=30X) AND (c<=39X) THEN
  530.           INC(i); num[i] := 0;
  531.           REPEAT
  532.             num[i] := 10*num[i]+ORD(c)-ORD(30X); GetCh;
  533.           UNTIL (c<30X) OR (c>39X);
  534.         END;
  535.         c := CAP(c);
  536.       UNTIL (c>=3FX(*"?"*)) AND (c<=5AX) OR (c=0X) OR (i=9);
  537.       IF c=4DX THEN
  538.         newcol := f; oldstyle := style; j := 0;
  539.         IF i=-1 THEN i:=0; num[0] := 0 END;
  540.         WHILE (i>=j) AND (sz<MaxLen-1) DO
  541.           CASE num[j] OF
  542.           0: style := SHORTSET{}; fg := 1; bg := 0; newcol := w |
  543.           1: INCL(style,Bold) |
  544.           2: fg := 2; newcol := w (* I hope this is correct *) |
  545.           3: INCL(style,Italic) |
  546.           4: INCL(style,Ulin) |
  547.           7: INCL(style,Inv); newcol := w |
  548.           30..37: fg := sys.VAL(INTEGER,sys.VAL(SET,num[j]-30) * {0,1}); newcol := w |
  549.           40..47: bg := sys.VAL(INTEGER,sys.VAL(SET,num[j]-40) * {0,1}); newcol := w |
  550.           ELSE END;
  551.           INC(j);
  552.         END;
  553.         IF (oldstyle#style) AND (sz<MaxLen) THEN
  554.           IF Italic IN style THEN IF Bold IN style THEN txt[sz] := boldit ELSE txt[sz] := italic END;
  555.                              ELSE IF Bold IN style THEN txt[sz] := bold   ELSE txt[sz] := plain  END;
  556.           END;
  557.           INC(sz);
  558.           IF (Ulin IN style) THEN
  559.             IF NOT((Ulin IN oldstyle)) AND (sz<MaxLen) THEN
  560.               txt[sz] := ulineon;
  561.               INC(sz);
  562.             END;
  563.           ELSE
  564.             IF (Ulin IN oldstyle) AND (sz<MaxLen) THEN
  565.               txt[sz] := ulineoff;
  566.               INC(sz);
  567.             END;
  568.           END;
  569.         END;
  570.         IF newcol AND (sz<MaxLen) THEN
  571.           IF Inv IN style THEN txt[sz] := CHR(fg+4*bg+1)
  572.                           ELSE txt[sz] := CHR(bg+4*fg+1) END;
  573.           INC(sz);
  574.         END;
  575.       END;   (* IF c="m" THEN *)
  576.     END;   (* LOOP *)
  577.     CASE c OF
  578.     20X..7FX:              txt[sz] := c; INC(sz); INC(wd) |
  579.     0A1X..0FFX: DEC(c,32); txt[sz] := c; INC(sz); INC(wd) |
  580.     8X: (* BS *)       IF wd>0 THEN DEC(sz); DEC(wd); END |
  581.     9X: (* TAB *)
  582.       REPEAT
  583.         txt[sz] := 20X; INC(sz); INC(wd)
  584.       UNTIL (sz=MaxLen) OR (wd=NumColumns) OR (sys.VAL(SET,sz)*{0..2}={}) |
  585.     0A0X:                txt[sz] := 20X; INC(sz); INC(wd) |
  586.     0AX,0X,0CX: EXIT |
  587.     ELSE END;
  588.     IF (wd>=NumColumns) OR (sz>=MaxLen) THEN EXIT END;
  589.   END;
  590.   l := AllocLine(sz);
  591.   l.len := le; l.size:= sz;
  592.   WHILE sz>0 DO DEC(sz); l.text[sz]:=txt[sz] END;
  593.   RETURN l;
  594. END GetTextLine;
  595.  
  596.  
  597. (*------  Write Line at Bottom of Text:  ------*)
  598.  
  599.  
  600. PROCEDURE AddBottomLine(Line: TextLinePtr; Fast: BOOLEAN);
  601.  
  602. VAR
  603.   i,j: INTEGER;
  604.   trash: LONGINT;
  605.   s1,d1,s2,d2: POINTER TO LONGINT;
  606.   a: LONGINT;
  607.  
  608. BEGIN
  609.   QText(8*(ScreenPos+NumLines),sys.ADR(Line.text),BM,sys.ADR(fontdata));
  610.   IF Fast THEN
  611.     INC(ri.ryOffset,8);
  612.     MakeThink(Sync);
  613.     CopyLine1(BM,NumColumns,NumLines,ScreenPos);
  614.   ELSE
  615.     a := 8*LONG(ScreenPos*NumColumns);
  616.     d1 := BM.planes[0] + a; s1 := sys.VAL(LONGINT,d1) + PageSize;
  617.     d2 := BM.planes[1] + a; s2 := sys.VAL(LONGINT,d2) + PageSize;
  618.     i := 8;
  619.     REPEAT
  620.       INC(ri.ryOffset);
  621.       IF NOT lace OR ODD(i) THEN MakeThink(TRUE) END;
  622.       j := NumColumns DIV 4;
  623.       REPEAT
  624.         d1^ := s1^; INC(d1,4); INC(s1,4);
  625.         d2^ := s2^; INC(d2,4); INC(s2,4);
  626.         DEC(j);
  627.       UNTIL j=0;
  628.       DEC(i);
  629.     UNTIL i=0;
  630.   END;
  631.   INC(ScreenPos);
  632.   IF ScreenPos=NumLines THEN
  633.     ScreenPos := 0;
  634.     ri.ryOffset := 0;
  635.   END;
  636. END AddBottomLine;
  637.  
  638.  
  639. (*------  Write String to Screen:  ------*)
  640.  
  641.  
  642. PROCEDURE Write(String: StringPtr; Fast: BOOLEAN);
  643.  
  644. VAR text: TextLine;
  645.  
  646. BEGIN
  647.   text := FirstLine^;
  648.   i := Length(String^);
  649.   IF i>=NumColumns THEN i := NumColumns-1 END;
  650.   text.text[i+1] := 0X;
  651.   REPEAT
  652.     text.text[i] := String^[i];
  653.     IF text.text[i]>80X THEN DEC(text.text[i],32) END;
  654.     DEC(i)
  655.   UNTIL i<0;
  656.   AddBottomLine(sys.ADR(text),Fast);
  657. END Write;
  658.  
  659.  
  660. (*------  Check whether BottomLine.next is NIL or not:  ------*)
  661.  
  662.  
  663. PROCEDURE TryBottomnext(): BOOLEAN;
  664. (* returns TRUE if BottomLine.next#NIL END; *)
  665.  
  666. BEGIN
  667.   IF (BottomLine.next=NIL) AND (MyFile#NIL) THEN
  668.     SignalNewData := w;
  669.     sys.SETREG(0,e.Wait(mySig));
  670.     SignalNewData := f;
  671.   END;
  672.   RETURN BottomLine.next#NIL;
  673. END TryBottomnext;
  674.  
  675.  
  676. (*------  Scroll down one Line:  ------*)
  677.  
  678.  
  679. PROCEDURE ScrollDown(Fast: BOOLEAN);
  680.  
  681. BEGIN
  682.   IF TryBottomnext() THEN
  683.     BottomLine := BottomLine.next;
  684.     INC(AnzLines);
  685.     INC(TextLength,BottomLine.len);
  686.   ELSE RETURN END;
  687.   IF AnzLines>=NumLines THEN TopLine := TopLine.next END;
  688.   AddBottomLine(BottomLine,Fast);
  689. END ScrollDown;
  690.  
  691.  
  692. (*------  Scroll Up one Line:  ------*)
  693.  
  694.  
  695. PROCEDURE ScrollUp(Fast: BOOLEAN);
  696.  
  697. VAR
  698.   i,j: INTEGER;
  699.   s1,d1,s2,d2: POINTER TO LONGINT;
  700.   a: LONGINT;
  701.  
  702. BEGIN
  703.   IF (TopLine.prev#NIL) AND (TopLine.prev.prev#NIL) THEN
  704.     TopLine := TopLine.prev;
  705.     DEC(TextLength,BottomLine.len);
  706.     DEC(AnzLines);
  707.     BottomLine := BottomLine.prev;
  708.     IF ScreenPos=0 THEN
  709.       ri.ryOffset  := NumLines*8;
  710.       ScreenPos := NumLines-1;
  711.     ELSE
  712.       DEC(ScreenPos);
  713.     END;
  714.     QText(8*ScreenPos,sys.ADR(TopLine.prev.text),BM,sys.ADR(fontdata));
  715.     IF Fast THEN
  716.       DEC(ri.ryOffset,8);
  717.       MakeThink(Sync);
  718.       CopyLine2(BM,NumColumns,NumLines,ScreenPos);
  719.     ELSE
  720.       a := 8*LONG((ScreenPos+1)*NumColumns);
  721.       s1 := BM.planes[0] + a; d1 := sys.VAL(LONGINT,s1) + PageSize;
  722.       s2 := BM.planes[1] + a; d2 := sys.VAL(LONGINT,s2) + PageSize;
  723.       i := 8;
  724.       REPEAT
  725.         DEC(ri.ryOffset);
  726.         IF NOT lace OR ODD(i) THEN MakeThink(TRUE) END;
  727.         j := NumColumns DIV 4;
  728.         REPEAT
  729.           DEC(d1,4); DEC(s1,4); d1^ := s1^;
  730.           DEC(d2,4); DEC(s2,4); d2^ := s2^;
  731.           DEC(j);
  732.         UNTIL j=0;
  733.         DEC(i);
  734.       UNTIL i=0;
  735.     END;
  736.   END;   (* IF TopLine#NIL ... *)
  737. END ScrollUp;
  738.  
  739.  
  740. (*------  Undo last Write():  ------*)
  741.  
  742.  
  743. PROCEDURE DelLine();
  744.  
  745. VAR
  746.   i,j: INTEGER;
  747.   s1,d1,s2,d2: POINTER TO LONGINT;
  748.   a: LONGINT;
  749.   text: TextLine;
  750.  
  751. BEGIN
  752.   IF ScreenPos=0 THEN
  753.     ri.ryOffset  := NumLines*8;
  754.     ScreenPos := NumLines;
  755.   END;
  756.   DEC(ScreenPos);
  757.   IF TopLine.prev#NIL THEN
  758.     QText(8*ScreenPos,sys.ADR(TopLine.prev.text),BM,sys.ADR(fontdata));
  759.   ELSE
  760.     QText(8*ScreenPos,sys.ADR(FirstLine.text),BM,sys.ADR(fontdata));
  761.   END;
  762.   a := (LONG(ScreenPos)+1)*8*LONG(NumColumns);
  763.   s1 := BM.planes[0] + a; d1 := sys.VAL(LONGINT,s1) + PageSize;
  764.   s2 := BM.planes[1] + a; d2 := sys.VAL(LONGINT,s2) + PageSize;
  765.   i := 8;
  766.   REPEAT
  767.     DEC(ri.ryOffset);
  768.     IF NOT lace OR ODD(i) THEN MakeThink(TRUE) END;
  769.     j := NumColumns DIV 4;
  770.     REPEAT
  771.       DEC(d1,4); DEC(s1,4); d1^ := s1^;
  772.       DEC(d2,4); DEC(s2,4); d2^ := s2^;
  773.       DEC(j);
  774.     UNTIL j=0;
  775.     DEC(i);
  776.   UNTIL i=0;
  777. END DelLine;
  778.  
  779.  
  780. (*------  Convert Integer to String:  ------*)
  781.  
  782.  
  783. PROCEDURE IntToStr(VAR String: String;
  784.                        At,Chars: INTEGER;
  785.                        int: LONGINT);
  786.  
  787. VAR
  788.   Cnt: INTEGER;
  789.   Ziff: LONGINT;
  790.  
  791. BEGIN
  792.   INC(Chars,At);
  793.   IF (Length(String)<Chars) AND (sys.SIZE(String)>=Chars) THEN
  794.     String[Chars] := 0X
  795.   END;
  796.   REPEAT
  797.     DEC(Chars);
  798.     String[Chars] := CHR(int MOD 10 + ORD(30X)); int := int DIV 10;
  799.   UNTIL (Chars=At) OR (int=0);
  800.   WHILE Chars>At DO DEC(Chars); String[Chars] := 20X END;
  801. END IntToStr;
  802.  
  803.  
  804. (*-------------------------------------------------------------------------*)
  805.  
  806.  
  807. PROCEDURE GetLength(t: TextLinePtr);
  808.  
  809. BEGIN
  810.   TextLength := 0; AnzLines := 0;
  811.   WHILE t#NIL DO INC(AnzLines); INC(TextLength,t.len); t := t.prev END;
  812. END GetLength;
  813.  
  814.  
  815. (*-------------------------------------------------------------------------*)
  816.  
  817.  
  818. PROCEDURE NewDisplay();
  819. (* Zeichnet ab BottomLine neu *)
  820.  
  821. VAR
  822.   i: INTEGER;
  823.   l: TextLinePtr;
  824.  
  825. BEGIN
  826.   ClearBitMaps;
  827.   i := 1;
  828.   l := BottomLine;
  829.   WHILE (i<NumLines) AND (BottomLine.next#NIL) DO
  830.     BottomLine := BottomLine.next;
  831.     INC(i);
  832.   END;
  833.   WHILE (i<NumLines) AND (l.prev#NIL) DO l := l.prev; INC(i) END;
  834.   BottomLine := l;
  835.   GetLength(l);
  836.   Write(sys.ADR(empty),w);
  837.   AddBottomLine(BottomLine,w);
  838.   i := 1;
  839.   WHILE i<NumLines DO
  840.     TopLine := l;
  841.     ScrollDown(w);
  842.     INC(i);
  843.   END;
  844.   Scroll := f;
  845. END NewDisplay;
  846.  
  847.  
  848. (*-------------------------------------------------------------------------*)
  849.  
  850.  
  851. PROCEDURE * ShowProc;
  852.  
  853. VAR
  854.   l: TextLinePtr;
  855.   Down: BOOLEAN;               (* Scroll-Direction                  *)
  856.   End: BOOLEAN;                (* Quit next time Space is pressed ? *)
  857.   i,j,k,m: INTEGER;
  858.   MyMsg: I.IntuiMessage;       (* contains Message                  *)
  859.   Shift: BOOLEAN;              (* Shifted Keystroke ?               *)
  860.   Alt: BOOLEAN;                (* Altered Keystroke ?               *)
  861.   win: I.WindowPtr;            (* window for Find & Goto            *)
  862.   Find,FindStr: ARRAY 80 OF CHAR; (* findstring / capitalized findstring *)
  863.   Goto: ARRAY 10 OF CHAR;      (* string containing goto line #  *)
  864.   li: LONGINT;                 (* longint value of line to go to *)
  865.   flen: INTEGER;               (* length of findstring *)
  866.   HiText: TextLine;            (* Highlited textline *)
  867.   OldHiText: TextLinePtr;      (* original, un-hilited text *)
  868.   found: BOOLEAN;              (* TRUE, if find was successful *)
  869.   chr: CHAR;                   (* converted keycode *)
  870.  
  871.  
  872.   PROCEDURE WaitAllRead();
  873.  
  874.   BEGIN
  875.     IF MyFile#NIL THEN
  876.       SignalAllRead := w;
  877.       sys.SETREG(0,e.Wait(mySig));
  878.       SignalAllRead := f;
  879.     END;
  880.   END WaitAllRead;
  881.  
  882.  
  883.   PROCEDURE HiLite(at,len: INTEGER);
  884.   (* Hilites len chars of BottomLine.text starting at position at *)
  885.  
  886.   VAR
  887.     c: INTEGER;
  888.     col: CHAR;
  889.  
  890.   BEGIN
  891.     OldHiText := BottomLine; HiText := OldHiText^; BottomLine := sys.ADR(HiText);
  892.     IF at+len+2<MaxLen THEN
  893.       c := 0; col := 5X;
  894.       WHILE c<at DO
  895.         IF HiText.text[c]<CHR(17) THEN col := HiText.text[c] END;
  896.         INC(c);
  897.       END;
  898.       HiText.text[at] := CHR(17-ORD(col));
  899.       c := at; INC(len,at);
  900.       WHILE c<len DO
  901.         HiText.text[c+1] := OldHiText.text[c];
  902.         INC(c);
  903.       END;
  904.       HiText.text[c+1] := col;
  905.       REPEAT
  906.         HiText.text[c+2] := OldHiText.text[c];
  907.         INC(c);
  908.       UNTIL HiText.text[c-1]=0X;
  909.     END;
  910.     IF HiText.next#NIL THEN HiText.next.prev := sys.ADR(HiText) END;
  911.     IF HiText.prev#NIL THEN HiText.prev.next := sys.ADR(HiText) END;
  912.   END HiLite;
  913.  
  914.  
  915.   PROCEDURE UnHiLite();
  916.  
  917.   BEGIN
  918.     IF HiText.next#NIL THEN HiText.next.prev := OldHiText END;
  919.     IF HiText.prev#NIL THEN HiText.prev.next := OldHiText END;
  920.   END UnHiLite;
  921.  
  922.  
  923.   PROCEDURE ChkBotNewDisp;
  924.  
  925.   VAR
  926.     c: INTEGER;
  927.     t: TextLinePtr;
  928.  
  929.   BEGIN
  930.     IF NOT found THEN
  931.       I.DisplayBeep(NIL);
  932.       IF TopLine.prev=NIL THEN BottomLine := TopLine
  933.                           ELSE BottomLine := TopLine.prev END;
  934.     END;
  935.     NewDisplay;
  936.     IF found THEN UnHiLite END;
  937.   END ChkBotNewDisp;
  938.  
  939.  
  940.   PROCEDURE Search(): BOOLEAN;
  941.   (* searches string and hilites it if found. result is TRUE if string found *)
  942.  
  943.   BEGIN
  944.     i := 0;
  945.     IF BottomLine.len<NumColumns THEN m := BottomLine.len ELSE m := NumColumns END;
  946.     WHILE i<BottomLine.size DO
  947.       j := 0; k := i;
  948.       WHILE CAP(BottomLine.text[k])=FindStr[j] DO
  949.         INC(j); INC(k);
  950.         IF FindStr[j]=0X THEN
  951.           sys.SETREG(0,TryBottomnext());
  952.           FindLine := BottomLine;
  953.           HiLite(k-flen,flen);
  954.           found := w; RETURN w;
  955.         END;
  956.       END;
  957.       INC(i);
  958.     END;
  959.     RETURN f;
  960.   END Search;
  961.  
  962.  
  963.   PROCEDURE DisplayInfo();
  964.  
  965.   BEGIN
  966. (* File: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xx % (xxxxxx of xxxxxx Bytes) xxxxxx Lines *)
  967.     IStr := "XFile: "; IStr[0] := 7X;
  968.     Append(IStr,sys.ADR(Name));
  969.     Append(IStr,sys.ADR("                              "));
  970.     IStr[36] := 0X;
  971.     Append(IStr,sys.ADR("xxx % (xxxxxx of xxxxxx Bytes) xxxxxx Lines"));
  972.     IntToStr(IStr,36,3,TextLength * 100 DIV FileLength);
  973.     IntToStr(IStr,43,6,TextLength);
  974.     IntToStr(IStr,53,6,FileLength);
  975.     IntToStr(IStr,67,6,AnzLines-1);
  976.     i := 79;
  977.     REPEAT IStr[i] := 20X; INC(i) UNTIL (i>=255) OR (i>=NumColumns+2);
  978.     IStr[i] := 0X; Write(sys.ADR(IStr),f);
  979.     Info := w;
  980.   END DisplayInfo;
  981.  
  982.   PROCEDURE GetString(VAR str: ARRAY OF CHAR; int: BOOLEAN);
  983.  
  984.   BEGIN
  985.     INC(Screen.height,Screen.height);
  986.     I.MakeScreen(Screen);
  987.     NuWindow.leftEdge    := 100;
  988.     NuWindow.topEdge     := NumLines*4-6+ri.ryOffset;
  989.     NuWindow.width       := NuScreen.width-200;
  990.     NuWindow.height      := 12;
  991.     NuWindow.blockPen    := 1;
  992.     NuWindow.idcmpFlags  := LONGSET{I.inactiveWindow,I.gadgetUp};
  993.     NuWindow.flags       := LONGSET{I.rmbTrap,I.activate};
  994.     NuWindow.firstGadget := sys.ADR(StrGadget);
  995.     NuWindow.screen      := Screen;
  996.     NuWindow.type        := I.customScreen;
  997.     StrGadget.leftEdge   := 2;
  998.     StrGadget.topEdge    := 2;
  999.     StrGadget.width      := NuWindow.width-4;
  1000.     StrGadget.height     := 8;
  1001.     StrGadget.activation := {I.stringCenter,I.relVerify};
  1002.     IF int THEN INCL(StrGadget.activation,I.longint) END;
  1003.     StrGadget.gadgetType := I.strGadget;
  1004.     StrGadget.specialInfo:= sys.ADR(StrInfo);
  1005.     StrInfo.buffer       := sys.ADR(str);
  1006.     StrInfo.maxChars     := LEN(str)-1;
  1007.     win := I.OpenWindow(NuWindow);
  1008.     IF win=NIL THEN RETURN END;
  1009.     REPEAT
  1010.       sys.SETREG(0,I.ActivateGadget(sys.ADR(StrGadget),win,NIL));
  1011.     UNTIL win.userPort.sigBit IN
  1012.            e.Wait(LONGSET{win.userPort.sigBit,
  1013.                           Window.userPort.sigBit});
  1014.     I.CloseWindow(win);
  1015.     Screen.height := Screen.height DIV 2;
  1016.   END GetString;
  1017.  
  1018.  
  1019.   PROCEDURE Help; (* executed when HELP or H is pressed *)
  1020.  
  1021.   BEGIN
  1022.     ClearBitMaps();
  1023.     Write(sys.ADR(empty),w);
  1024.     Write(sys.ADR("\x13             \x15  MuchMore V2.7 Commands:  "),w);
  1025.     Write(sys.ADR(empty),w);
  1026.     Write(sys.ADR(" \x0dSpace\x05,\x0d LMB\x05:         Start / Stop scrolling. Quit at end of file."),w);
  1027.     Write(sys.ADR(" \x0dBackSpace\x05,\x0d RMB\x05:     Start / Stop scrolling backwards."),w);
  1028.     Write(sys.ADR(" \x0dUp\x05/\x0dDown\x05:            Move one line \x0dup\x05 or \x0ddown\x05."),w);
  1029.     Write(sys.ADR(" \x0dShift \x05+\x0d Up\x05/\x0dDn\x05:      Start / Stop quick scrolling \x0dup\x05 or \x0ddown\x05."),w);
  1030.     Write(sys.ADR(" \x0dAlt\x05+\x0dUp\x05/\x0dDn\x05,\x0d PgUp\x05/\x0dDn\x05: Move one page \x0dup\x05 or \x0ddown\x05."),w);
  1031.     Write(sys.ADR(" \x0dT\x05,\x0d Home \x05/\x0d B\x05,\x0d End\x05:   Goto \x0dt\x05op / \x0db\x05ottom of text."),w);
  1032.     Write(sys.ADR(" \x0dF\x05,\x0dN\x05,\x0dP\x05:              \x0dF\x05ind string, \x0dN\x05ext, \x0dP\x05revious occurance"),w);
  1033.     Write(sys.ADR(" \x0dShift \x05+\x0d Fn\x05:         Set textmarker #n to current position"),w);
  1034.     Write(sys.ADR(" \x0dFn\x05:                 Goto marker #n or set marker #n if it wasn't set yet"),w);
  1035.     Write(sys.ADR(" \x0dG\x05:                  \x0dG\x05oto line #n"),w);
  1036.     Write(sys.ADR(" \x0dNK 0\x05:               Display Filelength etc."),w);
  1037.     Write(sys.ADR(" \x0dShift \x05+\x0d Alt \x05+\x0d O\x05:    Create print\x0do\x05ut of the text"),w);
  1038.     Write(sys.ADR(" \x0dW\x05:                  \x0dW\x05rite block between Marker #1 and #2 to file or prt"),w);
  1039.     Write(sys.ADR(" \x0dL\x05:                  \x0dL\x05oad new text (arp necessary)"),w);
  1040.     Write(sys.ADR(" \x0dHELP\x05,\x0d H\x05:            Show Commands."),w);
  1041.     Write(sys.ADR(" \x0dESC\x05,\x0d Q\x05,\x0d X\x05,\x0d NK 5\x05:\x0d    Q\x05uit."),w);
  1042.     Write(sys.ADR(" \x0dS\x05:                  Go to \x0dS\x05leep, pop up with left Alt-ESC."),w);
  1043.     Write(sys.ADR(empty),w);
  1044.     Write(sys.ADR("⌐ \x131990 Fridtjof Siebert, Nobileweg 67, D-7000 Stuttgart 40"),w);
  1045.     Write(sys.ADR("  \x13Please refer to MuchMore.ReadMe for a detailed copyright notice"),w);
  1046.     Write(sys.ADR(empty),w);
  1047.     Write(sys.ADR("  This is another product of the Amiga MODULA & OBERON Klub Stuttgart - \x0d\x13AMOK"),w);
  1048.     i := (NumLines-24) DIV 2;
  1049.     WHILE i>0 DO Write(sys.ADR(empty),w); DEC(i) END;
  1050.     LOOP
  1051.       e.WaitPort(Window.userPort);
  1052.       MyMsgPtr := sys.VAL(LONGINT,e.GetMsg(Window.userPort));
  1053.       IF (I.rawKey IN MyMsgPtr.class) AND (MyMsgPtr.code<128) THEN EXIT END;
  1054.       e.ReplyMsg(MyMsgPtr);
  1055.     END;
  1056.     e.ReplyMsg(MyMsgPtr);
  1057.     BottomLine := TopLine;
  1058.     NewDisplay
  1059.   END Help;
  1060.  
  1061.  
  1062.   PROCEDURE Bottom;  (* executed when END or B is pressed *)
  1063.  
  1064.   BEGIN
  1065.     WaitAllRead;
  1066.     BottomLine := LastLine;
  1067.     i := NumLines;
  1068.     WHILE (i>1) AND (BottomLine.prev#NIL) DO
  1069.       BottomLine := BottomLine.prev;
  1070.       DEC(i);
  1071.     END;
  1072.     NewDisplay
  1073.   END Bottom;
  1074.  
  1075.  
  1076.   PROCEDURE Space(): BOOLEAN;  (* executed if space or LMB is pressed *)
  1077.   (* IF result=w THEN EXIT END *)
  1078.  
  1079.   BEGIN
  1080.     Fast := Shift;
  1081.     IF (MyFile=NIL) AND (BottomLine.next=NIL) THEN
  1082.       IF End THEN RETURN w ELSE End:=w END;
  1083.     ELSE
  1084.       End := f;
  1085.     END;
  1086.     IF Down THEN
  1087.       IF Scroll OR End THEN DisplayInfo END;
  1088.       Scroll := NOT(Scroll);
  1089.     ELSE
  1090.       Down := w;
  1091.       Scroll := w;
  1092.     END;
  1093.     RETURN f;
  1094.   END Space;
  1095.  
  1096.  
  1097.   PROCEDURE BackSpace;  (* executed if backspace or RMB is pressed *)
  1098.  
  1099.   BEGIN
  1100.     Fast := Shift;
  1101.     Scroll := Down OR NOT Scroll;
  1102.     Down := f
  1103.   END BackSpace;
  1104.  
  1105.  
  1106. BEGIN
  1107.  
  1108.   sys.SETREG(13,e.exec.thisTask.userData);
  1109.   sys.SETREG(0,e.Wait(mySig));
  1110.  
  1111.   Down := w; End := f; Find[0] := 0X; Goto[0] := 0X;
  1112.  
  1113.   LOOP
  1114.  
  1115.     IF NewDisp THEN NewDisp := f; NewDisplay END;
  1116.  
  1117. (*------  Type Text:  ------*)
  1118.  
  1119.     LOOP
  1120.       IF Scroll THEN
  1121.         IF Down THEN
  1122.           ScrollDown(Fast);
  1123.           Scroll := (MyFile#NIL) OR (BottomLine.next#NIL);
  1124.         ELSE
  1125.           ScrollUp(Fast);
  1126.           Scroll := TopLine.prev#NIL;
  1127.         END;
  1128.       ELSE
  1129.         e.WaitPort(Window.userPort);
  1130.       END;
  1131.  
  1132.       MyMsgPtr := sys.VAL(LONGINT,e.GetMsg(Window.userPort));
  1133.  
  1134.       IF (MyMsgPtr#NIL) THEN
  1135.         IF NOT (I.inactiveWindow IN MyMsgPtr.class) THEN EXIT END;
  1136.         EXCL(Window.idcmpFlags,I.mouseButtons);
  1137.         e.ReplyMsg(MyMsgPtr);
  1138.         e.WaitPort(Window.userPort);
  1139.         INCL(Window.idcmpFlags,I.mouseButtons);
  1140.       END;
  1141.     END;
  1142.  
  1143.     MyMsg := MyMsgPtr^;
  1144.     e.ReplyMsg(MyMsgPtr);
  1145.  
  1146.     IF MyMsg.code<80H THEN
  1147.       IF    Info           THEN DelLine; Info := f;
  1148.       ELSIF MyMsg.code=0FH THEN DisplayInfo; Scroll := f END;
  1149.     END;
  1150.  
  1151.     Shift := {} # {ie.lShift,ie.rShift,ie.capsLock} * MyMsg.qualifier;
  1152.     Alt   := {} # {ie.lAlt  ,ie.rAlt}               * MyMsg.qualifier;
  1153.     Sync  := NOT  (                     ie.control IN MyMsg.qualifier);
  1154.     IF NOT(Sync OR Alt) THEN Shift := TRUE END;
  1155.  
  1156.     IF I.mouseButtons IN MyMsg.class THEN
  1157.  
  1158.       IF    (ie.leftButton  IN MyMsg.qualifier) AND Space() THEN EXIT
  1159.       ELSIF ie.rightButton IN MyMsg.qualifier               THEN BackSpace END;
  1160.  
  1161.     ELSIF (I.rawKey IN MyMsg.class) AND (MyMsg.code<80H) THEN
  1162.  
  1163.       CASE MyMsg.code OF
  1164.  
  1165.       40H:  IF Space() THEN EXIT END |                   (* Space *)
  1166.  
  1167.       41H:  BackSpace |                                (* BackSpace *)
  1168.  
  1169.       4DH,1EH,1FH:                                        (* Down *)
  1170.             IF Shift THEN
  1171.               Scroll := NOT(Down AND Scroll) OR NOT Fast;
  1172.               Fast := w; Down := w;
  1173.             ELSE
  1174.               IF Alt OR (MyMsg.code=1FH) THEN i:=NumLines-1 ELSE i:=1 END;
  1175.               REPEAT
  1176.                 ScrollDown(NOT Shift);
  1177.                 DEC(i);
  1178.               UNTIL i=0;
  1179.               Scroll := f;
  1180.             END |
  1181.  
  1182.       4CH,3EH,3FH:                                        (* Up *)
  1183.             IF Shift THEN
  1184.               Scroll := Down OR NOT Scroll OR NOT Fast;
  1185.               Fast := w; Down := f;
  1186.             ELSE
  1187.               IF Alt OR (MyMsg.code=3FH) THEN i:=NumLines-1 ELSE i:=1 END;
  1188.               REPEAT
  1189.                 ScrollUp(NOT Shift);
  1190.                 Scroll := f;
  1191.                 DEC(i);
  1192.               UNTIL i=0;
  1193.             END; |
  1194.  
  1195.       44H,43H:                                        (* CR *)
  1196.             ScrollDown(f);
  1197.             Scroll := f; |
  1198.  
  1199.       3DH: BottomLine := FirstLine; NewDisplay |      (* Home *)
  1200.  
  1201.       1DH: Bottom |                                   (* End *)
  1202.  
  1203.       50H..59H:                                       (* F1..F10 *)
  1204.             i := MyMsg.code-50H;
  1205.             IF NOT Shift AND (TextMarkers[i]#NIL) THEN
  1206.               BottomLine := TextMarkers[i];
  1207.               IF BottomLine.prev#NIL THEN BottomLine := BottomLine.prev END;
  1208.               NewDisplay;
  1209.             ELSE
  1210.               TextMarkers[i] := TopLine;
  1211.             END |
  1212.  
  1213.       5FH:  Help |
  1214.  
  1215.       45H,2EH: IF NOT Alt THEN EXIT END |             (* Quit *)
  1216.  
  1217.       ELSE
  1218.  
  1219.         IF MyMsg.code<40H THEN (* examine vanilla keycode: *)
  1220.  
  1221.           chr := KeyMap[MyMsg.code];
  1222.  
  1223.           CASE chr OF
  1224.  
  1225.           "t": BottomLine := FirstLine; NewDisplay |      (* Home *)
  1226.  
  1227.           "b": Bottom |                                   (* End *)
  1228.  
  1229.           "f","n","p":                            (* Find, Next, Previous *)
  1230.  
  1231.             IF chr="f" THEN
  1232.               GetString(Find,f); FindLine := NIL; flen := 0;
  1233.               LOOP
  1234.                 FindStr[flen] := CAP(Find[flen]);
  1235.                 IF    FindStr[flen]>80X THEN DEC(FindStr[flen],32)
  1236.                 ELSIF FindStr[flen]=0X  THEN EXIT END;
  1237.                 INC(flen);
  1238.               END;
  1239.               ClearBitMaps();
  1240.             END;
  1241.             found := f;
  1242.             IF FindStr[0]#0X THEN
  1243.               i := NumLines;
  1244.               IF FindLine#NIL THEN FindLine := FindLine.next END;
  1245.               WHILE (i>0) AND (BottomLine#NIL) AND (BottomLine#FindLine) DO
  1246.                 BottomLine := BottomLine^.prev; DEC(i);
  1247.               END;
  1248.               IF (BottomLine#FindLine) OR (BottomLine=NIL) THEN BottomLine := TopLine END;
  1249.               IF chr#"p" THEN (* next *)
  1250.                 WHILE (BottomLine#NIL) AND NOT Search() DO
  1251.                   sys.SETREG(0,TryBottomnext());
  1252.                   BottomLine := BottomLine.next;
  1253.                 END;
  1254.               ELSE                   (* previous *)
  1255.                 IF BottomLine.prev#NIL THEN BottomLine:=BottomLine.prev END;
  1256.                 REPEAT
  1257.                   BottomLine := BottomLine.prev
  1258.                 UNTIL (BottomLine=NIL) OR Search();
  1259.               END;
  1260.             ELSE
  1261.               BottomLine := NIL
  1262.             END;
  1263.             ChkBotNewDisp |
  1264.  
  1265.           "w":                                                  (* write block *)
  1266.  
  1267.             IF (TextMarkers[0]#NIL) AND (TextMarkers[1]#NIL) AND NOT print AND NOT save THEN
  1268.               savefrom := 0; savesize := 0;
  1269.               l := TextMarkers[0].prev; WHILE l.prev#NIL DO l := l.prev; INC(savefrom,l.len) END;
  1270.               l := TextMarkers[1].prev; WHILE l#NIL DO INC(savesize,l.len); l := l.prev END;
  1271.               l := TextMarkers[1]; i := NumLines; WHILE (i>1) AND (l#NIL) DO DEC(i); INC(savesize,LONG(l.len)); l := l.next END;
  1272.               DEC(savesize,savefrom);
  1273.               IF savesize>0 THEN
  1274.                 GetString(WriteName,f);
  1275.                 WaitAllRead; save := w; e.Signal(sys.ADR(Me.task),mySig); NewDisplay;
  1276.               END
  1277.             END |
  1278.  
  1279.           "o": IF Shift AND Alt AND NOT print AND NOT save THEN                (* Printout *)
  1280.                  PStr := 'TYPE "'; Append(PStr,sys.ADR(Name)); Append(PStr,sys.ADR('" TO PRT:'));
  1281.                  WaitAllRead; print := w; e.Signal(sys.ADR(Me.task),mySig);
  1282.                END |
  1283.  
  1284.           "l": ClearBitMaps;                                      (* Load Text *)
  1285.                MakeThink(TRUE); NewText := w; e.Signal(sys.ADR(Me.task),mySig);
  1286.                REPEAT UNTIL (mySigBit IN e.Wait(mySig)) AND NOT NewText |
  1287.  
  1288.           "g":                                                     (* goto *)
  1289.             GetString(Goto,w);
  1290.             li := SHORT(StrInfo.longInt);
  1291.             BottomLine := FirstLine;
  1292.             WHILE (li>0) AND TryBottomnext() DO
  1293.               BottomLine := BottomLine.next;
  1294.               DEC(li)
  1295.             END;
  1296.             NewDisplay |
  1297.  
  1298.           "h": Help |                                              (* Help *)
  1299.  
  1300.           "q","x": EXIT |                                          (* Quit *)
  1301.  
  1302.           "s":                                                (* Disappear *)
  1303.  
  1304.             IF NOT print AND NOT save AND (e.FindPort(MMissleeping)=NIL) THEN
  1305.               InputData.sleeping := w;
  1306.               e.Signal(sys.ADR(Me.task),mySig);
  1307.               sys.SETREG(0,e.Wait(mySig));
  1308.             END |
  1309.  
  1310.           ELSE END;
  1311.  
  1312.         END;   (* IF MyMsg.code<40H THEN *)
  1313.  
  1314.       END;   (* CASE MyMsg.code OF *)
  1315.  
  1316.     END;   (* IF I.rawKey IN MyMsg.class THEN *)
  1317.  
  1318.   END;   (* LOOP *)
  1319.  
  1320.   Done := w;
  1321.   e.Signal(sys.ADR(Me.task),mySig);
  1322.   LOOP sys.SETREG(0,e.Wait(LONGSET{})) END;
  1323.  
  1324. END ShowProc;
  1325.  
  1326.  
  1327. (*--------------------------  File Requester:  ----------------------------*)
  1328.  
  1329.  
  1330. PROCEDURE FileReq;
  1331.  
  1332.  
  1333. TYPE
  1334.   TagItem = STRUCT
  1335.               typ: LONGINT;
  1336.               data: LONGINT;
  1337.             END;
  1338.  
  1339. CONST
  1340.   tagDone   = 0;
  1341.   tagIgnore = 1;
  1342.   tagUser   = MIN(LONGINT);
  1343.   dummy     = tagUser + 80000H;
  1344.   taghail   = dummy + 1;
  1345.   leftEdge  = dummy + 3;         (* Initialize LeftEdge                  *)
  1346.   topEdge   = dummy + 4;         (* Initialize TopEdge                   *)
  1347.   width     = dummy + 5;
  1348.   height    = dummy + 6;
  1349.   hookFunc  = dummy + 7;         (* Hook function pointer                *)
  1350.   file      = dummy + 8;         (* Initial name of file follows         *)
  1351.   dir       = dummy + 9;         (* Initial string for filerequest dir   *)
  1352.  
  1353.  
  1354. TYPE
  1355.   NineTags = ARRAY 8 OF TagItem;
  1356.  
  1357. VAR
  1358.   fr: FileRequesterPtr;
  1359.   tags: NineTags;
  1360.   res: BOOLEAN;
  1361.  
  1362.  
  1363.   PROCEDURE AllocFileRequest {asl,-30} (tag{8}: ARRAY OF TagItem)    : FileRequesterPtr;
  1364.   PROCEDURE FreeFileRequest  {asl,-36} (fr{8}: FileRequesterPtr);
  1365.   PROCEDURE RequestFile      {asl,-42} (fr{8}: FileRequesterPtr): BOOLEAN;
  1366.  
  1367.   PROCEDURE FileRequest{arp,-294}(VAR filereq{8}: FileRequester): BOOLEAN;
  1368.  
  1369.  
  1370. BEGIN
  1371.   LOOP
  1372.     j := Length(Name);
  1373.     WHILE (j>0) AND (Name[j]#":") AND (Name[j]#"/") DO DEC(j) END;
  1374.     IF j=0 THEN j := -1 END;
  1375.     i := 0;
  1376.     WHILE i<=j DO Dirname[i] := Name[i]; INC(i) END; Dirname[i] := 0X;
  1377.     j := 0;
  1378.     REPEAT Filename[j] := Name[i]; INC(j); INC(i) UNTIL Name[i-1]=0X;
  1379.     sys.SETREG(0,I.WBenchToFront());
  1380.     IF asl=NIL THEN asl := e.OpenLibrary("asl.library",36) END;
  1381.     IF asl#NIL THEN
  1382.       tags := NineTags(taghail, sys.ADR(MuchText),
  1383.                        file,    NIL,
  1384.                        dir,     NIL,
  1385.                        leftEdge,20,
  1386.                        topEdge, 20,
  1387.                        width,   300,
  1388.                        height,  200,
  1389.                        tagDone, NIL);
  1390.       tags[1].data := sys.ADR(Filename);
  1391.       tags[2].data := sys.ADR(Dirname);
  1392.       fr := AllocFileRequest(tags);
  1393.       IF fr=NIL THEN Request(sys.ADR(oom)) END;
  1394.       res := RequestFile(fr);
  1395.       FreeFileRequest(fr);
  1396.       IF NOT res THEN EXIT END;
  1397.       Dirname := fr.ddir^;
  1398.       Filename := fr.ddef^;
  1399.     ELSE
  1400.       IF arp=NIL THEN arp := e.OpenLibrary("arp.library",34) END;
  1401.       IF arp#NIL THEN
  1402.         FR.hail := sys.ADR(MuchText);
  1403.         FR.ddef := sys.ADR(Filename);
  1404.         FR.ddir := sys.ADR(Dirname);
  1405.         FR.wind := NIL;
  1406.         IF NOT FileRequest(FR) THEN EXIT END;
  1407.       ELSE
  1408.         Request(sys.ADR(noarp))
  1409.       END;
  1410.     END;
  1411.     Name := Dirname;
  1412.     i := Length(Name);
  1413.     IF (i>0) THEN
  1414.       CASE Name[i-1] OF "/",":": ELSE
  1415.         Name[i] := "/"; INC(i);
  1416.       END;
  1417.     END;
  1418.     j := 0;
  1419.     LOOP
  1420.       Name[i] := Filename[j];
  1421.       IF (Name[i]=0X) OR (i=255) THEN EXIT END;
  1422.       INC(i);
  1423.       INC(j);
  1424.     END;
  1425.     Name[i] := 0X;
  1426.     IF Screen#NIL THEN I.ScreenToFront(Screen) END;
  1427.     IF Window#NIL THEN I.ActivateWindow(Window) END;
  1428.     RETURN
  1429.   END;
  1430.   HALT(0);
  1431. END FileReq;
  1432.  
  1433.  
  1434. (*------  Sleep:  ------*)
  1435.  
  1436. PROCEDURE Sleep();
  1437.  
  1438. BEGIN
  1439.   InputDevPort.node.name := sys.ADR(MMissleeping);
  1440.   InputData.sleeping := w;
  1441.   sys.SETREG(0,e.Wait(mySig));
  1442.   InputDevPort.node.name := sys.ADR(MMisawake);
  1443. END Sleep;
  1444.  
  1445. (*------------------------------  MAIN:  ----------------------------------*)
  1446.  
  1447.  
  1448. BEGIN
  1449.  
  1450. (*------  Init:  ------*)
  1451.  
  1452. (* These variables are automatically set to zero:
  1453.   Screen := NIL; Window := NIL; FirstLine := NIL; TopLine := NIL;
  1454.   BottomLine := NIL; MyFile := NIL; AnzLines := 0; Info := f;
  1455.   MyLock := NIL; FileInfo := NIL; ScreenPos := 0; arp := NIL;
  1456.   ShowTaskRunning := f; SignalNewData := f; SignalAllRead := f;
  1457.   Done := f; print := f; bg := 0; style := SHORTSET{}; OldDir := NIL;
  1458.   InputOpen := f; save := f; in := NIL; out := NIL;
  1459. *)
  1460.   mySigBit := -1; Me := sys.VAL(d.ProcessPtr,ol.Me); fg := 1;
  1461.   InputDevPort.sigBit := -1;
  1462.   WriteName := "PRT:"; MemIndex := ChunkSize; OldDir := Me.currentDir;
  1463.   Sync := TRUE;
  1464.  
  1465.   I.GetPrefs(sys.ADR(Prefs),sys.SIZE(Prefs));
  1466.   lace := Prefs.laceWB;
  1467.  
  1468.   mySigBit := e.AllocSignal(-1);
  1469.   IF mySigBit<0 THEN HALT(0) END;
  1470.   mySig := LONGSET{mySigBit};
  1471.  
  1472. (*------  Setup:  ------*)
  1473.  
  1474.   NEW(FirstLine);
  1475. (*FirstLine.size := 0;
  1476.   FirstLine.text[0] := 0X; *)
  1477.   NEW(FileInfo);
  1478.   IF FileInfo=NIL THEN Request(sys.ADR(oom)) END;
  1479.  
  1480. (*------  Init InputHandler:  ------*)
  1481.  
  1482.   InputData.wakeUpSignal := SHORT(mySigBit);
  1483.   InputData.sigTask := sys.ADR(Me.task);
  1484.   InputData.sleeping := f;
  1485.  
  1486. (* InputDevPort := CreatePort(NIL,0) *)
  1487.   InputDevPort.node.name := sys.ADR(MMisawake);
  1488.   InputDevPort.node.type:= e.msgPort;
  1489.   InputDevPort.flags := e.signal;
  1490.   InputDevPort.sigBit := e.AllocSignal(-1);
  1491.   IF InputDevPort.sigBit<0 THEN HALT(0) END;
  1492.   e.AddPort(sys.ADR(InputDevPort));
  1493.   InputDevPort.sigTask := sys.ADR(Me.task);
  1494. (* InputRequestBlock := CreateStdIO(InputDevPort) *)
  1495.   InputRequestBlock.message.node.type := e.message;
  1496.   InputRequestBlock.message.length := sys.SIZE(InputRequestBlock);
  1497.   InputRequestBlock.message.replyPort := sys.ADR(InputDevPort);
  1498.  
  1499.   HandlerStuff.data := sys.ADR(InputData);
  1500.   HandlerStuff.node.pri := 51;
  1501.  
  1502.   IF e.OpenDevice("input.device",0,sys.ADR(InputRequestBlock),LONGSET{})#0 THEN
  1503.     Request(sys.ADR("Need input.device"))
  1504.   END;
  1505.   InputOpen := w;
  1506.  
  1507.   HandlerStuff.code := InputHandler;
  1508.   InputRequestBlock.command := Input.addHandler;
  1509.   InputRequestBlock.data := sys.ADR(HandlerStuff);
  1510.   e.DoIO(sys.ADR(InputRequestBlock));
  1511.   HandlerActive := w;
  1512.  
  1513. (*------  Start:  ------*)
  1514.  
  1515.   IF ol.wbStarted THEN
  1516.  
  1517.     wbm := ol.wbenchMsg;
  1518.  
  1519.     IF wbm.numArgs=2 THEN
  1520.       ArgPtr := wbm.argList^[1].name; Name := ArgPtr^;
  1521.       sys.SETREG(0,d.CurrentDir(wbm.argList^[1].lock));
  1522.     ELSE
  1523.       sys.SETREG(0,d.CurrentDir(wbm.argList^[0].lock));
  1524.       FileReq
  1525.     END
  1526.  
  1527.   ELSE
  1528.  
  1529.     IF ol.dosCmdLen<=1 THEN
  1530.       FileReq
  1531.     ELSE
  1532.       CommLine := ol.dosCmdBuf;
  1533.       LOOP
  1534.         i:=0;
  1535.         WHILE CommLine^=20X DO INC(CommLine) END;
  1536.         IF CommLine^=0AX THEN EXIT END;
  1537.         IF CommLine^='"' THEN
  1538.           INC(CommLine);
  1539.           LOOP
  1540.             CASE CommLine^ OF
  1541.             '"': INC(CommLine); EXIT |
  1542.             0AX:                EXIT |
  1543.             ELSE
  1544.               Name[i] := CommLine^; INC(i); INC(CommLine);
  1545.             END;
  1546.           END;
  1547.         ELSE
  1548.           WHILE (CommLine^#0AX) AND (CommLine^#20X) DO
  1549.             Name[i] := CommLine^; INC(i); INC(CommLine);
  1550.           END;
  1551.         END;
  1552.         Name[i]:= 0X;
  1553.         IF Name="?"  THEN Request(sys.ADR(usage)) END;
  1554.         IF (Name[0]="-") AND (Name[2]=0X) THEN
  1555.           Name[0] := 0X;
  1556.           CASE Name[1] OF
  1557.             "s": Sleep        |
  1558.             "l": lace := NOT lace |
  1559.           END;
  1560.         END;
  1561.       END;
  1562.     END;
  1563.  
  1564.   END;
  1565.  
  1566.   LOOP
  1567.     MyFile := d.Open(Name,d.oldFile);
  1568.     IF MyFile#NIL THEN EXIT END;
  1569.     FileReq
  1570.   END;
  1571.  
  1572.   InitScreen();
  1573.  
  1574. (*------  Get KeyMap:  ------*)
  1575.  
  1576.  
  1577.   IF e.OpenDevice("console.device",-1,sys.ADR(wreq),LONGSET{})#0 THEN Request(sys.ADR(conerr)) END;
  1578.   console := wreq.device;
  1579. (*ievent.nextEvent := NIL;
  1580.   ievent.qualifier := {};
  1581.   ievent.eventAddress := NIL; *)
  1582.   ievent.class := ie.rawkey;
  1583.   i := 0;
  1584.   WHILE i<40H DO
  1585.     ievent.code := i;
  1586.     RawKeyConvert(sys.ADR(ievent),sys.ADR(KeyMap[i]),32,NIL);
  1587.     INC(i);
  1588.   END;
  1589.  
  1590. (*------  Init 2nd Task:  ------*)
  1591.  
  1592.   ShowTask.spLower := sys.ADR(ShowStack);
  1593.   ShowTask.spUpper := sys.ADR(ShowStack[999]);
  1594.   ShowTask.spReg   := ShowTask.spUpper;
  1595.   ShowTask.node.type := e.task;
  1596.   ShowTask.node.name := sys.ADR("Show.MM");
  1597.   ShowTask.node.pri  := Me.task.node.pri+1;
  1598.   ShowTask.userData  := sys.REG(13);           (* VarBase *)
  1599.  
  1600.   e.Forbid;
  1601.     e.AddTask(sys.ADR(ShowTask),ShowProc,NIL);
  1602.     ShowTaskRunning := w;
  1603.     Window.userPort.sigTask := sys.ADR(ShowTask);
  1604.   e.Permit;
  1605.  
  1606. (*------  Main Load / Display Loop:  ------*)
  1607.  
  1608.   LOOP
  1609.  
  1610.     RQLen := -1; RQPos := -1;
  1611.     AnzLines := 1;
  1612.     LastLine := FirstLine;
  1613.     BottomLine := FirstLine;
  1614.     TopLine    := FirstLine;
  1615.     TextLength := 0;
  1616.     FindLine   := NIL;
  1617.     i := 0; REPEAT TextMarkers[i] := NIL; INC(i) UNTIL i=10;
  1618.  
  1619.     MyLock := d.Lock(Name,d.sharedLock);
  1620.     IF MyLock=NIL THEN Request(sys.ADR(cof)) END;
  1621.     IF NOT d.Examine(MyLock,FileInfo) THEN Request(sys.ADR(cof)) END;
  1622.     FileLength := FileInfo.size;
  1623.  
  1624.     d.UnLock(MyLock); MyLock := NIL;
  1625.     IF FileLength=0 THEN Request(sys.ADR("File empty")) END;
  1626.  
  1627.     (*------  Start displaying & Loading:  ------*)
  1628.  
  1629.     NewDisp := TRUE;
  1630.  
  1631.     e.Signal(sys.ADR(ShowTask),mySig);
  1632.  
  1633.     REPEAT
  1634.       LoadLine := GetTextLine();
  1635.       IF LoadLine=NIL THEN
  1636.         d.Close(MyFile);
  1637.         MyFile := NIL;
  1638.       ELSE
  1639.         LoadLine.prev := LastLine;
  1640.         LastLine.next := LoadLine;
  1641.         LastLine := LoadLine;
  1642.       END;
  1643.       IF SignalNewData THEN e.Signal(sys.ADR(ShowTask),mySig) END;
  1644.     UNTIL (MyFile=NIL) OR Done OR NewText OR InputData.sleeping;
  1645.     IF SignalAllRead THEN e.Signal(sys.ADR(ShowTask),mySig) END;
  1646.     REPEAT
  1647.       sys.SETREG(0,e.Wait(mySig));
  1648.       IF print THEN
  1649.         in := d.Open(nil,d.oldFile); out := d.Open(nil,d.newFile);
  1650.         sys.SETREG(0,d.Execute(PStr,in,out));
  1651.         d.Close(in); in := NIL; d.Close(out); out := NIL; print := f;
  1652.       END;
  1653.       IF save THEN
  1654.         in := d.Open(Name,d.oldFile);
  1655.         IF in=NIL THEN I.DisplayBeep(NIL) ELSE
  1656.           ol.New(buffer,savesize);
  1657.           IF buffer=NIL THEN Request(sys.ADR(oom)) END;
  1658.           sys.SETREG(0,d.Seek(in,savefrom,0));
  1659.           IF d.Read(in,buffer^,savesize)#savesize THEN
  1660.             I.DisplayBeep(NIL); d.Close(in); in := NIL;
  1661.           ELSE
  1662.             d.Close(in); in := NIL;
  1663.             out := d.Open(WriteName,d.newFile);
  1664.             IF out=NIL THEN I.DisplayBeep(NIL) ELSE
  1665.               IF d.Write(out,buffer^,savesize)#savesize THEN I.DisplayBeep(NIL) END;
  1666.               d.Close(out); out := NIL;
  1667.             END;
  1668.           END;
  1669.           DISPOSE(buffer);
  1670.         END;
  1671.         save := f;
  1672.       END;
  1673.       IF Done THEN EXIT END;
  1674.     UNTIL NewText OR InputData.sleeping;
  1675.     IF MyFile#NIL THEN d.Close(MyFile); MyFile := NIL END;
  1676.     DisposeLines();
  1677.     FirstLine^.next := NIL; NewText := f;
  1678.     IF InputData.sleeping THEN
  1679.       CloseDisplay;
  1680.       Sleep;
  1681.       InitScreen;
  1682.       Window.userPort.sigTask := sys.ADR(ShowTask);
  1683.     END;
  1684.     REPEAT
  1685.       FileReq;
  1686.       MyFile := d.Open(Name,d.oldFile);
  1687.     UNTIL MyFile#NIL;
  1688.   END;   (* LOOP *)
  1689.  
  1690. CLOSE   (* cleanup: *)
  1691.  
  1692.   IF ShowTaskRunning THEN e.RemTask(sys.ADR(ShowTask))       END;
  1693.   CloseDisplay;
  1694.   IF MyFile#NIL      THEN d.Close(MyFile)                END;
  1695.   IF in#NIL          THEN d.Close(in)                    END;
  1696.   IF out#NIL         THEN d.Close(out)                   END;
  1697.   IF MyLock#NIL      THEN d.UnLock(MyLock)               END;
  1698.   IF OldDir#NIL      THEN sys.SETREG(0,d.CurrentDir(OldDir)) END;
  1699.   IF mySigBit>=0     THEN e.FreeSignal(mySigBit)         END;
  1700.   IF arp#NIL         THEN e.CloseLibrary(arp)            END;
  1701.   IF asl#NIL         THEN e.CloseLibrary(asl)            END;
  1702.   IF HandlerActive THEN
  1703.     InputRequestBlock.command := Input.remHandler;
  1704.     InputRequestBlock.data := sys.ADR(HandlerStuff);
  1705.     e.DoIO(sys.ADR(InputRequestBlock));
  1706.   END;
  1707.   IF InputOpen THEN e.CloseDevice(sys.ADR(InputRequestBlock)) END;
  1708.   IF InputDevPort.sigBit>0 THEN
  1709.     e.RemPort(sys.ADR(InputDevPort));
  1710.     e.FreeSignal(InputDevPort.sigBit)
  1711.   END;
  1712.  
  1713. END MuchMore.
  1714.  
  1715.