{INCLUDE FILE UDRAW2 -- IMPLEMENTATION OF UDRAW} {Copyright 1983, 1984, Apple Computer, Inc.} {changed 05/01 1503 Changes to allow people to use Clascal on the Workshop} {Segments: SgABCini(tialize and Terminate), SgDRWres(ident), SgABCc(o)ld, SgABCdbg} {$IFC fRngDraw} {$R+} {$ELSEC} {$R-} {$ENDC} {$IFC fSymDraw} {$D+} {$ELSEC} {$D-} {$ENDC} CONST magicNumber = 32768; VAR fontID: TFontIDArray; {$S SgDRWres} {$S SgABCini} PROCEDURE TrmntExceptionHandler; VAR ch: CHAR; error: INTEGER; BEGIN IF onDesktop THEN ImDying; {This must be done first} IF NOT amDying THEN BEGIN {$IFC fDbgDraw} WriteLn('TrmntExceptionHandler'); {$ENDC} amDying := TRUE; IF crashPad <> NIL THEN crashPad.Crash; END; {$IFC fDbgDraw} {Flush the input queue in case there was user typeahead to the alternate screen} WHILE KeyPress DO Read(ch); {$ENDC} IF NOT onDesktop THEN MoveConsole(error, mainscreen); END; {$S SgDRWres} {$S SgABCini} PROCEDURE QkDrError(error: INTEGER); BEGIN {$IFC fDbgDraw} ABCbreak('QkDrError', error); {$ENDC} HALT; END; {$S SgDRWres} {$S SgABCini} PROCEDURE InitQDWM; VAR error: INTEGER; workDir: Pathname; bootVol: e_name; bootDir: Pathname; {$IFC LibraryVersion < 30} bootPort: tports; {$ENDC} BEGIN {$IFC libraryVersion <= 20} InitGraf(@thePort, @QkDrError); {$ELSEC} InitGraf(@thePort); {$ENDC} crashPad := NIL; IF onDesktop THEN BEGIN OpenWM; SetPort(deskPort); wmIsInitialized := TRUE; END ELSE BEGIN {move WriteLns to alternate screen} MoveConsole(error, alscreen); {$IFC fDbgDraw} IF error > 0 THEN ABCBreak('MoveConsole error', error); {$ENDC} { set work directory to boot volume for FMOpen} Get_Working_Dir(error, workDir); {$IFC fDbgDraw} IF error > 0 THEN ABCBreak('Get_Working_Dir error', error); {$ENDC} {$IFC LibraryVersion < 30} bootPort := OSBootVol(error); {$IFC fDbgDraw} IF error > 0 THEN ABCBreak('OSBootVol error', error); {$ENDC} Get_Config_Name(error, bootPort, bootVol); {$IFC fDbgDraw} IF error > 0 THEN ABCBreak('Get_Config_Name error', error); {$ENDC} {$ELSEC} OSBootVol(error, bootVol); {$IFC fDbgDraw} IF error > 0 THEN ABCBreak('OSBootVol error', error); {$ENDC} {$ENDC} bootDir := CONCAT('-', bootVol); Set_Working_Dir(error, bootDir); {$IFC fDbgDraw} IF error > 0 THEN ABCBreak('Set_Working_Dir to boot vol error', error); {$ENDC} FMOpen(error); {$IFC fDbgDraw} IF error > 0 THEN ABCBreak('FMOpen error = ', error); {$ENDC} { Set work directory back after OpenWM } Set_Working_Dir(error, workDir); {$IFC fDbgDraw} IF error > 0 THEN ABCBreak('Set_Working_Dir back to prefix error = ', error); {$ENDC} END; END; {$S SgDRWres} {$S SgABCdbg} FUNCTION BindHeap(activeVsClip, doBind: BOOLEAN): THeap; BEGIN IF crashPad = NIL THEN BindHeap := NIL {no UABC to do it for me} ELSE BindHeap := crashPad.BindHeap(activeVsClip, doBind); END; {$S SgDRWres} {$S SgABCcld} FUNCTION FilerReason(error: INTEGER): FReason; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} FilerReason := allOk; IF error > 0 THEN CASE error OF 309: FilerReason := noDiskSpace; 315: FilerReason := noMemory; 4001: FilerReason := badData; OTHERWISE FilerReason := internalError; END; END; {$S SgDRWres} {$S SgABCini} PROCEDURE InitErrorAbort(error: INTEGER); BEGIN IF error > 0 THEN BEGIN {$IFC fDbgDraw} ABCbreak('InitErrorAbort', error); {$ENDC} IF onDesktop THEN TellFiler(error, initFailed, FilerReason(error), NIL); HALT; END ELSE IF wmIsInitialized THEN IF Abort THEN BEGIN IF onDesktop THEN TellFiler(error, initFailed, aUserAbort, NIL); HALT; END; END; {$S SgDRWres} {$S SgDRWres} PROCEDURE Reduce(VAR numerator, denominator: INTEGER); {reduce fraction to lowest terms} VAR factor: INTEGER; maxFactor: INTEGER; {also makes cosmetics} smallerNumerator: INTEGER; smallerDenominator: INTEGER; BEGIN {very crude at the moment} {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} maxFactor := MIN(numerator, denominator); FOR factor := maxFactor DOWNTO 2 DO BEGIN smallerNumerator := numerator DIV factor; smallerDenominator := denominator DIV factor; IF (factor * smallerNumerator = numerator) AND (factor * smallerDenominator = denominator) THEN BEGIN numerator := smallerNumerator; denominator := smallerDenominator; END; END; END; {$S SgDRWres} FUNCTION FPtPlusPt(operand1, operand2: Point): LONGINT; VAR result: Point; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := operand1.h + operand2.h; result.v := operand1.v + operand2.v; FPtPlusPt := LONGINT(result); END; {$S SgDRWres} FUNCTION FPtMinusPt(operand1, operand2: Point): LONGINT; VAR result: Point; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := operand1.h - operand2.h; result.v := operand1.v - operand2.v; FPtMinusPt := LONGINT(result); END; {$S SgABCdat} FUNCTION FPtMulInt(operand1: Point; operand2: INTEGER): LONGINT; VAR result: Point; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := operand1.h * operand2; result.v := operand1.v * operand2; FPtMulInt := LONGINT(result); END; {$S SgABCdat} FUNCTION FPtDivInt(operand1: Point; operand2: INTEGER): LONGINT; VAR result: Point; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := operand1.h DIV operand2; result.v := operand1.v DIV operand2; FPtDivInt := LONGINT(result); END; {$S SgDRWres} FUNCTION FPtMaxPt(operand1, operand2: Point): LONGINT; VAR result: Point; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := Max(operand1.h, operand2.h); result.v := Max(operand1.v, operand2.v); FPtMaxPt := LONGINT(result); END; {$S SgDRWres} FUNCTION FPtMinPt(operand1, operand2: Point): LONGINT; VAR result: Point; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := Min(operand1.h, operand2.h); result.v := Min(operand1.v, operand2.v); FPtMinPt := LONGINT(result); END; {$S SgDRWres} FUNCTION FDiagRect(operand1: Rect): LONGINT; VAR result: Point; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := operand1.right - operand1.left; result.v := operand1.bottom - operand1.top; FDiagRect := LONGINT(result); END; {$S SgABCdat} PROCEDURE BoolToStr(bool: BOOLEAN; str: TPstring); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} IF bool THEN str^ := 'TRUE' ELSE str^ := 'FALSE'; END; FUNCTION LIntDivLInt(i, j: LONGINT): LONGINT; EXTERNAL; FUNCTION LIntDivInt(i: LONGINT; j: INTEGER): LONGINT; EXTERNAL; FUNCTION LIntMulInt(i: LONGINT; j: INTEGER): LONGINT; EXTERNAL; {$S SgDRWres} FUNCTION LIntOvrInt(i: LONGINT; j: INTEGER): LONGINT; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} IF i>0 THEN LIntOvrInt := LIntDivInt(i+(j DIV 2), j) ELSE LIntOvrInt := LIntDivInt(i-(j DIV 2), j); END; {$S SgABCdat} PROCEDURE PtPlusPt(operand1, operand2: Point; VAR result: Point); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := operand1.h + operand2.h; result.v := operand1.v + operand2.v; END; {$S SgABCdat} PROCEDURE PtMinusPt(operand1, operand2: Point; VAR result: Point); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := operand1.h - operand2.h; result.v := operand1.v - operand2.v; END; {$S SgABCdat} PROCEDURE PtMulInt(operand1: Point; operand2: INTEGER; VAR result: Point); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := operand1.h * operand2; result.v := operand1.v * operand2; END; {$S SgABCdat} PROCEDURE PtDivInt(operand1: Point; operand2: INTEGER; VAR result: Point); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := operand1.h DIV operand2; result.v := operand1.v DIV operand2; END; {$IFC LibraryVersion <= 20} FUNCTION EqualPt(operand1, operand2: Point): BOOLEAN; BEGIN EqualPt := (operand1.h = operand2.h) AND (operand1.v = operand2.v); END; {$ENDC} {$S SgDRWres} PROCEDURE RectPlusRect(operand1, operand2: Rect; VAR result: Rect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.left := operand1.left + operand2.left; result.top := operand1.top + operand2.top; result.right := operand1.right + operand2.right; result.bottom := operand1.bottom + operand2.bottom; END; {$S SgDRWres} PROCEDURE RectMinusRect(operand1, operand2: Rect; VAR result: Rect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.left := operand1.left - operand2.left; result.top := operand1.top - operand2.top; result.right := operand1.right - operand2.right; result.bottom := operand1.bottom - operand2.bottom; END; {$IFC LibraryVersion <= 20} {$S SgDRWres} FUNCTION EqualRect(rectA, rectB: Rect): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} EqualRect := (rectA.left=rectB.left) AND (rectA.top=rectB.top) AND (rectA.right=rectB.right) AND (rectA.bottom=rectB.bottom); END; {$S SgDRWres} FUNCTION EmptyRect(r: Rect): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} WITH r DO EmptyRect := (left >= right) OR (top >= bottom); END; {$ENDC} {$S SgDRWres} PROCEDURE AlignRect(VAR dstRect: Rect; srcRect: Rect; vhs: VHSelect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} dstRect.topLeft.vh[vhs] := srcRect.topLeft.vh[vhs]; dstRect.botRight.vh[vhs] := srcRect.botRight.vh[vhs]; END; {$S SgDRWres} FUNCTION LengthRect(r: Rect; vhs: VHSelect): INTEGER; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} LengthRect := r.botRight.vh[vhs] - r.topLeft.vh[vhs]; END; {$S SgDRWres} FUNCTION RectsNest(outer, inner: Rect): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} RectsNest := RectHasPt(outer, inner.topLeft) AND RectHasPt(outer, inner.botRight); END; {$S SgDRWres} FUNCTION RectHasPt(dstRect: Rect; pt: Point): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} RectHasPt := (dstRect.left <= pt.h) AND (pt.h <= dstRect.right) AND (dstRect.top <= pt.v) AND (pt.v <= dstRect.bottom); END; {$S SgDRWres} PROCEDURE RectHavePt(dstRect: Rect; VAR pt: Point); BEGIN {if dstRect is negative size, left/top is forced} {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} pt.h := Max(dstRect.left, Min(dstRect.right, pt.h)); pt.v := Max(dstRect.top, Min(dstRect.bottom, pt.v)); END; {$S SgDRWres} PROCEDURE RectifyRect(VAR dstRect: Rect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} Pt2Rect(dstRect.topLeft, dstRect.botRight, dstRect); END; {$S SgDRWres} FUNCTION RectIsVisible(rectInPort: Rect): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} RectIsVisible := RectInRgn(rectInPort, focusRgn); END; {$S SgABCdbg} PROCEDURE PointToStr(pt: Point; str: TPstring); VAR s: S255; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} IntToStr(pt.h, str); IntToStr(pt.v, @s); str^ := CONCAT('(', str^, ',', s, ')'); END; {$S SgABCdbg} PROCEDURE RectToStr(r: Rect; str: TPstring); VAR s: S255; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} PointToStr(r.topLeft, str); PointToStr(r.botRight, @s); str^ := CONCAT('[', str^, ',', s, ']'); END; {$S SgDRWres} {$S SgDRWres} PROCEDURE LPtPlusLPt(operand1, operand2: LPoint; VAR result: LPoint); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := operand1.h + operand2.h; result.v := operand1.v + operand2.v; END; {$S SgDRWres} PROCEDURE LPtMinusLPt(operand1, operand2: LPoint; VAR result: LPoint); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := operand1.h - operand2.h; result.v := operand1.v - operand2.v; END; {$S SgABCdat} PROCEDURE LPtMulInt(operand1: LPoint; operand2: INTEGER; VAR result: LPoint); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := operand1.h * operand2; result.v := operand1.v * operand2; END; {$S SgABCdat} PROCEDURE LPtDivInt(operand1: LPoint; operand2: INTEGER; VAR result: LPoint); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.h := LIntDivInt(operand1.h, operand2); result.v := LIntDivInt(operand1.v, operand2); END; {$S SgDRWres} FUNCTION EqualLPt(operand1, operand2: LPoint): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} EqualLPt := (operand1.h = operand2.h) AND (operand1.v = operand2.v); END; {$S SgDRWres} PROCEDURE LRectPlusLRect(operand1, operand2: LRect; VAR result: LRect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.left := operand1.left + operand2.left; result.top := operand1.top + operand2.top; result.right := operand1.right + operand2.right; result.bottom := operand1.bottom + operand2.bottom; END; {$S SgDRWres} PROCEDURE LRectMinusLRect(operand1, operand2: LRect; VAR result: LRect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} result.left := operand1.left - operand2.left; result.top := operand1.top - operand2.top; result.right := operand1.right - operand2.right; result.bottom := operand1.bottom - operand2.bottom; END; {$S SgDRWres} FUNCTION EqualLRect(rectA, rectB: LRect): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} EqualLRect := (rectA.left=rectB.left) AND (rectA.top=rectB.top) AND (rectA.right=rectB.right) AND (rectA.bottom=rectB.bottom); END; {$S SgDRWres} FUNCTION EmptyLRect(r: LRect): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} WITH r DO EmptyLRect := (left >= right) OR (top >= bottom); END; {$S SgDRWres} PROCEDURE AlignLRect(VAR destLRect: LRect; srcLRect: LRect; vhs: VHSelect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} destLRect.topLeft.vh[vhs] := srcLRect.topLeft.vh[vhs]; destLRect.botRight.vh[vhs] := srcLRect.botRight.vh[vhs]; END; {$S SgDRWres} FUNCTION LengthLRect(r: LRect; vhs: VHSelect): LONGINT; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} LengthLRect := r.botRight.vh[vhs] - r.topLeft.vh[vhs]; END; {$S SgDRWres} FUNCTION LRectsNest(outer, inner: LRect): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} LRectsNest := LRectHasLPt(outer, inner.topLeft) AND LRectHasLPt(outer, inner.botRight); END; {$S SgDRWres} FUNCTION LRectHasLPt(destLRect: LRect; pt: LPoint): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} LRectHasLPt := (destLRect.left <= pt.h) AND (pt.h <= destLRect.right) AND (destLRect.top <= pt.v) AND (pt.v <= destLRect.bottom); END; {$S SgDRWres} PROCEDURE LRectHaveLPt(destLRect: LRect; VAR pt: LPoint); BEGIN {if destLRect is negative size, left/top is forced} {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} pt.h := Max(destLRect.left, Min(destLRect.right, pt.h)); pt.v := Max(destLRect.top, Min(destLRect.bottom, pt.v)); END; {$S SgDRWres} PROCEDURE RectifyLRect(VAR destLRect: LRect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} SetLRect(destLRect, Min(destLRect.left, destLRect.right), Min(destLRect.top, destLRect.bottom), Max(destLRect.left, destLRect.right), Max(destLRect.top, destLRect.bottom)); END; {$S SgDRWres} FUNCTION LRectIsVisible(srcLRect: LRect): BOOLEAN; VAR rectInPort: Rect; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.LRectToRect(srcLRect, rectInPort); IF EmptyRect(rectInPort) THEN LRectIsVisible := FALSE ELSE LRectIsVisible := RectInRgn(rectInPort, focusRgn); END; {$S SgABCdbg} PROCEDURE LPointToStr(pt: LPoint; str: TPstring); VAR s: S255; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} LIntToStr(pt.h, str); LIntToStr(pt.v, @s); str^ := CONCAT('(', str^, ',', s, ')'); END; {$S SgABCdbg} PROCEDURE LRectToStr(r: LRect; str: TPstring); VAR s: S255; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} LPointToStr(r.topLeft, str); LPointToStr(r.botRight, @s); str^ := CONCAT('[', str^, ',', s, ']'); END; {$S SgDRWres} {$S SgDRWres} PROCEDURE SetLPt(VAR destPt: LPoint; itsH, itsV: LONGINT); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} WITH destPt DO BEGIN h := itsH; v := itsV; END; END; {$S SgDRWres} PROCEDURE SetLRect(VAR dstRect: LRect; itsLeft, itsTop, itsRight, itsBottom: LONGINT); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} WITH dstRect DO BEGIN left := itsLeft; top := itsTop; right := itsRight; bottom := itsBottom; END; END; {$S SgDRWres} PROCEDURE OffsetLRect(VAR dstRect: LRect; dh, dv: LONGINT); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} WITH dstRect DO BEGIN left := left + dh; top := top + dv; right := right + dh; bottom := bottom + dv; END; END; {$S SgDRWres} PROCEDURE InsetLRect(VAR dstRect: LRect; dh, dv: LONGINT); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} WITH dstRect DO BEGIN left := left + dh; top := top + dv; right := right - dh; bottom := bottom - dv; IF (left >= right) OR (top >= bottom) THEN BEGIN left := 0; top := 0; right := 0; bottom := 0; END; END; END; {$S SgABCres} FUNCTION SectLRect(srcRectA, srcRectB: LRect; VAR dstRect: LRect): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} WITH dstRect DO BEGIN left := Max(srcRectA.left, srcRectB.left); top := Max(srcRectA.top, srcRectB.top); right := Min(srcRectA.right, srcRectB.right); bottom := Min(srcRectA.bottom, srcRectB.bottom); IF (left >= right) OR (top >= bottom) THEN BEGIN SectLRect := FALSE; left := 0; top := 0; right := 0; bottom := 0; END ELSE SectLRect := TRUE; END; END; {$S SgDRWres} PROCEDURE UnionLRect(srcRectA, srcRectB: LRect; VAR dstRect: LRect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} WITH dstRect DO BEGIN left := Min(srcRectA.left, srcRectB.left); top := Min(srcRectA.top, srcRectB.top); right := Max(srcRectA.right, srcRectB.right); bottom := Max(srcRectA.bottom, srcRectB.bottom); END; END; {$S SgDRWres} FUNCTION LPtInLRect(pt: LPoint; r: LRect): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} LPtInLRect := (r.left <= pt.h) AND (pt.h < r.right) AND (r.top <= pt.v) AND (pt.v < r.bottom); END; {$S SgABCdat} FUNCTION IsSmallPt(srcPt: LPoint): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} IsSmallPt := (ABS(srcPt.h) < MAXINT) AND (ABS(srcPt.v) < MAXINT); END; {$S SgABCdat} FUNCTION IsSmallRect(srcRect: LRect): BOOLEAN; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} IsSmallRect := IsSmallPt(srcRect.topLeft) AND IsSmallPt(srcRect.botRight); END; {Drawing Text} {$S SgABCdat} PROCEDURE DrawLText(textBuf: Ptr; startByte, numBytes: INTEGER); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} {$IFC libraryVersion > 20} IF thePad.scaled THEN thePad.DrawLText(textBuf, startByte, numBytes) ELSE DrawText(QDPtr(textBuf), startByte, numBytes); {$ELSEC} DrawText(WordPtr(textBuf), startByte, numBytes); {$ENDC} END; {Drawing lines, rectangles, and ovals} {$S SgDRWres} PROCEDURE MoveToL(h, v: LONGINT); VAR lPtInView: LPoint; ptInPort: Point; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} SetLPt(lPtInView, h, v); thePad.LPtToPt(lPtInView, ptInPort); MoveTo(ptInPort.h, ptInPort.v); END; {$S SgDRWres} PROCEDURE MoveL(dh, dv: LONGINT); VAR lPtInView: LPoint; ptInPort: Point; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} SetLPt(lPtInView, dh, dv); thePad.LDistToDist(lPtInView, ptInPort); Move(ptInPort.h, ptInPort.v); END; {$S SgDRWres} PROCEDURE LineToL(h, v: LONGINT); VAR lPtInView: LPoint; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} SetLPt(lPtInView, h, v); thePad.DrawLLine(lPtInView); END; {$S SgDRWres} PROCEDURE LineL(dh, dv: LONGINT); VAR lPtInView: LPoint; ptInPort: Point; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} SetLPt(lPtInView, dh, dv); thePad.LDistToDist(lPtInView, ptInPort); Line(ptInPort.h, ptInPort.v); END; {$S SgDRWres} PROCEDURE FrameLRect(r: LRect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLRect(frame, r); END; {$S SgDRWres} PROCEDURE PaintLRect(r: LRect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLRect(paint, r); END; {$S SgDRWres} PROCEDURE EraseLRect(r: LRect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLRect(erase, r); END; {$S SgDRWres} PROCEDURE InvrtLRect(r: LRect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLRect(invert, r); END; {$S SgDRWres} PROCEDURE FillLRect(r: LRect; lPat: LPattern); VAR pat: Pattern; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} IF amPrinting THEN thePad.LPatToPat(lPat, pat); {$IFC LibraryVersion <= 20} thePat := Pattern(lPat); {$ELSEC} thePort^.fillPat := Pattern(lPat); {$ENDC} thePad.DrawLRect(fill, r); END; {$S SgDRWres} PROCEDURE FrameLOval(r: LRect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLOval(frame, r); END; {$S SgDRWres} PROCEDURE PaintLOval(r: LRect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLOval(paint, r); END; {$S SgDRWres} PROCEDURE EraseLOval(r: LRect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLOval(erase, r); END; {$S SgDRWres} PROCEDURE InvrtLOval(r: LRect); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLOval(invert, r); END; {$S SgDRWres} PROCEDURE FillLOval(r: LRect; lPat: LPattern); VAR pat: Pattern; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} IF amPrinting THEN thePad.LPatToPat(lPat, pat); {$IFC LibraryVersion <= 20} thePat := Pattern(lPat); {$ELSEC} thePort^.fillPat := Pattern(lPat); {$ENDC} thePad.DrawLOval(fill, r); END; PROCEDURE FrameLRRect(r: LRect; ovalWidth, ovalHeight: INTEGER); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLRRect(frame, r, ovalWidth, ovalHeight); END; PROCEDURE PaintLRRect(r: LRect; ovalWidth, ovalHeight: INTEGER); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLRRect(paint, r, ovalWidth, ovalHeight); END; PROCEDURE EraseLRRect(r: LRect; ovalWidth, ovalHeight: INTEGER); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLRRect(erase, r, ovalWidth, ovalHeight); END; PROCEDURE InvrtLRRect(r: LRect; ovalWidth, ovalHeight: INTEGER); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLRRect(invert, r, ovalWidth, ovalHeight); END; PROCEDURE FillLRRect(r: LRect; ovalWidth, ovalHeight: INTEGER; lPat: LPattern); VAR pat: Pattern; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} IF amPrinting THEN thePad.LPatToPat(lPat, pat); {$IFC LibraryVersion <= 20} thePat := Pattern(lPat); {$ELSEC} thePort^.fillPat := Pattern(lPat); {$ENDC} thePad.DrawLRRect(fill, r, ovalWidth, ovalHeight) END; PROCEDURE FrameLArc(r: LRect; startAngle, arcAngle: INTEGER); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLArc(frame, r, startAngle, arcAngle); END; PROCEDURE PaintLArc(r: LRect; startAngle, arcAngle: INTEGER); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLArc(paint, r, startAngle, arcAngle); END; PROCEDURE EraseLArc(r: LRect; startAngle, arcAngle: INTEGER); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLArc(erase, r, startAngle, arcAngle); END; PROCEDURE InvrtLArc(r: LRect; startAngle, arcAngle: INTEGER); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} thePad.DrawLArc(invert, r, startAngle, arcAngle); END; PROCEDURE FillLArc(r: LRect; startAngle, arcAngle: INTEGER; lPat: LPattern); VAR pat: Pattern; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} IF amPrinting THEN thePad.LPatToPat(lPat, pat); {$IFC LibraryVersion <= 20} thePat := Pattern(lPat); {$ELSEC} thePort^.fillPat := Pattern(lPat); {$ENDC} thePad.DrawLArc(fill, r, startAngle, arcAngle); END; PROCEDURE RotatePattern(pInPat, pOutPat: Ptr; dh, dv: LONGINT); EXTERNAL; {$S SgABCdat} FUNCTION ClonePicture(pic: PicHandle; toHeap: THeap): PicHandle; VAR h: TH; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} h := HAllocate(THz(toHeap), pic^^.picSize); XferLeft(Ptr(pic^), Ptr(h^), pic^^.picSize); ClonePicture := PicHandle(h); END; {$S SgDRWres} PROCEDURE ResizeFeedback(mousePt: Point; minPt, maxPt: Point; outerRect: Rect; tabHeight, sbWidth, sbHeight: INTEGER; VAR newPt: Point); VAR rFrame: Rect; limitRect: Rect; oldMousePt: Point; innerTop: INTEGER; fTab: BOOLEAN; fHscroll: BOOLEAN; fVScroll: BOOLEAN; event: EventRecord; savePort: GrafPtr; PROCEDURE InitXorFrame; BEGIN fTab := TRUE; fHScroll := TRUE; fVScroll := TRUE; { set up scroll bar and tab widths } { the +1 's are to account for enlarging rFrame by one pixel } IF sbWidth > 0 THEN sbWidth := sbWidth+1 ELSE fVScroll := FALSE; IF sbHeight > 0 THEN sbHeight := sbHeight+1 ELSE fHScroll := FALSE; IF tabHeight > 0 THEN tabHeight := tabHeight+1 ELSE fTab := FALSE; { setup rFrame - the outer rect for XORing } rFrame := outerRect; InsetRect(rFrame, -1, -1); limitRect.topLeft := minPt; limitRect.botRight := maxPt; IF fTab THEN innerTop := rFrame.top+tabHeight ELSE innerTop := rFrame.top; { Setup the pen } PenNormal; PenPat(gray); PenMode(notPatXor); END; PROCEDURE XorFrame; BEGIN rFrame.botRight := newPt; FrameRect(rFrame); IF fTab THEN BEGIN MoveTo(rFrame.left, innerTop); LineTo(rFrame.right-1, innerTop); END; IF fHScroll THEN BEGIN MoveTo(rFrame.left, newPt.v-sbHeight); LineTo(rFrame.right-1, newPt.v-sbHeight); END; IF fVScroll THEN BEGIN MoveTo(newPt.h - sbWidth, innerTop); LineTo(newPt.h - sbWidth, rFrame.bottom-1); END; END; PROCEDURE DoDragFrame; VAR nxtPt: Point; BEGIN nxtPt := Point(FPtPlusPt(newPt, Point(FPtMinusPt(mousePt, oldMousePt)))); RectHavePt(limitRect, nxtPt); mousePt := Point(FPtPlusPt(Point(FPtMinusPt(nxtPt, newPt)), oldMousePt)); IF NOT EqualPt(nxtPt, newPt) THEN BEGIN XorFrame; { hide old } newPt := nxtPt; XorFrame; { draw new } END; END; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} InitXorFrame; { sets rFrame } newPt := rFrame.botRight; XorFrame; oldMousePt := mousePt; WHILE StillDown DO BEGIN GetMouse(mousePt); DoDragFrame; oldMousePt := mousePt; END; IF PeekEvent(event) AND (event.what = buttonUp) THEN BEGIN GetPort(savePort); SetPort(event.who); mousePt := event.where; LocalToGlobal(mousePt); SetPort(savePort); GlobalToLocal(mousePt); END ELSE GetMouse(mousePt); DoDragFrame; XorFrame; { hide last } newPt.h := newPt.h - 1; newPt.v := newPt.v - 1; END; { ResizeFeedback } {$S SgABCres} PROCEDURE PopFocus; BEGIN {$IFC fTrace}BP(6);{$ENDC} SetEmptyRgn(padRgn); {To save memory space} focusArea := focusStack[focusStkPtr]; thePad := NIL; IF focusArea <> NIL THEN focusArea.Focus; focusStkPtr := focusStkPtr - 1; {$IFC fTrace}EP;{$ENDC} END; {$S SgABCres} PROCEDURE PushFocus; BEGIN {$IFC fTrace}BP(6);{$ENDC} focusStkPtr := focusStkPtr + 1; focusStack[focusStkPtr] := focusArea; {$IFC fTrace}EP;{$ENDC} END; {$S SgDRWres} PROCEDURE MakeTypeStyle{(itsFamily: INTEGER; itsSize: INTEGER; itsFaces: TSetEFace/Style; VAR typeStyle: TTypeStyle)}; BEGIN {$IFC fTrace}BP(11);{$ENDC} WITH typeStyle DO BEGIN onFaces := itsFaces; font.fontFamily := itsFamily; font.fontSize := itsSize; END; {$IFC fTrace}EP;{$ENDC} END; FUNCTION QDFontNumber{(typeStyle: TTypeStyle): INTEGER}; BEGIN {$IFC fTrace}BP(11);{$ENDC} WITH typeStyle.font DO IF fontFamily = famSystem THEN QDFontNumber := fIDSystem ELSE QDFontNumber := fontID[fontFamily, fontSize]; {$IFC fTrace}EP;{$ENDC} END; PROCEDURE SetQDTypeStyle{(typeStyle: TTypeStyle)}; BEGIN {$IFC fTrace}BP(11);{$ENDC} TextFont(QDFontNumber(typeStyle)); TextFace(typeStyle.onFaces); {$IFC fTrace}EP;{$ENDC} END; METHODS OF TArea; {$IFC fDebugMethods} {$S SgABCdbg} PROCEDURE TArea.Fields(PROCEDURE Field(nameAndType: S255)); BEGIN Field('innerRect: Rect'); Field('outerRect: Rect'); Field('parentBranch: TBranchArea'); END; {$S SgDRWres} {$ENDC} FUNCTION TArea.ChildWithPt(pt: Point; childList: TList; VAR nearestPt: Point): TArea; VAR foundArea: TArea; s: TListScanner; BEGIN {$IFC fTrace}BP(6);{$ENDC} RectHavePt(SELF.innerRect, pt); s := childList.scanner; WHILE s.Scan(foundArea) DO IF RectHasPt(foundArea.outerRect, pt) THEN s.Done; IF foundArea = NIL THEN BEGIN {$IFC fDbgDraw} ABCbreak('ChildWithPt found no area', 0); {$ENDC} foundArea := TArea(childList.First); END; RectHavePt(foundArea.innerRect, pt); nearestPt := pt; ChildWithPt := foundArea; {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TArea.Erase; BEGIN {$IFC fTrace}BP(6);{$ENDC} FillRect(SELF.innerRect, white); {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TArea.Frame; VAR innerRect: Rect; borderRect: Rect; BEGIN {$IFC fTrace}BP(6);{$ENDC} innerRect := SELF.innerRect; IF NOT RectsNest(innerRect, focusRgn^^.rgnBBox) THEN BEGIN PenNormal; PenSize(1, 1); borderRect := innerRect; InsetRect(borderRect, -1, -1); FrameRect(borderRect); END; {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TArea.GetBorder(VAR border: Rect); BEGIN {$IFC fTrace}BP(3);{$ENDC} SetRect(border, -1, -1, 1, 1); {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TArea.SetInnerRect(newInnerRect: Rect); VAR border: Rect; BEGIN {$IFC fTrace}BP(7);{$ENDC} SELF.innerRect := newInnerRect; SELF.GetBorder(border); {$H-} RectPlusRect(SELF.innerRect, border, SELF.outerRect); {$H+} {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TArea.SetOuterRect(newOuterRect: Rect); VAR border: Rect; BEGIN {$IFC fTrace}BP(7);{$ENDC} SELF.outerRect := newOuterRect; SELF.GetBorder(border); {$H-} RectMinusRect(SELF.outerRect, border, SELF.innerRect); {$H+} {$IFC fTrace}EP;{$ENDC} END; {$S SgABCini} BEGIN fontID[famModern, size20Pitch] := fID20Pitch; fontID[famModern, size15Pitch] := fID15Pitch; fontID[famModern, size10Pitch] := fIDm10Pitch; fontID[famModern, size12Pitch] := fIDm12Pitch; fontID[famModern, size12Point] := fIDm12Point; fontID[famModern, size14Point] := fIDm14Point; fontID[famModern, size18Point] := fIDm18Point; fontID[famModern, size24Point] := fIDm24Point; fontID[famClassic, size20Pitch] := fID20Pitch; fontID[famClassic, size15Pitch] := fID15Pitch; fontID[famClassic, size10Pitch] := fIDc10Pitch; fontID[famClassic, size12Pitch] := fIDc12Pitch; fontID[famClassic, size12Point] := fIDc12Point; fontID[famClassic, size14Point] := fIDc14Point; fontID[famClassic, size18Point] := fIDc18Point; fontID[famClassic, size24Point] := fIDc24Point; MakeTypeStyle(famSystem, 0 {dummy}, [], sysTypeStyle); END; {$S SgDRWres} METHODS OF TPad; {$S sCldInit} FUNCTION TPad.CREATE(object: TObject; heap: THeap; itsInnerRect: Rect; itsViewedLRect: LRect; itsPadRes, itsViewRes: Point; itsPort: GrafPtr): TPad; VAR zoomFactor: TScaler; BEGIN {$IFC fTrace}BP(7);{$ENDC} IF object = NIL THEN object := NewObject(heap, THISCLASS); SELF := TPad(object); SELF.parentBranch := NIL; SetPt(zoomFactor.numerator, 1, 1); SetPt(zoomFactor.denominator, 1, 1); SELF.Redefine(itsInnerRect, itsViewedLRect, itsPadRes, itsViewRes, zoomFactor, itsPort); {$IFC fTrace}EP;{$ENDC} END; {$S SgDRWres} {$S sCldInit} PROCEDURE TPad.Redefine(itsInnerRect: Rect; itsViewedLRect: LRect; itsPadRes, itsViewRes: Point; itsZoomFactor: TScaler; itsPort: GrafPtr); VAR vhs: VHSelect; newOffset: LPoint; BEGIN {$IFC fTrace}BP(7);{$ENDC} SELF.SetInnerRect(itsInnerRect); WITH SELF, scaleFactor DO {$H-} BEGIN port := itsPort; viewedLRect := itsViewedLRect; availLRect := itsViewedLRect; InsetLRect(availLRect, -8192, -8192); clippedRect := itsInnerRect; zoomFactor := itsZoomFactor; {install new Resolutions} padRes := itsPadRes; viewedRes := itsViewRes; {compute scale factor from resolutions and zoom factor} FOR vhs := v TO h DO BEGIN numerator.vh[vhs] := itsPadRes.vh[vhs] * zoomFactor.numerator.vh[vhs]; denominator.vh[vhs] := itsViewRes.vh[vhs] * zoomFactor.denominator.vh[vhs]; Reduce(numerator.vh[vhs], denominator.vh[vhs]); END; scaled := (numerator.h <> denominator.h) OR (numerator.v <> denominator.v); {compute scroll offset} FOR vhs := v TO h DO newOffset.vh[vhs] := LIntOvrInt(LIntMulInt(itsViewedLRect.topLeft.vh[vhs], numerator.vh[vhs]), denominator.vh[vhs]) - itsInnerRect.topLeft.vh[vhs]; SELF.SetScrollOffset(newOffset); {$H+} END; {$IFC fTrace}EP;{$ENDC} END; {$S SgDRWres} {$IFC fDebugMethods} {$S SgABCdbg} PROCEDURE TPad.Fields(PROCEDURE Field(nameAndType: S255)); BEGIN TArea.Fields(Field); Field('port: Ptr'); Field('viewedLRect: LRect'); Field('visLRect: LRect'); Field('availLRect: LRect'); Field('scrollOffset: LPoint'); Field('origin: Point'); {+LSR+} Field('cdOffset: LPoint'); {+LSR+} Field('clippedRect: rect'); Field('padRes: Point'); Field('viewedRes: Point'); Field('scaled: BOOLEAN'); Field('scaleFactor: RECORD numerator: Point; denominator: Point END'); Field('zoomFactor: RECORD numerator: Point; denominator: Point END'); END; {$S SgDRWres} {$ENDC} PROCEDURE TPad.ClipFurtherTo(rBand: rect); {narrows down clip area at next Focus} VAR grafRect: Rect; BEGIN {$IFC fTrace}BP(7);{$ENDC} {$H-} IF SectRect(rBand, SELF.clippedRect, SELF.clippedRect) THEN; {$H+} {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TPad.DistToLDist(distInPort: Point; VAR lDistInView: LPoint); BEGIN {$IFC fTrace}BP(6);{$ENDC} IF SELF.scaled THEN WITH SELF.scaleFactor DO {$H-} BEGIN lDistInView.h := LIntOvrInt(LIntMulInt(distInPort.h, denominator.h), numerator.h); lDistInView.v := LIntOvrInt(LIntMulInt(distInPort.v, denominator.v), numerator.v); {$H+} END ELSE BEGIN lDistInView.h := distInPort.h; lDistInView.v := distInPort.v; END; {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TPad.DrawLLine(newLPt: LPoint); VAR newGrafPt: Point; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} SELF.LPtToPt(newLPt, newGrafPt); StdLine(newGrafPt); END; {$IFC LibraryVersion <= 20} {This is still not the right implementation when we are printing} PROCEDURE TPad.DrawLPicture(pic: PicHandle; r:LRect); VAR rectInPort: Rect; BEGIN SELF.LRectToRect(r, rectInPort); DrawPicture(pic, rectInPort); END; {$ELSEC} PROCEDURE TKStdText(byteCount: INTEGER; textBuf: QDPtr; numer, denom: Point); BEGIN StdText(byteCount, textBuf, numer, numer); END; PROCEDURE TKStdComment(kind, datasize: INTEGER; dataHandle: QDHandle); CONST picForeColor = 108; picBackColor = 109; VAR pData: TpLongint; BEGIN IF dataHandle <> NIL THEN IF dataSize <> 4 THEN BEGIN pData := TpLongint(ORD(dataHandle^)); CASE kind OF picForeColor: ForeColor(pData^); picBackColor: BackColor(pData^); END; END; END; {This is still not the right implementation when we are printing} PROCEDURE TPad.DrawLPicture(pic: PicHandle; r:LRect); VAR rectInPort: Rect; oldProcsPtr: QDProcsPtr; TKProcs: QDProcs; oldTextProc: QDPtr; oldCommentProc: QDPtr; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} WITH thePort^ DO BEGIN oldProcsPtr := grafprocs; IF oldProcsPtr = NIL THEN BEGIN SetStdProcs(TKProcs); grafprocs := @TKProcs; END; WITH grafprocs^ DO BEGIN oldTextProc := textProc; oldCommentProc := commentProc; IF amPrinting THEN BEGIN textProc := @TKStdText; commentProc := @TKStdComment; END; END; END; SELF.LRectToRect(r, rectInPort); DrawPicture(pic, rectInPort); WITH thePort^ DO BEGIN IF oldProcsPtr <> NIL THEN WITH grafprocs^ DO BEGIN textProcs := oldTextProc; commentProc := oldCommentProc; END; grafProcs := oldProcsPtr; END; END; {$ENDC} PROCEDURE TPad.DrawLRect(verb: GrafVerb; r: LRect); VAR rectInPort: Rect; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} SELF.LRectToRect(r, rectInPort); StdRect(verb, rectInPort); END; PROCEDURE TPad.DrawLRRect(verb: GrafVerb; r: LRect; ovalWidth, ovalHeight: INTEGER); VAR rectInPort: Rect; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} SELF.LRectToRect(r, rectInPort); StdRRect(verb, rectInPort, ovalWidth, ovalHeight); END; PROCEDURE TPad.DrawLOval(verb: GrafVerb; r: LRect); VAR rectInPort: Rect; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} SELF.LRectToRect(r, rectInPort); StdOval(verb, rectInPort); END; PROCEDURE TPad.DrawLArc(verb: GrafVerb; r: LRect; startAngle, arcAngle: INTEGER); VAR rectInPort: Rect; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} SELF.LRectToRect(r, rectInPort); StdArc(verb, rectInPort, startAngle, arcAngle); END; PROCEDURE TPad.DrawLBits(VAR srcBits: BitMap; VAR srcRect: Rect; VAR dstLRect: LRect; mode: INTEGER; maskRgn: RgnHandle); VAR dstGrafRect: Rect; BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} SELF.LRectToRect(dstLRect, dstGrafRect); StdBits(srcBits, srcRect,dstGrafRect, mode, maskRgn); END; {$S SgABCres} PROCEDURE TPad.Focus; VAR visRgn: RgnHandle; origin: Point; BEGIN {$IFC fTrace}BP(6);{$ENDC} IF SELF.Port <> printerPseudoPort THEN SetPort(SELF.port); {for the moment anyway don't tamper if being controlled by LisaPrint} SetOrigin(0, 0); {so thePort^.visRgn will be relative to a (0,0)-origined space, to match SELF.clippedRect and altVisRgn} RectRgn(padRgn, SELF.clippedRect); IF useAltVisRgn THEN visRgn := altVisRgn {Instigated by TWindow.StashPicture or TClipboard.Publicize} ELSE visRgn := thePort^.visRgn; SectRgn(padRgn, visRgn, padRgn); origin := SELF.origin; WITH origin DO {+LSR+} BEGIN SetOrigin(h, v); OffsetRgn(padRgn, h, v); END; SetClip(padRgn); focusRgn := padRgn; {focusRgn is an alias for either padRgn or visRgn} focusArea := SELF; thePad := SELF; WITH SELF DO {$H-} BEGIN SELF.RectToLRect(focusRgn^^.rgnBBox, visLRect); IF SectLRect(viewedLRect, visLRect, visLRect) THEN BEGIN END; {$H+} END; {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TPad.InvalLRect(r: LRect); VAR rectInPort: Rect; BEGIN {$IFC fTrace}BP(7);{$ENDC} SELF.LRectToRect(r, rectInPort); SELF.InvalRect(rectInPort); {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TPad.InvalRect(r: Rect); BEGIN {$IFC fTrace}BP(7);{$ENDC} IF SectRect(r, focusRgn^^.rgnBBox, r) THEN InvalRect(r); {$IFC fTrace}EP;{$ENDC} END; {$S SgDRWres} PROCEDURE TPad.LDistToDist(lDistInView: LPoint; VAR distInPort: Point); BEGIN {$IFC fTrace}BP(6);{$ENDC} IF SELF.scaled THEN WITH SELF.scaleFactor DO {$H-} BEGIN distInPort.h := LIntOvrInt(LIntMulInt(lDistInView.h, numerator.h), denominator.h); distInPort.v := LIntOvrInt(LIntMulInt(lDistInView.v, numerator.v), denominator.v); {$H+} END ELSE BEGIN distInPort.h := lDistInView.h; distInPort.v := lDistInView.v; END; {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TPad.LPatToPat(lPatInView: LPattern; VAR patInPort: Pattern); BEGIN {$IFC fTrace}BP(6);{$ENDC} IF amPrinting THEN RotatePattern(@lPatInView, @patInPort, SELF.cdOffset.h, SELF.cdOffset.v) ELSE patInPort := Pattern(lPatInView); {+LSR+} {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TPad.LPtToPt(lPtInView: LPoint; VAR ptInPort: Point); BEGIN {$IFC fTrace}BP(6);{$ENDC} LRectHaveLPt(SELF.availLRect, lPtInView); WITH SELF, cdOffset, scaleFactor DO {+LSR+} IF scaled THEN {$H-} BEGIN ptInPort.h := LIntOvrInt(LIntMulInt(lPtInView.h, numerator.h), denominator.h) - h; ptInPort.v := LIntOvrInt(LIntMulInt(lPtInView.v, numerator.v), denominator.v) - v; {$H+} END ELSE BEGIN ptInPort.h := lPtInView.h - h; ptInPort.v := lPtInView.v - v; END; {$IFC fTrace}EP;{$ENDC} END; {$S SgABCres} PROCEDURE TPad.LRectToRect(lRectInView: LRect; VAR rectInPort: Rect); BEGIN {$IFC fTrace}BP(6);{$ENDC} LRectHaveLPt(SELF.availLRect, lRectInView.topLeft); LRectHaveLPt(SELF.availLRect, lRectInView.botRight); WITH SELF, cdOffset, scaleFactor DO {+LSR+} IF scaled THEN {$H-} BEGIN rectInPort.left := LIntOvrInt(LIntMulInt(lRectInView.left, numerator.h), denominator.h) - h; rectInPort.top := LIntOvrInt(LIntMulInt(lRectInView.top, numerator.v), denominator.v) - v; rectInPort.right := LIntOvrInt(LIntMulInt(lRectInView.right, numerator.h), denominator.h) - h; rectInPort.bottom := LIntOvrInt(LIntMulInt(lRectInView.bottom, numerator.v), denominator.v) - v; {$H+} END ELSE BEGIN rectInPort.left := lRectInView.left - h; rectInPort.top := lRectInView.top - v; rectInPort.right := lRectInView.right - h; rectInPort.bottom := lRectInView.bottom - v; END; {$IFC fTrace}EP;{$ENDC} END; {$S SgDRWres} PROCEDURE TPad.OffsetBy(deltaLPt: LPoint); VAR vhs: VHSelect; newOffset: LPoint; BEGIN {$IFC fTrace}BP(7);{$ENDC} WITH SELF, deltaLPt DO {$H-} BEGIN OffsetLRect(viewedLRect, h, v); OffsetLRect(availLRect, h, v); {$H+} END; FOR vhs := v TO h DO {$H-} {+LSR+} WITH SELF, scaleFactor DO newOffset.vh[vhs] := LIntOvrInt(LIntMulInt(viewedLRect.topLeft.vh[vhs], numerator.vh[vhs]), denominator.vh[vhs]) - innerRect.topLeft.vh[vhs]; {$H+} SELF.SetScrollOffset(newOffset); {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TPad.PatToLPat(patInPort: Pattern; VAR lPatInView: LPattern); BEGIN {$IFC fTrace}BP(6);{$ENDC} IF amPrinting THEN RotatePattern(@patInPort, @lPatInView, -SELF.cdOffset.h, -SELF.cdOffset.v) ELSE LPatInView := LPattern(patInPort); {+LSR+} {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TPad.PtToLPt(ptInPort: Point; VAR lPtInView: LPoint); {$IFC fDbgDraw} VAR pt: Point; s: S255; {$ENDC} BEGIN {$IFC fTrace}BP(6);{$ENDC} WITH SELF, cdOffset, scaleFactor DO {+LSR+} IF scaled THEN {$H-} BEGIN lPtInView.h := LIntOvrInt(LIntMulInt(ptInPort.h + h, denominator.h), numerator.h); lPtInView.v := LIntOvrInt(LIntMulInt(ptInPort.v + v, denominator.v), numerator.v); {$H+} END ELSE BEGIN lPtInView.h := ptInPort.h + h; lPtInView.v := ptInPort.v + v; END; {$IFC fDbgDraw} SELF.LPtToPt(lPtInView, pt); IF NOT EqualPt(pt, ptInPort) THEN BEGIN PointToStr(ptInPort, @s); writeln('ptInPort:', s); LPointToStr(lPtInView, @s); writeln('lPtInView:',s); PointToStr(pt, @s); writeln('pt:', s); WrObj(SELF, 1, ''); writeln; ABCbreak('Error in TPad.PtToLPt', 0); END; {$ENDC} {$IFC fTrace}EP;{$ENDC} END; {$S SgABCres} PROCEDURE TPad.RectToLRect(rectInPort: Rect; VAR lRectInView: LRect); BEGIN {$IFC fTrace}BP(6);{$ENDC} WITH SELF, cdOffset, scaleFactor DO {+LSR+} IF scaled THEN {$H-} BEGIN lRectInView.left := LIntOvrInt(LIntMulInt(rectInPort.left + h, denominator.h), numerator.h); lRectInView.top := LIntOvrInt(LIntMulInt(rectInPort.top + v, denominator.v), numerator.v); lRectInView.right := LIntOvrInt(LIntMulInt(rectInPort.right + h, denominator.h), numerator.h); lRectInView.bottom := LIntOvrInt(LIntMulInt(rectInPort.bottom + v, denominator.v), numerator.v); {$H+} END ELSE BEGIN lRectInView.left := rectInPort.left + h; lRectInView.top := rectInPort.top + v; lRectInView.right := rectInPort.right + h; lRectInView.bottom := rectInPort.bottom + v; END; {$IFC fTrace}EP;{$ENDC} END; {$S SgDRWres} PROCEDURE TPad.SetPen(pen: PenState); VAR lPat: LPattern; BEGIN {$IFC fTrace}BP(7);{$ENDC} IF amPrinting THEN BEGIN noPad.PatToLPat(pen.pnPat, lPat); SELF.LPatToPat(lPat, pen.pnPat); END; SetPenState(pen); {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TPad.SetPenToHighlight(highTransit: THighTransit); BEGIN {$IFC fTrace}BP(7);{$ENDC} SELF.SetPen(highPen[highTransit]); {$IFC fTrace}EP;{$ENDC} END; PROCEDURE TPad.SetScrollOffset(VAR newOffset: LPoint); {recalculates the origin and cdOffset fields; does not change arg} VAR vhs: VHSelect; BEGIN {$IFC fTrace}BP(7);{$ENDC} WITH SELF DO BEGIN scrollOffset := newOffset; FOR vhs := v TO h DO BEGIN origin.vh[vhs] := newOffset.vh[vhs] MOD magicNumber; cdOffset.vh[vhs] := newOffset.vh[vhs] - origin.vh[vhs]; END; END; {$IFC fTrace}EP;{$ENDC} END; {$S Override} PROCEDURE TPad.SetZoomFactor; {.... ONLY SEEMS TO BE RELEVANT FOR PANE--NONSENSE HERE FOR NOW} BEGIN {$IFC fTrace}BP(7);{$ENDC} {$IFC fTrace}EP;{$ENDC} END; {$S SgABCdat} PROCEDURE TPad.DrawLText(textBuf: Ptr; startByte, numBytes: INTEGER); BEGIN {$IFC fMaxTrace}BP(1);{$ENDC} {$IFC fMaxTrace}EP;{$ENDC} WITH SELF.zoomFactor DO {$H-} {$IFC libraryVersion > 20} StdText(numBytes, QDPtr(ORD(textBuf) + startByte), numerator, denominator); {$ELSEC} DrawText(WordPtr(textBuf), startByte, numBytes); {$ENDC} {$H+} END; {$S SgDRWres} {$S SgABCini} BEGIN UnitAuthor('Apple'); printerPseudoPort := POINTER(0); crashPad := NIL; SetPt(screenRes, 90, 60); lPatWhite := LPattern(white); lPatBlack := LPattern(black); lPatGray := LPattern(gray); lPatLtGray := LPattern(ltGray); lPatDkGray := LPattern(dkGray); amPrinting := FALSE; END; {$S SgDRWres} METHODS OF TBranchArea; {$S SgABCcld} FUNCTION TBranchArea.CREATE(object: TObject; heap: THeap; vhs: VHSelect; hasElderFirst: BOOLEAN; whoCanResizeIt: TResizability; itsElderChild, itsYoungerChild: TArea): TBranchArea; BEGIN {$IFC fTrace}BP(7);{$ENDC} IF object = NIL THEN object := NewObject(heap, THISCLASS); SELF := TBranchArea(object); WITH SELF DO BEGIN outerRect := itsElderChild.outerRect; parentBranch := itsElderChild.parentBranch; arrangement := vhs; elderFirst := hasElderFirst; resizability := whoCanResizeIt; elderChild := itsElderChild; youngerChild := itsYoungerChild; END; itsElderChild.parentBranch := SELF; itsYoungerChild.parentBranch := SELF; {$IFC fTrace}EP;{$ENDC} END; {$S SgDRWres} {$IFC fDebugMethods} {$S SgABCdbg} PROCEDURE TBranchArea.Fields(PROCEDURE Field(nameAndType: S255)); BEGIN TArea.Fields(Field); Field('arrangement: Byte'); Field('elderFirst: BOOLEAN'); Field('resizability: Byte'); Field('elderChild: TArea'); Field('youngerChild: TArea'); END; {$S SgDRWres} {$ENDC} {$S SgABCcld} PROCEDURE TBranchArea.GetMinExtent(VAR minExtent: Point; windowIsResizingIt: BOOLEAN); VAR elderMinSize: Point; youngerMinSize: Point; vhs: VHSelect; BEGIN {$IFC fTrace}BP(7);{$ENDC} vhs := SELF.arrangement; SELF.elderChild.GetMinExtent(elderMinSize, TRUE); SELF.youngerChild.GetMinExtent(youngerMinSize, TRUE); IF windowIsResizingIt AND NOT (windowCanResizeIt IN SELF.resizability) THEN youngerMinSize.vh[vhs] := LengthRect(SELF.youngerChild.outerRect, vhs); minExtent.vh[vhs] := elderMinSize.vh[vhs] + youngerMinSize.vh[vhs]; vhs := orthogonal[vhs]; minExtent.vh[vhs] := Max(elderMinSize.vh[vhs], youngerMinSize.vh[vhs]); {$IFC fTrace}EP;{$ENDC} END; {$S SgDRWres} {$S SgABCcld} FUNCTION TBranchArea.OtherChild(child: TArea): TArea; BEGIN {$IFC fTrace}BP(7);{$ENDC} IF SELF.elderChild = child THEN OtherChild := SELF.youngerChild ELSE {$IFC fDbgDraw} IF SELF.youngerChild = child THEN OtherChild := SELF.elderChild ELSE ABCBreak('This panel branch does not have a child that is', ORD(child)); {$ELSEC} OtherChild := SELF.elderChild; {$ENDC} {$IFC fTrace}EP;{$ENDC} END; {$S SgDRWres} {$S SgABCcld} PROCEDURE TBranchArea.Redivide(newCd: INTEGER); VAR elderRect: Rect; youngerRect: Rect; BEGIN {$IFC fTrace}BP(7);{$ENDC} elderRect := SELF.elderChild.outerRect; youngerRect := SELF.youngerChild.outerRect; TRectCoords(elderRect)[SELF.elderFirst].vh[SELF.arrangement] := newCd; TRectCoords(youngerRect)[NOT SELF.elderFirst].vh[SELF.arrangement] := newCd; SELF.elderChild.ResizeOutside(elderRect); SELF.youngerChild.ResizeOutside(youngerRect); {$IFC fTrace}EP;{$ENDC} END; {$S SgDRWres} {$S SgABCcld} PROCEDURE TBranchArea.ReplaceChild(child, newChild: TArea); BEGIN {$IFC fTrace}BP(7);{$ENDC} IF SELF.elderChild = child THEN SELF.elderChild := newChild ELSE {$IFC fDbgDraw} IF SELF.youngerChild = child THEN SELF.youngerChild := newChild ELSE ABCBreak('This panel branch does not have a child that is', ORD(child)); {$ELSEC} SELF.youngerChild := newChild; {$ENDC} newChild.parentBranch := SELF; IF child.parentBranch = SELF THEN child.parentBranch := NIL; {$IFC fTrace}EP;{$ENDC} END; {$S SgDRWres} {$S SgABCcld} PROCEDURE TBranchArea.ResizeOutside(newOuterRect: Rect); VAR formerRect: Rect; elderChild: TArea; youngerChild: TArea; elderRect: Rect; youngerRect: Rect; vhs: VHSelect; eldFirst: BOOLEAN; minExtents: ARRAY [FALSE..TRUE] OF Point; newCd: INTEGER; deltaRect: Rect; BEGIN {$IFC fTrace}BP(7);{$ENDC} formerRect := SELF.outerRect; elderChild := SELF.elderChild; youngerChild := SELF.youngerChild; elderRect := elderChild.outerRect; youngerRect := youngerChild.outerRect; vhs := SELF.arrangement; eldFirst := SELF.elderFirst; IF windowCanResizeIt IN SELF.resizability THEN BEGIN {both children resize proportionally} MapRect(elderRect, formerRect, newOuterRect); MapRect(youngerRect, formerRect, newOuterRect); elderChild.GetMinExtent(minExtents[NOT eldFirst], TRUE); youngerChild.GetMinExtent(minExtents[eldFirst], TRUE); IF (minExtents[FALSE].vh[vhs] + minExtents[TRUE].vh[vhs]) < LengthRect(newOuterRect, vhs) THEN BEGIN {It is possible to satisfy both min constraints, so do so} newCd := Max(newOuterRect.topLeft.vh[vhs] + minExtents[FALSE].vh[vhs], Min(newOuterRect.botRight.vh[vhs] - minExtents[TRUE].vh[vhs], TRectCoords(elderRect)[eldFirst].vh[vhs])); TRectCoords(elderRect)[eldFirst].vh[vhs] := newCd; TRectCoords(youngerRect)[NOT eldFirst].vh[vhs] := newCd; END; END ELSE BEGIN {only elder child resizes in my direction} RectMinusRect(newOuterRect, formerRect, deltaRect); RectPlusRect(elderRect, deltaRect, elderRect); TRectCoords(deltaRect)[NOT eldFirst].vh[vhs] := TRectCoords(deltaRect)[eldFirst].vh[vhs]; RectPlusRect(youngerRect, deltaRect, youngerRect); END; youngerChild.ResizeOutside(youngerRect); elderChild.ResizeOutside(elderRect); SELF.outerRect := newOuterRect; {$IFC fTrace}EP;{$ENDC} END; {$S SgDRWres} {$S SgABCcld} FUNCTION TBranchArea.TopLeftChild: TArea; BEGIN {$IFC fTrace}BP(7);{$ENDC} IF SELF.elderFirst THEN TopLeftChild := SELF.elderChild ELSE TopLeftChild := SELF.youngerChild; {$IFC fTrace}EP;{$ENDC} END; {$S SgDRWres} {$S SgABCini} END; {$S SgDRWres} {$S SgABCini}