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