home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
300-399
/
ff378.lzh
/
MuchMorePoPa
/
MuchMorePoPa.mod
< prev
next >
Wrap
Text File
|
1990-10-10
|
61KB
|
1,871 lines
(*---------------------------------------------------------------------------
:Program. MuchMorePoPa.mod
:Author. Fridtjof Siebert
:Address. Nobileweg 67, D-7000 Stuttgart 40
:Shortcut. [fbs]
:Copyright. PD
:Language. OBERON
:Translator. Amiga Oberon Compiler
:History. V1.0 summer-88: First very slow internal version [fbs]
:History. V1.1 24-Sep-88: First published version [fbs]
:History. V1.2 26-Nov-88: Now displays Filelength & Percentage [fbs]
:History. 27-Nov-88: Mouse can be used instead of Space / BackSpace[fbs]
:History. V1.3 29-Apr-89: Strong increase in speed, removed WarpText [fbs]
:History. 29-Apr-89: Now supports Numeric Keys (Home,PgUp etc.) [fbs]
:History. 29-Apr-89: Now opens Screen as big as gfx.normalDisplay [fbs]
:History. V1.4 29/30-Apr-89: Asynchronus loading / displaying. Very nice[fbs]
:History. 30-Apr-89, 00:33: Removed bugs in Filelength & L-Command [fbs]
:History. 30-Apr-89, 02:21: Added Find-Command [fbs]
:History. 30-Apr-89, 10:30: Scrolling stops when window is inactive[fbs]
:History. 01-May-89: Allocates no more unneeded memory for text [fbs]
:History. 07-May-89: Allocates even less memory now [fbs]
:History. 14-May-89: Removed deadlock-bug with Find-Window [fbs]
:History. V1.5 25-May-89: Added print feature [fbs]
:History. 25-May-89: Removed all imports (apart from Arts) [fbs]
:History. 26-May-89: inspired by J. Kupfer, I added nk 5 to quit [fbs]
:History. 26-May-89: Now handle BS correctly [fbs]
:History. V1.6 02-Jul-89: Now supports several fontstyles and colors [fbs]
:History. V1.7 03-Jul-89: Is again as fast as it was with 2 colors [fbs]
:History. 03-Jul-89: Now no more crashes when quitting while print [fbs]
:History. 07-Jul-89: removed bug with texts of length 0 [fbs]
:History. V1.8 10-Jul-89: small bug in find-command removed [fbs]
:History. 10-Jul-89: now found strings are highlighted [fbs]
:History. 14-Jul-89: nk0 to display fileinfo [fbs]
:History. V2.0 06-Aug-89: Ported this to OBERON [fbs]
:History. 06-Aug-89: Added ARP-FileRequester [fbs]
:History. 07-Aug-89: Added L - (load new file) Command [fbs]
:History. V2.1 03-Sep-89: no more gurus if an r/w error occures [fbs]
:History. 03-Sep-89: MM used to execute CSI-Codes backwards. fixed [fbs]
:History. 03-Sep-89: ping / pong with Shift+Fn / Fn [fbs]
:History. 03-Sep-89: new command: goto [fbs]
:History. V2.2 05-Sep-89: will run with any keymapping now [fbs]
:History. V2.3 17-Sep-89: New command: sleep & Pop-Up feature [fbs]
:History. 17-Sep-89: "MuchMore -s" will go to sleep immediately [fbs]
:History. 17-Sep-89: Interprets <CSI>m as <CSI>0m now [fbs]
:History. V2.4 17-Sep-89: New command: write block "w" [fbs]
:History. 17-Sep-89: rewritten argument parser to allow quotes [fbs]
:History. V2.5 18-Sep-89: now uses the 8x8 font set with SetFont [fbs]
:History. 19-Sep-89: no more scatters memory. Allocates 4K Chunks [fbs]
:History. 07-Jun-90: Neu MuchMorePoPa unterstützt PowerPacker-Texte[fbs]
:History. V2.6 26-Jun-90: Made MuchMore reentrant [fbs]
:History. 26-Jun-90: Opens 1-Plane Screen if memory is rare [fbs]
:History. 26-Jun-90: Asynchronus fast scrolling with Ctrl-Up/Down [fbs]
:History. 26-Jun-90: Now supports interlaced screens [fbs]
:History. 08-Aug-90: CLI-Option '-l' to toggle interlaced mode [fbs]
:History. V2.7 09-Aug-90: no more RethinkDisplay()s,looks good with 2.0 [fbs]
:History. 10-Aug-90: Supports Kick2.0 ASL-FileRequester [fbs]
:History. 12-Aug-90: tempfile wasn't delete some times. now ok. [fbs]
:Contents. A Soft-Scrolling ASCII-File Printer.
:Usage. MuchMorePoPa {-s|-l} [Text]
:Remark. Compile: 'Oberon -dm MuchMorePoPa'
:Remark. Link: 'OLink -dm MuchMorePoPa OBJ MMQText.obj OBJ MMInput.obj OBJ PPData.o'
---------------------------------------------------------------------------*)
MODULE MuchMorePoPa;
(* $StackChk- $OvflChk- $RangeChk- $StackChk- $NilChk- $ReturnChk- $CaseChk- *)
IMPORT ol: OberonLib,
d: Dos,
e: Exec,
Input,
ie: InputEvent,
I: Intuition,
g: Graphics,
wb: Workbench,
km: KeyMap,
sys:SYSTEM;
(*-------------------------------------------------------------------------*)
CONST
empty = "";
oom = "Out of memory!";
cof = "Can't open file!";
usage = "Usage: MuchMorePoPa {-s|-l} [Text]";
rwerr = "Read/Write Error";
noarp = "Need arp for FileReq";
conerr = "Console problem";
MuchText = "MuchMorePoPa V2.7 © 1990 AMOK";
MMissleeping = "MM is sleeping";
MMisawake = "MM is awake";
nil = "NIL:";
w = TRUE;
f = FALSE;
MaxLen = 256;
(* Control codes for QText: *)
plain = CHR(17);
italic = CHR(18);
bold = CHR(19);
boldit = CHR(20);
ulineon = CHR(21);
ulineoff = CHR(22);
Italic = 0;
Bold = 1;
Ulin = 2;
Inv = 3;
TYPE
TextLinePtr = POINTER TO TextLine;
TextLine = STRUCT
next: TextLinePtr;
prev: TextLinePtr;
len: INTEGER;
size: INTEGER;
text: ARRAY MaxLen+1 OF CHAR;
END;
String = ARRAY 256 OF CHAR;
StringPtr = POINTER TO String;
FontData = ARRAY 8, 192, 8 OF CHAR;
FontDataPtr = POINTER TO FontData;
CONST
(* FileReqFlags *)
listFunc = 0;
gEventFunc = 1;
addGadFunc = 2;
newWindFunc = 3;
newIDCMP = 4;
doColor = 5;
doMsgFunc = 6;
doWildFunc = 7;
TYPE
STRPTR = POINTER TO CHAR;
FileRequesterPtr = POINTER TO FileRequester;
FileRequester = STRUCT
hail: STRPTR; (* Hailing text *)
ddef: StringPtr; (* Filename array (FCHARS+1) *)
ddir: StringPtr; (* Directory array (DSIZE+1) *)
wind: I.WindowPtr; (* Window requesting or NULL *)
funcFlags: SHORTSET; (* Control. See above. *)
reserved1: SHORTINT; (* Set this to 0 *)
function: PROCEDURE; (* Your function, see btdef's *)
reserved2: LONGINT; (* reserved *)
END;
VAR
Screen: I.ScreenPtr; (* Screen that contains the Text *)
BM: g.BitMapPtr; (* Screen's BitMap (external) *)
Window: I.WindowPtr; (* My window *)
MyFont: g.TextAttr; (* Topaz 8 *)
MyFile: d.FileHandlePtr; (* For loading Textfile *)
FirstLine: TextLinePtr; (* Saved Text *)
TopLine: TextLinePtr; (* Points to topmost Line *)
BottomLine: TextLinePtr; (* Last Line displayed on Screen *)
LoadLine: TextLinePtr; (* currently loaded Line *)
LastLine: TextLinePtr; (* Last element of LineList *)
Name,OldName: String; (* Text's Name *)
lace: BOOLEAN; (* use interlaced screen? *)
IStr,PStr: String; (* differently used *)
Buffer: ARRAY 512 OF CHAR; (* Buffer for Reading *)
RQPos: LONGINT; (* Position within ReadBuffer *)
RQLen: LONGINT; (* Number of CHARs in Buffer *)
NumLines: INTEGER; (* Number of Lines on Screen *)
NumColumns: INTEGER; (* Number of Columns on Screen *)
PageSize: LONGINT; (* 8*NumLines*NumColumns *)
AnzLines: LONGINT; (* Length of Text in Lines *)
fontdata: FontData; (* Fonts used by QText() *)
MyLock,OldDir: d.FileLockPtr; (* To Examine and Load File *)
FileInfo: d.FileInfoBlockPtr; (* to get File's length *)
FileLength,TextLength: LONGINT;(* Length of File and of Displayed Text *)
ScreenPos: INTEGER; (* actual position within bitmap *)
ShowTask: e.Task; (* the task that displays the text *)
ShowStack: ARRAY 1000 OF LONGINT; (* it's stack *)
ShowTaskRunning: BOOLEAN; (* is Showtask activated? *)
mySigBit: INTEGER; (* My SignalBit *)
mySig: LONGSET; (* My SignalSet = LONGSET{mySigBit} *)
SignalNewData: BOOLEAN; (* Signal when new data is loaded *)
SignalAllRead: BOOLEAN; (* send signal at end of text *)
Done: BOOLEAN; (* Quit *)
print: BOOLEAN; (* print text *)
NewText: BOOLEAN; (* load new text *)
Me: d.ProcessPtr; (* my main task *)
Info: BOOLEAN; (* is info currently displayed ? *)
MyMsgPtr: I.IntuiMessagePtr; (* for receiving Messages *)
i,j: INTEGER; (* count *)
Scroll: BOOLEAN; (* scrolling or waiting? *)
Fast: BOOLEAN; (* scrollquick? *)
Sync: BOOLEAN; (* scroll very quick? *)
in,out: d.FileHandlePtr; (* i/o for TYPE xxx TO PRT: *)
fg,bg: INTEGER; (* Text colors *)
style: SHORTSET; (* Text style *)
CommLine: POINTER TO CHAR; (* The CLI-commands *)
ArgPtr: POINTER TO String; (* to get WBArg *)
wbm: wb.WBStartupPtr; (* WBenchMessage *)
ri: g.RasInfoPtr; (* Screen's ViewPort's RasInfo *)
NuScreen: I.NewScreen; (* to open screens *)
NuWindow: I.NewWindow; (* to open window *)
Prefs: I.Preferences; (* Preferences (need wbLace) *)
StrGadget: I.Gadget; (* Gadget for Find-Command *)
StrInfo: I.StringInfo; (* its special info *)
arp: LONGINT; (* ArpBase *)
asl: LONGINT; (* ASL-librarybase *)
body,text,ok: I.IntuiText; (* IntuiTexts for AutoRequest *)
FR: FileRequester; (* The Requester *)
Filename: String; (* The Filename (without path) *)
Dirname: String; (* its path *)
NewDisp: BOOLEAN; (* need to rebuild Display ? *)
TextMarkers: ARRAY 10 OF TextLinePtr; (* Marked Positions in text *)
FindLine: TextLinePtr; (* Last found line *)
KeyMap: ARRAY 40H OF CHAR; (* console's KeyMap *)
wreq: e.IOStdReq; (* Request to communicate with the console *)
console: e.DevicePtr; (* the console.device *)
ievent: ie.InputEvent; (* InputEvent to convert keycodes *)
InputData: STRUCT
wakeUpSignal: SHORTINT; (* Signal that's wakes us up*)
sigTask: e.TaskPtr; (* MM's main task *)
sleeping: BOOLEAN; (* TRUE while we sleep *)
END;
InputDevPort: e.MsgPort; (* Input.Device's Port *)
InputRequestBlock: e.IOStdReq; (* its Requestblock *)
HandlerStuff: e.Interrupt; (* contains data about Input Handler *)
InputOpen: BOOLEAN; (* TRUE while input.device is open *)
HandlerActive: BOOLEAN; (* TRUE while InputHandler is active *)
WriteName: String; (* File to write Block *)
savefrom,savesize: LONGINT; (* How much to save? *)
save: BOOLEAN; (* save block *)
buffer: POINTER TO LONGINT; (* buffer to save file *)
c: CHAR; (* \ used by GetTextLine(); *)
le: INTEGER; (* / global for speed *)
DeCrunched: BOOLEAN;
decrnw: I.NewWindow;
decrwin: I.WindowPtr;
(*------ Memory: ------*)
CONST ChunkSize = 4096; (* size of allocated chunks *)
TYPE
MemChunkPtr = POINTER TO MemChunk; (* chunklist *)
MemChunk = STRUCT
prev: MemChunkPtr; (* link *)
data: ARRAY ChunkSize OF BYTE; (* ChinkSize Bytes of memory *)
END;
VAR
MemIndex: INTEGER; (* index in current Chunk *)
CurChunk: MemChunkPtr; (* current chunk *)
(*----------------- External Assembler Procedures: ----------------------*)
(*------ The fastest textoutput-Procedure in the world (maybe): ------*)
PROCEDURE QText{"QText"}(y{1}: INTEGER;
str{8}: LONGINT;
bm{9}: g.BitMapPtr;
fd{10}: FontDataPtr);
(*------ Get Font: ------*)
PROCEDURE GetFontData{"GetFontData"}(from{8},to{9}: LONGINT; linelen{7}: INTEGER);
(*------ Copy Line: ------*)
PROCEDURE CopyLine1{"CopyLine1"}(bm{8}: g.BitMapPtr; w{0},h{1},pos{2}: INTEGER);
PROCEDURE CopyLine2{"CopyLine2"}(bm{8}: g.BitMapPtr; w{0},h{1},pos{2}: INTEGER);
(*------ Input Handler: ------*)
PROCEDURE * InputHandler{"MMInputHandler"};
(*-------------------------------------------------------------------------*)
(*------ Console Procedure: ------*)
PROCEDURE RawKeyConvert{console,-48}(events{8}:ie.InputEventPtr;
buffer{9}:LONGINT;
length{1}:LONGINT;
keyMap{10}:LONGINT);
(*-------------------------------------------------------------------------*)
PROCEDURE Length(VAR s: String): INTEGER;
VAR l: INTEGER;
BEGIN l := -1; REPEAT INC(l) UNTIL (l>sys.SIZE(s)) OR (s[l]=0X); RETURN l;
END Length;
PROCEDURE Append(VAR s1: String; s2: StringPtr);
(* appends s2 to s1 *)
VAR p,q: INTEGER;
BEGIN
p := Length(s1); q := 0;
WHILE (p<=sys.SIZE(s1)) AND (s2^[q]#0X) AND (p<NumColumns) DO
s1[p] := s2^[q]; INC(p); INC(q)
END;
IF p<=sys.SIZE(s1) THEN s1[p] := 0X END;
END Append;
(*----------------------------- Requester: ------------------------------*)
PROCEDURE Request(Text: StringPtr);
VAR
out: d.FileHandlePtr;
c: CHAR;
BEGIN
IF ol.wbStarted THEN
body.frontPen := 0; body.backPen := 1; body.drawMode := g.jam2;
body.leftEdge := 12; body.topEdge := 8;
text := body; ok := body;
body.iText := sys.ADR(MuchText);
body.nextText := sys.ADR(text);
text.iText := Text; text.topEdge := 22;
ok.leftEdge := 6; ok.topEdge := 3; ok.iText := sys.ADR(" OK ");
sys.SETREG(0,I.AutoRequest(NIL,sys.ADR(body),NIL,sys.ADR(ok),
LONGSET{I.rawKey},LONGSET{},320,65));
ELSE
out := d.Output();
sys.SETREG(0,d.Write(out,Text^,Length(Text^)));
c := 0AX;
sys.SETREG(0,d.Write(out,c,1));
END;
HALT(0);
END Request;
(*-------------------------------------------------------------------------*)
(*-------------------------------------------------------------------------*)
(********************************************************************
* *
* 'PP_LoadData' PowerPacker DATA file support function V1.1 *
* *
* You may use this code for non-commercial purposes provided this *
* copyright notice is left intact ! *
* *
* Copyright (c) Aug 1989 by Nico François *
********************************************************************)
PROCEDURE LoadData*( file: ARRAY OF CHAR;
VAR buffer: e.ADDRESS;
VAR length: LONGINT): BOOLEAN;
CONST
SAFETYMARGIN = 64;
VAR
handle: d.FileHandlePtr;
lock: d.FileLockPtr;
ap,filestart: POINTER TO BYTE;
bufferlen: LONGINT;
hdr: LONGINT;
filelen,crunlen,efficiency: LONGINT;
CONST
PX20 = sys.VAL(LONGINT,'PX20');
PP11 = sys.VAL(LONGINT,'PP11');
PP20 = sys.VAL(LONGINT,'PP20');
PROCEDURE myRead(VAR t: ARRAY OF BYTE): BOOLEAN;
BEGIN
RETURN d.Read(handle,t,LEN(t))#LEN(t);
END myRead;
PROCEDURE DecrunchBuffer{"_pp_DecrunchBuffer"}(
endcrun{8}: e.ADDRESS;
buffer{9}: e.ADDRESS;
efficiency{0}: LONGINT);
BEGIN
lock := d.Lock(file,d.accessRead);
IF lock=NIL THEN RETURN FALSE END;
IF d.Examine(lock,FileInfo) THEN END;
d.UnLock(lock);
crunlen := FileInfo.size;
handle := d.Open(file,d.oldFile);
IF handle=NIL THEN RETURN FALSE END;
decrwin := NIL;
LOOP
IF myRead(hdr) THEN EXIT END;
IF (crunlen<=16) OR ((hdr#PP11) AND (hdr#PP20)) THEN EXIT END;
decrnw.leftEdge := NumColumns*4-125;
decrnw.topEdge := NumLines *4- 5 + ri.ryOffset;
decrnw.blockPen := 1;
decrnw.width := 250;
decrnw.height := 10;
decrnw.flags := LONGSET{I.activate};
decrnw.screen := Screen;
decrnw.type := I.customScreen;
decrnw.title := sys.ADR(" Decrunching ... please wait!");
decrwin := I.OpenWindow(decrnw);
IF decrwin=NIL THEN EXIT END;
IF d.Seek(handle,crunlen-4,d.beginning)=0 THEN END;
IF myRead(filelen) THEN EXIT END;
filelen := filelen DIV 256;
DEC(crunlen,8);
IF d.Seek(handle,4,d.beginning)=0 THEN END;
IF myRead(efficiency) THEN EXIT END;
bufferlen := filelen + SAFETYMARGIN;
ol.New(filestart,bufferlen);
IF filestart=NIL THEN EXIT END;
IF d.Read (handle,filestart^,crunlen) # crunlen THEN DISPOSE(filestart); EXIT END;
DecrunchBuffer(sys.VAL(LONGINT,filestart)+crunlen,
sys.VAL(LONGINT,filestart)+SAFETYMARGIN,efficiency);
ap := sys.VAL(LONGINT,filestart)+SAFETYMARGIN;
e.CopyMem(ap^,filestart^,filelen);
buffer := filestart;
length := filelen;
IF decrwin#NIL THEN I.CloseWindow(decrwin) END;
d.Close(handle);
RETURN TRUE;
END; (* LOOP *)
d.Close(handle);
IF decrwin#NIL THEN I.CloseWindow(decrwin) END;
RETURN FALSE;
END LoadData;
(*-------------------------------------------------------------------------*)
PROCEDURE Decrunch;
VAR
buffer: POINTER TO BYTE;
length: LONGINT;
handle: d.FileHandlePtr;
i,j: INTEGER;
win: I.WindowPtr;
BEGIN
DeCrunched := FALSE;
IF LoadData(Name,buffer,length) THEN
OldName := Name;
i := Length(Name);
LOOP
DEC(i);
IF i<0 THEN EXIT END;
CASE OldName[i] OF "/",":": EXIT END;
END;
Name := "T:MMPP_"; j := 7;
REPEAT
INC(i);
Name[j] := OldName[i];
INC(j);
UNTIL OldName[i]=0X;
DeCrunched := TRUE;
win := Me.windowPtr; Me.windowPtr := -1;
handle := d.Open(Name,d.newFile);
IF handle=NIL THEN
REPEAT
DEC(j);
Name[j+2] := Name[j];
UNTIL j=0;
Name[0] := "R"; Name[1] := "A"; Name[2] := "M";
handle := d.Open(Name,d.newFile);
END;
IF handle#NIL THEN
IF d.Write(handle,buffer^,length)=0 THEN END;
d.Close(handle);
END;
Me.windowPtr := win;
DISPOSE(buffer);
END;
END Decrunch;
(*-------------------------------------------------------------------------*)
PROCEDURE AllocLine(sz: INTEGER): TextLinePtr;
VAR
a: TextLinePtr;
newchunk: MemChunkPtr;
BEGIN
INC(sz,sys.SIZE(TextLine)-MaxLen); IF ODD(sz) THEN INC(sz) END;
IF MemIndex+sz<=ChunkSize THEN (* does mem fit into current chunk ? *)
INC(MemIndex,sz); (* increment index in current chunk *)
ELSE
NEW(newchunk); (* allocate new chunk *)
IF newchunk=NIL THEN Request(sys.ADR(oom)) END;
newchunk.prev := CurChunk; (* link chunk into list *)
CurChunk := newchunk;
MemIndex := sz;
END;
RETURN sys.ADR(CurChunk.data[MemIndex-sz]);
END AllocLine;
PROCEDURE DisposeLines();
VAR chunk: MemChunkPtr;
BEGIN
WHILE CurChunk#NIL DO
chunk := CurChunk.prev;
DISPOSE(CurChunk);
CurChunk := chunk;
END;
MemIndex := ChunkSize;
END DisposeLines;
(*-------------------------------------------------------------------------*)
PROCEDURE MakeThink(sync: BOOLEAN);
BEGIN
I.MakeScreen(Screen);
g.MrgCop(I.ViewAddress());
IF sync THEN g.WaitBOVP(sys.ADR(Screen.viewPort)) END;
END MakeThink;
(*------ Clear Display: ------*)
PROCEDURE ClearBitMaps();
BEGIN
g.BltClear(BM.planes[0],2*PageSize,LONGSET{});
g.BltClear(BM.planes[1],2*PageSize,LONGSET{});
ScreenPos := 0;
ri.ryOffset := 0;
END ClearBitMaps;
(*------------------------ Open Display: --------------------------------*)
PROCEDURE InitScreen();
VAR c: CHAR;
BEGIN
(*------ Open Screen: ------*)
NumColumns := g.gfx.normalDisplayColumns DIV 32 * 4;
IF NumColumns>MaxLen THEN NumColumns := MaxLen END;
NuScreen.viewModes := {g.hires};
NumLines := g.gfx.normalDisplayRows DIV 8;
IF lace THEN
INC(NumLines,NumLines);
INCL(NuScreen.viewModes,g.lace);
END;
NuScreen.width := 8*NumColumns;
PageSize := 8*LONG(NumLines*NumColumns);
NuScreen.height := 16*NumLines;
NuScreen.depth := 2;
MyFont.name := sys.ADR("topaz.font");
MyFont.ySize := 8;
NuScreen.font := sys.ADR(MyFont);
NuScreen.type := I.customScreen+{I.screenQuiet};
LOOP
Screen := I.OpenScreen(NuScreen);
IF Screen#NIL THEN EXIT END;
DEC(NuScreen.depth);
IF NuScreen.depth=0 THEN Request(sys.ADR(oom)) END;
END;
BM := Screen.rastPort.bitMap;
IF NuScreen.depth=1 THEN BM.planes[1] := BM.planes[0] END;
ri := Screen.viewPort.rasInfo;
ClearBitMaps;
ri.ryOffset := 32;
Screen.height := Screen.height DIV 2;
MakeThink(TRUE);
I.RethinkDisplay;
(*------ Get Font: ------*)
IStr[64] := 0X;
j := 0; c := 20X;
g.SetDrMd(sys.ADR(Screen.rastPort),g.jam1);
g.SetAPen(sys.ADR(Screen.rastPort),1);
WHILE j<32 DO
i := 0; WHILE i<48 DO IStr[i] := c; INC(i); INC(c) END;
IF c=80X THEN c := 0A0X END;
g.Move(sys.ADR(Screen.rastPort),0,Screen.rastPort.font.baseline+j);
g.Text(sys.ADR(Screen.rastPort),IStr,48);
INC(j,8);
END;
GetFontData(Screen.bitMap.planes[0],sys.ADR(fontdata),NumColumns);
(*------ Open Window: ------*)
NuWindow.flags := LONGSET{I.rmbTrap,I.activate,I.borderless,I.reportMouse};
NuWindow.screen := Screen;
NuWindow.type := I.customScreen;
NuWindow.topEdge:= 10;
NuWindow.width := NuScreen.width;
NuWindow.height := Screen.height-10;
NuWindow.idcmpFlags := LONGSET{I.inactiveWindow,I.activeWindow,I.rawKey,
I.mouseButtons};
Window := I.OpenWindow(NuWindow);
IF Window=NIL THEN Request(sys.ADR(oom)) END;
END InitScreen;
(*-------------------------------------------------------------------------*)
PROCEDURE CloseDisplay();
BEGIN
IF Window#NIL THEN I.CloseWindow(Window); Window := NIL END;
IF Screen#NIL THEN I.CloseScreen(Screen); Screen := NIL END;
END CloseDisplay;
(*------ Read one TextLine into a Variable: ------*)
PROCEDURE GetTextLine(): TextLinePtr;
(* returns NIL at EOF *)
VAR
l: TextLinePtr;
sz,wd,i,j: INTEGER;
txt: ARRAY MaxLen+1 OF CHAR;
num: ARRAY 10 OF INTEGER;
newcol: BOOLEAN;
oldstyle: SHORTSET;
PROCEDURE GetCh();
BEGIN
IF RQPos=RQLen THEN
RQLen := d.Read(MyFile,Buffer,sys.SIZE(Buffer));
IF RQLen<0 THEN Request(sys.ADR(rwerr)) END;
RQPos := 0;
END;
IF RQLen=0 THEN c := 0X ELSE
c := Buffer[RQPos]; IF c=0X THEN c:=1X END;
INC(RQPos); INC(le);
END;
END GetCh;
BEGIN
IF RQLen=0 THEN RETURN NIL END;
sz := 0; wd := 0; le := 0;
IF Italic IN style THEN IF Bold IN style THEN txt[sz] := boldit ELSE txt[sz] := italic END; INC(sz);
ELSE IF Bold IN style THEN txt[sz] := bold; INC(sz) END;
END;
IF Ulin IN style THEN txt[sz] := ulineon; INC(sz) END;
IF Inv IN style THEN txt[sz] := CHR(fg+4*bg+1); INC(sz)
ELSIF (fg#1) OR (bg#0) THEN txt[sz] := CHR(bg+4*fg+1); INC(sz) END;
LOOP
LOOP
GetCh;
IF sys.VAL(CHAR,sys.VAL(SHORTSET,c)*SHORTSET{0..6})#1BX THEN EXIT END;
i := -1;
REPEAT
GetCh;
IF (c>=30X) AND (c<=39X) THEN
INC(i); num[i] := 0;
REPEAT
num[i] := 10*num[i]+ORD(c)-ORD(30X); GetCh;
UNTIL (c<30X) OR (c>39X);
END;
c := CAP(c);
UNTIL (c>=3FX(*"?"*)) AND (c<=5AX) OR (c=0X) OR (i=9);
IF c=4DX THEN
newcol := f; oldstyle := style; j := 0;
IF i=-1 THEN i:=0; num[0] := 0 END;
WHILE (i>=j) AND (sz<MaxLen-1) DO
CASE num[j] OF
0: style := SHORTSET{}; fg := 1; bg := 0; newcol := w |
1: INCL(style,Bold) |
2: fg := 2; newcol := w (* I hope this is correct *) |
3: INCL(style,Italic) |
4: INCL(style,Ulin) |
7: INCL(style,Inv); newcol := w |
30..37: fg := sys.VAL(INTEGER,sys.VAL(SET,num[j]-30) * {0,1}); newcol := w |
40..47: bg := sys.VAL(INTEGER,sys.VAL(SET,num[j]-40) * {0,1}); newcol := w |
ELSE END;
INC(j);
END;
IF (oldstyle#style) AND (sz<MaxLen) THEN
IF Italic IN style THEN IF Bold IN style THEN txt[sz] := boldit ELSE txt[sz] := italic END;
ELSE IF Bold IN style THEN txt[sz] := bold ELSE txt[sz] := plain END;
END;
INC(sz);
IF (Ulin IN style) THEN
IF NOT((Ulin IN oldstyle)) AND (sz<MaxLen) THEN
txt[sz] := ulineon;
INC(sz);
END;
ELSE
IF (Ulin IN oldstyle) AND (sz<MaxLen) THEN
txt[sz] := ulineoff;
INC(sz);
END;
END;
END;
IF newcol AND (sz<MaxLen) THEN
IF Inv IN style THEN txt[sz] := CHR(fg+4*bg+1)
ELSE txt[sz] := CHR(bg+4*fg+1) END;
INC(sz);
END;
END; (* IF c="m" THEN *)
END; (* LOOP *)
CASE c OF
20X..7FX: txt[sz] := c; INC(sz); INC(wd) |
0A1X..0FFX: DEC(c,32); txt[sz] := c; INC(sz); INC(wd) |
8X: (* BS *) IF wd>0 THEN DEC(sz); DEC(wd); END |
9X: (* TAB *)
REPEAT
txt[sz] := 20X; INC(sz); INC(wd)
UNTIL (sz=MaxLen) OR (wd=NumColumns) OR (sys.VAL(SET,sz)*{0..2}={}) |
0A0X: txt[sz] := 20X; INC(sz); INC(wd) |
0AX,0X,0CX: EXIT |
ELSE END;
IF (wd>=NumColumns) OR (sz>=MaxLen) THEN EXIT END;
END;
l := AllocLine(sz);
l.len := le; l.size:= sz;
WHILE sz>0 DO DEC(sz); l.text[sz]:=txt[sz] END;
RETURN l;
END GetTextLine;
(*------ Write Line at Bottom of Text: ------*)
PROCEDURE AddBottomLine(Line: TextLinePtr; Fast: BOOLEAN);
VAR
i,j: INTEGER;
trash: LONGINT;
s1,d1,s2,d2: POINTER TO LONGINT;
a: LONGINT;
BEGIN
QText(8*(ScreenPos+NumLines),sys.ADR(Line.text),BM,sys.ADR(fontdata));
IF Fast THEN
INC(ri.ryOffset,8);
MakeThink(Sync);
CopyLine1(BM,NumColumns,NumLines,ScreenPos);
ELSE
a := 8*LONG(ScreenPos*NumColumns);
d1 := BM.planes[0] + a; s1 := sys.VAL(LONGINT,d1) + PageSize;
d2 := BM.planes[1] + a; s2 := sys.VAL(LONGINT,d2) + PageSize;
i := 8;
REPEAT
INC(ri.ryOffset);
IF NOT lace OR ODD(i) THEN MakeThink(TRUE) END;
j := NumColumns DIV 4;
REPEAT
d1^ := s1^; INC(d1,4); INC(s1,4);
d2^ := s2^; INC(d2,4); INC(s2,4);
DEC(j);
UNTIL j=0;
DEC(i);
UNTIL i=0;
END;
INC(ScreenPos);
IF ScreenPos=NumLines THEN
ScreenPos := 0;
ri.ryOffset := 0;
END;
END AddBottomLine;
(*------ Write String to Screen: ------*)
PROCEDURE Write(String: StringPtr; Fast: BOOLEAN);
VAR text: TextLine;
BEGIN
text := FirstLine^;
i := Length(String^);
IF i>=NumColumns THEN i := NumColumns-1 END;
text.text[i+1] := 0X;
REPEAT
text.text[i] := String^[i];
IF text.text[i]>80X THEN DEC(text.text[i],32) END;
DEC(i)
UNTIL i<0;
AddBottomLine(sys.ADR(text),Fast);
END Write;
(*------ Check whether BottomLine.next is NIL or not: ------*)
PROCEDURE TryBottomnext(): BOOLEAN;
(* returns TRUE if BottomLine.next#NIL END; *)
BEGIN
IF (BottomLine.next=NIL) AND (MyFile#NIL) THEN
SignalNewData := w;
sys.SETREG(0,e.Wait(mySig));
SignalNewData := f;
END;
RETURN BottomLine.next#NIL;
END TryBottomnext;
(*------ Scroll down one Line: ------*)
PROCEDURE ScrollDown(Fast: BOOLEAN);
BEGIN
IF TryBottomnext() THEN
BottomLine := BottomLine.next;
INC(AnzLines);
INC(TextLength,BottomLine.len);
ELSE RETURN END;
IF AnzLines>=NumLines THEN TopLine := TopLine.next END;
AddBottomLine(BottomLine,Fast);
END ScrollDown;
(*------ Scroll Up one Line: ------*)
PROCEDURE ScrollUp(Fast: BOOLEAN);
VAR
i,j: INTEGER;
s1,d1,s2,d2: POINTER TO LONGINT;
a: LONGINT;
BEGIN
IF (TopLine.prev#NIL) AND (TopLine.prev.prev#NIL) THEN
TopLine := TopLine.prev;
DEC(TextLength,BottomLine.len);
DEC(AnzLines);
BottomLine := BottomLine.prev;
IF ScreenPos=0 THEN
ri.ryOffset := NumLines*8;
ScreenPos := NumLines-1;
ELSE
DEC(ScreenPos);
END;
QText(8*ScreenPos,sys.ADR(TopLine.prev.text),BM,sys.ADR(fontdata));
IF Fast THEN
DEC(ri.ryOffset,8);
MakeThink(Sync);
CopyLine2(BM,NumColumns,NumLines,ScreenPos);
ELSE
a := 8*LONG((ScreenPos+1)*NumColumns);
s1 := BM.planes[0] + a; d1 := sys.VAL(LONGINT,s1) + PageSize;
s2 := BM.planes[1] + a; d2 := sys.VAL(LONGINT,s2) + PageSize;
i := 8;
REPEAT
DEC(ri.ryOffset);
IF NOT lace OR ODD(i) THEN MakeThink(TRUE) END;
j := NumColumns DIV 4;
REPEAT
DEC(d1,4); DEC(s1,4); d1^ := s1^;
DEC(d2,4); DEC(s2,4); d2^ := s2^;
DEC(j);
UNTIL j=0;
DEC(i);
UNTIL i=0;
END;
END; (* IF TopLine#NIL ... *)
END ScrollUp;
(*------ Undo last Write(): ------*)
PROCEDURE DelLine();
VAR
i,j: INTEGER;
s1,d1,s2,d2: POINTER TO LONGINT;
a: LONGINT;
text: TextLine;
BEGIN
IF ScreenPos=0 THEN
ri.ryOffset := NumLines*8;
ScreenPos := NumLines;
END;
DEC(ScreenPos);
IF TopLine.prev#NIL THEN
QText(8*ScreenPos,sys.ADR(TopLine.prev.text),BM,sys.ADR(fontdata));
ELSE
QText(8*ScreenPos,sys.ADR(FirstLine.text),BM,sys.ADR(fontdata));
END;
a := (LONG(ScreenPos)+1)*8*LONG(NumColumns);
s1 := BM.planes[0] + a; d1 := sys.VAL(LONGINT,s1) + PageSize;
s2 := BM.planes[1] + a; d2 := sys.VAL(LONGINT,s2) + PageSize;
i := 8;
REPEAT
DEC(ri.ryOffset);
IF NOT lace OR ODD(i) THEN MakeThink(TRUE) END;
j := NumColumns DIV 4;
REPEAT
DEC(d1,4); DEC(s1,4); d1^ := s1^;
DEC(d2,4); DEC(s2,4); d2^ := s2^;
DEC(j);
UNTIL j=0;
DEC(i);
UNTIL i=0;
END DelLine;
(*------ Convert Integer to String: ------*)
PROCEDURE IntToStr(VAR String: String;
At,Chars: INTEGER;
int: LONGINT);
VAR
Cnt: INTEGER;
Ziff: LONGINT;
BEGIN
INC(Chars,At);
IF (Length(String)<Chars) AND (sys.SIZE(String)>=Chars) THEN
String[Chars] := 0X
END;
REPEAT
DEC(Chars);
String[Chars] := CHR(int MOD 10 + ORD(30X)); int := int DIV 10;
UNTIL (Chars=At) OR (int=0);
WHILE Chars>At DO DEC(Chars); String[Chars] := 20X END;
END IntToStr;
(*-------------------------------------------------------------------------*)
PROCEDURE GetLength(t: TextLinePtr);
BEGIN
TextLength := 0; AnzLines := 0;
WHILE t#NIL DO INC(AnzLines); INC(TextLength,t.len); t := t.prev END;
END GetLength;
(*-------------------------------------------------------------------------*)
PROCEDURE NewDisplay();
(* Zeichnet ab BottomLine neu *)
VAR
i: INTEGER;
l: TextLinePtr;
BEGIN
ClearBitMaps;
i := 1;
l := BottomLine;
WHILE (i<NumLines) AND (BottomLine.next#NIL) DO
BottomLine := BottomLine.next;
INC(i);
END;
WHILE (i<NumLines) AND (l.prev#NIL) DO l := l.prev; INC(i) END;
BottomLine := l;
GetLength(l);
Write(sys.ADR(empty),w);
AddBottomLine(BottomLine,w);
i := 1;
WHILE i<NumLines DO
TopLine := l;
ScrollDown(w);
INC(i);
END;
Scroll := f;
END NewDisplay;
(*-------------------------------------------------------------------------*)
PROCEDURE * ShowProc;
VAR
l: TextLinePtr;
Down: BOOLEAN; (* Scroll-Direction *)
End: BOOLEAN; (* Quit next time Space is pressed ? *)
i,j,k,m: INTEGER;
MyMsg: I.IntuiMessage; (* contains Message *)
Shift: BOOLEAN; (* Shifted Keystroke ? *)
Alt: BOOLEAN; (* Altered Keystroke ? *)
win: I.WindowPtr; (* window for Find & Goto *)
Find,FindStr: ARRAY 80 OF CHAR; (* findstring / capitalized findstring *)
Goto: ARRAY 10 OF CHAR; (* string containing goto line # *)
li: LONGINT; (* longint value of line to go to *)
flen: INTEGER; (* length of findstring *)
HiText: TextLine; (* Highlited textline *)
OldHiText: TextLinePtr; (* original, un-hilited text *)
found: BOOLEAN; (* TRUE, if find was successful *)
chr: CHAR; (* converted keycode *)
PROCEDURE WaitAllRead();
BEGIN
IF MyFile#NIL THEN
SignalAllRead := w;
sys.SETREG(0,e.Wait(mySig));
SignalAllRead := f;
END;
END WaitAllRead;
PROCEDURE HiLite(at,len: INTEGER);
(* Hilites len chars of BottomLine.text starting at position at *)
VAR
c: INTEGER;
col: CHAR;
BEGIN
OldHiText := BottomLine; HiText := OldHiText^; BottomLine := sys.ADR(HiText);
IF at+len+2<MaxLen THEN
c := 0; col := 5X;
WHILE c<at DO
IF HiText.text[c]<CHR(17) THEN col := HiText.text[c] END;
INC(c);
END;
HiText.text[at] := CHR(17-ORD(col));
c := at; INC(len,at);
WHILE c<len DO
HiText.text[c+1] := OldHiText.text[c];
INC(c);
END;
HiText.text[c+1] := col;
REPEAT
HiText.text[c+2] := OldHiText.text[c];
INC(c);
UNTIL HiText.text[c-1]=0X;
END;
IF HiText.next#NIL THEN HiText.next.prev := sys.ADR(HiText) END;
IF HiText.prev#NIL THEN HiText.prev.next := sys.ADR(HiText) END;
END HiLite;
PROCEDURE UnHiLite();
BEGIN
IF HiText.next#NIL THEN HiText.next.prev := OldHiText END;
IF HiText.prev#NIL THEN HiText.prev.next := OldHiText END;
END UnHiLite;
PROCEDURE ChkBotNewDisp;
VAR
c: INTEGER;
t: TextLinePtr;
BEGIN
IF NOT found THEN
I.DisplayBeep(NIL);
IF TopLine.prev=NIL THEN BottomLine := TopLine
ELSE BottomLine := TopLine.prev END;
END;
NewDisplay;
IF found THEN UnHiLite END;
END ChkBotNewDisp;
PROCEDURE Search(): BOOLEAN;
(* searches string and hilites it if found. result is TRUE if string found *)
BEGIN
i := 0;
IF BottomLine.len<NumColumns THEN m := BottomLine.len ELSE m := NumColumns END;
WHILE i<BottomLine.size DO
j := 0; k := i;
WHILE CAP(BottomLine.text[k])=FindStr[j] DO
INC(j); INC(k);
IF FindStr[j]=0X THEN
sys.SETREG(0,TryBottomnext());
FindLine := BottomLine;
HiLite(k-flen,flen);
found := w; RETURN w;
END;
END;
INC(i);
END;
RETURN f;
END Search;
PROCEDURE DisplayInfo();
BEGIN
(* File: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xx % (xxxxxx of xxxxxx Bytes) xxxxxx Lines *)
IStr := "XFile: "; IStr[0] := 7X;
Append(IStr,sys.ADR(Name));
Append(IStr,sys.ADR(" "));
IStr[36] := 0X;
Append(IStr,sys.ADR("xxx % (xxxxxx of xxxxxx Bytes) xxxxxx Lines"));
IntToStr(IStr,36,3,TextLength * 100 DIV FileLength);
IntToStr(IStr,43,6,TextLength);
IntToStr(IStr,53,6,FileLength);
IntToStr(IStr,67,6,AnzLines-1);
i := 79;
REPEAT IStr[i] := 20X; INC(i) UNTIL (i>=255) OR (i>=NumColumns+2);
IStr[i] := 0X; Write(sys.ADR(IStr),f);
Info := w;
END DisplayInfo;
PROCEDURE GetString(VAR str: ARRAY OF CHAR; int: BOOLEAN);
BEGIN
INC(Screen.height,Screen.height);
I.MakeScreen(Screen);
NuWindow.leftEdge := 100;
NuWindow.topEdge := NumLines*4-6+ri.ryOffset;
NuWindow.width := NuScreen.width-200;
NuWindow.height := 12;
NuWindow.blockPen := 1;
NuWindow.idcmpFlags := LONGSET{I.inactiveWindow,I.gadgetUp};
NuWindow.flags := LONGSET{I.rmbTrap,I.activate};
NuWindow.firstGadget := sys.ADR(StrGadget);
NuWindow.screen := Screen;
NuWindow.type := I.customScreen;
StrGadget.leftEdge := 2;
StrGadget.topEdge := 2;
StrGadget.width := NuWindow.width-4;
StrGadget.height := 8;
StrGadget.activation := {I.stringCenter,I.relVerify};
IF int THEN INCL(StrGadget.activation,I.longint) END;
StrGadget.gadgetType := I.strGadget;
StrGadget.specialInfo:= sys.ADR(StrInfo);
StrInfo.buffer := sys.ADR(str);
StrInfo.maxChars := LEN(str)-1;
win := I.OpenWindow(NuWindow);
IF win=NIL THEN RETURN END;
REPEAT
sys.SETREG(0,I.ActivateGadget(sys.ADR(StrGadget),win,NIL));
UNTIL win.userPort.sigBit IN
e.Wait(LONGSET{win.userPort.sigBit,
Window.userPort.sigBit});
I.CloseWindow(win);
Screen.height := Screen.height DIV 2;
END GetString;
PROCEDURE Help; (* executed when HELP or H is pressed *)
BEGIN
ClearBitMaps();
Write(sys.ADR("\x13 \x15 MuchMorePoPa V2.7 Commands: "),w);
Write(sys.ADR(empty),w);
Write(sys.ADR(" \x0dSpace\x05,\x0d LMB\x05: Start / Stop scrolling. Quit at end of file."),w);
Write(sys.ADR(" \x0dBackSpace\x05,\x0d RMB\x05: Start / Stop scrolling backwards."),w);
Write(sys.ADR(" \x0dUp\x05/\x0dDown\x05: Move one line \x0dup\x05 or \x0ddown\x05."),w);
Write(sys.ADR(" \x0dShift \x05+\x0d Up\x05/\x0dDn\x05: Start / Stop quick scrolling \x0dup\x05 or \x0ddown\x05."),w);
Write(sys.ADR(" \x0dAlt\x05+\x0dUp\x05/\x0dDn\x05,\x0d PgUp\x05/\x0dDn\x05: Move one page \x0dup\x05 or \x0ddown\x05."),w);
Write(sys.ADR(" \x0dT\x05,\x0d Home \x05/\x0d B\x05,\x0d End\x05: Goto \x0dt\x05op / \x0db\x05ottom of text."),w);
Write(sys.ADR(" \x0dF\x05,\x0dN\x05,\x0dP\x05: \x0dF\x05ind string, \x0dN\x05ext, \x0dP\x05revious occurance"),w);
Write(sys.ADR(" \x0dShift \x05+\x0d Fn\x05: Set textmarker #n to current position"),w);
Write(sys.ADR(" \x0dFn\x05: Goto marker #n or set marker #n if it wasn't set yet"),w);
Write(sys.ADR(" \x0dG\x05: \x0dG\x05oto line #n"),w);
Write(sys.ADR(" \x0dNK 0\x05: Display Filelength etc."),w);
Write(sys.ADR(" \x0dShift \x05+\x0d Alt \x05+\x0d O\x05: Create print\x0do\x05ut of the text"),w);
Write(sys.ADR(" \x0dW\x05: \x0dW\x05rite block between Marker #1 and #2 to file or prt"),w);
Write(sys.ADR(" \x0dL\x05: \x0dL\x05oad new text (arp necessary)"),w);
Write(sys.ADR(" \x0dHELP\x05,\x0d H\x05: Show Commands."),w);
Write(sys.ADR(" \x0dESC\x05,\x0d Q\x05,\x0d X\x05,\x0d NK 5\x05:\x0d Q\x05uit."),w);
Write(sys.ADR(" \x0dS\x05: Go to \x0dS\x05leep, pop up with left Alt-ESC."),w);
Write(sys.ADR(empty),w);
Write(sys.ADR("© \x131990 Fridtjof Siebert, Nobileweg 67, D-7000 Stuttgart 40"),w);
Write(sys.ADR(" \x13Please refer to MuchMorePoPa.ReadMe for a detailed copyright notice"),w);
Write(sys.ADR(" \x13Decruncher is © Aug 1989 by Nico François"),w);
Write(sys.ADR(empty),w);
Write(sys.ADR(" This is another product of the Amiga MODULA & OBERON Klub Stuttgart - \x0d\x13AMOK"),w);
i := (NumLines-24) DIV 2;
WHILE i>0 DO Write(sys.ADR(empty),w); DEC(i) END;
LOOP
e.WaitPort(Window.userPort);
MyMsgPtr := sys.VAL(LONGINT,e.GetMsg(Window.userPort));
IF (I.rawKey IN MyMsgPtr.class) AND (MyMsgPtr.code<128) THEN EXIT END;
e.ReplyMsg(MyMsgPtr);
END;
e.ReplyMsg(MyMsgPtr);
BottomLine := TopLine;
NewDisplay
END Help;
PROCEDURE Bottom; (* executed when END or B is pressed *)
BEGIN
WaitAllRead;
BottomLine := LastLine;
i := NumLines;
WHILE (i>1) AND (BottomLine.prev#NIL) DO
BottomLine := BottomLine.prev;
DEC(i);
END;
NewDisplay
END Bottom;
PROCEDURE Space(): BOOLEAN; (* executed if space or LMB is pressed *)
(* IF result=w THEN EXIT END *)
BEGIN
Fast := Shift;
IF (MyFile=NIL) AND (BottomLine.next=NIL) THEN
IF End THEN RETURN w ELSE End:=w END;
ELSE
End := f;
END;
IF Down THEN
IF Scroll OR End THEN DisplayInfo END;
Scroll := NOT(Scroll);
ELSE
Down := w;
Scroll := w;
END;
RETURN f;
END Space;
PROCEDURE BackSpace; (* executed if backspace or RMB is pressed *)
BEGIN
Fast := Shift;
Scroll := Down OR NOT Scroll;
Down := f
END BackSpace;
BEGIN
sys.SETREG(13,e.exec.thisTask.userData);
sys.SETREG(0,e.Wait(mySig));
Down := w; End := f; Find[0] := 0X; Goto[0] := 0X;
LOOP
IF NewDisp THEN NewDisp := f; NewDisplay END;
(*------ Type Text: ------*)
LOOP
IF Scroll THEN
IF Down THEN
ScrollDown(Fast);
Scroll := (MyFile#NIL) OR (BottomLine.next#NIL);
ELSE
ScrollUp(Fast);
Scroll := TopLine.prev#NIL;
END;
ELSE
e.WaitPort(Window.userPort);
END;
MyMsgPtr := sys.VAL(LONGINT,e.GetMsg(Window.userPort));
IF (MyMsgPtr#NIL) THEN
IF NOT (I.inactiveWindow IN MyMsgPtr.class) THEN EXIT END;
EXCL(Window.idcmpFlags,I.mouseButtons);
e.ReplyMsg(MyMsgPtr);
e.WaitPort(Window.userPort);
INCL(Window.idcmpFlags,I.mouseButtons);
END;
END;
MyMsg := MyMsgPtr^;
e.ReplyMsg(MyMsgPtr);
IF MyMsg.code<80H THEN
IF Info THEN DelLine; Info := f;
ELSIF MyMsg.code=0FH THEN DisplayInfo; Scroll := f END;
END;
Shift := {} # {ie.lShift,ie.rShift,ie.capsLock} * MyMsg.qualifier;
Alt := {} # {ie.lAlt ,ie.rAlt} * MyMsg.qualifier;
Sync := NOT ( ie.control IN MyMsg.qualifier);
IF NOT(Sync OR Alt) THEN Shift := TRUE END;
IF I.mouseButtons IN MyMsg.class THEN
IF (ie.leftButton IN MyMsg.qualifier) AND Space() THEN EXIT
ELSIF ie.rightButton IN MyMsg.qualifier THEN BackSpace END;
ELSIF (I.rawKey IN MyMsg.class) AND (MyMsg.code<80H) THEN
CASE MyMsg.code OF
40H: IF Space() THEN EXIT END | (* Space *)
41H: BackSpace | (* BackSpace *)
4DH,1EH,1FH: (* Down *)
IF Shift THEN
Scroll := NOT(Down AND Scroll) OR NOT Fast;
Fast := w; Down := w;
ELSE
IF Alt OR (MyMsg.code=1FH) THEN i:=NumLines-1 ELSE i:=1 END;
REPEAT
ScrollDown(NOT Shift);
DEC(i);
UNTIL i=0;
Scroll := f;
END |
4CH,3EH,3FH: (* Up *)
IF Shift THEN
Scroll := Down OR NOT Scroll OR NOT Fast;
Fast := w; Down := f;
ELSE
IF Alt OR (MyMsg.code=3FH) THEN i:=NumLines-1 ELSE i:=1 END;
REPEAT
ScrollUp(NOT Shift);
Scroll := f;
DEC(i);
UNTIL i=0;
END; |
44H,43H: (* CR *)
ScrollDown(f);
Scroll := f; |
3DH: BottomLine := FirstLine; NewDisplay | (* Home *)
1DH: Bottom | (* End *)
50H..59H: (* F1..F10 *)
i := MyMsg.code-50H;
IF NOT Shift AND (TextMarkers[i]#NIL) THEN
BottomLine := TextMarkers[i];
IF BottomLine.prev#NIL THEN BottomLine := BottomLine.prev END;
NewDisplay;
ELSE
TextMarkers[i] := TopLine;
END |
5FH: Help |
45H,2EH: IF NOT Alt THEN EXIT END | (* Quit *)
ELSE
IF MyMsg.code<40H THEN (* examine vanilla keycode: *)
chr := KeyMap[MyMsg.code];
CASE chr OF
"t": BottomLine := FirstLine; NewDisplay | (* Home *)
"b": Bottom | (* End *)
"f","n","p": (* Find, Next, Previous *)
IF chr="f" THEN
GetString(Find,f); FindLine := NIL; flen := 0;
LOOP
FindStr[flen] := CAP(Find[flen]);
IF FindStr[flen]>80X THEN DEC(FindStr[flen],32)
ELSIF FindStr[flen]=0X THEN EXIT END;
INC(flen);
END;
ClearBitMaps();
END;
found := f;
IF FindStr[0]#0X THEN
i := NumLines;
IF FindLine#NIL THEN FindLine := FindLine.next END;
WHILE (i>0) AND (BottomLine#NIL) AND (BottomLine#FindLine) DO
BottomLine := BottomLine^.prev; DEC(i);
END;
IF (BottomLine#FindLine) OR (BottomLine=NIL) THEN BottomLine := TopLine END;
IF chr#"p" THEN (* next *)
WHILE (BottomLine#NIL) AND NOT Search() DO
sys.SETREG(0,TryBottomnext());
BottomLine := BottomLine.next;
END;
ELSE (* previous *)
IF BottomLine.prev#NIL THEN BottomLine:=BottomLine.prev END;
REPEAT
BottomLine := BottomLine.prev
UNTIL (BottomLine=NIL) OR Search();
END;
ELSE
BottomLine := NIL
END;
ChkBotNewDisp |
"w": (* write block *)
IF (TextMarkers[0]#NIL) AND (TextMarkers[1]#NIL) AND NOT print AND NOT save THEN
savefrom := 0; savesize := 0;
l := TextMarkers[0].prev; WHILE l.prev#NIL DO l := l.prev; INC(savefrom,l.len) END;
l := TextMarkers[1].prev; WHILE l#NIL DO INC(savesize,l.len); l := l.prev END;
l := TextMarkers[1]; i := NumLines; WHILE (i>1) AND (l#NIL) DO DEC(i); INC(savesize,LONG(l.len)); l := l.next END;
DEC(savesize,savefrom);
IF savesize>0 THEN
GetString(WriteName,f);
WaitAllRead; save := w; e.Signal(sys.ADR(Me.task),mySig); NewDisplay;
END
END |
"o": IF Shift AND Alt AND NOT print AND NOT save THEN (* Printout *)
PStr := 'TYPE "'; Append(PStr,sys.ADR(Name)); Append(PStr,sys.ADR('" TO PRT:'));
WaitAllRead; print := w; e.Signal(sys.ADR(Me.task),mySig);
END |
"l": ClearBitMaps; (* Load Text *)
MakeThink(TRUE); NewText := w; e.Signal(sys.ADR(Me.task),mySig);
REPEAT UNTIL (mySigBit IN e.Wait(mySig)) AND NOT NewText |
"g": (* goto *)
GetString(Goto,w);
li := SHORT(StrInfo.longInt);
BottomLine := FirstLine;
WHILE (li>0) AND TryBottomnext() DO
BottomLine := BottomLine.next;
DEC(li)
END;
NewDisplay |
"h": Help | (* Help *)
"q","x": EXIT | (* Quit *)
"s": (* Disappear *)
IF NOT print AND NOT save AND (e.FindPort(MMissleeping)=NIL) THEN
InputData.sleeping := w;
e.Signal(sys.ADR(Me.task),mySig);
sys.SETREG(0,e.Wait(mySig));
END |
ELSE END;
END; (* IF MyMsg.code<40H THEN *)
END; (* CASE MyMsg.code OF *)
END; (* IF I.rawKey IN MyMsg.class THEN *)
END; (* LOOP *)
Done := w;
e.Signal(sys.ADR(Me.task),mySig);
LOOP sys.SETREG(0,e.Wait(LONGSET{})) END;
END ShowProc;
(*-------------------------- File Requester: ----------------------------*)
PROCEDURE FileReq;
TYPE
TagItem = STRUCT
typ: LONGINT;
data: LONGINT;
END;
CONST
tagDone = 0;
tagIgnore = 1;
tagUser = MIN(LONGINT);
dummy = tagUser + 80000H;
taghail = dummy + 1;
leftEdge = dummy + 3; (* Initialize LeftEdge *)
topEdge = dummy + 4; (* Initialize TopEdge *)
width = dummy + 5;
height = dummy + 6;
hookFunc = dummy + 7; (* Hook function pointer *)
file = dummy + 8; (* Initial name of file follows *)
dir = dummy + 9; (* Initial string for filerequest dir *)
TYPE
NineTags = ARRAY 8 OF TagItem;
VAR
fr: FileRequesterPtr;
tags: NineTags;
res: BOOLEAN;
PROCEDURE AllocFileRequest {asl,-30} (tag{8}: ARRAY OF TagItem) : FileRequesterPtr;
PROCEDURE FreeFileRequest {asl,-36} (fr{8}: FileRequesterPtr);
PROCEDURE RequestFile {asl,-42} (fr{8}: FileRequesterPtr): BOOLEAN;
PROCEDURE FileRequest{arp,-294}(VAR filereq{8}: FileRequester): BOOLEAN;
BEGIN
LOOP
j := Length(Name);
WHILE (j>0) AND (Name[j]#":") AND (Name[j]#"/") DO DEC(j) END;
IF j=0 THEN j := -1 END;
i := 0;
WHILE i<=j DO Dirname[i] := Name[i]; INC(i) END; Dirname[i] := 0X;
j := 0;
REPEAT Filename[j] := Name[i]; INC(j); INC(i) UNTIL Name[i-1]=0X;
sys.SETREG(0,I.WBenchToFront());
IF asl=NIL THEN asl := e.OpenLibrary("asl.library",36) END;
IF asl#NIL THEN
tags := NineTags(taghail, sys.ADR(MuchText),
file, NIL,
dir, NIL,
leftEdge,20,
topEdge, 20,
width, 300,
height, 200,
tagDone, NIL);
tags[1].data := sys.ADR(Filename);
tags[2].data := sys.ADR(Dirname);
fr := AllocFileRequest(tags);
IF fr=NIL THEN Request(sys.ADR(oom)) END;
res := RequestFile(fr);
FreeFileRequest(fr);
IF NOT res THEN EXIT END;
Dirname := fr.ddir^;
Filename := fr.ddef^;
ELSE
IF arp=NIL THEN arp := e.OpenLibrary("arp.library",34) END;
IF arp#NIL THEN
FR.hail := sys.ADR(MuchText);
FR.ddef := sys.ADR(Filename);
FR.ddir := sys.ADR(Dirname);
FR.wind := NIL;
IF NOT FileRequest(FR) THEN EXIT END;
ELSE
Request(sys.ADR(noarp))
END;
END;
Name := Dirname;
i := Length(Name);
IF (i>0) THEN
CASE Name[i-1] OF "/",":": ELSE
Name[i] := "/"; INC(i);
END;
END;
j := 0;
LOOP
Name[i] := Filename[j];
IF (Name[i]=0X) OR (i=255) THEN EXIT END;
INC(i);
INC(j);
END;
Name[i] := 0X;
IF Screen#NIL THEN I.ScreenToFront(Screen) END;
IF Window#NIL THEN I.ActivateWindow(Window) END;
RETURN
END;
HALT(0);
END FileReq;
(*------ Sleep: ------*)
PROCEDURE Sleep();
BEGIN
InputDevPort.node.name := sys.ADR(MMissleeping);
InputData.sleeping := w;
sys.SETREG(0,e.Wait(mySig));
InputDevPort.node.name := sys.ADR(MMisawake);
END Sleep;
(*------------------------------ MAIN: ----------------------------------*)
BEGIN
(*------ Init: ------*)
(* These variables are automatically set to zero:
Screen := NIL; Window := NIL; FirstLine := NIL; TopLine := NIL;
BottomLine := NIL; MyFile := NIL; AnzLines := 0; Info := f;
MyLock := NIL; FileInfo := NIL; ScreenPos := 0; arp := NIL;
ShowTaskRunning := f; SignalNewData := f; SignalAllRead := f;
Done := f; print := f; bg := 0; style := SHORTSET{}; OldDir := NIL;
InputOpen := f; save := f; in := NIL; out := NIL;
*)
mySigBit := -1; Me := sys.VAL(d.ProcessPtr,ol.Me); fg := 1;
InputDevPort.sigBit := -1;
WriteName := "PRT:"; MemIndex := ChunkSize; OldDir := Me.currentDir;
Sync := TRUE;
I.GetPrefs(sys.ADR(Prefs),sys.SIZE(Prefs));
lace := Prefs.laceWB;
mySigBit := e.AllocSignal(-1);
IF mySigBit<0 THEN HALT(0) END;
mySig := LONGSET{mySigBit};
(*------ Setup: ------*)
NEW(FirstLine);
(*FirstLine.size := 0;
FirstLine.text[0] := 0X; *)
NEW(FileInfo);
IF FileInfo=NIL THEN Request(sys.ADR(oom)) END;
(*------ Init InputHandler: ------*)
InputData.wakeUpSignal := SHORT(mySigBit);
InputData.sigTask := sys.ADR(Me.task);
InputData.sleeping := f;
(* InputDevPort := CreatePort(NIL,0) *)
InputDevPort.node.name := sys.ADR(MMisawake);
InputDevPort.node.type:= e.msgPort;
InputDevPort.flags := e.signal;
InputDevPort.sigBit := e.AllocSignal(-1);
IF InputDevPort.sigBit<0 THEN HALT(0) END;
e.AddPort(sys.ADR(InputDevPort));
InputDevPort.sigTask := sys.ADR(Me.task);
(* InputRequestBlock := CreateStdIO(InputDevPort) *)
InputRequestBlock.message.node.type := e.message;
InputRequestBlock.message.length := sys.SIZE(InputRequestBlock);
InputRequestBlock.message.replyPort := sys.ADR(InputDevPort);
HandlerStuff.data := sys.ADR(InputData);
HandlerStuff.node.pri := 51;
IF e.OpenDevice("input.device",0,sys.ADR(InputRequestBlock),LONGSET{})#0 THEN
Request(sys.ADR("Need input.device"))
END;
InputOpen := w;
HandlerStuff.code := InputHandler;
InputRequestBlock.command := Input.addHandler;
InputRequestBlock.data := sys.ADR(HandlerStuff);
e.DoIO(sys.ADR(InputRequestBlock));
HandlerActive := w;
(*------ Start: ------*)
IF ol.wbStarted THEN
wbm := ol.wbenchMsg;
IF wbm.numArgs=2 THEN
ArgPtr := wbm.argList^[1].name; Name := ArgPtr^;
sys.SETREG(0,d.CurrentDir(wbm.argList^[1].lock));
ELSE
sys.SETREG(0,d.CurrentDir(wbm.argList^[0].lock));
FileReq
END
ELSE
IF ol.dosCmdLen<=1 THEN
FileReq
ELSE
CommLine := ol.dosCmdBuf;
LOOP
i:=0;
WHILE CommLine^=20X DO INC(CommLine) END;
IF CommLine^=0AX THEN EXIT END;
IF CommLine^='"' THEN
INC(CommLine);
LOOP
CASE CommLine^ OF
'"': INC(CommLine); EXIT |
0AX: EXIT |
ELSE
Name[i] := CommLine^; INC(i); INC(CommLine);
END;
END;
ELSE
WHILE (CommLine^#0AX) AND (CommLine^#20X) DO
Name[i] := CommLine^; INC(i); INC(CommLine);
END;
END;
Name[i]:= 0X;
IF Name="?" THEN Request(sys.ADR(usage)) END;
IF (Name[0]="-") AND (Name[2]=0X) THEN
Name[0] := 0X;
CASE Name[1] OF
"s": Sleep |
"l": lace := NOT lace |
END;
END;
END;
END;
END;
InitScreen();
LOOP
Decrunch;
MyFile := d.Open(Name,d.oldFile);
IF MyFile#NIL THEN EXIT END;
FileReq
END;
(*------ Get KeyMap: ------*)
IF e.OpenDevice("console.device",-1,sys.ADR(wreq),LONGSET{})#0 THEN Request(sys.ADR(conerr)) END;
console := wreq.device;
(*ievent.nextEvent := NIL;
ievent.qualifier := {};
ievent.eventAddress := NIL; *)
ievent.class := ie.rawkey;
i := 0;
WHILE i<40H DO
ievent.code := i;
RawKeyConvert(sys.ADR(ievent),sys.ADR(KeyMap[i]),32,NIL);
INC(i);
END;
(*------ Init 2nd Task: ------*)
ShowTask.spLower := sys.ADR(ShowStack);
ShowTask.spUpper := sys.ADR(ShowStack[999]);
ShowTask.spReg := ShowTask.spUpper;
ShowTask.node.type := e.task;
ShowTask.node.name := sys.ADR("Show.MM");
ShowTask.node.pri := Me.task.node.pri+1;
ShowTask.userData := sys.REG(13); (* VarBase *)
e.Forbid;
e.AddTask(sys.ADR(ShowTask),ShowProc,NIL);
ShowTaskRunning := w;
Window.userPort.sigTask := sys.ADR(ShowTask);
e.Permit;
(*------ Main Load / Display Loop: ------*)
LOOP
RQLen := -1; RQPos := -1;
AnzLines := 1;
LastLine := FirstLine;
BottomLine := FirstLine;
TopLine := FirstLine;
TextLength := 0;
FindLine := NIL;
i := 0; REPEAT TextMarkers[i] := NIL; INC(i) UNTIL i=10;
MyLock := d.Lock(Name,d.sharedLock);
IF MyLock=NIL THEN Request(sys.ADR(cof)) END;
IF NOT d.Examine(MyLock,FileInfo) THEN Request(sys.ADR(cof)) END;
FileLength := FileInfo.size;
d.UnLock(MyLock); MyLock := NIL;
IF FileLength=0 THEN Request(sys.ADR("File empty")) END;
(*------ Start displaying & Loading: ------*)
NewDisp := TRUE;
e.Signal(sys.ADR(ShowTask),mySig);
REPEAT
LoadLine := GetTextLine();
IF LoadLine=NIL THEN
d.Close(MyFile);
MyFile := NIL;
ELSE
LoadLine.prev := LastLine;
LastLine.next := LoadLine;
LastLine := LoadLine;
END;
IF SignalNewData THEN e.Signal(sys.ADR(ShowTask),mySig) END;
UNTIL (MyFile=NIL) OR Done OR NewText OR InputData.sleeping;
IF SignalAllRead THEN e.Signal(sys.ADR(ShowTask),mySig) END;
REPEAT
sys.SETREG(0,e.Wait(mySig));
IF print THEN
in := d.Open(nil,d.oldFile); out := d.Open(nil,d.newFile);
sys.SETREG(0,d.Execute(PStr,in,out));
d.Close(in); in := NIL; d.Close(out); out := NIL; print := f;
END;
IF save THEN
in := d.Open(Name,d.oldFile);
IF in=NIL THEN I.DisplayBeep(NIL) ELSE
ol.New(buffer,savesize);
IF buffer=NIL THEN Request(sys.ADR(oom)) END;
sys.SETREG(0,d.Seek(in,savefrom,0));
IF d.Read(in,buffer^,savesize)#savesize THEN
I.DisplayBeep(NIL); d.Close(in); in := NIL;
ELSE
d.Close(in); in := NIL;
out := d.Open(WriteName,d.newFile);
IF out=NIL THEN I.DisplayBeep(NIL) ELSE
IF d.Write(out,buffer^,savesize)#savesize THEN I.DisplayBeep(NIL) END;
d.Close(out); out := NIL;
END;
END;
DISPOSE(buffer);
END;
save := f;
END;
IF Done THEN EXIT END;
UNTIL NewText OR InputData.sleeping;
IF MyFile#NIL THEN d.Close(MyFile); MyFile := NIL END;
IF DeCrunched THEN
IF d.DeleteFile(Name) THEN END;
Name := OldName;
END;
DisposeLines();
FirstLine^.next := NIL; NewText := f;
IF InputData.sleeping THEN
CloseDisplay;
Sleep;
InitScreen;
Window.userPort.sigTask := sys.ADR(ShowTask);
END;
REPEAT
FileReq;
Decrunch;
MyFile := d.Open(Name,d.oldFile);
UNTIL MyFile#NIL;
END; (* LOOP *)
CLOSE (* cleanup: *)
IF ShowTaskRunning THEN e.RemTask(sys.ADR(ShowTask)) END;
CloseDisplay;
IF MyFile#NIL THEN d.Close(MyFile) END;
IF DeCrunched AND d.DeleteFile(Name) THEN END;
IF in#NIL THEN d.Close(in) END;
IF out#NIL THEN d.Close(out) END;
IF MyLock#NIL THEN d.UnLock(MyLock) END;
IF OldDir#NIL THEN sys.SETREG(0,d.CurrentDir(OldDir)) END;
IF mySigBit>=0 THEN e.FreeSignal(mySigBit) END;
IF arp#NIL THEN e.CloseLibrary(arp) END;
IF asl#NIL THEN e.CloseLibrary(asl) END;
IF HandlerActive THEN
InputRequestBlock.command := Input.remHandler;
InputRequestBlock.data := sys.ADR(HandlerStuff);
e.DoIO(sys.ADR(InputRequestBlock));
END;
IF InputOpen THEN e.CloseDevice(sys.ADR(InputRequestBlock)) END;
IF InputDevPort.sigBit>0 THEN
e.RemPort(sys.ADR(InputDevPort));
e.FreeSignal(InputDevPort.sigBit)
END;
END MuchMorePoPa.