{#E} Module UtilDefs; { This module must be imported after Screen and Perq_ScreenNEW. } {=============================================================================} EXPORTS {=============================================================================} CONST WordLength = 16; {****** RPrqWrdL;} WordLenMin1 = WordLength-1; QuadWordSize = 4; MaxFontDefGrid = 100; {Standard Char-set uses only 26 grid lines. } FontHeadSize = 260; {Size of Height, Base, Index and Filler fields.} XMax = 767; YMax = 1023; Pi = 3.141592654; TYPE Posint = 0..MaxInt; {****** RPosInt;} Byte = 0..255; HexByte = 0..15; BitnoRange = 0..WordLenMin1; Bits = PACKED ARRAY[BitnoRange] OF Boolean; XRange = 0..XMax; {****** RXPqScr;} YRange = 0..YMax; {****** RYPqScr;} Point = RECORD X: INTEGER; Y: INTEGER; END; ULine = RECORD P1,P2: Point; END; BoxSize = RECORD Width: XRange; Height: YRange; END; Box = RECORD LowPos: Point; Size: BoxSize; END; Circle = RECORD Origo: Point; Radius: Posint; END; Arrow = RECORD L: ULine; EdgeSize: Posint; EdgeAngle: Real; END; NewFontPtr = ^NewFont; NewFont = {PACKED} RECORD Height: Posint; {Vertical Y-size. } Base: Posint; {Y-pos of Baseline, from top. } Index: ARRAY[0..#177] OF {Table of 128 Char-entries, } {??????indexed by Char? } PACKED RECORD CASE Boolean OF true: (Offset: XRange; {Starting X-position. } Line: 0..63; {Line*Height = starting Y-pos. } Width: Posint);{Horisontal X-size. } false: (Loc: Posint; {Loc = 768*Y+X, } Widd: Posint) {i.e. absolute positioning? } END; Filler: ARRAY[0..1] OF Integer; {Needed for Pat-array to start on} {a quadword: 1+1+2*128+2 = 260. } Pat: PACKED ARRAY[0..MaxFontDefGrid-1,XRange] OF Boolean; {See notes below! } END; { @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ The first index-set of the Pas-array is Char-set specific, i.e. [0..NScanLines-1, --] where NScanLines = Round( 128 / (768 DIV Average_Width) ) * Height . Ex. Standard Char-set: Width (for all chars) = 9, Height = 13. NScanLines = Round( 128 / 85 ) * 13 = 2 * 13 = 26. I.e. this font definition occupies: 260 + 26*48 = 1508 words. Given a FontPtr, FP. Then the bit pattern for the i'th character is (logically): FP^.Pat [Yline*YHeight .. Yline*YHeight + YHeight - 1, XOffset .. XOffset + XWidth - 1] where YHeight:=FP^.Height; XWidth :=FP^.Width[i]; XOffset:=FP^.Offset[i]; YLine :=FP^.Line[i]; Note that PACKED Booleans in PERQ-PASCAL are numbered inversely within a word, so that the second x-index must be computed as: off:=x MOD 16; newx:=x + (15-off) - off; "$Range-" must be used when indexing a full-size screen, because of Y-index overflow. Also note, that FP as a RasterOp-parm must be "adjusted" by 260, or alternatively the Source_X_Position must be increased by 260*WordLength (which may cause this value to exceed 767). @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ } VAR dummmmmmmmy: Boolean; FUNCTION FLIP16(I: Posint):Posint; PROCEDURE WRITEBITS(w:Integer); FUNCTION MAX(i,j: Integer):Integer; FUNCTION MIN(i,j: Integer):Integer; FUNCTION Inside_Range(i,Low,High: Integer):Boolean; FUNCTION Adjust_Range(i,Low,High: Integer):Integer; FUNCTION Int_To_String(Int : Integer):String; FUNCTION String_To_Int(Str : String) :Integer; {#P} {=============================================================================} PRIVATE {=============================================================================} {#E}IMPORTS Perq_String FROM Perq_String; {#E}FUNCTION FLIP16(I: Posint):Posint; BEGIN {Turn 4 least significant bits around 15. Let I = yyyxxxx, bitwise.} {Note FLIP16(FLIP16(I)) = I. } {$Range-} { FLIP16 := yyy0000 + WordLenMin1 - xxxx; } FLIP16 := LAND(I,-WordLength) + WordLenMin1 - LAND(I,WordLenMin1); {$Range=} END; {FLIP16-function} {#E}PROCEDURE WRITEBITS(w:Integer); VAR Bitno: BitnoRange; Bw: Bits; BEGIN Bw:=RECAST(w,Bits); FOR Bitno:=WordLenMin1 DOWNTO 0 DO WRITE( RECAST(Bw[Bitno],Integer) : 1); { WRITE(w : WordLength : 2); Don't work to write 16 binary digits.} END; {WRITEBITS-procedure} {#P} {#E}FUNCTION MAX(i,j: Integer):Integer; BEGIN IF i > j THEN MAX:=i ELSE MAX:=j; END; {MAX-function} {#E}FUNCTION MIN(i,j: Integer):Integer; BEGIN IF i < j THEN MIN:=i ELSE MIN:=j; END; {MIN-function} {#E}FUNCTION Inside_Range(i,Low,High: Integer):Boolean; VAR t: INTEGER; BEGIN IF Low > High THEN BEGIN t:= Low; Low:= High; High:= t; END; Inside_Range := (i >= Low) and (i <= High); END; {Inside_Range-function} {#E}FUNCTION Adjust_Range(i,Low,High: Integer):Integer; BEGIN Adjust_Range := MIN(High, MAX(Low, i)); END; {Adjust_Range-function} {#P} {#E}FUNCTION Int_To_String{#D} ( Int : Integer ) :String; {@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@} {@ @} {@ Int must be : (0,32767) @} {@ @} {@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@} VAR Digit,Start : Integer; Power,First : Integer; Str : String[5]; BEGIN First :=Length(Str)+1; REPEAT IF int > 9999 THEN BEGIN start:=1; Power:=10000; END ELSE IF int > 999 THEN BEGIN start:=2; Power:=1000; END ELSE IF int > 99 THEN BEGIN start:=3; Power:=100; END ELSE IF int > 9 THEN BEGIN start:=4; Power:=10; END ELSE BEGIN start:=5; Power:=1; END; digit := int DIV Power; int := int - Power*digit; First := MIN(First,start); Str[start]:= CHR(digit+ORD('0')); UNTIL ( int = 0 ); Int_to_String := SubStr(Str, First, Length(Str)+1-First); END; {Int_to_String-function} {#E}FUNCTION String_To_Int{#D} ( Str : String ) : Integer; VAR i,Int : integer; BEGIN Int := 0; FOR i:= 1 TO LENGTH(Str) DO IF NOT (Str[i] IN ['0'..'9'] ) THEN { ERROR('Not digit','String_To_Int') } WRITELN('Not digit in ', Str, ' in PROC String_To_Int') ELSE Int := ORD(str[i]) - ORD('0') + 10*Int; String_To_Int := Int; END; {String_to_Int-function} {#P} {#E}FUNCTION Scale_Point{#D} (P:Point; S: Real) : Point; BEGIN P.X:=Round(P.X*S); P.Y:=Round(P.Y*S); Scale_Point := P; END; {Scale_Line-function} {#E}FUNCTION Scale_Line{#D} (L:ULine ; S: Real) : ULine; BEGIN L.P1:=Scale_Point(L.P1,S); L.P2:=Scale_Point(L.P2,S); Scale_Line := L; END {Scale_Line-function} .