Created
March 4, 2011 02:46
-
-
Save nf/854084 to your computer and use it in GitHub Desktop.
MacPaint Pascal Source
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
PROGRAM MacPaint; | |
{ BitMap Painting Program by Bill Atkinson } | |
{$D- } | |
{$R- } | |
{$X- } | |
USES {$U obj:HeapZone } HeapZone, | |
{$U obj:QuickDraw } QuickDraw, | |
{$U obj:MacFMgr } Fonts, | |
{$U obj:GrafUtil } GrafUtil, | |
{$U obj:MacEMgr } Events, | |
{$U obj:MacWMgr } Windows, | |
{$U obj:MacDskMgr } DeskMgr, | |
{$U obj:TextEdit } TextEdit, | |
{$U obj:MacDMgr } Dialogs, | |
{$U obj:MacRMgr } Resources, | |
{$U obj:MacSMgr } ScrapMgr, | |
{$U obj:MacMMgr } Menus, | |
{$U obj:MacCMgr } Controls, | |
{$U obj:StdFile } StdFile, | |
{$U Obj:MacPrint } MacPrint; | |
CONST paintFont = 249; | |
minDiskSpace = 16384; | |
firstPat = 0; | |
lastPat = 37; | |
corner = 18; { diameter of curvature for roundRects } | |
shiftCode = 63; | |
optionCode = 61; | |
featureCode = 48; | |
alphaCode = 62; | |
bsCode = 52; | |
enterCode = 51; | |
undoCode = 53; | |
tabCode = 55; | |
printMsg = 1; | |
endOfFile = -39; | |
fileExists = -48; | |
appleMenu = 1; | |
fileMenu = 2; | |
newItem = 1; | |
openItem = 2; | |
closeItem = 3; | |
saveItem = 4; | |
saveAsItem = 5; | |
revertItem = 6; | |
prDraftItem = 7; | |
prFinalItem = 8; | |
prCatItem = 9; | |
quitItem = 10; | |
editMenu = 3; | |
undoItem = 1; | |
blank0Item = 2; | |
cutItem = 3; | |
copyItem = 4; | |
pasteItem = 5; | |
clearItem = 6; | |
blank1Item = 7; | |
invertItem = 8; | |
fillItem = 9; | |
edgesItem = 10; | |
hFlipItem = 11; | |
vFlipItem = 12; | |
rotateItem = 13; | |
aidsMenu = 4; | |
gridItem = 1; | |
fatItem = 2; | |
pageItem = 3; | |
patEdItem = 4; | |
brushItem = 5; | |
symItem = 6; | |
introItem = 7; | |
shortItem = 8; | |
fontMenu = 5; | |
firstFont = 1; | |
sizeMenu = 6; | |
firstSize = 1; | |
lastSize = 9; | |
styleMenu = 7; | |
plainItem = 1; | |
boldItem = 2; | |
italicItem = 3; | |
underItem = 4; | |
outlineItem = 5; | |
shadowItem = 6; | |
blank2Item = 7; | |
leftItem = 8; | |
centerItem = 9; | |
rightItem = 10; | |
firstMenu = appleMenu; | |
lastMenu = styleMenu; | |
docWidth = 576; | |
docHeight = 720; | |
docRow = 72; | |
bandHeight = 48; | |
bandCount = 15; | |
patLeft = 77; { pattern rectangle } | |
patRight = 500; | |
patTop = 300; | |
patBottom = 335; | |
patMid = 317; | |
patSpace = 20; | |
patRow = 19; { how many patterns each row } | |
patStart = 120; { patRight - patRow*patSpace } | |
lineLeft = 15; { line attributes rectangle } | |
lineRight = 68; | |
lineTop = 258; | |
lineBottom = 335; | |
lineMid = 40; { (lineLeft + lineRight) DIV 2 } | |
toolLeft = 15; { tool rectangle } | |
toolRight = 68; | |
toolTop = 28; | |
toolBottom = 249; | |
toolMid = 41; { (toolLeft + toolRight) DIV 2 } | |
toolSpace = 22; | |
lassoTool = 0; | |
selectTool = 1; | |
grabberTool = 2; | |
textTool = 3; | |
fillTool = 4; | |
sprayTool = 5; | |
brushTool = 6; | |
pencilTool = 7; | |
lineTool = 8; | |
eraseTool = 9; | |
rectTool = 11; | |
closeDlog = 2001; | |
quitDlog = 2002; | |
patEdDlog = 2003; | |
brushDlog = 2004; | |
symDlog = 2005; | |
paintDlog = 2006; | |
revertAlrt = 2101; | |
diskAlrt = 2102; | |
wFullAlrt = 2103; | |
wProtAlrt = 2104; | |
wErrAlrt = 2105; | |
rErrAlrt = 2106; | |
rScrapAlrt = 2107; | |
wScrapAlrt = 2108; | |
workSpaceAlrt = 2109; | |
memFullAlrt = 2110; | |
fileLockAlrt = 2111; | |
notPntgAlrt = 2112; | |
bigScrapAlrt = 2113; | |
notRoomAlrt = 2114; | |
oldPrAlrt = 2115; | |
titleString = 2201; | |
fontCmdString = 2202; | |
headerString = 2203; | |
untitledString = 2204; | |
rescueString = 2205; | |
saveString = 2206; | |
patListID = 0; { use system patlist } | |
introPic = 2400; | |
shortPic = 2401; | |
okBtn = 2501; | |
cancelBtn = 2502; | |
buttonCorner = 8; { diameter for button roundRects } | |
maxLines = 20; { how many lines of type-in text } | |
TYPE Str63 = String[63]; | |
DiskBlock = ARRAY[0..255] OF INTEGER; | |
ShapeCode = (rectShape,rRectShape,ovalShape); | |
Longs24 = ARRAY[1..24] OF LongInt; | |
EntryPtr = ^QueueEntry; { for mask stuff } | |
QueueEntry = RECORD | |
addr: LongInt; | |
bump: INTEGER; { +2 or -2 for right or left } | |
twoH: INTEGER; { 2 times horiz word coord } | |
mask: INTEGER; | |
END; | |
VAR heapJam: BOOLEAN; | |
tempWord: INTEGER; | |
tempLong: LongInt; | |
finderMsg: INTEGER; | |
active: BOOLEAN; | |
ornFlag: BOOLEAN; | |
scrnFlag: BOOLEAN; { TRUE when screen in altbuf } | |
quitFlag: BOOLEAN; | |
theEvent: EventRecord; | |
okPrint: BOOLEAN; | |
workFrom,workTo: INTEGER; { file refNums of working files } | |
rescueFlag: BOOLEAN; | |
docName: Str63; | |
docDrive: INTEGER; | |
docVersion: INTEGER; | |
workDrive: INTEGER; | |
workSize: LongInt; { current size of workFrom file } | |
scrapFile: INTEGER; | |
scrapByte: LongInt; | |
docDirty: BOOLEAN; | |
workDirty: BOOLEAN; | |
windOpen: BOOLEAN; | |
heapTop: LongInt; | |
myWind: WindowRecord; | |
deskWind: WindowRecord; | |
okButton,cancelButton: ControlHandle; | |
theKey: CHAR; | |
shiftFlag: BOOLEAN; | |
featureFlag: BOOLEAN; | |
optionFlag: BOOLEAN; | |
hiResFlag: BOOLEAN; | |
theMenu: INTEGER; | |
theItem: INTEGER; | |
textFlag: BOOLEAN; | |
textLoc: Point; | |
textLeft: INTEGER; | |
caretLoc: Point; | |
caretState: BOOLEAN; | |
nextCaretTime: LongInt; | |
textLines: INTEGER; | |
textHandles: ARRAY[1..maxLines] OF StringHandle; | |
prevSizeChar: CHAR; | |
nextSizeChar: CHAR; | |
clickTime: LongInt; | |
clickCount: INTEGER; | |
clickLoc: Point; | |
killDouble: BOOLEAN; | |
skipDouble: BOOLEAN; | |
myMenus: ARRAY[firstMenu..lastMenu] OF MenuHandle; | |
patterns: ARRAY[firstPat..lastPat] OF Pattern; | |
lineSize: INTEGER; | |
halfLineSize: INTEGER; | |
borderFlag: BOOLEAN; | |
thePat: Pattern; | |
thePatIndex: INTEGER; | |
gridOn: BOOLEAN; { is the grid requested ? } | |
toolGrid: BOOLEAN; { does the current tool grid ? } | |
toolCursor: Cursor; | |
cursorFlag: BOOLEAN; { true for new cursor shape } | |
inWindow: BOOLEAN; | |
inSel: BOOLEAN; | |
fatScroll: BOOLEAN; | |
txScrapHndl: Handle; | |
txScrapSize: LongInt; | |
txMinWidth: INTEGER; | |
txMinHeight: INTEGER; | |
txMaxCount: INTEGER; | |
theFont: INTEGER; | |
lastFont: INTEGER; | |
theFontID: INTEGER; | |
fontSizes: ARRAY[firstSize..lastSize] OF INTEGER; | |
theFontSize: INTEGER; | |
txJustItem: INTEGER; | |
textJust: INTEGER; | |
info: FontInfo; | |
zeroRect: Rect; | |
pageRect: Rect; | |
docRect: Rect; | |
patRect: Rect; | |
fillSample: Rect; | |
lineRect: Rect; | |
toolRect: Rect; | |
whiteFlag: BOOLEAN; | |
acceptFlag: BOOLEAN; | |
selFlag: BOOLEAN; | |
selRect: Rect; | |
pivot: Point; | |
edgeFlag: BOOLEAN; { true if edges in altBits } | |
lassoBlack: BOOLEAN; | |
maskFlag: BOOLEAN; { true if mask in maskBits } | |
maskBits: BitMap; | |
maskHandle: Handle; | |
maskPaste: BOOLEAN; | |
oldWhiteFlag: BOOLEAN; | |
oldAcceptFlag: BOOLEAN; | |
oldSelFlag: BOOLEAN; | |
oldSelRect: Rect; | |
oldPivot: Point; | |
oldMaskFlag: BOOLEAN; | |
oldLassoBlack: BOOLEAN; | |
selIndex: INTEGER; | |
theTool: INTEGER; | |
prevTool: INTEGER; | |
theBrush: INTEGER; | |
hSymFlag: BOOLEAN; | |
vSymFlag: BOOLEAN; | |
hvSymFlag: BOOLEAN; | |
vhSymFlag: BOOLEAN; | |
symByte: QDByte; | |
fatFlag: BOOLEAN; | |
fatBits: BitMap; | |
fatBuf: ARRAY[0..31,0..1] OF LongInt; | |
fatCenter: Point; | |
docBits: BitMap; | |
mainBits: BitMap; | |
mainBuf: ARRAY[0..239,0..12] OF LongInt; | |
altBits: BitMap; | |
altBuf: ARRAY[0..239,0..12] OF LongInt; | |
scrnPtr: QDPtr; | |
myPinRect: Rect; | |
hConstrain: BOOLEAN; { used by HVConstrain } | |
vConstrain: BOOLEAN; { used by HVConstrain } | |
ptConstrain: Point; { used by HVConstrain } | |
rwShftDh: INTEGER; { inputs to ReadWrite } | |
rwShftDv: INTEGER; | |
rwResult: INTEGER; { IO result from ReadWrite } | |
patEdPt: Point; | |
whichMenu: INTEGER; { for EnableOne } | |
PROCEDURE EjectReset; EXTERNAL; | |
FUNCTION PixelTrue(h,v: INTEGER; bits: BitMap): BOOLEAN; EXTERNAL; | |
PROCEDURE MapCursor(tool,lineSize,brush: INTEGER; dstPtr: QDPtr); EXTERNAL; | |
FUNCTION Monkey: BOOLEAN; EXTERNAL; | |
PROCEDURE Stretch2x(srcPtr,dstPtr: QDPtr); EXTERNAL; | |
PROCEDURE MySetItemStyle(menu: menuHandle; item: INTEGER; | |
txFace: INTEGER); EXTERNAL; | |
PROCEDURE MyGetItem(menu: menuHandle; item: INTEGER; | |
VAR itemString: Str63); EXTERNAL; | |
PROCEDURE MoreMasters; EXTERNAL; | |
PROCEDURE ExitToShell; EXTERNAL; | |
FUNCTION Trunc8(i: INTEGER): INTEGER; EXTERNAL; | |
FUNCTION GetDoubleTime: LONGINT; EXTERNAL; | |
FUNCTION GetCaretTime: LONGINT; EXTERNAL; | |
PROCEDURE SystemBeep(duration: INTEGER); EXTERNAL; | |
PROCEDURE Moov(dh,dv: INTEGER); EXTERNAL; | |
FUNCTION MapSym(hSym,vSym,hvSym,vhSym: BOOLEAN): QDByte; EXTERNAL; | |
FUNCTION StackPtr: LongInt; EXTERNAL; | |
PROCEDURE ShieldCursor(shieldRect: Rect; offset: Point); EXTERNAL; | |
FUNCTION WorstStack: LongInt; EXTERNAL; | |
FUNCTION EqualString(str1,str2: Str255): BOOLEAN; EXTERNAL; | |
PROCEDURE ExpandPat(pat: Pattern; VAR exPat: Longs24; | |
hShift: INTEGER); EXTERNAL; | |
PROCEDURE DrawBrush(brush: Bits16; exPat: Longs24; | |
hCenter,vCenter: INTEGER; | |
dstBits: BitMap; clip: Rect; orMode: BOOLEAN); EXTERNAL; | |
FUNCTION NearPt(pt1,pt2: Point; tol: INTEGER): BOOLEAN; EXTERNAL; | |
PROCEDURE HToneRow(thisRow,nextRow: QDPtr; | |
dstBits: BitMap; | |
hStart,vStart,hSize: INTEGER; | |
whiteLevel,blackLevel: INTEGER; | |
threshold: BOOLEAN); EXTERNAL; | |
PROCEDURE SampleBits(src,dst: QDPtr); EXTERNAL; | |
PROCEDURE DeleteChar(str: Str255); EXTERNAL; | |
PROCEDURE AppendChar(ch: CHAR; str: str255); EXTERNAL; | |
PROCEDURE WindPaint(flag: BOOLEAN); EXTERNAL; | |
PROCEDURE TrimBBox(dstBuf: QDPtr; VAR dstRect: Rect); EXTERNAL; | |
PROCEDURE GridMouse(hMask,vMask,hOffset,vOffset: INTEGER); EXTERNAL; | |
PROCEDURE UnloadSeg(segPtr: QDPtr); EXTERNAL; | |
PROCEDURE GetSelPat(patIndex: INTEGER; VAR pat: Pattern); EXTERNAL; | |
PROCEDURE CalcEdges(srcBuf,dstBuf: QDPtr; topVert,height: INTEGER; | |
lassoBlack: BOOLEAN); EXTERNAL; | |
PROCEDURE AntsToScrn(edgeBuf,srcnPtr: QDPtr; | |
maskRect: Rect; patIndex: INTEGER); EXTERNAL; | |
PROCEDURE InvertChunk(dstAddr: LongInt; wordWd,height: INTEGER); EXTERNAL; | |
PROCEDURE PackBits(VAR srcPtr,dstPtr: QDPtr; srcBytes: INTEGER); EXTERNAL; | |
PROCEDURE UnpackBits(VAR srcPtr,dstPtr: QDPtr; dstBytes: INTEGER); EXTERNAL; | |
PROCEDURE InvertBuf(bufPtr: QDPtr); EXTERNAL; | |
PROCEDURE ZeroBuf(bufPtr: QDPtr); EXTERNAL; | |
PROCEDURE ZeroFat(fatPtr: QDPtr); EXTERNAL; | |
PROCEDURE ZeroMem(bandPtr: QDPtr; byteCount: INTEGER); EXTERNAL; | |
PROCEDURE CopyLongs(srcPtr,dstPtr: QDPtr; longCount: INTEGER); EXTERNAL; | |
FUNCTION EqualLongs(srcPtr,dstPtr: QDPtr; longCount: INTEGER): BOOLEAN; EXTERNAL; | |
PROCEDURE BufToBuf(srcPtr,dstPtr: QDPtr); EXTERNAL; | |
PROCEDURE BufOrBuf(srcPtr,dstPtr: QDPtr); EXTERNAL; | |
PROCEDURE BufXorBuf(srcPtr,dstPtr: QDPtr); EXTERNAL; | |
PROCEDURE BufAndBuf(srcPtr,dstPtr: QDPtr); EXTERNAL; | |
PROCEDURE ScrnToBuf(scrnPtr,bufPtr: QDPtr); EXTERNAL; | |
PROCEDURE BufToScrn(bufPtr,scrnPtr: QDPtr; top,bottom: INTEGER); EXTERNAL; | |
PROCEDURE SwapBuf(srcBuf,dstBuf: QDPtr); EXTERNAL; | |
PROCEDURE FatToScrn(fatPtr,scrnPtr: QDPtr); EXTERNAL; | |
PROCEDURE VFlipBuf(srcBuf,dstBuf: QDPtr); EXTERNAL; | |
PROCEDURE HFlipBuf(srcBuf,dstBuf: QDPtr; top,bot: INTEGER); EXTERNAL; | |
PROCEDURE RotBuf(srcBuf,dstBuf: QDPtr; height: INTEGER); EXTERNAL; | |
FUNCTION GetRgnMax: INTEGER; EXTERNAL; | |
FUNCTION VertSeed(mask,data: INTEGER): INTEGER; EXTERNAL; | |
PROCEDURE MaskIt(dstStart,dstLimit,srcOffset: LongInt; | |
hLim,row: INTEGER; | |
readPtr,donePtr: EntryPtr; | |
VAR writePtr: EntryPtr); EXTERNAL; | |
{ I/O routines } | |
PROCEDURE FlushVol(driveNum: INTEGER); EXTERNAL; | |
FUNCTION FinderDoc(VAR drive,version: INTEGER; strPtr: QDPtr): INTEGER; EXTERNAL; | |
PROCEDURE SetDocType(drive,version: INTEGER; docName: Str63); EXTERNAL; | |
FUNCTION CheckPntg(drive,version: INTEGER; docName: Str63): BOOLEAN; EXTERNAL; | |
PROCEDURE FileInfo(drive,version: INTEGER; fName: Str63; | |
VAR fileDate,fileSize: LongInt); EXTERNAL; | |
FUNCTION DiskSpace(drive: INTEGER): LongInt; EXTERNAL; | |
FUNCTION CountFiles(drive: INTEGER; VAR str: Str63): INTEGER; EXTERNAL; | |
FUNCTION NextFile(drive: INTEGER; index: INTEGER; fileType: ResType; | |
VAR str: Str63; VAR version: INTEGER): BOOLEAN; EXTERNAL; | |
FUNCTION CreateFile(drive,version: INTEGER; fileName: Str63): INTEGER; EXTERNAL; | |
FUNCTION DeleteFile(drive,version: INTEGER; fileName: Str63): INTEGER; EXTERNAL; | |
FUNCTION OpenFile(drive,version: INTEGER; fileName: Str63; | |
ownBuf: QDPtr; VAR refNum: INTEGER): INTEGER; EXTERNAL; | |
FUNCTION CloseFile(refNum: INTEGER): INTEGER; EXTERNAL; | |
FUNCTION SetEOF(refNum: INTEGER; byteCount: LongInt): INTEGER; EXTERNAL; | |
FUNCTION ReadData(refNum: INTEGER; | |
VAR startByte: LongInt; | |
byteCount: LongInt; | |
bufPtr: QDPtr): INTEGER; EXTERNAL; | |
FUNCTION WriteData(refNum: INTEGER; | |
VAR startByte: LongInt; | |
byteCount: LongInt; | |
bufPtr: QDPtr): INTEGER; EXTERNAL; | |
FUNCTION Min(i,j: INTEGER): INTEGER; EXTERNAL; | |
FUNCTION Max(i,j: INTEGER): INTEGER; EXTERNAL; | |
FUNCTION PinWord(i,min,max: INTEGER): INTEGER; EXTERNAL; | |
PROCEDURE PinPt(VAR pt: Point; pinRect: Rect); EXTERNAL; | |
PROCEDURE SwapBool(VAR a,b: BOOLEAN); EXTERNAL; | |
PROCEDURE SwapWord(VAR a,b: INTEGER); EXTERNAL; | |
PROCEDURE SwapPt(VAR a,b: Point); EXTERNAL; | |
PROCEDURE SwapRect(VAR a,b: Rect); EXTERNAL; | |
{$S } | |
FUNCTION KeyIsDown(keyCode: INTEGER): BOOLEAN; | |
VAR keys: KeyMap; | |
BEGIN | |
GetKeys(keys); | |
KeyIsDown := BitTst(@keys,keyCode); | |
END; | |
{$S } | |
PROCEDURE GetFatMouse(VAR pt: Point); | |
BEGIN | |
GetMouse(pt); | |
IF fatFlag THEN | |
BEGIN | |
IF theTool <> eraseTool THEN | |
BEGIN | |
pt.h := pt.h - 4; { center on pixel } | |
pt.v := pt.v - 4; | |
END; | |
MapPt(pt,myWind.port.portRect,fatBits.bounds); | |
END; | |
END; | |
{$S } | |
PROCEDURE GridPoint(VAR pt: Point); | |
BEGIN | |
IF gridOn AND toolGrid THEN | |
BEGIN | |
pt.h := Trunc8(pt.h + 4); | |
pt.v := Trunc8(pt.v + 4); | |
END; | |
END; | |
{$S } | |
PROCEDURE GetGridMouse(VAR pt: Point); | |
BEGIN | |
GetFatMouse(pt); | |
GridPoint(pt); | |
END; | |
{$S } | |
PROCEDURE PinGridMouse(VAR pt: Point); | |
BEGIN | |
GetGridMouse(pt); | |
PinPt(pt,myPinRect); | |
END; | |
{$S } | |
PROCEDURE InitConstrain(startPt: Point); | |
BEGIN | |
hConstrain := TRUE; | |
vConstrain := TRUE; | |
ptConstrain := startPt; | |
END; | |
{$S } | |
PROCEDURE HVConstrain(VAR newPt: Point); | |
VAR dh,dv: INTEGER; | |
BEGIN | |
IF shiftFlag THEN { constrain to horiz or vert } | |
BEGIN | |
IF hConstrain AND vConstrain THEN { still chosing direction } | |
BEGIN | |
dh := ABS(newPt.h-ptConstrain.h); | |
dv := ABS(newPt.v-ptConstrain.v); | |
IF (dh > dv) AND (dh > 1) THEN vConstrain := FALSE; | |
IF (dv > dh) AND (dv > 1) THEN hConstrain := FALSE; | |
END; | |
IF hConstrain THEN newPt.v := ptConstrain.v; { horiz } | |
IF vConstrain THEN newPt.h := ptConstrain.h; { vert } | |
END; | |
END; | |
{$S } | |
PROCEDURE CursorNormal; | |
BEGIN | |
InitCursor; { arrow, not hidden } | |
GridMouse(-1,-1,0,0); { no grid } | |
END; | |
{$S } | |
PROCEDURE BusyCursor; | |
TYPE crsrPtr = ^Cursor; | |
crsrHndl = ^CrsrPtr; | |
VAR hourGlass: crsrHndl; | |
BEGIN | |
GridMouse(-1,-1,0,0); { no grid } | |
cursorFlag := TRUE; | |
hourGlass := Pointer(ORD(GetCursor(4))); | |
SetCursor(hourGlass^^); | |
END; | |
{$S } | |
PROCEDURE SetPinRect(size: INTEGER); | |
VAR halfSize: INTEGER; | |
BEGIN | |
halfSize := size DIV 2; | |
myPinRect := myWind.port.portRect; | |
IF fatFlag THEN myPinRect := fatBits.bounds; | |
WITH myPinRect DO | |
BEGIN | |
left := left + halfSize; | |
top := top + halfSize; | |
right := right - size + halfSize; | |
bottom := bottom - size + halfSize; | |
IF gridOn AND toolGrid THEN | |
BEGIN | |
left := Trunc8(left + 7); | |
top := Trunc8(top + 7); | |
right := Trunc8(right); | |
bottom := Trunc8(bottom); | |
END; | |
END; | |
END; | |
{$S } | |
PROCEDURE SetLineSize(size: INTEGER); | |
BEGIN | |
lineSize := size; | |
halfLineSize := lineSize DIV 2; | |
SetPinRect(size); | |
END; | |
{$S } | |
PROCEDURE JamLine; | |
BEGIN | |
PenNormal; | |
PenSize(lineSize,lineSize); | |
IF optionFlag THEN PenPat(thePat); | |
IF featureFlag THEN PenMode(patOr); | |
END; | |
{$S } | |
PROCEDURE JamFill; | |
BEGIN | |
PenNormal; | |
PenPat(thePat); | |
IF featureFlag THEN PenMode(patOr); | |
END; | |
{$S } | |
PROCEDURE SetSelRect(r: Rect; newPivot: BOOLEAN); | |
VAR center: Point; | |
dstRect: Rect; | |
bool: BOOLEAN; | |
BEGIN | |
dstRect := myWind.port.portRect; | |
IF fatFlag THEN dstRect := fatBits.bounds; | |
bool := SectRect(r,dstRect,selRect); | |
center.h := (selRect.left + selRect.right) DIV 2; | |
center.v := (selRect.top + selRect.bottom) DIV 2; | |
IF newPivot THEN pivot := center; | |
IF NOT fatFlag THEN fatCenter := center; | |
END; | |
{$S } | |
PROCEDURE BandToScrn(srcBits: BitMap; top,bottom: INTEGER); | |
{ top and bottom are in local coords of document } | |
VAR shieldRect: Rect; | |
BEGIN | |
IF NOT windOpen THEN EXIT(BandToScrn); | |
IF fatFlag THEN | |
BEGIN | |
CopyBits(srcBits,fatBits,fatBits.bounds,fatBits.bounds,srcCopy,Nil); | |
FatToScrn(@fatBuf,scrnPtr); | |
END | |
ELSE | |
BEGIN | |
shieldRect := myWind.port.portRect; | |
shieldRect.top := top; | |
shieldRect.bottom := bottom; | |
{ calc buffer relative coords for BufToScrn } | |
top := top - myWind.port.portRect.top; | |
bottom := bottom - myWind.port.portRect.top; | |
IF top < 0 THEN top := 0; | |
IF bottom > 240 THEN bottom := 240; | |
ShieldCursor(shieldRect,myWind.port.portBits.bounds.topLeft); | |
BufToScrn(Pointer(ORD(srcBits.baseAddr)),scrnPtr,top,bottom); | |
ShowCursor; | |
END; | |
END; | |
{$S } | |
PROCEDURE BitsToScrn(srcBits: BitMap); | |
BEGIN | |
BandToScrn(srcBits, myWind.port.portRect.top, | |
myWind.port.portRect.bottom); | |
END; | |
{$S } | |
PROCEDURE AltToScrn; | |
VAR savePort: GrafPtr; | |
BEGIN | |
GetPort(savePort); | |
SetPort(@myWind); | |
SetPortBits(docBits); | |
BitsToScrn(altBits); | |
SetPort(savePort); | |
END; | |
{$S } | |
PROCEDURE ScrnToAlt; | |
BEGIN | |
IF fatFlag | |
THEN CopyBits(fatBits,altBits,fatBits.bounds,fatBits.bounds,srcCopy,Nil) | |
ELSE ScrnToBuf(scrnPtr,altBits.baseAddr); | |
END; | |
{$S } | |
PROCEDURE MaskToAlt(srcRect,dstRect: Rect; mode: INTEGER); | |
{ share common code } | |
BEGIN | |
maskBits.baseAddr := Pointer(ORD(maskHandle^)); | |
CopyBits(maskBits,altBits,srcRect,dstRect,mode,Nil); | |
END; | |
{$S } | |
PROCEDURE MainToAlt; | |
VAR saveBits: BitMap; | |
BEGIN | |
BufToBuf(@mainBuf,@altBuf); | |
scrnFlag := FALSE; | |
IF whiteFlag THEN | |
BEGIN | |
IF selFlag THEN | |
BEGIN | |
saveBits := thePort^.portBits; | |
SetPortBits(altBits); | |
EraseRect(oldSelRect); | |
SetPortBits(saveBits); | |
END; | |
IF maskFlag THEN MaskToAlt(selRect,oldSelRect,srcBic); | |
END; | |
END; | |
{$S } | |
PROCEDURE InvertCaret; | |
VAR savePort: GrafPtr; | |
BEGIN | |
GetPort(savePort); | |
SetPort(@myWind); | |
IF fatFlag THEN SetPortBits(fatBits); | |
PenNormal; | |
PenMode(patXor); | |
MoveTo(caretLoc.h,caretLoc.v-info.ascent); | |
LineTo(caretLoc.h,caretLoc.v+info.descent-1); | |
IF fatFlag THEN FatToScrn(@fatBuf,scrnPtr); | |
SetPortBits(docBits); | |
SetPort(savePort); | |
caretState := NOT caretState; | |
END; | |
{$S } | |
PROCEDURE AcceptEdits; | |
BEGIN | |
BufToBuf(@altBuf,@mainBuf); | |
oldAcceptFlag := acceptFlag; | |
oldWhiteFlag := whiteFlag; | |
oldMaskFlag := maskFlag; | |
oldSelFlag := selFlag; | |
oldSelRect := selRect; | |
oldPivot := pivot; | |
oldLassoBlack := lassoBlack; | |
acceptFlag := FALSE; | |
END; | |
{$S } | |
PROCEDURE ScrollMask(dh,dv: INTEGER); | |
BEGIN | |
HLock(maskHandle); | |
maskBits.baseAddr := Pointer(ORD(maskHandle^)); | |
SetPortBits(maskBits); | |
ScrollRect(maskBits.bounds,dh,dv,myWind.port.clipRgn); | |
ClipRect(pageRect); | |
SetPortBits(docBits); | |
HUnlock(maskHandle); | |
END; | |
{$S } | |
FUNCTION AllocMask: BOOLEAN; | |
BEGIN | |
maskHandle := NewHandle(12480); | |
IF maskHandle = Nil THEN | |
BEGIN | |
AllocMask := FALSE; | |
heapJam := TRUE; | |
END | |
ELSE | |
BEGIN | |
AllocMask := TRUE; | |
hLock(maskHandle); | |
maskBits := altBits; | |
maskBits.baseAddr := Pointer(ORD(maskHandle^)); | |
END; | |
END; | |
{$S } | |
PROCEDURE KillMask; | |
BEGIN | |
IF maskHandle <> Nil THEN | |
BEGIN | |
DisposHandle(maskHandle); | |
maskHandle := Nil; | |
END; | |
maskFlag := FALSE; | |
oldMaskFlag := FALSE; { can't undo it } | |
END; | |
{$S } | |
PROCEDURE KillStuff; | |
VAR line: INTEGER; | |
BEGIN | |
IF txScrapHndl <> Nil THEN | |
BEGIN | |
DisposHandle(txScrapHndl); | |
txScrapHndl := Nil; | |
txScrapSize := 0; | |
END; | |
FOR line := 1 TO textLines DO | |
DisposHandle(Pointer(ORD(textHandles[line]))); | |
textLines := 0; | |
textFlag := FALSE; | |
KillMask; | |
selFlag := FALSE; | |
AltToScrn; { hide selection } | |
END; | |
{$S } | |
PROCEDURE Undo; | |
BEGIN | |
IF textFlag OR (txScrapHndl <> Nil) THEN KillStuff; | |
SwapBuf(@mainBuf,@altBuf); | |
SwapBool(acceptFlag,oldAcceptFlag); | |
SwapBool(whiteFlag,oldWhiteFlag); | |
SwapBool(maskFlag,oldMaskFlag); | |
SwapBool(lassoBlack,oldLassoBlack); | |
SwapBool(selFlag,oldSelFlag); | |
SwapRect(selRect,oldSelRect); | |
SwapPt(pivot,oldPivot); | |
IF maskFlag OR oldMaskFlag THEN | |
BEGIN | |
IF NOT EqualRect(selRect,oldSelRect) | |
THEN ScrollMask(selRect.left-oldSelRect.left,selRect.top-oldSelRect.top); | |
END; | |
AltToScrn; | |
END; | |
{$S } | |
PROCEDURE Constrain(startPt: Point; VAR newPt: Point; hvOk: BOOLEAN); | |
VAR dh,dv,absDh,absDv,delta: INTEGER; | |
oldPt: Point; | |
BEGIN | |
oldPt := newPt; | |
dh := newPt.h - startPt.h; | |
dv := newPt.v - startPt.v; | |
absDh := ABS(dh); | |
absDv := ABS(dv); | |
delta := Min(absDh,absDv); | |
IF dh < 0 THEN dh := -delta ELSE dh := delta; | |
IF dv < 0 THEN dv := -delta ELSE dv := delta; | |
newPt.h := startPt.h + dh; | |
newPt.v := startPt.v + dv; | |
IF hvOK THEN | |
BEGIN | |
IF absDh > 2*absDv THEN | |
BEGIN | |
newPt.h := oldPt.h; | |
newPt.v := startPt.v; { horizontal } | |
END; | |
IF absDv > 2*absDh THEN | |
BEGIN | |
newPt.h := startPt.h; { vertical } | |
newPt.v := oldPt.v; | |
END; | |
END; | |
END; | |
{$S } | |
PROCEDURE CreateShape(shape: ShapeCode; filled: BOOLEAN); | |
VAR startPt,newPt,oldPt: Point; | |
dstRect: Rect; | |
BEGIN | |
JamLine; | |
PinGridMouse(startPt); | |
dstRect.topLeft := startPt; | |
dstRect.botRight := startPt; | |
oldPt.h := 1000; { fake out first time } | |
WHILE StillDown DO | |
BEGIN | |
PinGridMouse(newPt); | |
IF shiftFlag THEN Constrain(startPt,newPt,FALSE); { drag square } | |
IF NOT EqualPt(newPt,oldPt) THEN | |
BEGIN | |
MainToAlt; | |
Pt2Rect(startPt,newPt,dstRect); | |
WITH dstRect DO | |
BEGIN | |
left := left - halfLineSize; | |
top := top - halfLineSize; | |
right := right + lineSize - halfLineSize; | |
bottom := bottom + lineSize - halfLineSize; | |
END; | |
SetPortBits(altBits); | |
IF filled THEN | |
BEGIN | |
JamFill; | |
CASE shape OF | |
rectShape: PaintRect(dstRect); | |
rRectShape: PaintRoundRect(dstRect,corner,corner); | |
ovalShape: PaintOval(dstRect); | |
END; | |
END; | |
IF borderFlag OR NOT filled THEN | |
BEGIN | |
JamLine; | |
CASE shape OF | |
rectShape: FrameRect(dstRect); | |
rRectShape: FrameRoundRect(dstRect,corner,corner); | |
ovalShape: FrameOval(dstRect); | |
END; | |
END; | |
AltToScrn; { returns to docBits } | |
oldPt:=newPt; | |
END; | |
END; | |
END; | |
{$S SegPrint } | |
FUNCTION PrintRect(srcBits: BitMap; srcRect: Rect): BOOLEAN; | |
VAR event: EventRecord; | |
saveOrigin: Point; | |
theControl: ControlHandle; | |
BEGIN | |
PrintRect := TRUE; | |
PrCtlCall(iPrBitsCtl,ORD(@srcBits),ORD(@srcRect),lPaintBits+2*ORD(hiResFlag)); | |
{ check for cancel button } | |
IF GetNextEvent(everyEvent,event) AND (event.what = mouseDown) THEN | |
BEGIN | |
saveOrigin := myWind.port.portRect.topLeft; | |
SetOrigin(0,0); | |
GlobalToLocal(event.where); | |
IF FindControl(event.where,@myWind,theControl) = 0 THEN SystemBeep(8) | |
ELSE IF TrackControl(theControl,event.where,Nil) <> 0 THEN | |
BEGIN | |
PrintRect := FALSE; | |
SetOrigin(saveOrigin.h,saveOrigin.v); | |
EXIT(PrintRect); | |
END; | |
SetOrigin(saveOrigin.h,saveOrigin.v); | |
END; | |
END; | |
{$S } | |
PROCEDURE PatchText(count: INTEGER; textPtr: QDPtr; numer,denom: Point); | |
{ draw text in chunks to cut stack needs, preventing croak } | |
VAR myCount: INTEGER; | |
BEGIN | |
WHILE count > 0 DO | |
BEGIN | |
myCount := Min(count,txMaxCount); | |
StdText(myCount,textPtr,numer,denom); | |
textPtr := Pointer(ORD(textPtr) + myCount); | |
count := count - myCount; | |
END; | |
END; | |
{$S } | |
PROCEDURE DrawTxScrap(dstRect: Rect); | |
VAR i: INTEGER; | |
myProcs: QDProcs; | |
BEGIN | |
KillMask; { not enough room in heap for mask and font } | |
ClipRect(dstRect); | |
EraseRect(dstRect); | |
InsetRect(dstRect,2,0); | |
dstRect.right := Max(dstRect.right,dstRect.left + txMinWidth); | |
dstRect.bottom := Max(dstRect.bottom,dstRect.top + txMinHeight); | |
SetStdProcs(myProcs); | |
thePort^.grafProcs := @myProcs; | |
myProcs.textProc := @PatchText; | |
i := CharWidth('A'); { swap in font } | |
HLock(txScrapHndl); | |
TextBox(txScrapHndl^,txScrapSize,dstRect,textJust); | |
HUnlock(txScrapHndl); | |
ClipRect(pageRect); | |
thePort^.grafProcs := Nil; { restore to normal } | |
END; | |
{$S } | |
PROCEDURE UpdateText; | |
LABEL 9; | |
VAR line,horiz,vert,width,lineHeight: INTEGER; | |
h: StringHandle; | |
dstRect: Rect; | |
savePort: GrafPtr; | |
i: INTEGER; | |
myProcs: QDProcs; | |
BEGIN | |
GetPort(savePort); | |
SetPort(@myWind); | |
IF txScrapHndl <> Nil THEN { update text scrap } | |
BEGIN | |
SetPortBits(altBits); | |
DrawTxScrap(selRect); | |
AltToScrn; | |
GOTO 9; | |
END; | |
IF (NOT textFlag) OR (textLines < 1) THEN GOTO 9; | |
KillMask; { not enough room in heap for mask and font } | |
SetPortBits(altBits); | |
MainToAlt; | |
lineHeight := info.ascent + info.descent + info.leading; | |
IF gridOn THEN lineHeight := Trunc8(lineHeight + 7); | |
SetStdProcs(myProcs); | |
thePort^.grafProcs := @myProcs; | |
myProcs.textProc := @PatchText; | |
vert := textLoc.v; | |
FOR line := 1 TO textLines DO | |
BEGIN | |
horiz := textLeft; | |
IF line = 1 THEN horiz := textLoc.h; | |
h := textHandles[line]; | |
IF Length(h^^) > 0 THEN | |
BEGIN | |
i := CharWidth('A'); { swap in font } | |
HLock(Pointer(ORD(h))); | |
width := StringWidth(h^^); | |
IF BitTst(@thePort^.txFace,6) THEN width := width + 5; | |
{ IF italic IN thePort^.txFace THEN width := width + 5; } | |
IF textJust = teFillRight THEN horiz := horiz - width; | |
IF textJust = teFillCenter THEN horiz := horiz - (width DIV 2); | |
MoveTo(horiz,vert); | |
WITH dstRect DO | |
BEGIN | |
left := horiz - 1; | |
right := horiz + width + 1; | |
top := vert - info.ascent; | |
bottom := vert + info.descent; | |
horiz := right - 1; | |
END; | |
EraseRect(dstRect); | |
DrawString(h^^); | |
HUnlock(Pointer(ORD(h))); | |
END; | |
vert := vert + lineHeight; | |
END; | |
thePort^.grafProcs := Nil; { restore to normal } | |
caretLoc.h := horiz; | |
caretLoc.v := vert - lineHeight; | |
AltToScrn; | |
9: SetPort(savePort); | |
nextCaretTime := 0; { make caret show } | |
END; | |
{$S SegUpdate } | |
PROCEDURE DrawPat; | |
VAR i,h: INTEGER; | |
tempRect: Rect; | |
savePort: GrafPtr; | |
BEGIN | |
GetPort(savePort); | |
SetPort(@deskWind); | |
OffsetRect(patRect,1,1); | |
PaintRect(patRect); | |
OffsetRect(patRect,-1,-1); | |
EraseRect(patRect); | |
FrameRect(patRect); | |
thePat := patterns[thePatIndex]; | |
SetRect(fillSample,patLeft+8,patTop+6,patStart-7,patBottom-6); | |
FrameRect(fillSample); | |
InsetRect(fillSample,1,1); | |
FillRect(fillSample,thePat); | |
SetRect(tempRect,patStart-1,patTop+1,patRight-1,patBottom-1); | |
PaintRect(tempRect); | |
h := patStart; | |
FOR i := 0 TO patRow-1 DO | |
BEGIN | |
tempRect.left := h; | |
h := h + patSpace; | |
tempRect.right := h - 1; | |
tempRect.top := patTop+1; | |
tempRect.bottom := patMid; | |
FillRect(tempRect,patterns[i]); | |
tempRect.top := patMid + 1; | |
tempRect.bottom := patBottom-1; | |
FillRect(tempRect,patterns[i+patRow]); | |
END; | |
SetPort(savePort); | |
END; | |
{$S } | |
FUNCTION MyAlert(whichAlert: INTEGER): INTEGER; | |
BEGIN | |
CursorNormal; { arrow, no grid } | |
MyAlert := Alert(whichAlert,Nil); | |
cursorFlag := TRUE; | |
END; | |
{$S } | |
PROCEDURE BorrowAlt; | |
BEGIN | |
ScrnToBuf(scrnPtr,@altBuf); { stash screen image in alt } | |
scrnFlag := TRUE; { remember what's in alt } | |
END; | |
PROCEDURE UpdateWindow(whichWindow: WindowPtr; okToSmash: BOOLEAN); FORWARD; | |
FUNCTION SaveAlert(whichAlert: INTEGER): INTEGER; | |
BEGIN | |
BorrowAlt; { save screen image for refresh } | |
SaveAlert := MyAlert(whichAlert); | |
UpdateWindow(@myWind,FALSE); | |
MainToAlt; { get rid of saved screen image } | |
END; | |
{$S } | |
FUNCTION WriteError(result: INTEGER; discard: Handle): BOOLEAN; | |
VAR aResult,whichAlert: INTEGER; | |
BEGIN | |
WriteError := FALSE; | |
IF (result <> 0) AND (result <> fileExists) THEN | |
BEGIN | |
whichAlert := wErrAlrt; | |
IF result = -34 THEN whichAlert := wFullAlrt; | |
IF result = -44 THEN whichAlert := wProtAlrt; | |
IF result = -61 THEN whichAlert := fileLockAlrt; | |
IF discard <> Nil THEN DisposHandle(discard); { make room for alert } | |
aResult := MyAlert(whichAlert); | |
WriteError := TRUE; | |
END; | |
END; | |
{$S } | |
FUNCTION ReadError(result: INTEGER; discard: Handle): BOOLEAN; | |
VAR aResult: INTEGER; | |
BEGIN | |
ReadError := FALSE; | |
IF (result <> 0) AND (result <> endOfFile) THEN | |
BEGIN | |
{ alert trouble reading } | |
IF discard <> Nil THEN DisposHandle(discard); { make room for alert } | |
aResult := MyAlert(rErrAlrt); | |
ReadError := TRUE; | |
END; | |
END; | |
{$S } | |
PROCEDURE ReadWrite(srcFile,dstFile: INTEGER; | |
fromMain,toAlt,toShrink,toPrint,newPat: BOOLEAN); | |
{ read and unpack from srcFile, operate on, then pack and write to dstFile } | |
{ srcFile and dstFile should already be opened } | |
{ IF dstFile = 0, then don't write to dstFile } | |
{ IF newPat, then read patterns from srcFile } | |
{ returns rwResult = 0 for SUCCESS } | |
LABEL 9; | |
CONST dstBlocks = 6; { how many blocks in dstbuf } | |
bandSize = 3584; { docRow * bandHeight + 128 } | |
heapSlop = 1024; | |
TYPE Bytes72 = PACKED ARRAY[1..docRow] OF QDByte; | |
VAR dstBuf: ARRAY[1..dstBlocks] OF DiskBlock; | |
bandSlop: PACKED ARRAY[1..128] OF QDByte; { must follow bandbuf ! } | |
bandBuf: ARRAY[0..50] OF Bytes72; | |
bandBits: BitMap; | |
result,band,scanLine: INTEGER; | |
srcByte,dstByte: LongInt; | |
dstDrive: INTEGER; | |
srcPtr,dstPtr,bandPtr: QDPtr; | |
mainRect,altRect: Rect; | |
hitMain,hitAlt: BOOLEAN; | |
shrinkRect: Rect; | |
vert: INTEGER; | |
grow: LongInt; | |
srcSize: LongInt; | |
srcHandle: Handle; | |
srcFirst,srcLast: ^DiskBlock; | |
srcRect,dstRect,erasRect: Rect; | |
srcScan,srcGoal: INTEGER; | |
byteCount: LongInt; | |
saveOrigin: Point; | |
oldPtr: QDPtr; | |
badDoc: BOOLEAN; | |
hiResBits: BitMap; | |
hiResHndl: Handle; | |
hiResPtr: QDPtr; | |
hiResBand: INTEGER; | |
FUNCTION GetScan: BOOLEAN; | |
{ unpack the next scanline, checking for bad data } | |
BEGIN | |
GetScan := TRUE; | |
IF (srcGoal < 0) OR (srcGoal > 719) THEN { blank line } | |
BEGIN | |
ZeroMem(bandPtr,docRow); | |
bandPtr := Pointer(ORD(bandPtr)+docRow); | |
END | |
ELSE WHILE srcScan <= srcGoal DO | |
BEGIN | |
IF NOT badDoc THEN | |
BEGIN | |
oldPtr := bandPtr; | |
UnpackBits(srcPtr,bandPtr,docRow); | |
IF ORD(bandPtr) - ORD(oldPtr) <> docRow THEN | |
BEGIN | |
SystemBeep(8); | |
badDoc := TRUE; | |
bandPtr := oldPtr; | |
END; | |
END; | |
IF badDoc THEN | |
BEGIN | |
ZeroMem(bandPtr,docRow); | |
bandPtr := Pointer(ORD(bandPtr)+docRow); | |
END; | |
IF srcScan < srcGoal THEN bandPtr := @bandBuf[1]; | |
srcScan := srcScan + 1; | |
IF ORD(srcPtr) >= ORD(srcLast) THEN | |
BEGIN | |
srcFirst^ := srcLast^; | |
result := ReadData(srcFile,srcByte,srcSize-512, | |
Pointer(ORD(srcFirst)+512)); | |
IF ReadError(result,srcHandle) THEN | |
BEGIN | |
badDoc := TRUE; | |
GetScan := FALSE; | |
END; | |
srcPtr := Pointer(ORD(srcPtr) - srcSize + 512); | |
END; | |
END; | |
srcGoal := srcGoal + 1; | |
END; | |
BEGIN | |
rwResult := -1; { assume failure } | |
BusyCursor; | |
SetPort(@myWind); | |
okPrint := toPrint; | |
IF toAlt THEN ScrnToAlt; | |
IF toShrink THEN | |
BEGIN | |
FillRect(myWind.port.portRect,ltGray); | |
shrinkRect := myWind.port.portRect; | |
shrinkRect.left := shrinkRect.left + 208 - 96; | |
shrinkRect.right := shrinkRect.left + 192; | |
PenNormal; | |
EraseRect(shrinkRect); | |
InsetRect(shrinkRect,-1,-1); | |
FrameRect(shrinkRect); | |
InsetRect(shrinkRect,1,1); | |
shrinkRect.bottom := shrinkRect.top + bandHeight DIV 3; | |
END; | |
IF toPrint THEN | |
BEGIN | |
{ draw cancel button } | |
saveOrigin := myWind.port.portRect.topLeft; | |
SetOrigin(0,0); | |
ShowControl(cancelButton); | |
SetOrigin(saveOrigin.h,saveOrigin.v); | |
IF hiResFlag THEN { allocate hiResBuf and init hiResBits } | |
BEGIN | |
hiResHndl := NewHandle(3024); { 21 scanlines of 144 bytes each } | |
WITH hiResBits DO | |
BEGIN | |
rowBytes := 144; | |
bounds.left := 0; | |
bounds.top := 0; | |
bounds.right := 1152; | |
bounds.bottom := 16; | |
END; | |
END; | |
END; | |
WITH bandBits DO | |
BEGIN | |
baseAddr := @bandBuf[1]; | |
rowBytes := docRow; | |
bounds.left := 0; | |
bounds.top := 0; | |
bounds.right := docWidth; | |
bounds.bottom := bandHeight; | |
END; | |
dstByte := 0; | |
srcByte := 0; | |
result := ReadData(srcFile,srcByte,512,@dstBuf); { read header } | |
IF ReadError(result,Nil) THEN GOTO 9; | |
IF dstBuf[1,1] < 2 THEN { old format, has no patterns } | |
BEGIN | |
newPat := FALSE; { will install patterns below } | |
dstBuf[1,1] := 2; { new format } | |
END; | |
IF newPat THEN IF NOT EqualLongs(@dstBuf[1,2],@patterns,38*2) THEN | |
BEGIN | |
CopyLongs(@dstBuf[1,2],@patterns,38*2); | |
DrawPat; | |
END; | |
CopyLongs(@patterns,@dstBuf[1,2],38*2); | |
srcSize := BitAnd(MaxMem(grow)-heapSlop,$FFFFFE00); { trunc to mult of 512 } | |
srcHandle := NewHandle(srcSize); | |
HLock(srcHandle); | |
srcFirst := Pointer(ORD(srcHandle^)); | |
srcLast := Pointer(ORD(srcFirst) + srcSize - 512); | |
{ prime srcBuf } | |
result := ReadData(srcFile,srcByte,srcSize,Pointer(ORD(srcFirst))); | |
IF ReadError(result,srcHandle) THEN GOTO 9; | |
srcPtr := Pointer(ORD(srcFirst)); | |
dstPtr := @dstBuf[2]; { put packed bits after header } | |
srcScan := 0; | |
srcGoal := -rwShftDv; | |
ZeroMem(@bandBuf[0],docRow); { clear first fake scan line } | |
bandPtr := @bandBuf[1]; | |
badDoc := FALSE; | |
IF NOT GetScan THEN GOTO 9; { get 1st real scanline into bandBuf[1] } | |
IF NOT GetScan THEN GOTO 9; { get 2nd real scanline into bandBuf[2] } | |
FOR band := 1 to bandCount DO | |
BEGIN | |
bandPtr := @bandBuf[3]; | |
{ read and unpack into bandBuf[3] .. bandBuf[50] } | |
FOR scanLine := 1 TO 48 DO IF NOT GetScan THEN GOTO 9; | |
{ now operate on unpacked band buffer } | |
hitMain := SectRect(mainBits.bounds,bandBits.bounds,mainRect); | |
IF fromMain AND hitMain THEN { merge new data from mainBits } | |
BEGIN | |
CopyBits(mainBits,bandBits,mainRect,mainRect,srcCopy,Nil); | |
END; | |
IF rwShftDh <> 0 THEN | |
BEGIN | |
srcRect := bandBits.bounds; | |
dstRect := bandBits.bounds; | |
erasRect := bandBits.bounds; | |
IF rwShftDh > 0 THEN | |
BEGIN | |
srcRect.right := srcRect.right - rwShftDh; | |
dstRect.left := dstRect.left + rwShftDh; | |
erasRect.right := erasRect.left + rwShftDh; | |
END | |
ELSE | |
BEGIN | |
srcRect.left := srcRect.left - rwShftDh; | |
dstRect.right := dstRect.right + rwShftDh; | |
erasRect.left := erasRect.right + rwShftDh; | |
END; | |
CopyBits(bandBits,bandBits,srcRect,dstRect,srcCopy,Nil); | |
CopyBits(bandBits,bandBits,erasRect,erasRect,srcXor,Nil); { erase } | |
END; | |
IF toShrink THEN { draw shrunken view } | |
BEGIN | |
CopyBits(bandBits,docBits,bandBits.bounds,shrinkRect,srcCopy,Nil); | |
OffsetRect(shrinkRect,0,bandHeight DIV 3); | |
END; | |
IF okPrint THEN | |
BEGIN | |
IF hiResFlag THEN | |
BEGIN | |
HLock(hiResHndl); | |
hiResPtr := Pointer(ORD(hiResHndl^)); | |
hiResBits.baseAddr := Pointer(ORD(hiResPtr)+288); | |
bandPtr := @bandBuf; | |
FOR hiResBand := 1 TO 6 DO IF okPrint THEN | |
BEGIN | |
Stretch2x(bandPtr,hiResPtr); | |
okPrint := PrintRect(hiResBits,hiResBits.bounds); | |
bandPtr := Pointer(ORD(bandPtr)+576); | |
END; | |
END | |
ELSE { print loRes } | |
BEGIN | |
okPrint := PrintRect(bandBits,bandBits.bounds); | |
END; | |
END; | |
hitAlt := SectRect(altBits.bounds,bandBits.bounds,altRect); | |
IF (toAlt AND hitAlt) THEN | |
BEGIN | |
CopyBits(bandBits,altBits,altRect,altRect,srcCopy,Nil); | |
BandToScrn(altBits,altRect.top,altRect.bottom); | |
END; | |
OffsetRect(bandBits.bounds,0,bandHeight); | |
bandPtr := @bandBuf[1]; | |
IF dstFile <> 0 THEN FOR scanLine := 1 TO bandHeight DO | |
BEGIN | |
PackBits(bandPtr,dstPtr,docRow); | |
IF ORD(dstPtr) >= ORD(@dstBuf) + SizeOf(dstBuf)-512 THEN | |
BEGIN | |
result := WriteData(dstFile,dstByte,SizeOf(dstBuf)-512,@dstBuf); | |
IF WriteError(result,srcHandle) THEN GOTO 9; | |
dstBuf[1] := dstBuf[dstBlocks]; | |
dstPtr := Pointer(ORD(dstPtr) - SizeOf(dstBuf) + 512); | |
END; | |
END; | |
CopyLongs(@bandBuf[48],@bandBuf[0],54); { move up last 3 scans } | |
END; { for band } | |
IF dstFile <> 0 THEN | |
BEGIN | |
{ flush partial dstBuf, round up to full block } | |
byteCount := BitAnd(ORD(dstPtr) - ORD(@dstBuf) + 511,$FFFFFE00); | |
result := WriteData(dstFile,dstByte,byteCount,@dstBuf); | |
IF WriteError(result,srcHandle) THEN GOTO 9; | |
dstDrive := workDrive; | |
IF dstFile <> workTo THEN | |
BEGIN | |
dstDrive := docDrive; | |
result := SetEOF(dstFile,dstByte); | |
END; | |
FlushVol(dstDrive); | |
END; | |
rwResult := 0; { success } | |
DisposHandle(srcHandle); | |
9: IF dstFile = workTo THEN workSize := dstByte; | |
IF toPrint THEN { 'Hide' button without leaving white } | |
BEGIN | |
IF hiResFlag THEN DisposHandle(hiResHndl); | |
HidePen; | |
HideControl(cancelButton); | |
ShowPen; | |
END; | |
END; | |
{$S } | |
PROCEDURE ShowEdges; | |
VAR tempRect: Rect; | |
BEGIN | |
IF NOT edgeFlag THEN EXIT(ShowEdges); { edges aren't in altBits } | |
IF fatFlag THEN | |
BEGIN | |
SetPortBits(fatBits); | |
PenMode(patXor); | |
GetSelPat(selIndex,myWind.port.pnPat); | |
PaintRect(selRect); | |
CopyBits(altBits,myWind.port.portBits,selRect,selRect,srcBic,Nil); | |
PaintRect(selRect); | |
SetPortBits(docBits); | |
FatToScrn(@fatBuf,scrnPtr); | |
END | |
ELSE | |
BEGIN | |
tempRect := selRect; | |
OffsetRect(tempRect,-altBits.bounds.left,-altBits.bounds.top); | |
AntsToScrn(@altBuf,scrnPtr,tempRect,selIndex); | |
END | |
END; | |
{$S SegScrap } | |
FUNCTION WScrapError(result: INTEGER): BOOLEAN; | |
BEGIN | |
WScrapError := FALSE; | |
IF result <> 0 THEN | |
BEGIN | |
{ alert trouble writing scrap } | |
result := MyAlert(wScrapAlrt); | |
WScrapError := TRUE; | |
END; | |
END; | |
{$S SegScrap } | |
PROCEDURE MyPutPic(dataPtr: QDPtr; byteCount: INTEGER); | |
VAR result: INTEGER; | |
reply: BOOLEAN; | |
BEGIN | |
result := WriteData(scrapFile,scrapByte,byteCount,dataPtr); | |
reply := WScrapError(result); | |
END; | |
{$S SegScrap } | |
PROCEDURE CutOrCopy(cutFlag: BOOLEAN); | |
LABEL 9; | |
VAR result: INTEGER; | |
myProcs: QDProcs; | |
dummyPic: PicHandle; | |
scrapType: ResType; | |
scrapWord: INTEGER; | |
scrapLong: LongInt; | |
scrapRect: Rect; | |
scrapPtr: pScrapStuff; | |
srcRect: Rect; | |
maxHeight: INTEGER; | |
BEGIN | |
IF NOT (selFlag OR maskFlag) THEN EXIT(CutOrCopy); | |
IF ZeroScrap <> 0 THEN EXIT(CutOrCopy); | |
IF UnloadScrap <> 0 THEN EXIT(CutOrCopy); | |
IF acceptFlag THEN AcceptEdits; | |
scrapPtr := InfoScrap; | |
result := OpenFile(0,0,scrapPtr^.scrapName^,Nil,scrapFile); | |
scrapRect := selRect; | |
scrapByte := 0; | |
scrapType := 'PICT'; | |
result := WriteData(scrapFile,scrapByte,4,@scrapType); | |
IF WScrapError(result) THEN GOTO 9; | |
{ put long of object Length=zero, and word of picSize=zero } | |
result := WriteData(scrapFile,scrapByte,6,@zeroRect); | |
IF WScrapError(result) THEN GOTO 9; | |
{ put PicFrame } | |
result := WriteData(scrapFile,scrapByte,8,@scrapRect); | |
IF WScrapError(result) THEN GOTO 9; | |
{ and maskBits with altBits } | |
IF maskFlag THEN MaskToAlt(selRect,selRect,notSrcBic); | |
SetPort(@myWind); | |
SetStdProcs(myProcs); | |
myProcs.putPicProc := @MyPutPic; | |
thePort^.grafProcs := @myProcs; | |
dummyPic := OpenPicture(scrapRect); | |
IF maskFlag THEN PicComment(12345,0,Nil); | |
ClipRect(pageRect); | |
{ worst case bitmap of 3584 bytes, 4 bands } | |
maxHeight := (selRect.right - selRect.left + 32) DIV 7; | |
srcRect := selRect; | |
WHILE NOT EmptyRect(srcRect) DO | |
BEGIN | |
srcRect.bottom := Min(srcRect.bottom, srcRect.top + maxHeight); | |
CopyBits(altBits,thePort^.portBits,srcRect,srcRect,srcCopy,Nil); | |
srcRect.top := srcRect.bottom; | |
srcRect.bottom := selRect.bottom; | |
END; | |
ClosePicture; | |
KillPicture(dummyPic); | |
thePort^.grafProcs := Nil; { restore to normal } | |
IF maskFlag THEN { restore clobbered altBits } | |
BEGIN | |
IF fatFlag THEN MainToAlt; | |
ScrnToAlt; | |
END; | |
result := SetEOF(scrapFile,scrapByte); | |
scrapPtr^.scrapSize := scrapByte; | |
scrapLong := scrapByte - 8; | |
scrapWord := scrapLong; | |
scrapByte := 4; | |
{ backpatch scrap object length } | |
result := WriteData(scrapFile,scrapByte,4,@scrapLong); | |
IF WScrapError(result) THEN GOTO 9; | |
{ backpatch picSize word } | |
result := WriteData(scrapFile,scrapByte,2,@scrapWord); | |
IF WScrapError(result) THEN GOTO 9; | |
9: result := CloseFile(scrapFile); | |
FlushVol(0); | |
IF cutFlag THEN | |
BEGIN | |
MainToAlt; | |
AltToScrn; | |
selFlag := FALSE; | |
maskFlag := FALSE; | |
END; | |
END; | |
{$S SegPaste } | |
FUNCTION RScrapError(result: INTEGER): BOOLEAN; | |
BEGIN | |
RScrapError := FALSE; | |
IF (result <> 0) AND (result <> -49) THEN | |
BEGIN | |
{ alert trouble reading scrap } | |
result := MyAlert(rScrapAlrt); | |
RScrapError := TRUE; | |
END; | |
END; | |
{$S SegPaste } | |
PROCEDURE MyGetPic(dataPtr: QDPtr; byteCount: INTEGER); | |
VAR result: INTEGER; | |
reply: BOOLEAN; | |
BEGIN | |
result := ReadData(scrapFile,scrapByte,byteCount,dataPtr); | |
reply := RScrapError(result); | |
END; | |
{$S SegPaste } | |
PROCEDURE MyPicComment(kind,dataSize: INTEGER; dataHandle: QDHandle); | |
BEGIN | |
IF kind = 12345 THEN | |
BEGIN | |
maskPaste := TRUE; | |
ZeroBuf(@altBuf); | |
END; | |
END; | |
{$S SegPaste } | |
PROCEDURE CenterScrap(VAR r: Rect); | |
{ Center scrap rectangle in current window. } | |
{ Exit fatBits if rect is too wide or too tall. } | |
VAR width,height: INTEGER; | |
windRect: Rect; | |
saveGrid: BOOLEAN; | |
BEGIN | |
saveGrid := toolGrid; | |
toolGrid := TRUE; | |
width := r.right - r.left; | |
height := r.bottom - r.top; | |
IF (width > 48) OR (height > 30) THEN { won't fit in fatBits } | |
BEGIN | |
fatFlag := FALSE; | |
CheckItem(myMenus[aidsMenu],fatItem,fatFlag); | |
END; | |
windRect := altBits.bounds; | |
IF fatFlag THEN windRect := fatBits.bounds; | |
WITH r DO | |
BEGIN | |
left := (windRect.left + windRect.right - width) DIV 2; | |
top := (windRect.top + windRect.bottom - height) DIV 2; | |
IF NOT fatFlag THEN GridPoint(topLeft); { dont let fat get off screen } | |
right := left + width; | |
bottom := top + height; | |
END; | |
toolGrid := saveGrid; | |
END; | |
PROCEDURE InvTool; FORWARD; | |
PROCEDURE SetToolCursor; FORWARD; | |
PROCEDURE CalcMask(srcBits,dstBits: BitMap; | |
limitRect: Rect; | |
firstPt: Point; | |
firstBlack: BOOLEAN; | |
invertDst: BOOLEAN); FORWARD; | |
{$S } | |
FUNCTION HalfHeap: LongInt; | |
CONST rgnSlop = 4840; { 240 * 16 for last line, plus 1000 slop } | |
VAR grow: LongInt; | |
BEGIN | |
HalfHeap := BitShift((MaxMem(grow)-rgnSlop),-1); | |
END; | |
{$S SegPaste } | |
PROCEDURE Paste; | |
LABEL 2,5; | |
VAR result: INTEGER; | |
srcRect: Rect; | |
dstRect: Rect; | |
grow: LongInt; | |
scrapHandle: Handle; | |
scrapPic: PicHandle; | |
scrapSize: LongInt; | |
scrapStart: LongInt; | |
scrapFound: BOOLEAN; | |
myProcs: QDProcs; | |
dummyPic: PicHandle; | |
wasSel: BOOLEAN; | |
scrapPtr: pScrapStuff; | |
BEGIN | |
SetPort(@myWind); | |
wasSel := selFlag; | |
selFlag := FALSE; | |
AcceptEdits; | |
KillStuff; { get rid of text, sel, mask } | |
maskPaste := FALSE; | |
scrapFound := FALSE; | |
whiteFlag := FALSE; | |
scrapPtr := InfoScrap; | |
{ check for picture scrap } | |
scrapSize := GetScrap(Nil,'PICT',scrapStart); | |
IF scrapSize > 0 THEN | |
BEGIN | |
result := OpenFile(0,0,scrapPtr^.scrapName^,Nil,scrapFile); | |
IF rScrapError(result) THEN EXIT(Paste); | |
scrapByte := scrapStart + 2; | |
result := ReadData(scrapFile,scrapByte,8,@srcRect); | |
IF rScrapError(result) THEN GOTO 2; | |
dummyPic := OpenPicture(srcRect); | |
ClosePicture; | |
SetStdProcs(myProcs); | |
myProcs.getPicProc := @MyGetPic; | |
myProcs.commentProc := @MyPicComment; | |
thePort^.grafProcs := @myProcs; | |
dstRect := selRect; | |
IF NOT wasSel THEN | |
BEGIN | |
dstRect := srcRect; | |
CenterScrap(dstRect); | |
END; | |
SetPortBits(altBits); | |
EraseRect(dstRect); | |
DrawPicture(dummyPic,dstRect); | |
thePort^.grafProcs := Nil; { restore to normal } | |
KillPicture(dummyPic); | |
2: result := CloseFile(scrapFile); | |
scrapFound := TRUE; | |
IF NOT maskPaste THEN GOTO 5; | |
IF NOT AllocMask THEN | |
BEGIN | |
MainToAlt; | |
EXIT(Paste); | |
END; | |
CalcMask(altBits,maskBits,dstRect,dstRect.topLeft,FALSE,TRUE); | |
maskFlag := TRUE; | |
lassoBlack := FALSE; | |
oldLassoBlack := FALSE; | |
{ restore altBuf everywhere except for mask area } | |
BufXorBuf(@mainBuf,@altBuf); | |
BufAndBuf(maskBits.baseAddr,@altBuf); | |
BufXorBuf(@mainBuf,@altBuf); | |
HUnlock(maskHandle); | |
GOTO 5; | |
END; | |
{ no picture in scrap, check for text } | |
scrapSize := GetScrap(Nil,'TEXT',scrapStart); | |
IF (scrapSize > 0) AND (scrapSize < HalfHeap) THEN | |
BEGIN | |
txScrapHndl := NewHandle(10); | |
txScrapSize := GetScrap(txScrapHndl,'TEXT',scrapStart); | |
dstRect := selRect; | |
IF NOT wasSel THEN | |
BEGIN { draw once just to get bounding box } | |
dstRect := altBits.bounds; | |
InsetRect(dstRect,50,0); | |
ZeroBuf(@altBuf); | |
SetPortBits(altBits); | |
DrawTxScrap(dstRect); | |
OffsetRect(dstRect,-altBits.bounds.left,-altBits.bounds.top); | |
TrimBBox(@altBuf,dstRect); | |
OffsetRect(dstRect,altBits.bounds.left,altBits.bounds.top); | |
CenterScrap(dstRect); | |
InsetRect(dstRect,-6,-4); | |
MainToAlt; | |
END; | |
{ now draw for real } | |
SetPortBits(altBits); | |
DrawTxScrap(dstRect); | |
scrapFound := TRUE; | |
END; | |
5: AltToScrn; | |
IF scrapFound THEN | |
BEGIN | |
SetSelRect(dstRect,TRUE); | |
oldSelRect := selRect; { to avoid ScrollMask in Undo } | |
SetPort(@deskWind); | |
InvTool; | |
IF maskPaste THEN | |
BEGIN | |
maskFlag := TRUE; | |
theTool := lassoTool; | |
END | |
ELSE | |
BEGIN | |
selFlag := TRUE; | |
theTool := selectTool; | |
END; | |
InvTool; | |
SetToolCursor; | |
toolGrid := TRUE; | |
END; | |
END; | |
{$S SegFlip } | |
PROCEDURE TraceEdges; | |
VAR srcRect,dstRect: Rect; | |
delta: INTEGER; | |
BEGIN | |
IF acceptFlag THEN AcceptEdits; | |
delta := 2; | |
IF KeyIsDown(shiftCode) THEN delta := 3; { asymmetric shadow } | |
srcRect := selRect; | |
WITH srcRect DO | |
BEGIN | |
left := left + 1; | |
right := right - delta + 1; | |
top := top + 1; | |
bottom := bottom - delta + 1; | |
END; | |
IF NOT AllocMask THEN EXIT(TraceEdges); | |
BufToBuf(@altBuf,maskBits.baseAddr); | |
{ smear horizontally } | |
dstRect := srcRect; | |
OffsetRect(dstRect,-1,0); | |
CopyBits(altBits,altBits,srcRect,dstRect,srcOr,Nil); { smear left } | |
OffsetRect(dstRect,delta,0); | |
CopyBits(altBits,altBits,srcRect,dstRect,srcOr,Nil); { smear right } | |
{ smear vertically } | |
dstRect := srcRect; | |
OffsetRect(dstRect,0,-1); | |
CopyBits(altBits,altBits,srcRect,dstRect,srcOr,Nil); { smear up } | |
OffsetRect(dstRect,0,delta); | |
CopyBits(altBits,altBits,srcRect,dstRect,srcOr,Nil); { smear down } | |
{ punch hole in middle } | |
MaskToAlt(srcRect,srcRect,srcBic); | |
KillMask; | |
AltToScrn; | |
END; | |
{$S SegFlip } | |
PROCEDURE HFlip; | |
VAR srcRect: Rect; | |
BEGIN | |
IF acceptFlag THEN AcceptEdits; | |
IF NOT AllocMask THEN EXIT(HFlip); | |
HFlipBuf(@altBuf,maskBits.baseAddr, | |
selRect.top-altBits.bounds.top, | |
selRect.bottom-altBits.bounds.top); | |
srcRect := selRect; | |
srcRect.left := altBits.bounds.left + altBits.bounds.right - selRect.right; | |
srcRect.right := altBits.bounds.left + altBits.bounds.right - selRect.left; | |
MaskToAlt(srcRect,selRect,srcCopy); | |
AltToScrn; | |
KillMask; | |
END; | |
{$S SegFlip } | |
PROCEDURE VFlip; | |
VAR srcRect: Rect; | |
BEGIN | |
IF acceptFlag THEN AcceptEdits; | |
IF NOT AllocMask THEN EXIT(VFlip); | |
VFlipBuf(@altBuf,maskBits.baseAddr); | |
srcRect := selRect; | |
srcRect.top := altBits.bounds.top + altBits.bounds.bottom - selRect.bottom; | |
srcRect.bottom := altBits.bounds.top + altBits.bounds.bottom - selRect.top; | |
MaskToAlt(srcRect,selRect,srcCopy); | |
AltToScrn; | |
KillMask; | |
END; | |
{$S SegFlip } | |
PROCEDURE Rotate; | |
VAR bufRect: Rect; | |
flipRect: Rect; | |
flopRect: Rect; | |
bool: BOOLEAN; | |
BEGIN | |
IF acceptFlag THEN AcceptEdits; | |
IF (selRect.right - selRect.left) = (selRect.bottom - selRect.top) THEN | |
BEGIN { square selection } | |
flipRect := selRect; | |
flopRect := flipRect; | |
END | |
ELSE | |
BEGIN { selection is not square } | |
WITH flipRect DO | |
BEGIN | |
left := pivot.h - (pivot.v - selRect.top); | |
right := pivot.h - (pivot.v - selRect.bottom); | |
top := pivot.v + (pivot.h - selRect.right); | |
bottom := pivot.v + (pivot.h - selRect.left); | |
END; | |
bool := SectRect(flipRect,altBits.bounds,flipRect); | |
WITH flopRect DO | |
BEGIN | |
left := pivot.h + pivot.v - flipRect.bottom; | |
right := pivot.h + pivot.v - flipRect.top; | |
top := pivot.v - pivot.h + flipRect.left; | |
bottom := pivot.v - pivot.h + flipRect.right; | |
END; | |
END; | |
IF NOT AllocMask THEN EXIT(Rotate); | |
ZeroBuf(maskBits.baseAddr); | |
bufRect := flopRect; | |
OffsetRect(bufRect,altBits.bounds.left - flopRect.left, | |
altBits.bounds.top - flopRect.top); | |
CopyBits(altBits,altBits,flopRect,bufRect,srcCopy,Nil); | |
RotBuf(@altBuf,maskBits.baseAddr,bufRect.bottom - bufRect.top); | |
MainToAlt; | |
bufRect := flipRect; | |
OffsetRect(bufRect,altBits.bounds.left - flipRect.left, | |
altBits.bounds.bottom - flipRect.bottom); | |
MaskToAlt(bufRect,flipRect,srcCopy); | |
AltToScrn; | |
KillMask; | |
SetSelRect(flipRect,FALSE); | |
END; | |
{$S } | |
PROCEDURE BrushPaint(brush: Bits16; pat: Pattern); | |
VAR newPt,oldPt: Point; | |
exPat: Longs24; | |
dstBits: BitMap; | |
clip: Rect; | |
hMid,vMid: INTEGER; | |
dh,dv,tol: INTEGER; | |
PROCEDURE BrushAt(h,v: INTEGER); | |
BEGIN | |
DrawBrush(brush,exPat,h+hMid,v+vMid,dstBits,clip,featureFlag); | |
END; | |
PROCEDURE SymBrush(h,v: INTEGER); | |
VAR symCopy: QDByte; | |
BEGIN | |
h := h - hMid; | |
v := v - vMid; | |
BrushAt(h,v); | |
symCopy := symByte + symByte; | |
IF fatFlag | |
OR (symCopy = 0) | |
OR (theTool <> brushTool) | |
THEN EXIT(SymBrush); | |
IF symCopy < 0 THEN BrushAt(-h,v); | |
symCopy := symCopy + symCopy; | |
IF symCopy < 0 THEN BrushAt(h,-v); | |
symCopy := symCopy + symCopy; | |
IF symCopy < 0 THEN BrushAt(-h,-v); | |
symCopy := symCopy + symCopy; | |
IF symCopy < 0 THEN BrushAt(v,h); | |
symCopy := symCopy + symCopy; | |
IF symCopy < 0 THEN BrushAt(-v,h); | |
symCopy := symCopy + symCopy; | |
IF symCopy < 0 THEN BrushAt(v,-h); | |
symCopy := symCopy + symCopy; | |
IF symCopy < 0 THEN BrushAt(-v,-h); | |
END; | |
PROCEDURE PaintBrush(pt: Point); | |
BEGIN | |
HideCursor; | |
SymBrush(pt.h,pt.v); | |
IF fatFlag THEN FatToScrn(@fatBuf,scrnPtr); | |
ShowCursor; | |
END; | |
PROCEDURE BrushLine; | |
VAR dh,dv,step,nSteps: INTEGER; | |
horiz,vert,deltaH,deltaV: Fixed; | |
BEGIN | |
dh := newPt.h - oldPt.h; | |
dv := newPt.v - oldPt.v; | |
nSteps := Max(ABS(dh),ABS(dv)); | |
deltaH := FixRatio(dh,nSteps); | |
deltaV := FixRatio(dv,nSteps); | |
horiz := BitShift(oldPt.h,16) + $00008000; | |
vert := BitShift(oldPt.v,16) + $00008000; | |
HideCursor; | |
FOR step := 1 TO nSteps DO | |
BEGIN | |
horiz := horiz + deltaH; | |
vert := vert + deltaV; | |
SymBrush(HiWord(horiz),HiWord(vert)); | |
END; | |
IF fatFlag THEN FatToScrn(@fatBuf,scrnPtr); | |
ShowCursor; | |
END; | |
BEGIN | |
IF theTool = eraseTool THEN featureFlag := FALSE; { don't allow orMode } | |
hMid := (myWind.port.portRect.left + myWind.port.portRect.right) DIV 2; | |
vMid := (myWind.port.portRect.top + myWind.port.portRect.bottom) DIV 2; | |
dstBits := docBits; | |
clip := myWind.port.portRect; | |
IF fatFlag THEN | |
BEGIN | |
dstBits := fatBits; | |
clip := fatBits.bounds; | |
END; | |
ExpandPat(pat,exPat,dstBits.bounds.left); | |
GetFatMouse(oldPt); | |
PaintBrush(oldPt); | |
InitConstrain(oldPt); | |
tol := 1; | |
IF theTool = eraseTool THEN tol := 0; | |
IF theTool = sprayTool THEN tol := 2; | |
REPEAT | |
GetFatMouse(newPt); | |
HVConstrain(newPt); | |
dh := ABS(newPt.h - oldPt.h); | |
dv := ABS(newPt.v - oldPt.v); | |
IF dh + dv > tol THEN | |
BEGIN | |
IF theTool = sprayTool | |
THEN PaintBrush(newPt) | |
ELSE BrushLine; | |
oldPt := newPt; | |
END; | |
UNTIL NOT StillDown; | |
ScrnToAlt; | |
END; | |
{$S } | |
PROCEDURE AltBufLine(pt1,pt2,oldPt: Point); | |
VAR lineTop,lineBot: INTEGER; | |
BEGIN | |
lineTop := Min(oldPt.v, Min(pt1.v,pt2.v)) - halfLineSize; | |
lineBot := Max(oldPt.v, Max(pt1.v,pt2.v)) - halfLineSize + lineSize; | |
SetPortBits(altBits); | |
MoveTo(pt1.h-halfLineSize,pt1.v-halfLineSize); | |
LineTo(pt2.h-halfLineSize,pt2.v-halfLineSize); | |
SetPortBits(docBits); | |
BandToScrn(altBits,lineTop,lineBot); | |
END; | |
PROCEDURE ScrollDoc; FORWARD; | |
PROCEDURE MenuCommand(theMenu,theItem: INTEGER); FORWARD; | |
{$S } | |
PROCEDURE PencilPaint; | |
VAR newPt,oldPt,startPt: Point; | |
saveSize: INTEGER; | |
BEGIN | |
IF fatScroll THEN | |
BEGIN | |
ScrollDoc; | |
EXIT(PencilPaint); | |
END; | |
IF featureFlag THEN { enter or leave fatBits } | |
BEGIN | |
MenuCommand(aidsMenu,fatItem); | |
EXIT(PencilPaint); | |
END; | |
saveSize := lineSize; | |
SetLineSize(1); | |
PinGridMouse(startPt); | |
PenNormal; | |
IF PixelTrue(startPt.h,startPt.v,altBits) THEN PenPat(white); | |
AltBufLine(startPt,startPt,startPt); | |
InitConstrain(startPt); | |
oldPt := startPt; | |
REPEAT | |
PinGridMouse(newPt); | |
HVConstrain(newPt); | |
IF NOT EqualPt(oldPt,newPt) THEN | |
BEGIN | |
AltBufLine(oldPt,newPt,oldPt); | |
oldPt := newPt; | |
END; | |
UNTIL NOT StillDown; | |
SetLineSize(saveSize); | |
END; | |
{$S } | |
PROCEDURE EraseSome; | |
VAR brush: Bits16; | |
BEGIN | |
brush := toolCursor.mask; { all ones } | |
IF fatFlag THEN { only 2 by 2 } | |
BEGIN | |
ZeroMem(@brush,32); | |
brush[7] := $0180; | |
brush[8] := $0180; | |
END; | |
BrushPaint(brush,white); | |
END; | |
{$S } | |
PROCEDURE CalcMask(* srcBits,dstBits: BitMap; | |
limitRect: Rect; | |
firstPt: Point; | |
firstBlack: BOOLEAN; | |
invertDst: BOOLEAN *); | |
{ given data in srcBits, compute mask into dstBits } | |
{ WARNING: srcBits and dstBits must be the wired-in size } | |
LABEL 9; | |
CONST row = 52; { rowbytes } | |
queueSize = 400; { how many entries big } | |
VAR aQueue,bQueue: ARRAY[0..queueSize] OF QueueEntry; | |
readPtr: EntryPtr; | |
writePtr: EntryPtr; | |
donePtr: EntryPtr; | |
dstStart,dstLimit,srcOffset: LongInt; | |
firstByte,firstMask: INTEGER; | |
firstPtr: ^INTEGER; | |
dh,dv: INTEGER; | |
leftByte,rightByte: INTEGER; | |
wordsWide,height: INTEGER; | |
BEGIN | |
ZeroBuf(dstBits.baseAddr); | |
IF NOT firstBlack THEN InvertBuf(srcBits.baseAddr); | |
dh := -dstBits.bounds.left; | |
dv := -dstBits.bounds.top; | |
OffsetRect(limitRect,dh,dv); { make global } | |
firstPt.h := firstPt.h + dh; | |
firstPt.v := firstPt.v + dv; | |
limitRect.left := BitAnd(limitRect.left,$FFF0); { round down to word } | |
limitRect.right := BitAnd(limitRect.right+15,$FFF0); { round up to word } | |
leftByte := limitRect.left DIV 8; | |
rightByte := limitRect.right DIV 8; | |
dstStart := ORD(dstBits.baseAddr) + limitRect.top * row + leftByte; | |
dstLimit := ORD(dstBits.baseAddr) + limitRect.bottom * row + leftByte; | |
srcOffset := ORD(srcBits.BaseAddr) - ORD(dstBits.baseAddr); | |
firstByte := 2*(firstPt.h DIV 16); | |
firstPtr := Pointer(ORD(srcBits.baseAddr) + firstPt.v * row + firstByte); | |
firstMask := 0; | |
BitSet(@firstMask,BitAnd(firstPt.h,15)); | |
firstMask := VertSeed(firstMask,firstPtr^); | |
IF firstMask = 0 THEN GOTO 9; | |
{ Prime "aQueue" with seed at first point } | |
writePtr := @aQueue; | |
WITH writePtr^ DO | |
BEGIN | |
addr := ORD(firstPtr)-srcOffset; | |
bump := 2; | |
twoH := firstByte - leftByte; | |
mask := firstMask; | |
END; | |
writePtr := Pointer(ORD(writePtr) + SizeOf(queueEntry)); | |
{ Ping pong between the two Queues. Read each entry from one queue } | |
{ and push all the untried ones it spawns onto the other queue. } | |
REPEAT | |
donePtr := writePtr; | |
readPtr := @aQueue; { read from queue A } | |
writePtr := @bQueue; { push into queue B } | |
MaskIt(dstStart,dstLimit,srcOffset, | |
rightByte-leftByte,row,readPtr,donePtr,writePtr); | |
donePtr := writePtr; | |
readPtr := @bQueue; { read from queue B } | |
writePtr := @aQueue; { push into queue A } | |
MaskIt(dstStart,dstLimit,srcOffset, | |
rightByte-leftByte,row,readPtr,donePtr,writePtr); | |
UNTIL writePtr = @aQueue; { until aQueue is empty } | |
9: IF NOT firstBlack THEN InvertBuf(srcBits.baseAddr); { restore src } | |
IF invertDst THEN | |
BEGIN | |
height := limitRect.bottom - limitRect.top; | |
wordsWide := (limitRect.right - limitRect.left) DIV 16; | |
InvertChunk(dstStart,wordsWide,height); | |
END; | |
END; | |
{$S } | |
PROCEDURE SeedFill(startPt: Point); | |
VAR firstBlack: BOOLEAN; | |
BEGIN | |
firstBlack := PixelTrue(startPt.h,startPt.v,mainBits); | |
CalcMask(mainBits,altBits,altBits.bounds,startPt,firstBlack,FALSE); | |
SetPortBits(altBits); | |
PenPat(thePat); | |
IF firstBlack THEN | |
BEGIN | |
PenMode(patBic); | |
PaintRect(altBits.bounds); | |
InvertBuf(@altBuf); | |
BufAndBuf(@mainBuf,@altBuf); | |
END | |
ELSE | |
BEGIN | |
PenMode(notPatBic); | |
PaintRect(altBits.bounds); | |
BufOrBuf(@mainBuf,@altBuf); | |
END; | |
PenNormal; | |
AltToScrn; | |
clickTime := TickCount; | |
GetMouse(clickLoc); | |
LocalToGlobal(clickLoc); | |
killDouble := TRUE; | |
END; | |
{$S } | |
PROCEDURE HollowCurve; | |
VAR newPt,oldPt: Point; | |
tol: INTEGER; | |
BEGIN | |
tol := 3; | |
IF fatFlag THEN tol := 1; | |
JamLine; | |
PinGridMouse(oldPt); | |
AltBufLine(oldPt,oldPt,oldPt); | |
REPEAT | |
PinGridMouse(newPt); | |
IF NOT NearPt(oldPt,newPt,tol) THEN | |
BEGIN | |
AltBufLine(oldPt,newPt,oldPt); | |
oldPt := newPt; | |
END; | |
UNTIL NOT StillDown; | |
END; | |
{$S } | |
FUNCTION GetRgn(fillFlag: BOOLEAN): RgnHandle; | |
CONST ptMax = 1000; | |
VAR firstPt,oldPt,newPt: Point; | |
tempRgn: RgnHandle; | |
memLimit,grow: LongInt; | |
ptArray: ARRAY[0..ptMax] OF Point; | |
i,dh,dv,ptIndex: INTEGER; | |
dstBits: BitMap; | |
BEGIN | |
IF fillFlag THEN JamLine; | |
dstBits := docBits; | |
IF fatFlag THEN dstBits := fatBits; | |
memLimit := HalfHeap; { leave half for packed region } | |
IF memLimit > 20000 THEN memLimit := 20000; | |
OpenRgn; | |
ShowPen; | |
PinGridMouse(firstPt); | |
MoveTo(firstPt.h-halfLineSize,firstPt.v-halfLineSize); | |
SetPortBits(dstBits); | |
Line(0,0); | |
SetPortBits(docBits); | |
IF fatFlag THEN FatToScrn(@fatBuf,scrnPtr); | |
oldPt := firstPt; | |
ptIndex := 1; | |
REPEAT | |
PinGridMouse(newPt); | |
dh := ABS(newPt.h - oldPt.h); | |
dv := ABS(newPt.v - oldPt.v); | |
IF (dh + dv) > 1 THEN | |
BEGIN | |
SetPortBits(dstBits); | |
LineTo(newPt.h-halfLineSize,newPt.v-halfLineSize); | |
SetPortBits(docBits); | |
IF fatFlag THEN FatToScrn(@fatBuf,scrnPtr); | |
ptArray[ptIndex] := newPt; | |
ptIndex := ptIndex + 1; | |
oldPt := newPt; | |
END; | |
UNTIL (NOT StillDown) OR (GetRgnMax > memLimit) OR (ptIndex = ptMax); | |
{ close the curve } | |
SetPortBits(dstBits); | |
LineTo(firstPt.h-halfLineSize,firstPt.v-halfLineSize); | |
SetPortBits(docBits); | |
IF fatFlag THEN FatToScrn(@fatBuf,scrnPtr); | |
HidePen; | |
tempRgn:=NewRgn; | |
CloseRgn(tempRgn); | |
OffsetRgn(tempRgn,halfLineSize,halfLineSize); | |
IF fillFlag THEN | |
BEGIN | |
SetPortBits(altBits); | |
JamFill; | |
PaintRgn(tempRgn); | |
JamLine; | |
IF NOT borderFlag THEN PenPat(thePat); | |
MoveTo(firstPt.h-halfLineSize,firstPt.v-halfLineSize); | |
FOR i := 1 to ptIndex - 1 DO | |
LineTo(ptArray[i].h-halfLineSize,ptArray[i].v-halfLineSize); | |
LineTo(firstPt.h-halfLineSize,firstPt.v-halfLineSize); | |
END; | |
GetRgn := tempRgn; | |
AltToScrn; | |
END; | |
{$S } | |
PROCEDURE KillEdges; | |
{ discard edgeMask, restoring altBits to most recent edits } | |
VAR dstBits: BitMap; | |
mode: INTEGER; | |
BEGIN | |
IF edgeFlag THEN | |
BEGIN | |
mode := srcOr; | |
IF lassoBlack then mode := srcBic; | |
{ replace ants with black or white } | |
dstBits := docBits; | |
IF fatFlag THEN dstBits := fatBits; | |
CopyBits(altBits,dstBits,selRect,selRect,mode,Nil); | |
IF fatFlag THEN MainToAlt; | |
ScrnToAlt; | |
IF fatFlag THEN AltToScrn; | |
edgeFlag := FALSE; | |
END; | |
END; | |
{$S } | |
PROCEDURE ClearSel; | |
BEGIN | |
IF selFlag OR maskFlag THEN | |
BEGIN | |
IF acceptFlag THEN AcceptEdits; | |
MainToAlt; | |
AltToScrn; | |
IF txScrapHndl <> Nil THEN KillStuff; | |
selFlag := FALSE; | |
maskFlag := FALSE; | |
END; | |
END; | |
{$S } | |
PROCEDURE InvertSel; | |
BEGIN | |
IF acceptFlag THEN AcceptEdits; | |
IF selFlag THEN | |
BEGIN | |
SetPortBits(altBits); | |
InvertRect(selRect); | |
SetPortBits(docBits); | |
END; | |
IF maskFlag THEN | |
BEGIN | |
MaskToAlt(maskBits.bounds,altBits.bounds,srcXor); | |
lassoBlack := NOT lassoBlack; | |
END; | |
AltToScrn; | |
END; | |
{$S } | |
PROCEDURE FillSel; | |
BEGIN | |
IF acceptFlag THEN AcceptEdits; | |
SetPortBits(altBits); | |
PenNormal; | |
PenPat(thePat); | |
IF selFlag THEN PaintRect(selRect); | |
IF maskFlag THEN | |
BEGIN | |
PenMode(patXor); | |
PaintRect(selRect); | |
MaskToAlt(maskBits.bounds,altBits.bounds,srcBic); | |
PaintRect(selRect); | |
END; | |
PenNormal; | |
SetPortBits(docBits); | |
AltToScrn; | |
END; | |
{$S } | |
PROCEDURE StraightLine; | |
VAR newPt,oldPt,startPt: Point; | |
lineTop,lineBot: INTEGER; | |
BEGIN | |
JamLine; | |
PinGridMouse(startPt); | |
oldPt.h := 1000; { force first time } | |
REPEAT | |
PinGridMouse(newPt); | |
IF shiftFlag THEN Constrain(startPt,newPt,TRUE); | |
IF NOT EqualPt(newPt,oldPt) THEN | |
BEGIN | |
MainToAlt; { erase old } | |
AltBufLine(startPt,newPt,oldPt); | |
oldPt := newPt; | |
END; | |
UNTIL NOT StillDown; | |
END; | |
{$S } | |
FUNCTION PolyLine(startPt: Point; VAR endPt: Point): BOOLEAN; | |
{ returns TRUE if aborted } | |
VAR newPt,oldPt: Point; | |
sync: LongInt; | |
event: EventRecord; | |
abort: BOOLEAN; | |
BEGIN | |
oldPt.h := 1000; { force first time } | |
REPEAT | |
PinGridMouse(newPt); | |
IF shiftFlag THEN Constrain(startPt,newPt,TRUE); | |
IF NOT EqualPt(newPt,oldPt) THEN | |
BEGIN | |
AltToScrn; { restore screen and fatBits } | |
IF fatFlag THEN | |
BEGIN | |
SetPortBits(fatBits); | |
MoveTo(startPt.h-halfLineSize,startPt.v-halfLineSize); | |
LineTo(newPt.h-halfLineSize,newPt.v-halfLineSize); | |
SetPortBits(docBits); | |
FatToScrn(@fatBuf,scrnPtr); | |
END | |
ELSE | |
BEGIN | |
MoveTo(startPt.h-halfLineSize,startPt.v-halfLineSize); | |
LineTo(newPt.h-halfLineSize,newPt.v-halfLineSize); | |
END; | |
sync := TickCount; | |
REPEAT UNTIL TickCount > sync + 2; | |
oldPt := newPt; | |
END; | |
event.what := nullEvent; | |
abort := FALSE; | |
IF GetNextEvent(everyEvent,event) THEN | |
BEGIN | |
abort := (event.what = keyDown) | |
OR ((event.what = mouseDown) AND NOT PtInRect(event.where,docRect)); | |
END; | |
UNTIL abort OR (event.what = mouseUp); | |
IF event.what = mouseUp THEN | |
BEGIN | |
clickTime := event.when; | |
clickLoc := event.where; | |
END; | |
endPt := newPt; | |
IF abort THEN endPt := startPt; | |
PolyLine := abort; | |
END; | |
{$S } | |
PROCEDURE CreatePoly(filled: BOOLEAN); | |
CONST ptMax = 1000; | |
VAR startPt,oldPt,newPt: Point; | |
tempRgn: RgnHandle; | |
event: EventRecord; | |
done: BOOLEAN; | |
closed: BOOLEAN; | |
fillState: QDHandle; | |
memLimit,grow: LongInt; | |
ptArray: ARRAY[0..ptMax] OF Point; | |
i,ptIndex: INTEGER; | |
BEGIN | |
IF clickCount > 1 THEN EXIT(CreatePoly); | |
memLimit := HalfHeap; { leave half for packed region } | |
IF memLimit > 20000 THEN memLimit := 20000; | |
JamLine; | |
fillState := Nil; | |
IF filled THEN | |
BEGIN | |
OpenRgn; | |
ShowPen; | |
fillState := myWind.port.rgnSave; | |
myWind.port.rgnSave := Nil; { disable during dragging } | |
END; | |
PinGridMouse(startPt); { get initial starting point } | |
oldPt := startPt; | |
ptIndex := 1; | |
REPEAT | |
done := PolyLine(oldPt,newPt); | |
IF NOT done THEN | |
BEGIN | |
ScrnToAlt; { consolidate line into altBits } | |
ptArray[ptIndex] := newPt; | |
ptIndex := ptIndex + 1; | |
myWind.port.rgnSave := fillState; | |
HidePen; | |
MoveTo(oldPt.h,oldPt.v); | |
LineTo(newPt.h,newPt.v); | |
ShowPen; | |
myWind.port.rgnSave := Nil; | |
END; | |
closed := FALSE; | |
IF ptIndex > 2 THEN | |
BEGIN | |
closed := NearPt(newPt,startPt,4*lineSize); | |
done := done OR closed; | |
done := done OR NearPt(newPt,oldPt,4*lineSize); | |
END; | |
done := done OR (ptIndex = ptMax); | |
IF filled THEN done := done OR (GetRgnMax > memLimit); | |
oldPt := newPt; | |
UNTIL done; | |
IF filled OR closed THEN AltBufLine(newPt,startPt,newPt); | |
IF filled THEN | |
BEGIN | |
myWind.port.rgnSave := fillState; | |
HidePen; | |
MoveTo(newPt.h,newPt.v); | |
LineTo(startPt.h,startPt.v); { close region definition } | |
tempRgn := NewRgn; | |
CloseRgn(tempRgn); | |
SetPortBits(altBits); | |
JamFill; | |
PaintRgn(tempRgn); | |
DisposeRgn(tempRgn); | |
JamLine; | |
IF NOT borderFlag THEN PenPat(thePat); | |
MoveTo(startPt.h-halfLineSize,startPt.v-halfLineSize); | |
FOR i := 1 TO ptIndex - 1 DO | |
LineTo(ptArray[i].h-halfLineSize,ptArray[i].v-halfLineSize); | |
LineTo(startPt.h-halfLineSize,startPt.v-halfLineSize); | |
END; | |
AltToScrn; | |
killDouble := TRUE; | |
END; | |
{$S } | |
PROCEDURE ScrollFat; | |
VAR startPt,oldPt,newPt: Point; | |
dstRect: Rect; | |
dh,dv: INTEGER; | |
minDh,maxDh,minDv,maxDv: INTEGER; | |
saveFat: Rect; | |
BEGIN | |
saveFat := fatBits.bounds; | |
GetMouse(startPt); | |
InitConstrain(startPt); | |
oldPt := startPt; | |
maxDh := fatBits.bounds.left - myWind.port.portRect.left; | |
minDh := fatBits.bounds.right - myWind.port.portRect.right; | |
maxDv := fatBits.bounds.top - myWind.port.portRect.top; | |
minDv := fatBits.bounds.bottom - myWind.port.portRect.bottom; | |
REPEAT | |
GetMouse(newPt); | |
HVConstrain(newPt); | |
IF NOT EqualPt(newPt,oldPt) THEN | |
BEGIN | |
dh := (newPt.h - startPt.h) DIV 3; | |
dv := (newPt.v - startPt.v) DIV 3; | |
dh := PinWord(dh, minDh, maxDh); | |
dv := PinWord(dv, minDv, maxDv); | |
fatBits.bounds := saveFat; | |
OffsetRect(fatBits.bounds,-dh,-dv); | |
BitsToScrn(mainBits); | |
oldPt:=newPt; | |
END; | |
UNTIL NOT StillDown; | |
fatCenter.h := (fatBits.bounds.left + fatBits.bounds.right) DIV 2; | |
fatCenter.v := (fatBits.bounds.top + fatBits.bounds.bottom) DIV 2; | |
END; | |
{$S } | |
PROCEDURE ScrollTo(newOrigin: Point); | |
VAR pinRect: Rect; | |
dstFile: INTEGER; | |
BEGIN | |
SetPort(@myWind); | |
SetRect(pinRect,0,0,docWidth-416,docHeight-240); | |
PinPt(newOrigin,pinRect); | |
SetOrigin(newOrigin.h,newOrigin.v); | |
docBits := myWind.port.portBits; | |
altBits.bounds := myWind.port.portRect; | |
dstFile := 0; | |
IF workDirty THEN dstFile := workTo; | |
ReadWrite(workFrom,dstFile,workDirty,TRUE,FALSE,FALSE,FALSE); | |
IF workDirty THEN | |
BEGIN | |
SwapWord(workFrom,workTo); | |
workDirty := FALSE; | |
END; | |
mainBits.bounds := altBits.bounds; | |
maskBits.bounds := altBits.bounds; | |
AcceptEdits; | |
fatCenter.h := newOrigin.h+208; | |
fatCenter.v := newOrigin.v+120; | |
END; | |
{$S } | |
PROCEDURE ScrollDoc; | |
VAR startPt,oldPt,newPt: Point; | |
oldOrigin,newOrigin: Point; | |
pinRect: Rect; | |
BEGIN | |
IF fatFlag THEN | |
BEGIN | |
ScrollFat; | |
EXIT(ScrollDoc); | |
END; | |
SetPort(@myWind); | |
oldOrigin := myWind.port.portRect.topLeft; | |
newOrigin := oldOrigin; | |
SetRect(pinRect,0,0,docWidth-416,docHeight-240); | |
AcceptEdits; | |
GetGridMouse(startPt); | |
LocalToGlobal(startPt); | |
InitConstrain(startPt); | |
oldPt := startPt; | |
REPEAT | |
GetGridMouse(newPt); | |
LocalToGlobal(newPt); | |
HVConstrain(newPt); | |
IF NOT EqualPt(newPt,oldPt) THEN | |
BEGIN | |
newOrigin := oldOrigin; | |
SubPt(newPt,newOrigin); | |
AddPt(startPt,newOrigin); | |
PinPt(newOrigin,pinRect); | |
SetOrigin(newOrigin.h,newOrigin.v); | |
docBits := myWind.port.portBits; | |
altBits.bounds := myWind.port.portRect; | |
ZeroBuf(@altBuf); | |
CopyBits(mainBits,altBits,mainBits.bounds,mainBits.bounds,srcCopy,Nil); | |
AltToScrn; | |
oldPt:=newPt; | |
END; | |
UNTIL NOT StillDown; | |
IF NOT EqualPt(newOrigin,oldOrigin) THEN ScrollTo(newOrigin); | |
END; | |
{$S } | |
PROCEDURE DragImage; | |
LABEL 9; | |
VAR startPt,oldPt,newPt,tempPt: Point; | |
srcRect,dstRect,oldDstRect: Rect; | |
dh,dv,minDh,maxDh,minDv,maxDv: INTEGER; | |
anchorPt: Point; | |
fromRect,toRect: Rect; | |
hSame,vSame: BOOLEAN; | |
third: INTEGER; | |
saveGrid: BOOLEAN; | |
multiFlag: BOOLEAN; | |
copyFlag: BOOLEAN; | |
stretchFlag: BOOLEAN; | |
stretchText: BOOLEAN; | |
tol: INTEGER; | |
tempRect: Rect; | |
srcBits: BitMap; | |
BEGIN | |
workDirty := TRUE; | |
docDirty := TRUE; | |
saveGrid := toolGrid; | |
toolGrid := TRUE; { make grid work for lassoTool drag } | |
multiFlag := optionFlag AND featureFlag; | |
copyFlag := optionFlag AND NOT featureFlag; | |
stretchFlag := featureFlag AND NOT optionFlag; | |
IF copyFlag THEN acceptFlag := TRUE; | |
IF acceptFlag THEN AcceptEdits; | |
IF optionFlag THEN whiteFlag := FALSE; { copy or multicopy } | |
IF multiFlag THEN acceptFlag := TRUE; | |
tempRect := myWind.port.portRect; | |
IF fatFlag THEN tempRect := fatBits.bounds; | |
minDh := tempRect.left - selRect.left; | |
maxDh := tempRect.right - selRect.right; | |
minDv := tempRect.top - selRect.top; | |
maxDv := tempRect.bottom - selRect.bottom; | |
PenNormal; | |
GetSelPat(selIndex,myWind.port.pnPat); | |
srcRect := selRect; | |
dstRect := srcRect; | |
GetGridMouse(startPt); | |
InitConstrain(startPt); | |
IF maskFlag THEN stretchFlag := FALSE; { can't stretch a lasso selection } | |
IF stretchFlag THEN WITH selRect DO { set up anchor point for stretching } | |
BEGIN | |
hSame := FALSE; | |
third := (right - left) DIV 3; | |
IF startPt.h < left + third THEN anchorPt.h := right | |
ELSE IF startPt.h > right - third THEN anchorPt.h := left | |
ELSE hSame := TRUE; | |
vSame := FALSE; | |
third := (bottom - top) DIV 3; | |
IF startPt.v < top + third THEN anchorPt.v := bottom | |
ELSE IF startPt.v > bottom - third THEN anchorPt.v := top | |
ELSE vSame := TRUE; | |
IF hSame AND vSame THEN stretchFlag := FALSE; { move instead of stretch } | |
END; | |
stretchText := stretchFlag AND (txScrapHndl <> Nil); | |
IF (NOT maskFlag) AND (not stretchText) THEN | |
BEGIN | |
IF NOT AllocMask THEN GOTO 9; | |
BufToBuf(@altBuf,maskBits.baseAddr); | |
END; | |
tol := 1; | |
IF multiFlag THEN | |
BEGIN | |
tol := 2*lineSize; | |
IF tol = 2 THEN tol := 1; | |
END; | |
srcBits := docBits; | |
IF fatFlag THEN srcBits := fatBits; | |
oldPt.h := 1000; { force first time } | |
REPEAT | |
GetGridMouse(newPt); | |
IF NOT stretchFlag THEN HVConstrain(newPt); | |
IF NOT NearPt(newPt,oldPt,tol) THEN | |
BEGIN | |
oldDstRect := dstRect; | |
dstRect := srcRect; | |
IF stretchFlag THEN | |
BEGIN | |
tempPt := startPt; | |
IF shiftFlag THEN { preserve aspect } | |
BEGIN | |
Constrain(anchorPt,tempPt,FALSE); | |
Constrain(anchorPt,newPt,FALSE); | |
END; | |
Pt2Rect(anchorPt,tempPt,fromRect); | |
Pt2Rect(anchorPt,newPt,toRect); | |
IF hSame THEN | |
BEGIN | |
toRect.left := fromRect.left; | |
toRect.right := fromRect.right; | |
END; | |
IF vSame THEN | |
BEGIN | |
toRect.top := fromRect.top; | |
toRect.bottom := fromRect.bottom; | |
END; | |
MapRect(dstRect,fromRect,toRect); | |
END | |
ELSE | |
BEGIN | |
dh := PinWord(newPt.h - startPt.h, minDh, maxDh); | |
dv := PinWord(newPt.v - startPt.v, minDv, maxDv); | |
IF gridOn AND toolGrid THEN | |
BEGIN | |
dh := Trunc8(dh); | |
dv := Trunc8(dv); | |
END; | |
OffsetRect(dstRect,dh,dv); | |
END; | |
IF (NOT multiFlag) AND (NOT stretchText) THEN MainToAlt; | |
IF selFlag THEN | |
BEGIN | |
SetPortBits(altBits); | |
IF stretchText THEN | |
BEGIN | |
MainToAlt; | |
DrawTxScrap(dstRect); | |
END | |
ELSE MaskToAlt(srcRect,dstRect,srcCopy); | |
IF NOT multiFlag THEN FrameRect(dstRect); { draw ants } | |
END; | |
IF maskFlag THEN | |
BEGIN | |
CopyBits(srcBits,altBits,oldDstRect,dstRect,srcXor,Nil); | |
MaskToAlt(srcRect,dstRect,srcBic); | |
CopyBits(srcBits,altBits,oldDstRect,dstRect,srcXor,Nil); | |
END; | |
AltToScrn; | |
oldPt := newPt; | |
END; { if not NearPt } | |
UNTIL NOT StillDown; | |
IF selFlag THEN | |
BEGIN | |
SetSelRect(dstRect,TRUE); | |
SetPortBits(altBits); | |
IF stretchText THEN | |
BEGIN | |
MainToAlt; | |
DrawTxScrap(dstRect); | |
END | |
ELSE IF NOT multiFlag THEN { erase marching ants } | |
BEGIN | |
MainToAlt; | |
MaskToAlt(srcRect,dstRect,srcCopy); | |
END; | |
AltToScrn; | |
END; | |
IF maskFlag THEN | |
BEGIN | |
selRect := dstRect; | |
ScrollMask(dh,dv); | |
END; | |
IF NOT maskFlag THEN KillMask; | |
9: toolGrid := saveGrid; | |
END; | |
{$S } | |
PROCEDURE SelDragImage; | |
LABEL 9; | |
VAR dstRect: Rect; | |
now: INTEGER; | |
saveSize: INTEGER; | |
oldIndex: INTEGER; | |
startPt,newPt,oldPt: Point; | |
BEGIN | |
dstRect := myWind.port.portRect; | |
IF fatFlag THEN dstRect := fatBits.bounds; | |
IF insel AND (featureFlag OR NOT EqualRect(selRect,dstRect)) THEN | |
BEGIN | |
DragImage; | |
EXIT(SelDragImage); | |
END; | |
{ make a new rectangular selection } | |
KillStuff; | |
oldSelFlag := FALSE; | |
oldMaskFlag := FALSE; | |
saveSize := lineSize; | |
SetLineSize(1); { for PinGridMouse } | |
PenNormal; | |
PinGridMouse(startPt); | |
dstRect.topLeft := startPt; | |
dstRect.botRight := startPt; | |
IF NOT AllocMask THEN GOTO 9; | |
oldIndex := -1; { force first } | |
WHILE StillDown DO | |
BEGIN | |
now := LoWord(TickCount); | |
IF fatFlag THEN now := now DIV 3; { slow it down } | |
selIndex := BitAnd(now,7); | |
IF selIndex <> oldIndex THEN | |
BEGIN | |
PinGridMouse(newPt); | |
Pt2Rect(startPt,newPt,dstRect); | |
selFlag := NOT EmptyRect(dstRect); | |
IF selFlag THEN | |
BEGIN | |
dstRect.right := dstRect.right + 1; | |
dstRect.bottom := dstRect.bottom + 1; | |
END; | |
BufToBuf(@altBuf,maskBits.baseAddr); | |
SetPortBits(maskBits); | |
GetSelPat(selIndex,myWind.port.pnPat); | |
FrameRect(dstRect); | |
SetPortBits(docBits); | |
bitsToScrn(maskBits); | |
oldIndex := selIndex; | |
END; | |
END; | |
KillMask; | |
IF selFlag THEN SetSelRect(dstRect,TRUE); | |
acceptFlag := TRUE; | |
whiteFlag := TRUE; | |
9: SetLineSize(saveSize); | |
END; | |
{$S } | |
PROCEDURE Lasso(startPt: Point); | |
LABEL 9; | |
VAR lassoRgn: RgnHandle; | |
dh,dv: INTEGER; | |
saveSize: INTEGER; | |
srcBits: BitMap; | |
BEGIN | |
KillStuff; | |
whiteFlag := FALSE; | |
oldMaskFlag := FALSE; | |
lassoBlack := FALSE; | |
oldLassoBlack := FALSE; | |
saveSize := lineSize; | |
lineSize := 1; | |
halfLineSize := 0; | |
SetPinRect(2); | |
PenNormal; | |
lassoRgn := GetRgn(FALSE); | |
selRect := lassoRgn^^.rgnBBox; | |
IF EmptyRgn(lassoRgn) THEN | |
BEGIN | |
DisposeRgn(lassoRgn); | |
GOTO 9; | |
END; | |
InsetRect(selRect,-1,-1); | |
ZeroBuf(@altBuf); | |
srcBits := docBits; | |
IF fatFlag THEN srcBits := fatBits; | |
CopyBits(srcBits,altBits,selRect,selRect,srcCopy,lassoRgn); | |
DisposeRgn(lassoRgn); | |
IF NOT AllocMask THEN GOTO 9; | |
CalcMask(altBits,maskBits,selRect,selRect.topLeft,FALSE,TRUE); | |
maskFlag := TRUE; | |
OffsetRect(selRect,-maskBits.bounds.left,-maskBits.bounds.top); | |
TrimBBox(maskBits.baseAddr,selRect); | |
OffsetRect(selRect,maskBits.bounds.left,maskBits.bounds.top); | |
HUnlock(maskHandle); | |
IF EmptyRect(selRect) THEN KillMask; | |
IF fatFlag THEN BufToBuf(@mainBuf,@altBuf); | |
ScrnToAlt; { restore alt } | |
InsetRect(selRect,-1,-1); | |
SetSelRect(selRect,TRUE); { establish fatCenter } | |
9: whiteFlag := TRUE; | |
acceptFlag := TRUE; | |
oldSelRect := selRect; { avoid ScrollMask in Undo } | |
SetLineSize(saveSize); | |
END; | |
{$S } | |
PROCEDURE PlaceCaret(startPt: Point; newLeft: BOOLEAN); | |
BEGIN | |
{ avoid accidental consolidation from menu double click } | |
IF (theEvent.when < clickTime + GetDoubleTime) | |
AND NearPt(theEvent.where,clickLoc,4) | |
THEN EXIT(PlaceCaret); | |
AcceptEdits; | |
KillStuff; | |
GridPoint(startPt); | |
textLoc := startPt; | |
caretLoc := startPt; | |
IF newLeft THEN textLeft := startPt.h; | |
textFlag := TRUE; | |
textLines := 0; | |
ObscureCursor; | |
END; | |
{$S } | |
PROCEDURE EditDoc; | |
VAR pt: Point; | |
BEGIN | |
IF (theTool > textTool) OR (theTool = grabberTool) THEN | |
BEGIN | |
{ kill the text ? } | |
AcceptEdits; { kill selection ants } | |
whiteFlag := FALSE; | |
acceptFlag := TRUE; | |
END; | |
IF NOT fatFlag THEN GetMouse(fatCenter); | |
GetFatMouse(pt); { not gridded } | |
IF theTool > textTool THEN | |
BEGIN | |
workDirty := TRUE; | |
docDirty := TRUE; | |
END; | |
CASE theTool OF | |
0: IF inSel THEN DragImage ELSE Lasso(pt); { lasso or drag } | |
1: SelDragImage; { select or drag } | |
2: ScrollDoc; { scroll document } | |
3: PlaceCaret(pt,TRUE); { start new text } | |
4: SeedFill(pt); { seed fill } | |
5: BrushPaint(toolCursor.data,thePat); { spray paint } | |
6: BrushPaint(toolCursor.data,thePat); { paint with brush } | |
7: PencilPaint; { pencil } | |
8: StraightLine; { straight line } | |
9: EraseSome; { eraser } | |
10: CreateShape(rectShape,FALSE); { hollow rect } | |
11: CreateShape(rectShape,TRUE); { filled rect } | |
12: CreateShape(rRectShape,FALSE); { hollow roundRect } | |
13: CreateShape(rRectShape,TRUE); { filled roundRect } | |
14: CreateShape(ovalShape,FALSE); { hollow oval } | |
15: CreateShape(ovalShape,TRUE); { filled oval } | |
16: HollowCurve; { hollow curve } | |
17: DisposeRgn(GetRgn(TRUE)); { filled curve } | |
18: CreatePoly(FALSE); { hollow polygon } | |
19: CreatePoly(TRUE); { filled polygon } | |
END; | |
END; | |
{$S } | |
PROCEDURE TrackCursor; | |
LABEL 1; | |
VAR wasInWindow: BOOLEAN; | |
wasInSel: BOOLEAN; | |
wasFatScroll: BOOLEAN; | |
oldIndex: INTEGER; | |
ticks: LongInt; | |
now: INTEGER; | |
hOffset,vOffset: INTEGER; | |
bitNum: LongInt; | |
mousePt: Point; | |
dh,dv: INTEGER; | |
saveTool: INTEGER; | |
BEGIN | |
ticks := TickCount; | |
IF textFlag AND (ticks > nextCaretTime) THEN | |
BEGIN | |
InvertCaret; | |
nextCaretTime := ticks + GetCaretTime; | |
END; | |
wasInWindow := inWindow; | |
wasInSel := inSel; | |
wasFatScroll := fatScroll; | |
fatScroll := fatFlag AND KeyIsDown(optionCode) AND (theTool = pencilTool); | |
IF fatScroll <> wasFatScroll THEN | |
BEGIN | |
saveTool := theTool; | |
IF fatScroll THEN theTool := grabberTool; | |
SetToolCursor; | |
theTool := saveTool; | |
END; | |
SetPort(@myWind); | |
SetPortBits(docBits); | |
GetMouse(mousePt); | |
inWindow := windOpen AND PtInRect(mousePt,myWind.port.portRect); | |
GetFatMouse(mousePt); | |
IF maskFlag THEN { lasso selection } | |
BEGIN | |
IF NOT edgeFlag THEN | |
BEGIN | |
maskBits.baseAddr := Pointer(ORD(maskHandle^)); | |
CalcEdges(Pointer(ORD(maskHandle^)),@altBuf, | |
selRect.top-altBits.bounds.top, | |
selRect.bottom-selRect.top,lassoBlack); | |
edgeFlag := TRUE; | |
END; | |
maskBits.baseAddr := Pointer(ORD(maskHandle^)); | |
inSel := TRUE; | |
FOR dh := -2 TO 2 DO | |
FOR dv := -2 TO 2 DO | |
IF PixelTrue(mousePt.h + dh, mousePt.v + dv, maskBits) THEN GOTO 1; | |
inSel := FALSE; { none of the pixels was true } | |
1: | |
END | |
ELSE inSel := selFlag AND PtInRect(mousePt,selRect); | |
IF cursorFlag | |
OR (inWindow <> wasInWindow) | |
OR (inSel <> wasInSel) THEN { time for a new cursor } | |
BEGIN | |
IF NOT inWindow THEN CursorNormal | |
ELSE | |
BEGIN | |
IF gridOn AND toolGrid THEN | |
BEGIN | |
hOffset := BitAnd(-myWind.port.portBits.bounds.left,7); | |
vOffset := BitAnd(-myWind.port.portBits.bounds.top,7); | |
GridMouse(-8,-8,hOffset,vOffset); | |
END; | |
IF inSel | |
THEN SetCursor(arrow) | |
ELSE SetCursor(toolCursor); | |
END; | |
END; | |
oldIndex := selIndex; | |
now := LoWord(ticks); | |
IF fatFlag THEN now := now DIV 3; { slow down ants } | |
selIndex := BitAnd(now,7); | |
IF selIndex <> oldIndex THEN | |
BEGIN | |
IF edgeFlag THEN ShowEdges; | |
IF selFlag THEN | |
BEGIN | |
PenNormal; | |
GetSelPat(selIndex,myWind.port.pnPat); | |
IF fatFlag THEN | |
BEGIN | |
SetPortBits(fatBits); | |
FrameRect(selRect); | |
SetPortBits(docBits); | |
FatToScrn(@fatBuf,scrnPtr); | |
END | |
ELSE FrameRect(selRect); | |
END; | |
END; | |
cursorFlag := FALSE; | |
END; | |
{$S } | |
PROCEDURE TextChar; | |
VAR textPtr: QDPtr; | |
thisLine: StringHandle; | |
len: INTEGER; | |
txHndl: StringHandle; | |
BEGIN | |
IF NOT textFlag THEN EXIT(TextChar); | |
workDirty := TRUE; | |
docDirty := TRUE; | |
IF acceptFlag THEN AcceptEdits; | |
whiteFlag := FALSE; | |
IF theKey = CHR(3) { enter } THEN | |
BEGIN | |
PlaceCaret(caretLoc,FALSE); | |
EXIT(TextChar); | |
END; | |
IF textLines = 0 THEN { create first stringhandle } | |
BEGIN | |
txHndl := Pointer(ORD(NewHandle(82))); | |
IF txHndl = Nil THEN EXIT(TextChar); | |
textHandles[1] := txHndl; | |
txHndl^^ := ''; { install empty string } | |
textLines := 1; | |
END; | |
IF theKey = CHR(13) THEN | |
BEGIN | |
{ start a new line } | |
IF textLines = maxLines THEN EXIT(TextChar); | |
txHndl := Pointer(ORD(NewHandle(82))); | |
IF txHndl = Nil THEN EXIT(TextChar); | |
textLines := textLines + 1; | |
textHandles[textLines] := txHndl; | |
txHndl^^ := ''; { install empty string } | |
END; | |
IF theKey = CHR(8) THEN | |
BEGIN | |
{ backspace over a character } | |
thisLine := textHandles[textLines]; | |
len := Length(thisLine^^); | |
IF len > 0 THEN DeleteChar(thisLine^^) | |
ELSE IF textLines > 0 THEN | |
BEGIN | |
DisposHandle(Pointer(ORD(thisLine))); | |
textLines := textLines - 1; | |
END; | |
END; | |
IF theKey >= ' ' THEN | |
BEGIN | |
{ add theKey to text and re-draw } | |
thisLine := textHandles[textLines]; | |
len := Length(thisLine^^); | |
IF len < 80 THEN AppendChar(theKey,thisLine^^); | |
END; | |
{ redraw this line of text } | |
ObscureCursor; | |
UpdateText; | |
END; | |
{$S } | |
PROCEDURE InvTool; | |
VAR tempRect: Rect; | |
BEGIN | |
WITH tempRect DO | |
BEGIN | |
top := toolTop + 1 + (theTool DIV 2) * toolSpace; | |
bottom := top + toolSpace - 1; | |
IF ODD(theTool) THEN | |
BEGIN | |
left := toolMid+1; | |
right := toolRight-1 | |
END | |
ELSE | |
BEGIN | |
left := toolLeft+1; | |
right := toolMid; | |
END; | |
END; { with tempRect } | |
InvertRect(tempRect); | |
END; | |
{$S SegUpdate } | |
PROCEDURE DrawTool; | |
VAR i,h,v,whichChar: INTEGER; | |
tempRect: Rect; | |
BEGIN | |
OffsetRect(toolRect,1,1); | |
PaintRect(toolRect); | |
OffsetRect(toolRect,-1,-1); | |
EraseRect(toolRect); | |
FrameRect(toolRect); | |
MoveTo(toolMid,toolTop); | |
LineTo(toolMid,toolBottom); | |
v := toolTop; | |
whichChar := ORD('E'); | |
FOR i := 0 TO 9 DO | |
BEGIN | |
MoveTo(toolLeft + 14 - CharWidth(CHR(whichChar)) DIV 2, v + 4); | |
DrawChar(CHR(whichChar)); | |
whichChar := whichChar + 1; | |
MoveTo(toolMid + 14 - CharWidth(CHR(whichChar)) DIV 2, v + 4); | |
DrawChar(CHR(whichChar)); | |
whichChar := whichChar + 1; | |
v := v + toolSpace; | |
MoveTo(toolLeft,v); | |
IF i <> 9 THEN LineTo(toolRight-1,v); | |
END; | |
InvTool; | |
END; | |
PROCEDURE DrawLine; FORWARD; | |
{$S } | |
PROCEDURE UpdateWindow(* whichWindow: WindowPtr; okToSmash: BOOLEAN *); | |
BEGIN | |
SetPort(whichWindow); | |
BeginUpdate(whichWindow); | |
IF whichWindow = @myWind THEN | |
BEGIN | |
IF okToSmash AND NOT scrnFlag THEN BitsToScrn(altBits) | |
ELSE CopyBits(altBits,myWind.port.portBits, | |
altBits.bounds,myWind.port.portRect,srcCopy,Nil) | |
END | |
ELSE IF whichWindow = @deskWind THEN | |
BEGIN | |
FillRect(deskWind.port.portRect,gray); | |
IF RectInRgn(toolRect,deskWind.port.visRgn) THEN DrawTool; | |
IF RectInRgn(lineRect,deskWind.port.visRgn) THEN DrawLine; | |
IF RectInRgn(patRect,deskWind.port.visRgn) THEN DrawPat; | |
END; | |
EndUpdate(whichWindow); | |
END; | |
{$S } | |
PROCEDURE SetToolCursor; | |
VAR saveBits: BitMap; | |
savePort: GrafPtr; | |
dataCh,maskCh: CHAR; | |
hotH,hotV: INTEGER; | |
BEGIN | |
hotH := 8; | |
hotV := 8; | |
maskCh := CHR(97); { all zeros } | |
CASE theTool OF | |
lassoTool: BEGIN | |
dataCh := CHR(69); | |
hotH := 2; | |
hotV := 15; | |
END; | |
selectTool: | |
BEGIN | |
dataCh := CHR(114); | |
maskCh := CHR(115); | |
END; | |
grabberTool: | |
BEGIN | |
dataCh := CHR(71); | |
maskCh := CHR(109); | |
END; | |
textTool: | |
BEGIN | |
dataCh := CHR(110); | |
hotV := 13; | |
END; | |
fillTool: | |
BEGIN | |
dataCh := CHR(73); | |
maskCh := CHR(93); | |
hotH := 13; | |
hotV := 16; | |
END; | |
sprayTool: dataCh := CHR(111); | |
brushTool: dataCh := CHR(120 + theBrush); | |
pencilTool: | |
BEGIN | |
dataCh := CHR(76); | |
maskCh := CHR(116); | |
hotH := 3; | |
hotV := 16; | |
END; | |
eraseTool: | |
BEGIN | |
dataCh := CHR(119); { erase box } | |
maskCh := CHR(120); { all ones } | |
END; | |
OTHERWISE CASE lineSize OF | |
1: dataCh := CHR(89); | |
2: dataCh := CHR(90); | |
4: dataCh := CHR(91); | |
8: dataCh := CHR(92); | |
END; | |
END; | |
GetPort(savePort); | |
SetPort(@deskWind); | |
saveBits := deskWind.port.portBits; | |
ZeroMem(@toolCursor.data,64); { clear data and mask } | |
deskWind.port.portBits.baseAddr := @toolCursor.data; | |
deskWind.port.portBits.rowBytes := 2; | |
SetRect(deskWind.port.portBits.bounds,toolLeft,toolTop,toolLeft+16,toolTop+16); | |
MoveTo(toolLeft,toolTop); | |
DrawChar(dataCh); | |
deskWind.port.portBits.baseAddr := @toolCursor.mask; | |
MoveTo(toolLeft,toolTop); | |
DrawChar(maskCh); | |
toolCursor.hotSpot.h := hotH; | |
toolCursor.hotSpot.v := hotv; | |
deskWind.port.portBits := saveBits; | |
SetPort(savePort); | |
cursorFlag := TRUE; | |
END; | |
{$S SegBrush } | |
PROCEDURE ChooseBrush; | |
CONST hLeft = 16; | |
vTop = 16; | |
hSpace = 32; | |
vSpace = 32; | |
hLeft2 = 24; { hLeft + hSpace DIV 2 - 8 } | |
vTop2 = 24; { vTop + vSpace DIV 2 - 8 } | |
nRows = 4; { beware, wired into BitAnd below } | |
nCols = 8; | |
maxRow = 3; { nRows - 1 } | |
maxCol = 7; { nCols - 1 } | |
VAR myDialog: DialogPtr; | |
dResult: INTEGER; | |
row,col: INTEGER; | |
pt: Point; | |
horiz,vert,brush: INTEGER; | |
PROCEDURE InvBrush; | |
VAR tempRect: Rect; | |
BEGIN | |
WITH tempRect DO | |
BEGIN | |
left := hLeft + col * hSpace; | |
right := left + hSpace; | |
top := vTop + row * vSpace; | |
bottom := top + vSpace; | |
PenSize(2,2); | |
PenMode(patXor); | |
FrameRect(tempRect); | |
PenNormal; | |
END; | |
END; | |
BEGIN | |
AcceptEdits; | |
myDialog := GetNewDialog(brushDlog, Nil, Pointer(-1)); | |
SetPort(myDialog); | |
TextFont(paintFont); | |
brush := 120; | |
horiz := hLeft2; | |
FOR col := 0 TO maxCol DO | |
BEGIN | |
vert := vTop2; | |
FOR row := 0 TO maxRow DO | |
BEGIN | |
MoveTo(horiz,vert); | |
DrawChar(CHR(brush)); | |
vert := vert + vSpace; | |
brush := brush + 1; | |
END; | |
horiz := horiz + hSpace; | |
END; | |
TextFont(systemFont); | |
col := theBrush DIV nRows; | |
row := BitAnd(theBrush,3); | |
InvBrush; { highlight old } | |
ModalDialog(Nil,dResult); | |
GetMouse(pt); | |
InvBrush; { unhighlight old } | |
row := PinWord((pt.v - vTop) DIV vSpace,0,maxRow); | |
col := PinWord((pt.h - hLeft) DIV hSpace,0,maxCol); | |
InvBrush; { highlight new } | |
theBrush := row + col*nRows; | |
SetToolCursor; | |
REPEAT UNTIL NOT StillDown; | |
DisposDialog(myDialog); | |
killDouble := TRUE; | |
END; | |
PROCEDURE ShowPage; FORWARD; | |
{$S } | |
PROCEDURE ChooseTool(pt: Point); | |
VAR tempRect: Rect; | |
cheapSet: LongInt; | |
BEGIN | |
KillStuff; | |
oldSelFlag := FALSE; | |
acceptFlag := FALSE; | |
fatScroll := FALSE; | |
SetPort(@deskWind); | |
IF theTool <> eraseTool THEN prevTool := theTool; | |
InvTool; { deselect old tool } | |
theTool := 2*((pt.v - toolTop) DIV toolSpace); | |
IF theTool > 18 then theTool := 18; | |
IF pt.h > toolMid THEN theTool := theTool + 1; | |
tempRect := myWind.port.portRect; | |
IF fatFlag THEN tempRect := fatBits.bounds; | |
IF (theTool = eraseTool) AND (clickCount > 1) AND windOpen | |
THEN { erase all } | |
BEGIN | |
AcceptEdits; | |
SetPort(@myWind.port); | |
SetPortBits(altBits); | |
EraseRect(tempRect); | |
AltToScrn; | |
SetPort(@deskWind); | |
theTool := prevTool; { we wont need the eraser anymore } | |
clickCount := 1; { for below } | |
workDirty := TRUE; | |
docDirty := TRUE; | |
END; | |
InvTool; { select new tool } | |
SetToolCursor; | |
cheapSet := $50BF3000; | |
toolGrid := BitTst(@cheapSet,theTool); | |
{ toolGrid := theTool IN [1,3,8,10,11,12,13,14,15,18,19]; } | |
IF theTool = textTool THEN | |
BEGIN | |
SetPort(@myWind); | |
GetFontInfo(info); { swap in font } | |
END; | |
IF clickCount > 1 THEN | |
BEGIN | |
IF theTool = brushTool THEN ChooseBrush; | |
IF windOpen THEN | |
BEGIN | |
IF theTool = selectTool THEN { select entire window } | |
BEGIN | |
tempRect.right := tempRect.right + 1; | |
tempRect.bottom := tempRect.bottom + 1; | |
SetSelRect(tempRect,TRUE); | |
selFlag := TRUE; | |
oldSelRect := selRect; | |
whiteFlag := TRUE; | |
acceptFlag := TRUE; | |
END; | |
IF theTool = grabberTool THEN ShowPage; | |
IF theTool = pencilTool THEN MenuCommand(aidsMenu,fatItem); | |
END; | |
END; | |
END; | |
{$S } | |
PROCEDURE InvLnSize; | |
CONST check = 65; | |
VAR v: INTEGER; | |
BEGIN | |
SetPort(@deskWind); | |
v := lineTop + 5; | |
IF borderFlag THEN CASE lineSize OF | |
1: v := lineTop + 15; | |
2: v := lineTop + 26; | |
4: v := lineTop + 38; | |
8: v := lineTop + 52; | |
END; | |
MoveTo(lineLeft + 2, v); | |
TextMode(srcXor); | |
DrawChar(CHR(check)); | |
TextMode(srcOr); | |
END; | |
{$S } | |
PROCEDURE ChooseLine(pt: Point); | |
BEGIN | |
InvLnSize; { un-check old line size } | |
lineSize := 1; | |
borderFlag := (pt.v > lineTop + 18); | |
IF pt.v > lineTop + 28 THEN lineSize := 2; | |
IF pt.v > lineTop + 39 THEN lineSize := 4; | |
IF pt.v > lineTop + 52 THEN lineSize := 8; | |
SetLineSize(lineSize); | |
InvLnSize; { check new line size } | |
IF theTool >= lineTool THEN SetToolCursor; { update toolCursor } | |
END; | |
{$S SegUpdate } | |
PROCEDURE DrawLine; | |
VAR i,h,v: INTEGER; | |
tempRect: Rect; | |
BEGIN | |
OffsetRect(lineRect,1,1); | |
PaintRect(lineRect); | |
OffsetRect(lineRect,-1,-1); | |
EraseRect(lineRect); | |
FrameRect(lineRect); | |
WITH tempRect DO | |
BEGIN | |
right := lineRight - 7; | |
left := lineLeft + 17; | |
top := lineTop + 12; | |
bottom := top + 1; | |
FillRect(tempRect,ltGray); { no border } | |
top := lineTop + 23; | |
bottom := top + 1; | |
PaintRect(tempRect); { line size 1 } | |
top := lineTop + 33; | |
bottom := top + 2; | |
PaintRect(tempRect); { line size 2 } | |
top := lineTop + 44; | |
bottom := top + 4; | |
PaintRect(tempRect); { line size 4 } | |
top := lineTop + 57; | |
bottom := top + 8; | |
PaintRect(tempRect); { line size 8 } | |
END; | |
InvLnSize; | |
END; | |
{$S SegPatEdit } | |
FUNCTION MyFilter(theDialog: DialogPtr; | |
VAR event: EventRecord; | |
VAR item: INTEGER): BOOLEAN; | |
VAR windPeek: WindowPeek; | |
BEGIN | |
MyFilter := FALSE; | |
IF event.what = mouseDown THEN | |
BEGIN | |
windPeek := Pointer(ORD(theDialog)); | |
IF PtInRect(event.where,docRect) | |
AND NOT PtInRgn(event.where,windPeek^.strucRgn) THEN | |
BEGIN | |
patEdPt := event.where; | |
item := 4; | |
MyFilter := TRUE; | |
END; | |
END; | |
END; | |
{$S SegPatEdit } | |
PROCEDURE EditPat; | |
VAR myDialog: DialogPtr; | |
dResult: INTEGER; | |
i,j: INTEGER; | |
editRect,sampleRect,tempRect: Rect; | |
savePort: GrafPtr; | |
newPat: Pattern; | |
newPt,oldPt: Point; | |
bitNum: LongInt; | |
whiteFlg: BOOLEAN; | |
PROCEDURE GetPoint(VAR pt: Point); | |
BEGIN | |
GetMouse(pt); | |
pt.h := PinWord((pt.h - editRect.left) DIV 8, 0,7); | |
pt.v := PinWord((pt.v - editRect.top) DIV 8, 0,7); | |
END; | |
PROCEDURE PlotDot(ix,iy: INTEGER); | |
VAR tempRect: Rect; | |
BEGIN | |
WITH tempRect DO | |
BEGIN | |
left := editRect.left + ix * 8; | |
right := left + 7; | |
top := editRect.top + iy * 8; | |
bottom := top + 7; | |
END; | |
PaintRect(tempRect); | |
END; | |
BEGIN | |
GetPort(savePort); { needed ? } | |
KillStuff; | |
AcceptEdits; | |
newPat := patterns[thePatIndex]; | |
myDialog := GetNewDialog(patEdDlog, Nil, POINTER(-1)); | |
SetPort(myDialog); | |
PenNormal; | |
SetRect(editRect,15,15,80,80); | |
FrameRect(editRect); | |
InsetRect(editRect,1,1); | |
bitNum := 0; | |
FOR j := 0 TO 7 DO | |
FOR i := 0 to 7 DO | |
BEGIN | |
IF BitTst(@newPat,bitNum) THEN PlotDot(i,j); | |
bitNum := bitNum + 1; | |
END; | |
SetRect(sampleRect,95,15,160,80); | |
FrameRect(sampleRect); | |
InsetRect(sampleRect,1,1); | |
FillRect(sampleRect,newPat); | |
REPEAT | |
ModalDialog(@MyFilter,dResult); | |
CASE dResult OF | |
1: BEGIN { hit OK } | |
IF NOT EqualLongs(@newPat,@thePat,2) THEN | |
BEGIN | |
patterns[thePatIndex] := newPat; | |
workDirty := TRUE; | |
docDirty := TRUE; | |
DrawPat; | |
END; | |
END; | |
2: BEGIN { hit CANCEL } | |
END; | |
3: BEGIN { click in 8 by 8 } | |
GetPoint(oldPt); | |
bitNum := 8 * oldPt.v + oldPt.h; | |
whiteFlg := BitTst(@newPat,bitNum); | |
PenNormal; | |
IF whiteFlg THEN PenPat(white); | |
PlotDot(oldPt.h,oldPt.v); | |
IF whiteFlg THEN BitClr(@newPat,bitNum) | |
ELSE BitSet(@newPat,bitNum); | |
FillRect(sampleRect,newPat); | |
REPEAT | |
GetPoint(newPt); | |
IF NOT EqualPt(oldPt,newPt) THEN | |
BEGIN | |
PlotDot(newPt.h,newPt.v); | |
bitNum := 8 * newPt.v + newPt.h; | |
IF whiteFlg THEN BitClr(@newPat,bitNum) | |
ELSE BitSet(@newPat,bitNum); | |
FillRect(sampleRect,newPat); | |
oldPt := newPt; | |
END; | |
UNTIL NOT StillDown; | |
END; | |
4: BEGIN { pick up pattern } | |
PenNormal; | |
newPat := white; | |
EraseRect(editRect); | |
EraseRect(sampleRect); | |
SetPort(@myWind); | |
GlobalToLocal(patEdPt); | |
patEdPt.h := Trunc8(patEdPt.h + 4); | |
patEdPt.v := Trunc8(patEdPt.v + 4); | |
bitNum := 0; | |
FOR j := 0 TO 7 DO | |
FOR i := 0 to 7 DO | |
BEGIN | |
IF GetPixel(patEdPt.h+i,patEdPt.v+j) THEN | |
BEGIN | |
BitSet(@newPat,bitNum); | |
SetPort(myDialog); | |
PlotDot(i,j); | |
SetPort(@myWind); | |
END; | |
bitNum := bitNum + 1; | |
END; | |
SetPort(myDialog); | |
FillRect(sampleRect,newPat); | |
END; | |
END; { case dResult } | |
UNTIL (dResult = 1) OR (dResult = 2); | |
DisposDialog(myDialog); | |
SetPort(savePort); | |
END; | |
{$S } | |
PROCEDURE ChoosePat(pt: Point); | |
BEGIN | |
IF pt.h > patStart THEN | |
BEGIN | |
thePatIndex := (pt.h - patStart) DIV patSpace; | |
IF pt.v > patMid THEN thePatIndex := thePatIndex + patRow; | |
thePat := patterns[thePatIndex]; | |
FillRect(fillSample,thePat); | |
END; | |
IF clickCount > 1 THEN EditPat; | |
END; | |
{$S SegSym } | |
PROCEDURE Symmetry; | |
CONST hLeft = 32; | |
vTop = 16; | |
hRight = 144; | |
vBottom = 128; | |
hMid = 88; | |
vMid = 72; | |
VAR myDialog: DialogPtr; | |
dResult: INTEGER; | |
savePort: GrafPtr; | |
clickPt: Point; | |
midPt: Point; | |
symRect: Rect; | |
PROCEDURE DrawSym; | |
BEGIN | |
SetRect(symRect,hLeft,vTop,hRight,vBottom); | |
EraseRect(symRect); | |
FrameRect(symRect); | |
InsetRect(symRect,1,1); | |
ClipRect(symRect); | |
PenNormal; | |
MoveTo(hMid,vTop); | |
IF hSymFlag THEN | |
BEGIN | |
PenSize(3,3); | |
Moov(-1,-1); | |
END; | |
Line(0,112); | |
PenNormal; | |
MoveTo(hLeft,vMid); | |
IF vSymFlag THEN | |
BEGIN | |
PenSize(3,3); | |
Moov(-1,-1); | |
END; | |
Line(112,0); | |
PenNormal; | |
MoveTo(hLeft,vTop); | |
IF hvSymFlag THEN | |
BEGIN | |
PenSize(3,3); | |
Moov(-1,-1); | |
END; | |
Line(112,112); | |
PenNormal; | |
MoveTo(hLeft,vBottom); | |
IF vhSymFlag THEN | |
BEGIN | |
PenSize(3,3); | |
Moov(-1,-1); | |
END; | |
Line(112,-112); | |
ClipRect(thePort^.portRect); | |
PenNormal; | |
END; | |
BEGIN | |
GetPort(savePort); { needed ? } | |
AcceptEdits; | |
midPt.h := hMid; | |
midPt.v := vMid; | |
myDialog := GetNewDialog(symDlog, Nil, Pointer(-1)); | |
SetPort(myDialog); | |
DrawSym; | |
REPEAT | |
ModalDialog(Nil,dResult); | |
CASE dResult OF | |
1: BEGIN { hit OK } | |
END; | |
2: BEGIN { hit CANCEL } | |
hSymFlag := FALSE; | |
vSymFlag := FALSE; | |
hvSymFlag := FALSE; | |
vhSymFlag := FALSE; | |
END; | |
3: BEGIN | |
GetMouse(clickPt); | |
Constrain(midPt,clickPt,TRUE); | |
IF clickPt.h = midPt.h THEN hSymFlag := NOT hSymFlag | |
ELSE IF clickPt.v = midPt.v THEN vSymFlag := NOT vSymFlag | |
ELSE IF (clickPt.h-midPt.h) = (clickPt.v - midPt.v) | |
THEN hvSymFlag := NOT hvSymFlag | |
ELSE vhSymFlag := NOT vhSymFlag; | |
DrawSym; | |
REPEAT UNTIL NOT StillDown; | |
END; | |
END; { case dResult } | |
UNTIL (dResult = 1) OR (dResult = 2); | |
symByte := MapSym(hSymFlag,vSymFlag,hvSymFlag,vhSymFlag); | |
CheckItem(myMenus[aidsMenu],symItem,(symByte <> -128)); | |
DisposDialog(myDialog); | |
SetPort(savePort); | |
END; | |
{$S SegPage } | |
PROCEDURE ShowPage; | |
LABEL 9; | |
VAR event: EventRecord; | |
newPt,oldPt: Point; | |
smallPage: Rect; | |
windRect: Rect; | |
oldWindRect: Rect; | |
newOrigin: Point; | |
windLeft,windTop: INTEGER; | |
shiftDh: INTEGER; | |
shiftDv: INTEGER; | |
scrollDh: INTEGER; | |
scrollDv: INTEGER; | |
shiftPage,scrollPage: BOOLEAN; | |
dstRect: Rect; | |
dstFile: INTEGER; | |
ok,cancel: BOOLEAN; | |
theControl: ControlHandle; | |
saveOrigin: Point; | |
BEGIN | |
AcceptEdits; | |
fatFlag := FALSE; | |
CheckItem(myMenus[aidsMenu],fatItem,fatFlag); | |
{ draw small image } | |
dstFile := 0; | |
IF workDirty THEN dstFile := workTo; | |
ReadWrite(workFrom,dstFile,workDirty,FALSE,TRUE,FALSE,FALSE); | |
IF rwResult <> 0 THEN | |
BEGIN | |
quitFlag := TRUE; | |
EXIT(ShowPage); | |
END; | |
IF workDirty THEN | |
BEGIN | |
SwapWord(workFrom,workTo); | |
workDirty := FALSE; | |
END; | |
InitCursor; { get rid of hourglass } | |
smallPage := myWind.port.portRect; | |
smallPage.left := myWind.port.portRect.left + 208 - 96; | |
smallPage.right := smallPage.left + 192; | |
windRect := myWind.port.portRect; | |
MapRect(windRect,pageRect,smallPage); | |
oldWindRect := windRect; | |
{ allocate offscreen buffer for small image } | |
IF NOT AllocMask THEN GOTO 9; | |
saveOrigin := myWind.port.portRect.topLeft; | |
SetOrigin(0,0); | |
ShowControl(okButton); | |
ShowControl(cancelButton); | |
SetOrigin(saveOrigin.h,saveOrigin.v); | |
ScrnToAlt; | |
BufToBuf(@altBuf,maskBits.baseAddr); | |
PenMode(patXor); | |
PenPat(gray); | |
SetPortBits(altBits); | |
FrameRect(windRect); { draw initial windRect in xor } | |
AltToScrn; | |
ok := FALSE; | |
cancel := FALSE; | |
shiftDh := 0; | |
shiftDv := 0; | |
REPEAT | |
REPEAT UNTIL GetNextEvent(everyEvent,event) { ignore all events } | |
AND (event.what = mouseDown); { till a button down } | |
shiftFlag := (BitAnd(event.modifiers,shiftKey) <> 0); | |
GlobalToLocal(event.where); | |
oldPt := event.where; | |
IF NOT PtInRect(event.where,smallPage) THEN | |
BEGIN | |
LocalToGlobal(event.where); | |
SetOrigin(0,0); | |
GlobalToLocal(event.where); | |
IF FindControl(event.where,@myWind,theControl) = 0 THEN SystemBeep(8) | |
ELSE IF TrackControl(theControl,event.where,Nil) <> 0 THEN | |
BEGIN | |
IF theControl = okButton THEN ok := TRUE; | |
IF theControl = cancelButton THEN cancel := TRUE; | |
END; | |
SetOrigin(saveOrigin.h,saveOrigin.v); | |
END; | |
InitConstrain(oldPt); | |
windLeft := windRect.left; | |
windTop := windRect.top; | |
IF PtInRect(oldPt,windRect) THEN { scroll page } | |
REPEAT | |
GetMouse(newPt); | |
HVConstrain(newPt); | |
IF NOT EqualPt(newPt,oldPt) THEN | |
BEGIN | |
SetPortBits(altBits); | |
FrameRect(windRect); { erase old windRect } | |
windLeft := windLeft + newPt.h - oldPt.h; | |
windTop := windTop + newPt.v - oldPt.v; | |
WITH windRect DO | |
BEGIN | |
left := PinWord(windLeft,smallPage.left,smallPage.right-138); | |
top := PinWord(windTop,smallPage.top,smallPage.bottom-80); | |
right := left + 138; | |
bottom := top + 80; | |
END; | |
FrameRect(windRect); { draw new windRect } | |
AltToScrn; | |
oldPt := newPt; | |
END; | |
UNTIL NOT StillDown | |
ELSE IF PtInRect(oldPt,smallPage) THEN { shift page } | |
BEGIN | |
ClipRect(smallPage); | |
REPEAT | |
GetMouse(newPt); | |
HVConstrain(newPt); | |
IF NOT EqualPt(newPt,oldPt) THEN | |
BEGIN | |
shiftDh := shiftDh + newPt.h - oldPt.h; | |
shiftDv := shiftDv + newPt.v - oldPt.v; | |
dstRect := smallPage; | |
OffsetRect(dstRect,shiftDh,shiftDv); | |
SetPortBits(altBits); | |
EraseRect(smallPage); | |
MaskToAlt(smallPage,dstRect,srcCopy); | |
FrameRect(windRect); | |
AltToScrn; | |
oldPt := newPt; | |
END; | |
UNTIL NOT StillDown; | |
ClipRect(pageRect); | |
END; | |
UNTIL ok OR cancel; | |
{ 'Hide' buttons without leaving white } | |
HidePen; | |
HideControl(okButton); | |
HideControl(cancelButton); | |
ShowPen; | |
PenNormal; | |
KillMask; | |
IF ok THEN | |
BEGIN | |
{ always shift to nearest 8 to keep patterns aligned } | |
shiftDh := ((3 * shiftDh) DIV 8) * 8; | |
shiftDv := ((3 * shiftDv) DIV 8) * 8; | |
shiftPage := (shiftDh <> 0) OR (shiftDv <> 0); | |
scrollDh := 3 * (windRect.left - oldWindRect.left); | |
scrollDv := 3 * (windRect.top - oldWindRect.top); | |
scrollPage := (scrollDh <> 0) OR (scrollDv <> 0); | |
IF shiftPage OR scrollPage THEN | |
BEGIN | |
newOrigin := myWind.port.portRect.topLeft; | |
newOrigin.h := newOrigin.h + scrollDh; | |
newOrigin.v := newOrigin.v + scrollDv; | |
{ pin at edges if less than 3 from edges } | |
IF newOrigin.h < 3 THEN newOrigin.h := 0; | |
IF newOrigin.v < 3 THEN newOrigin.v := 0; | |
IF newOrigin.h > docWidth-419 THEN newOrigin.h := docWidth-416; | |
IF newOrigin.v > docHeight-243 THEN newOrigin.v := docHeight-240; | |
SetOrigin(newOrigin.h,newOrigin.v); | |
docBits := myWind.port.portBits; | |
altBits.bounds := myWind.port.portRect; | |
OffsetRect(mainBits.bounds,0,shiftDv); { for ReadWrite } | |
dstFile := 0; | |
IF shiftPage THEN dstFile := workTo; | |
rwShftDh := shiftDh; | |
rwShftDv := shiftDv; | |
ReadWrite(workFrom,dstFile,TRUE,TRUE,FALSE,FALSE,FALSE); | |
rwShftDh := 0; | |
rwShftDv := 0; | |
IF shiftPage THEN | |
BEGIN | |
SwapWord(workFrom,workTo); | |
docDirty := TRUE; | |
END; | |
mainBits.bounds := altBits.bounds; | |
maskBits.bounds := altBits.bounds; | |
fatCenter.h := newOrigin.h+208; | |
fatCenter.v := newOrigin.v+120; | |
AcceptEdits; | |
END; | |
END; { if OK } | |
9: MainToAlt; | |
AltToScrn; | |
END; | |
{$S SegPrint } | |
FUNCTION OldPrDrvr: BOOLEAN; | |
{ Open print driver and check for old version. } | |
VAR aResult: INTEGER; | |
BEGIN | |
PrDrvrOpen; | |
PrNoPurge; | |
OldPrDrvr := FALSE; | |
IF PrDrvrVers < 2 THEN | |
BEGIN | |
OldPrDrvr := TRUE; | |
PrPurge; | |
PrDrvrClose; | |
aResult := MyAlert(oldPrAlrt); | |
END; | |
END; | |
{$S SegPrint } | |
PROCEDURE PrintDoc; | |
VAR dstFile: INTEGER; | |
BEGIN | |
IF OldPrDrvr THEN EXIT(PrintDoc); | |
AcceptEdits; | |
dstFile := 0; | |
IF workDirty THEN dstFile := workTo; | |
PrCtlCall(iPrDevCtl,lPrReset,0,0); | |
ReadWrite(workFrom,dstFile,workDirty,FALSE,TRUE,TRUE,FALSE); | |
PrCtlCall(iPrDevCtl,lPrPageEnd,0,0); | |
IF workDirty THEN | |
BEGIN | |
SwapWord(workFrom,workTo); | |
workDirty := FALSE; | |
END; | |
AltToScrn; | |
PrPurge; | |
PrDrvrClose; | |
END; | |
{$S SegPrint } | |
PROCEDURE FinderPrint; | |
LABEL 9; | |
VAR result,srcFile: INTEGER; | |
BEGIN | |
IF OldPrDrvr THEN EXIT(FinderPrint); | |
REPEAT | |
SetWTitle(@myWind,docName); | |
result := OpenFile(docDrive,docVersion,docName,Nil,srcFile); | |
IF ReadError(result,Nil) THEN GOTO 9; | |
PrCtlCall(iPrDevCtl,lPrReset,0,0); | |
ReadWrite(srcFile,0,FALSE,FALSE,TRUE,TRUE,FALSE); | |
PrCtlCall(iPrDevCtl,lPrPageEnd,0,0); | |
result := CloseFile(srcFile); | |
AltToScrn; | |
IF (NOT okPrint) OR (rwResult <> 0) THEN GOTO 9; | |
finderMsg := FinderDoc(docDrive,docVersion,@docName); | |
UNTIL finderMsg <> printMsg; | |
9: | |
PrPurge; | |
PrDrvrClose; | |
END; | |
{$S SegPrint } | |
PROCEDURE GetCatPic(drive,version,index: INTEGER; VAR name: Str63); | |
LABEL 9; | |
CONST bandSize = 704; { docRow * 8 + 128 } | |
VAR bandBuf: ARRAY[1..bandSize] OF QDByte; | |
bandBits: BitMap; | |
result,band,scanLine: INTEGER; | |
srcByte: LongInt; | |
srcPtr,bandPtr,oldPtr: QDPtr; | |
grow: LongInt; | |
srcSize: LongInt; | |
srcHandle: Handle; | |
srcFirst,srcLast: ^DiskBlock; | |
srcBytes: ARRAY[1..72] OF QDByte; | |
srcFile: INTEGER; | |
dstRect: Rect; | |
thisRow,nextRow: ARRAY[0..72] OF QDByte; { one extra ! } | |
BEGIN | |
WITH dstRect DO | |
BEGIN | |
left := 28 + 112 * index; | |
right := left + 72; | |
top := 32; | |
bottom := top + 90; | |
END; | |
FrameRect(dstRect); | |
MoveTo(dstRect.left + 36 - StringWidth(name) DIV 2, dstRect.bottom + 16); | |
DrawString(name); | |
result := OpenFile(drive,version,name,Nil,srcFile); | |
IF (result <> 0) THEN EXIT(GetCatPic); | |
srcByte := 512; { skip header } | |
srcSize := BitAnd(MaxMem(grow),$FFFFFE00); { trunc to mult of 512 } | |
srcHandle := NewHandle(srcSize); | |
HLock(srcHandle); | |
srcFirst := Pointer(ORD(srcHandle^)); | |
srcLast := Pointer(ORD(srcFirst) + srcSize - 512); | |
WITH bandBits DO | |
BEGIN | |
baseAddr := @bandBuf; | |
rowBytes := docRow; | |
bounds.left := 0; | |
bounds.top := 0; | |
bounds.right := docWidth; | |
bounds.bottom := 8; | |
END; | |
{ prime srcBuf } | |
result := ReadData(srcFile,srcByte,srcSize,Pointer(ORD(srcFirst))); | |
IF (result <> 0) AND (result <> endOfFile) THEN GOTO 9; | |
srcPtr := Pointer(ORD(srcFirst)); | |
FOR band := 1 to 90 DO | |
BEGIN | |
bandPtr := @bandBuf; | |
FOR scanLine := 1 TO 8 DO { read and unpack 8 scanlines } | |
BEGIN | |
oldPtr := bandPtr; | |
UnpackBits(srcPtr,bandPtr,docRow); | |
IF ORD(bandPtr) - ORD(oldPtr) <> docRow THEN | |
BEGIN | |
SystemBeep(8); { bad document } | |
GOTO 9; | |
END; | |
IF ORD(srcPtr) >= ORD(srcLast) THEN | |
BEGIN | |
srcFirst^ := srcLast^; | |
result := ReadData(srcFile,srcByte,srcSize-512, | |
Pointer(ORD(srcFirst)+512)); | |
IF (result <> 0) AND (result <> endOfFile) THEN GOTO 9; | |
srcPtr := Pointer(ORD(srcPtr) - srcSize + 512); | |
END; | |
END; | |
SampleBits(@bandBuf,@nextRow); | |
IF band = 1 THEN thisRow := nextRow; | |
HToneRow(@thisRow,@nextRow,thePort^.portBits, | |
dstRect.left,dstRect.top,72,8,64,FALSE); | |
thisRow := nextRow; | |
OffsetRect(dstRect,0,1); | |
END; | |
9: HUnlock(srcHandle); | |
DisposHandle(srcHandle); | |
result := CloseFile(srcFile); | |
END; | |
{$S SegPrint } | |
PROCEDURE PrintCatalog; | |
VAR i,horiz,vert,doc: INTEGER; | |
tempPort: GrafPort; | |
docCount: INTEGER; | |
fileName: Str63; | |
fileVersion: INTEGER; | |
headerHandle: StringHandle; | |
BEGIN | |
IF OldPrDrvr THEN EXIT(PrintCatalog); | |
BusyCursor; | |
OpenPort(@tempPort); | |
TextFont(3); { Ardmore } | |
TextSize(12); | |
WITH tempPort.portBits DO | |
BEGIN | |
baseAddr := @altBuf; { borrow memory from altBuf } | |
rowBytes := 72; | |
bounds.left := 0; | |
bounds.right := 576; | |
bounds.top := 0; | |
bounds.bottom := 144; | |
END; | |
RectRgn(tempPort.visRgn,tempPort.portBits.bounds); | |
ZeroBuf(@altBuf); | |
MoveTo(28,10); | |
headerHandle := GetString(headerString); | |
i := CharWidth('A'); { swap font before de-referencing } | |
DrawString(headerHandle^^); | |
DrawChar(' '); | |
docCount := CountFiles(docDrive,fileName); | |
DrawString(fileName); | |
SetFontLock(TRUE); | |
horiz := 0; | |
vert := 0; | |
FOR doc := 1 TO docCount DO | |
IF NextFile(docDrive,doc,'PNTG',fileName,fileVersion) THEN | |
BEGIN | |
IF NOT EqualString(fileName,'Paint1') | |
AND NOT EqualString(fileName,'Paint2') | |
THEN | |
BEGIN | |
GetCatPic(docDrive,fileVersion,horiz,fileName); | |
horiz := horiz + 1; | |
IF horiz > 4 THEN | |
BEGIN | |
IF vert = 0 THEN PrCtlCall(iPrDevCtl,lPrReset,0,0); | |
okPrint := PrintRect(tempPort.portBits,tempPort.portBits.bounds); | |
ZeroBuf(@altBuf); | |
horiz := 0; | |
vert := vert + 1; | |
IF vert > 4 THEN | |
BEGIN | |
PrCtlCall(iPrDevCtl,lPrPageEnd,0,0); | |
vert := 0; | |
END; | |
END; | |
END; | |
END; | |
IF horiz <> 0 THEN { print last partial row } | |
BEGIN | |
okPrint := PrintRect(tempPort.portBits,tempPort.portBits.bounds); | |
vert := vert + 1; | |
END; | |
IF vert <> 0 THEN PrCtlCall(iPrDevCtl,lPrPageEnd,0,0); | |
DrawChar(' '); { make sure right font is unlocked. (disk swap) } | |
SetFontLock(FALSE); | |
MainToAlt; | |
ClosePort(@tempPort); | |
SetPort(@myWind); | |
PrPurge; | |
PrDrvrClose; | |
END; | |
{$S } | |
PROCEDURE NewDocInit; | |
BEGIN | |
mainBits.baseAddr := @mainBuf; | |
mainBits.rowBytes := 52; | |
SetRect(mainBits.bounds,80,120,80+416,120+240); | |
ZeroBuf(@mainBuf); | |
altBits := mainBits; | |
altBits.baseAddr := @altBuf; | |
ZeroBuf(@altBuf); | |
fatBits.baseAddr := @fatBuf; | |
fatBits.rowBytes := 8; | |
SetRect(fatBits.bounds,80+208-26,120+120-15,80+208+26,120+120+15); | |
fatCenter.h := 80+208; | |
fatCenter.v := 120+120; | |
pivot := fatCenter; | |
ZeroFat(@fatBuf); { install right and bottom borders } | |
fatFlag := FALSE; | |
CheckItem(myMenus[aidsMenu],fatItem,fatFlag); | |
SetPort(@myWind); | |
EraseRect(myWind.port.portRect); | |
TextFont(theFontID); | |
SetOrigin(mainBits.bounds.left,mainBits.bounds.top); | |
docBits := myWind.port.portBits; | |
textFlag := FALSE; | |
maskFlag := FALSE; | |
maskHandle := Nil; | |
edgeFlag := FALSE; | |
maskBits := mainBits; | |
whiteFlag := FALSE; | |
acceptFlag := FALSE; | |
selFlag := FALSE; | |
selRect := zeroRect; | |
lassoBlack := FALSE; | |
textLoc := zeroRect.topLeft; | |
textLeft := 0; | |
caretLoc := zeroRect.topLeft; | |
oldWhiteFlag := whiteFlag; | |
oldAcceptFlag := acceptFlag; | |
oldMaskFlag := maskFlag; | |
oldSelFlag := selFlag; | |
oldSelRect := selRect; | |
oldPivot := pivot; | |
oldLassoBlack := lassoBlack; | |
selIndex := 0; | |
docDirty := FALSE; | |
workDirty := FALSE; | |
END; | |
{$S } | |
PROCEDURE BlankDoc(dstFile: INTEGER); | |
VAR result,scanLine: INTEGER; | |
srcBuf: ARRAY[1..4] OF DiskBlock; | |
srcPtr: QDPtr; | |
dstByte: LongInt; | |
BEGIN | |
ZeroMem(@srcBuf,SizeOf(srcBuf)); | |
srcBuf[1,1] := 2; { version = 2 } | |
CopyLongs(@patterns,@srcBuf[1,2],38*2); { install current patterns } | |
srcPtr := @srcBuf[2]; | |
FOR scanLine := 1 TO 720 DO { fake up a blank packed document } | |
BEGIN | |
srcPtr^ := -71; { fill 72 opcode } | |
srcPtr := Pointer(ORD(srcPtr)+1); | |
srcPtr^ := 0; { fill data = 0 } | |
srcPtr := Pointer(ORD(srcPtr)+1); | |
END; | |
dstByte := 0; | |
result := WriteData(dstFile,dstByte,SizeOf(srcBuf),@srcBuf); | |
IF dstFile = workFrom THEN workSize := dstByte; | |
IF WriteError(result,Nil) THEN EXIT(BlankDoc); | |
FlushVol(workDrive); | |
END; | |
{$S } | |
FUNCTION SizeOfMain: LongInt; | |
{ how many bytes big is mainBuf when packed } | |
VAR srcPtr,dstPtr: QDPtr; | |
dstBuf: PACKED ARRAY[0..53] OF QDByte; | |
byteCount: LongInt; | |
scanline: INTEGER; | |
BEGIN | |
byteCount := 0; | |
srcPtr := @mainBuf; | |
FOR scanline := 1 TO 240 DO | |
BEGIN | |
dstPtr := @dstBuf; | |
PackBits(srcPtr,dstPtr,52); | |
byteCount := byteCount + ORD(dstPtr) - ORD(@dstBuf); | |
END; | |
SizeOfMain := byteCount; | |
END; | |
{$S } | |
FUNCTION SaveDoc(askFirst: BOOLEAN): BOOLEAN; | |
LABEL 1; | |
VAR result: INTEGER; | |
newFile: BOOLEAN; | |
saveFile: INTEGER; | |
reply: sfReply; | |
where: Point; | |
promptHndl: StringHandle; | |
bytesNeeded: LongInt; | |
bytesAvail: LongInt; | |
fileDate: LongInt; | |
fileSize: LongInt; | |
BEGIN | |
SaveDoc := FALSE; { assume failure } | |
{ set up reply in case SFPutFile not called } | |
reply.fName := docName; | |
reply.vRefnum := docDrive; | |
reply.version := docVersion; | |
1: IF askFirst OR (Length(docName) = 0) THEN | |
BEGIN | |
AcceptEdits; | |
BorrowAlt; { save screen image for refresh } | |
where.h := 124; | |
where.v := 100; | |
promptHndl := GetString(saveString); | |
HLock(Pointer(ORD(promptHndl))); | |
SFPutFile(where,promptHndl^^,docName,Nil,@reply); | |
HUnlock(Pointer(ORD(promptHndl))); | |
UpdateWindow(@myWind,FALSE); | |
MainToAlt; { restore saved screen image } | |
IF NOT reply.good THEN EXIT(SaveDoc); { hit cancel } | |
END; | |
bytesAvail := DiskSpace(reply.vRefnum); | |
{ create in case it didn't exist } | |
result := CreateFile(reply.vRefnum,reply.version,reply.fName); | |
newFile := (result <> fileExists); | |
IF NOT newFile THEN | |
BEGIN | |
IF NOT CheckPntg(reply.vRefnum,reply.version,reply.fName) THEN | |
BEGIN | |
{ existing doc is not a MacPaint document } | |
result := MyAlert(notPntgAlrt); | |
askFirst := TRUE; | |
GOTO 1; { try again } | |
END; | |
FileInfo(reply.vRefnum,reply.version,reply.fName,fileDate,fileSize); | |
bytesAvail := bytesAvail + fileSize; { since we will overwrite it } | |
END; | |
IF WriteError(result,Nil) THEN EXIT(SaveDoc); | |
bytesNeeded := workSize; | |
IF workDirty THEN bytesNeeded := bytesNeeded + SizeOfMain; | |
IF bytesNeeded > bytesAvail THEN { not enough room to save } | |
BEGIN | |
result := MyAlert(notRoomAlrt); | |
IF newFile THEN | |
result := DeleteFile(reply.vRefnum,reply.version,reply.fName); | |
askFirst := TRUE; | |
GOTO 1; { try again } | |
END; | |
result := OpenFile(reply.vRefnum,reply.version,reply.fName,Nil,saveFile); | |
IF WriteError(result,Nil) THEN EXIT(SaveDoc); | |
ReadWrite(workFrom,saveFile,workDirty,FALSE,FALSE,FALSE,FALSE); | |
result := CloseFile(saveFile); | |
IF WriteError(result,Nil) OR (rwResult <> 0) THEN | |
BEGIN | |
IF newFile THEN | |
result := DeleteFile(reply.vRefnum,reply.version,reply.fName); | |
EXIT(SaveDoc); | |
END; | |
{ only set docType if successfull } | |
SetDocType(reply.vRefnum,reply.version,reply.fName); | |
IF (docDrive <> reply.vRefNum) | |
OR (docVersion <> reply.version) | |
OR NOT EqualString(docName,reply.fName) THEN | |
BEGIN | |
docName := reply.fName; | |
docDrive := reply.vRefnum; | |
docVersion := reply.version; | |
SetWTitle(@myWind,docName); | |
END; | |
FlushVol(reply.vRefnum); | |
docDirty := FALSE; | |
SaveDoc := TRUE; | |
END; | |
{$S } | |
PROCEDURE RevertDoc; | |
VAR result,srcFile: INTEGER; | |
BEGIN | |
result := SaveAlert(revertAlrt); { are you sure } | |
IF result <> 1 THEN EXIT(RevertDoc); | |
IF Length(docName) = 0 THEN | |
BEGIN | |
NewDocInit; | |
BlankDoc(workFrom); | |
END | |
ELSE | |
BEGIN | |
result := OpenFile(docDrive,docVersion,docName,Nil,srcFile); | |
IF ReadError(result,Nil) THEN EXIT(RevertDoc); | |
ReadWrite(srcFile,workTo,FALSE,TRUE,FALSE,FALSE,TRUE); | |
result := CloseFile(srcFile); | |
IF (rwResult <> 0) OR WriteError(result,Nil) THEN EXIT(RevertDoc); | |
SwapWord(workFrom,workTo); | |
END; | |
docDirty := FALSE; | |
workDirty := FALSE; | |
AcceptEdits; | |
AltToScrn; | |
END; | |
{$S } | |
PROCEDURE OpenMyWind; | |
VAR i: INTEGER; | |
BEGIN | |
ShowWindow(@myWind); | |
SelectWindow(@myWind); | |
SetPort(@myWind); | |
ValidRect(myWind.port.portRect); | |
windOpen := TRUE; | |
END; | |
{$S } | |
FUNCTION ShouldSave(dialogNum: INTEGER): INTEGER; | |
{ returns 1 = save, 2 = forget, 3 = cancel } | |
VAR myDialog: DialogPtr; | |
dResult: INTEGER; | |
BEGIN | |
AcceptEdits; | |
BorrowAlt; { save screen image for refresh } | |
myDialog := GetNewDialog(dialogNum, Nil, Pointer(-1)); | |
ModalDialog(Nil,dResult); | |
DisposDialog(myDialog); | |
UpdateWindow(@myWind,FALSE); | |
MainToAlt; { restore saved screen image } | |
ShouldSave := dResult; | |
END; | |
{$S } | |
PROCEDURE CloseMyWind; | |
VAR result: INTEGER; | |
BEGIN | |
IF docDirty AND windOpen THEN | |
BEGIN | |
result := ShouldSave(closeDlog); | |
IF result = 3 { cancel } THEN EXIT(CloseMyWind); | |
IF result = 1 { save } THEN | |
BEGIN | |
IF NOT SaveDoc(FALSE) THEN EXIT(CloseMyWind); | |
END; | |
END; | |
HideWindow(@myWind); | |
UpdateWindow(@deskWind,FALSE); | |
windOpen := FALSE; | |
selFlag := FALSE; { so edit menu disabled } | |
maskFlag := FALSE; | |
END; | |
{$S } | |
PROCEDURE SetTitle(stringNumber: INTEGER); | |
VAR titleHandle: StringHandle; | |
BEGIN | |
titleHandle := GetString(stringNumber); | |
HLock(Pointer(ORD(titleHandle))); | |
SetWTitle(@myWind,titleHandle^^); | |
HUnlock(Pointer(ORD(titleHandle))); | |
END; | |
{$S SegInit } | |
PROCEDURE OpenFirstDoc; | |
VAR result,srcFile: INTEGER; | |
BEGIN | |
{ docName and docDrive were set up by FinderDoc } | |
quitFlag := TRUE; { assume failure } | |
IF Length(docName) = 0 THEN | |
BEGIN | |
IF rescueFlag THEN | |
BEGIN | |
SetTitle(rescueString); | |
ReadWrite(workFrom,0,FALSE,TRUE,FALSE,FALSE,TRUE); | |
docDirty := TRUE; | |
END | |
ELSE SetTitle(untitledString); | |
END | |
ELSE | |
BEGIN | |
SetWTitle(@myWind,docName); | |
result := OpenFile(docDrive,docVersion,docName,Nil,srcFile); | |
IF ReadError(result,Nil) THEN EXIT(OpenFirstDoc); | |
ReadWrite(srcFile,workTo,FALSE,TRUE,FALSE,FALSE,TRUE); | |
result := CloseFile(srcFile); | |
IF rwResult <> 0 THEN EXIT(OpenFirstDoc); { with quitFlag TRUE } | |
SwapWord(workFrom,workTo); | |
END; | |
quitFlag := FALSE; | |
AcceptEdits; | |
AltToScrn; | |
END; | |
{$S } | |
PROCEDURE NewDoc; | |
VAR patHandle: Handle; | |
patPtr: QDPtr; | |
BEGIN | |
NewDocInit; | |
docName := ''; | |
docDrive := -1; | |
SetTitle(untitledString); | |
OpenMyWind; | |
{ install default patterns } | |
patHandle := GetResource('PAT#',patListID); | |
patPtr := Pointer(ORD(patHandle^)+2); | |
IF NOT EqualLongs(patPtr,@patterns,38*2) THEN | |
BEGIN | |
CopyLongs(patPtr,@patterns,38*2); | |
DrawPat; | |
END; | |
BlankDoc(workFrom); | |
AcceptEdits; | |
END; | |
{$S } | |
PROCEDURE OpenDoc; | |
VAR result: INTEGER; | |
types: sfTypeList; | |
reply: sfReply; | |
srcFile: INTEGER; | |
where: Point; | |
BEGIN | |
where.h := 112; | |
where.v := 70; | |
types[0] := 'PNTG'; | |
reply.vRefnum := docDrive; | |
SFGetFile(where,' ',Nil,1,@types,Nil,@reply); | |
UpdateWindow(@deskWind,FALSE); | |
IF NOT reply.good THEN EXIT(OpenDoc); | |
NewDocInit; | |
docDrive := reply.vRefnum; | |
result := OpenFile(reply.vRefnum,reply.version,reply.fName,Nil,srcFile); | |
IF ReadError(result,Nil) THEN EXIT(OpenDoc); | |
docName := reply.fName; | |
SetWTitle(@myWind,docName); | |
OpenMyWind; | |
ReadWrite(srcFile,workTo,FALSE,TRUE,FALSE,FALSE,TRUE); | |
result := CloseFile(srcFile); | |
IF rwResult <> 0 THEN EXIT(OpenDoc); | |
IF WriteError(result,Nil) THEN EXIT(OpenDoc); | |
SwapWord(workFrom,workTo); | |
AcceptEdits; | |
AltToScrn; | |
END; | |
{$S SegHelp } | |
PROCEDURE ShowPicture(whichPicture: INTEGER); | |
VAR myPic: PicHandle; | |
event: EventRecord; | |
saveOrigin: Point; | |
theControl: ControlHandle; | |
BEGIN | |
KillStuff; | |
myPic := GetPicture(whichPicture); | |
IF myPic = Nil THEN EXIT(ShowPicture); | |
HNoPurge(Pointer(ORD(myPic))); | |
DrawPicture(myPic,myWind.port.portRect); | |
HPurge(Pointer(ORD(myPic))); | |
saveOrigin := myWind.port.portRect.topLeft; | |
SetOrigin(0,0); | |
ShowControl(cancelButton); | |
REPEAT | |
REPEAT UNTIL GetNextEvent(everyEvent,event) { ignore all events } | |
AND (event.what = mouseDown); { till mouse button } | |
GlobalToLocal(event.where); | |
IF FindControl(event.where,@myWind,theControl) = 0 THEN SystemBeep(8) | |
ELSE IF TrackControl(theControl,event.where,Nil) <> 0 THEN | |
BEGIN | |
HideControl(cancelButton); | |
SetOrigin(saveOrigin.h,saveOrigin.v); | |
AltToScrn; | |
EXIT(ShowPicture); | |
END; | |
UNTIL FALSE; { until Cancel hit } | |
END; | |
{$S } | |
PROCEDURE SetupText; | |
BEGIN | |
GetFontInfo(info); | |
txMinWidth := info.widMax+7; { bold1,outL1,shad2,ital1,slop2 } | |
txMinHeight := info.ascent + info.descent + info.leading; | |
txMaxCount := 40; | |
IF BitTst(@myWind.port.txFace,3) { shadow } | |
OR BitTst(@myWind.port.txFace,4) { outline } | |
THEN txMaxCount := 16; | |
END; | |
{$S } | |
PROCEDURE MenuCommand(* theMenu,theItem: INTEGER *); | |
VAR myDialog: DialogPtr; | |
dResult: INTEGER; | |
myString: Str63; | |
newFace: Style; | |
tempRect: Rect; | |
i,refNum: INTEGER; | |
styleWord: INTEGER; | |
bool: BOOLEAN; | |
BEGIN | |
IF theItem <= 0 THEN EXIT(MenuCommand); | |
SetPort(@myWind); | |
Case theMenu OF | |
appleMenu: IF NOT Monkey THEN | |
BEGIN | |
IF active THEN | |
BEGIN | |
KillStuff; { get rid of text, sel, mask } | |
AcceptEdits; | |
BorrowAlt; { save screen image for refresh } | |
END; | |
IF theItem = 1 THEN | |
BEGIN | |
{ About MacPaint... } | |
myDialog := GetNewDialog(paintDlog, Nil, Pointer(-1)); | |
ModalDialog(Nil,dResult); | |
DisposDialog(myDialog); | |
UpdateWindow(@myWind,FALSE); | |
IF active THEN MainToAlt; { restore saved screen image } | |
END | |
ELSE | |
BEGIN | |
CursorNormal; | |
cursorFlag := TRUE; | |
MyGetItem(myMenus[appleMenu],theItem,myString); | |
tempLong := MaxMem(tempLong); { purge and compact heap } | |
refNum := OpenDeskAcc(myString); | |
active := FALSE; { so cursorNormal sticks } | |
ornFlag := TRUE; | |
END; | |
END; | |
fileMenu: IF NOT Monkey THEN | |
BEGIN | |
KillStuff; { get rid of text, sel, mask } | |
AcceptEdits; | |
hiResFlag := FALSE; | |
IF theItem = prFinalItem THEN hiResFlag := TRUE; | |
CASE theItem OF | |
newItem: NewDoc; | |
openItem: OpenDoc; | |
closeItem: CloseMyWind; | |
saveItem: bool := SaveDoc(FALSE); | |
saveAsItem: bool := SaveDoc(TRUE); | |
revertItem: RevertDoc; | |
prDraftItem,prFinalItem: PrintDoc; | |
prCatItem: PrintCatalog; | |
quitItem: quitFlag := TRUE; | |
END; | |
END; | |
editMenu: | |
BEGIN | |
IF active AND (theItem <> copyItem) THEN | |
BEGIN | |
workDirty := TRUE; | |
docDirty := TRUE; | |
END; | |
IF NOT SystemEdit(theItem-1) THEN | |
CASE theItem OF | |
undoItem: Undo; | |
clearItem: ClearSel; | |
copyItem: CutOrCopy(FALSE); | |
cutItem: CutOrCopy(TRUE); | |
pasteItem: Paste; | |
invertItem: InvertSel; | |
fillItem: FillSel; | |
edgesItem: TraceEdges; | |
hFlipItem: HFlip; | |
vFlipItem: VFlip; | |
rotateItem: Rotate; | |
END; | |
END; | |
aidsMenu: | |
BEGIN | |
CASE theItem OF | |
gridItem: | |
BEGIN | |
gridOn := NOT gridOn; | |
CheckItem(myMenus[aidsMenu],gridItem,gridOn); | |
UpdateText; { in case grid changes vert spacing } | |
END; | |
fatItem: | |
BEGIN | |
AcceptEdits; | |
fatFlag := NOT fatFlag; | |
CheckItem(myMenus[aidsMenu],fatItem,fatFlag); | |
IF fatFlag THEN | |
BEGIN | |
IF maskFlag OR selFlag THEN | |
BEGIN | |
fatCenter.h := (selRect.left + selRect.right) DIV 2; | |
fatCenter.v := (selRect.top + selRect.bottom) DIV 2; | |
END; | |
tempRect := myWind.port.portRect; | |
InsetRect(tempRect,26,15); | |
PinPt(fatCenter,tempRect); | |
WITH fatBits.bounds DO | |
BEGIN | |
left := fatCenter.h - 26; | |
right := fatCenter.h + 26; | |
top := fatCenter.v - 15; | |
bottom := fatCenter.v + 15; | |
END; | |
bool := SectRect(selRect,fatBits.bounds,tempRect); | |
IF NOT EqualRect(selRect,tempRect) THEN | |
BEGIN | |
KillStuff; | |
oldSelFlag := FALSE; | |
END; | |
END; | |
AltToScrn; | |
END; | |
pageItem: | |
BEGIN | |
KillStuff; | |
ShowPage; | |
END; | |
brushItem: | |
BEGIN | |
KillStuff; | |
ChooseBrush; | |
END; | |
patEdItem: | |
BEGIN | |
KillStuff; | |
EditPat; | |
END; | |
symItem: | |
BEGIN | |
KillStuff; | |
Symmetry; | |
END; | |
introItem: | |
BEGIN | |
ShowPicture(introPic); | |
END; | |
shortItem: | |
BEGIN | |
ShowPicture(shortPic); | |
END; | |
END; { case theItem } | |
END; { aidsMenu } | |
fontMenu: | |
BEGIN { choose font } | |
KillMask; { not enough room in heap for mask and font } | |
CheckItem(myMenus[fontMenu],theFont,FALSE); | |
theFont := theItem; | |
CheckItem(myMenus[fontMenu],theFont,TRUE); | |
MyGetItem(myMenus[fontMenu],theFont,myString); | |
GetFNum(myString,theFontID); | |
TextFont(theFontID); | |
TextSize(fontSizes[theFontSize]); | |
SetupText; | |
UpdateText; | |
FOR i := firstSize TO lastSize DO | |
BEGIN | |
styleWord := 0; | |
IF RealFont(theFontID,fontSizes[i]) THEN styleWord := 8; {outline} | |
MySetItemStyle(myMenus[sizeMenu],i,styleWord); | |
END; | |
END; | |
sizeMenu: | |
BEGIN { choose font size } | |
KillMask; { not enough room in heap for mask and font } | |
CheckItem(myMenus[sizeMenu],theFontSize,FALSE); | |
theFontSize := theItem; | |
CheckItem(myMenus[sizeMenu],theFontSize,TRUE); | |
TextSize(fontSizes[theFontSize]); | |
SetupText; | |
UpdateText; | |
END; | |
styleMenu: | |
BEGIN | |
IF theItem < 7 THEN { set TextFace } | |
BEGIN | |
IF theItem = plainItem | |
THEN newFace := [] | |
ELSE | |
BEGIN { toggle a bit of style } | |
newFace := myWind.port.txFace; | |
IF BitTst(@newFace,9-theItem) | |
THEN BitClr(@newFace,9-theItem) | |
ELSE BitSet(@newFace,9-theItem); | |
END; | |
thePort^.txFace := newFace; | |
SetupText; | |
UpdateText; | |
CheckItem(myMenus[styleMenu],plainItem,newFace=[]); | |
FOR i := boldItem TO shadowItem DO | |
CheckItem(myMenus[styleMenu],i,BitTst(@newFace,9-i)); | |
END | |
ELSE | |
BEGIN { choose justification } | |
txJustItem := theItem; | |
textJust := teFillLeft; | |
IF txJustItem = centerItem THEN textJust := teFillCenter; | |
IF txJustItem = rightItem THEN textJust := teFillRight; | |
UpdateText; | |
FOR i := leftItem TO rightItem DO | |
CheckItem(myMenus[styleMenu],i,i=txJustItem); | |
END; | |
END; | |
END; { case theMenu } | |
END; { menucommand } | |
{$S } | |
PROCEDURE EnableOne(whichItem: INTEGER; enable: BOOLEAN); | |
VAR menuHndl: MenuHandle; | |
BEGIN | |
menuHndl := myMenus[whichMenu]; | |
IF enable | |
THEN EnableItem(menuHndl,whichItem) | |
ELSE DisableItem(menuHndl,whichItem); | |
END; | |
{$S } | |
PROCEDURE CheckMenus; | |
VAR item: INTEGER; | |
textOK,selOrMask: BOOLEAN; | |
BEGIN | |
selOrMask := selFlag OR maskFlag; | |
textOk := (txScrapHndl <> Nil) OR NOT selOrMask; | |
whichMenu := fileMenu; | |
EnableOne(newItem,NOT windOpen); | |
EnableOne(openItem,NOT windOpen); | |
EnableOne(saveItem,windOpen); | |
EnableOne(saveAsItem,windOpen); | |
EnableOne(revertItem,windOpen); | |
EnableOne(prDraftItem,windOpen); | |
EnableOne(prFinalItem,windOpen); | |
EnableOne(closeItem,windOpen); | |
whichMenu := editMenu; | |
EnableOne(undoItem,windOpen); | |
FOR item := cutItem TO clearItem DO EnableOne(item,selOrMask); | |
EnableOne(invertItem,selOrMask); | |
EnableOne(fillItem,selOrMask); | |
FOR item := edgesItem TO rotateItem DO EnableOne(item,selFlag); | |
EnableOne(pasteItem,windOpen); | |
IF NOT active THEN FOR item := undoItem TO clearItem DO EnableOne(item,TRUE); | |
EnableOne(blank0Item,FALSE); | |
EnableOne(blank1Item,FALSE); | |
{ aids menu } | |
whichMenu := aidsMenu; | |
EnableOne(pageItem,windOpen); | |
EnableOne(introItem,windOpen); | |
EnableOne(shortItem,windOpen); | |
whichMenu := fontMenu; | |
FOR item := firstFont to lastFont DO EnableOne(item,textOk); | |
whichMenu := sizeMenu; | |
FOR item := firstSize to lastSize DO EnableOne(item,textOk); | |
whichMenu := styleMenu; | |
FOR item := plainItem to rightItem DO EnableOne(item,textOk); | |
EnableOne(blank2Item,FALSE); | |
END; | |
{$S } | |
PROCEDURE CommandChar; | |
{ a command key was pressed. Do appropriate command if any } | |
VAR minTime: LongInt; | |
menuResult: LongInt; | |
textOK: BOOLEAN; | |
BEGIN | |
textOk := (txScrapHndl <> Nil) OR NOT (selFlag OR maskFlag); | |
IF textOK THEN | |
BEGIN | |
IF theKey = prevSizeChar THEN { previous or smaller font } | |
BEGIN | |
IF shiftFlag THEN | |
BEGIN | |
IF theFont > firstFont | |
THEN MenuCommand(fontMenu,theFont-1); { previous font } | |
END | |
ELSE | |
BEGIN | |
IF theFontSize > firstSize | |
THEN MenuCommand(sizeMenu,theFontSize-1); { smaller fontSize } | |
END; | |
EXIT(CommandChar); | |
END; | |
IF theKey = nextSizeChar THEN { next or bigger font } | |
BEGIN | |
IF shiftFlag THEN | |
BEGIN | |
IF theFont < lastFont | |
THEN MenuCommand(fontMenu,theFont+1); { next font } | |
END | |
ELSE | |
BEGIN | |
IF theFontSize < lastSize | |
THEN MenuCommand(sizeMenu,theFontSize+1); { bigger fontSize } | |
END; | |
EXIT(CommandChar); | |
END; | |
END; { if textOk } | |
CheckMenus; | |
menuResult := MenuKey(theKey); | |
theMenu := HiWord(menuResult); | |
theItem := LoWord(menuResult); | |
HiLiteMenu(theMenu); | |
minTime := TickCount+3; { 1/20th of a second } | |
MenuCommand(theMenu,theItem); | |
REPEAT UNTIL TickCount > minTime; { make sure the hilite shows } | |
HiLiteMenu(0); | |
END; | |
{$S } | |
PROCEDURE ProcessTheEvent; | |
VAR where: Point; | |
menuResult: LongInt; | |
i: INTEGER; | |
code: INTEGER; | |
whichWindow: WindowPtr; | |
BEGIN | |
shiftFlag := (BitAnd(theEvent.modifiers,shiftKey) <> 0); | |
featureFlag := (BitAnd(theEvent.modifiers,cmdKey) <> 0); | |
optionFlag := (BitAnd(theEvent.modifiers,optionKey) <> 0); | |
IF theEvent.what <> mouseUp THEN | |
BEGIN | |
IF caretState THEN InvertCaret; | |
KillEdges; { restore altBits if it was borrowed for mask edges } | |
END; | |
CASE theEvent.what OF | |
mouseUp: | |
BEGIN | |
clickTime := theEvent.when; | |
clickLoc := theEvent.where; | |
END; | |
mouseDown: | |
BEGIN | |
code := FindWindow(theEvent.where,whichWindow); | |
IF (theEvent.when < clickTime + GetDoubleTime) | |
AND NearPt(theEvent.where,clickLoc,4) | |
THEN clickCount := clickCount + 1 | |
ELSE clickCount := 1; | |
IF killDouble AND (clickCount > 1) THEN code := -1; { ignore it ! } | |
killDouble := FALSE; | |
IF skipDouble THEN clickCount := 1; | |
skipDouble := (clickCount > 1); | |
SetPort(whichWindow); | |
SetPinRect(lineSize); | |
CASE code OF | |
inSysWindow: SystemClick(theEvent,whichWindow); | |
inMenuBar: | |
BEGIN | |
CheckMenus; { enable or disable items } | |
CursorNormal; | |
menuResult := MenuSelect(theEvent.where); | |
theMenu := HiWord(menuResult); | |
theItem := LoWord(menuResult); | |
MenuCommand(theMenu,theItem); | |
HiLiteMenu(0); | |
IF NOT Monkey THEN | |
quitFlag := (theMenu = fileMenu) AND (theItem = quitItem); | |
IF quitFlag THEN EXIT(ProcessTheEvent); | |
clickTime := TickCount; | |
GetMouse(clickLoc); | |
LocalToGlobal(clickLoc); | |
skipDouble := TRUE; | |
END; | |
inContent,inGrow: | |
IF active THEN | |
BEGIN | |
IF whichWindow = @myWind THEN | |
BEGIN | |
IF fatFlag | |
AND (theEvent.where.h <= 80+52+3) | |
AND (theEvent.where.v <= 48+30+1) | |
THEN MenuCommand(aidsMenu,fatItem) { turn off FatBits } | |
ELSE EditDoc; | |
skipDouble := TRUE; { force next click to single click } | |
END | |
ELSE IF whichWindow = @deskWind THEN | |
BEGIN | |
IF PtInRect(theEvent.where,toolRect) | |
THEN ChooseTool(theEvent.where); | |
IF PtInRect(theEvent.where,lineRect) | |
THEN ChooseLine(theEvent.where); | |
IF PtInRect(theEvent.where,patRect) | |
THEN ChoosePat(theEvent.where); | |
END; { click in deskWind } | |
END; { inContent } | |
inGoAway: IF active THEN | |
BEGIN | |
IF TrackGoAway(@myWind,theEvent.where) | |
THEN MenuCommand(fileMenu,closeItem); | |
END; | |
END; { case code } | |
END; { mouseDown } | |
keyDown,autoKey: IF active THEN | |
BEGIN | |
SetPort(@myWind); | |
theKey := CHR(BitAnd(theEvent.message,255)); | |
IF featureFlag THEN | |
BEGIN | |
CommandChar; | |
EXIT(ProcessTheEvent); | |
END; | |
IF (theKey = CHR(96)) AND NOT textFlag THEN | |
BEGIN | |
MenuCommand(editMenu,undoItem); | |
EXIT(ProcessTheEvent); | |
END; | |
IF (theKey = CHR(8)) AND NOT textFlag THEN | |
BEGIN | |
MenuCommand(editMenu,clearItem); | |
EXIT(ProcessTheEvent); | |
END; | |
TextChar; | |
END; | |
updateEvt: | |
BEGIN | |
whichWindow := Pointer(theEvent.message); | |
UpdateWindow(whichWindow,active); | |
END; | |
activateEvt: | |
BEGIN | |
active := ODD(theEvent.modifiers); | |
IF ornFlag THEN | |
BEGIN | |
FOR i := fileMenu to lastMenu DO | |
BEGIN | |
whichMenu := i; | |
IF i <> editMenu THEN EnableOne(0,active); | |
END; | |
DrawMenuBar; | |
END; | |
IF active THEN | |
BEGIN | |
ornFlag := FALSE; { no ornaments up } | |
UpdateWindow(@myWind,active); { take care of pending updates } | |
MainToAlt; { restore saved screen image } | |
END; | |
END; | |
END; { case theEvent.what } | |
END; { ProcessEvent } | |
{$S } | |
FUNCTION MyGrowHeap(bytesNeeded: LongInt): LongInt; | |
BEGIN | |
MyGrowHeap := 0; | |
END; | |
{$S SegInit } | |
PROCEDURE SetUpMenus; | |
{ once-only initialization for my menus } | |
VAR i: INTEGER; | |
BEGIN | |
InitMenus; { initialize Unit Menus } | |
FOR i:=firstMenu to lastMenu DO | |
BEGIN | |
myMenus[i] := GetMenu(i); | |
IF i = appleMenu THEN | |
BEGIN | |
myMenus[i]^^.menuData[1] := CHR(20); { apple character } | |
AddResMenu(myMenus[appleMenu],'DRVR'); | |
END; | |
IF i = fontMenu THEN | |
BEGIN | |
AddResMenu(myMenus[fontMenu],'FONT'); | |
lastFont := CountMItems(myMenus[fontMenu]); | |
END; | |
InsertMenu(myMenus[i],0); | |
END; | |
END; | |
{$S SegInit } | |
PROCEDURE InitOnce; | |
VAR dummyHndl: Handle; | |
i: INTEGER; | |
wind: GrafPtr; | |
result: INTEGER; | |
refNum: INTEGER; | |
patHandle: Handle; | |
scrnOffset: LongInt; | |
fontName: Str255; | |
itemString: Str63; | |
fontCmdHndl: StringHandle; | |
titleHndl: StringHandle; | |
grow: LongInt; | |
date1,date2: LongInt; | |
size1,size2: LongInt; | |
FUNCTION WorkError(result: INTEGER): BOOLEAN; | |
VAR aResult: INTEGER; | |
BEGIN | |
WorkError := FALSE; | |
IF (result <> 0) AND (result <> fileExists) THEN | |
BEGIN | |
aResult := MyAlert(workSpaceAlrt); | |
WorkError := TRUE; | |
END; | |
END; | |
BEGIN | |
TEInit; | |
InitDialogs(Nil); { no restart proc } | |
heapJam := FALSE; | |
quitFlag := TRUE; { assume failure } | |
finderMsg := -1; { in case exit } | |
heapTop := StackPtr - 9216; { save 9K for stack } | |
SetApplLimit(Pointer(heapTop)); | |
IF MemError <> 0 THEN { oops, heap already too big } | |
BEGIN | |
result := MyAlert(bigScrapAlrt); | |
EXIT(InitOnce); | |
END; | |
dummyHndl := NewHandle(10000000); { force max heap grow now } | |
SetGrowZone(@MyGrowHeap); { then take over grow proc } | |
IF (FreeMem < 17000) THEN { quit if not enough heap } | |
BEGIN | |
result := MyAlert(memFullAlrt); | |
EXIT(InitOnce); | |
END; | |
IF DiskSpace(0) < minDiskSpace THEN { quit if disk is full } | |
BEGIN | |
result := MyAlert(diskAlrt); | |
EXIT(InitOnce); | |
END; | |
active := TRUE; | |
ornFlag := TRUE; { fake out first activate } | |
scrnFlag := FALSE; | |
SetRect(zeroRect,0,0,0,0); | |
SetRect(pageRect,0,0,576,720); | |
SetRect(docRect,80,48,496,288); | |
SetRect(toolRect,toolLeft,toolTop,toolRight,toolBottom); | |
SetRect(lineRect,lineLeft,lineTop,lineRight,lineBottom); | |
SetRect(patRect,patLeft,patTop,patRight,patBottom); | |
FlushEvents(everyEvent,0); | |
patHandle := GetResource('PAT#',patListID); | |
CopyLongs(Pointer(ORD(patHandle^)+2),@patterns,38*2); | |
scrnOffset := docRect.top * screenBits.rowBytes + docRect.left DIV 8; | |
scrnPtr := Pointer(ORD(screenBits.baseAddr) + scrnOffset); | |
titleHndl := GetString(titleString); { 'MacPaint by Bill Atkinson' } | |
docName := titleHndl^^; | |
wind := NewWindow(@myWind,docRect,docName,TRUE,documentProc,Nil,TRUE,1); | |
okButton := GetNewControl(okBtn,@myWind); | |
cancelButton := GetNewControl(cancelBtn,@myWind); | |
windOpen := TRUE; | |
SetPort(wind); | |
ClipRect(pageRect); | |
ValidRect(myWind.port.portRect); | |
WindPaint(FALSE); { disable paintWhite } | |
wind := NewWindow(@deskWind,screenBits.bounds,'desk', | |
TRUE,documentProc,Nil,FALSE,1); | |
WindPaint(TRUE); | |
SetPort(@deskWind); | |
FillRect(deskWind.port.portRect,gray); | |
TextFont(paintFont); | |
theTool := brushTool; | |
prevTool := theTool; | |
toolGrid := FALSE; | |
theBrush := 7; { small round brush } | |
borderFlag := TRUE; | |
SetLineSize(1); | |
thePatIndex := 0; | |
SetToolCursor; | |
UpdateWindow(@deskWind,FALSE); | |
SetUpMenus; | |
nextCaretTime := 0; | |
caretState := FALSE; | |
clickTime := 0; | |
clickCount := 1; | |
killDouble := FALSE; | |
skipDouble := FALSE; | |
gridOn := FALSE; | |
hSymFlag := FALSE; | |
vSymFlag := FALSE; | |
hvSymFlag := FALSE; | |
vhSymFlag := FALSE; | |
symByte := -128; | |
textLines := 0; { no type-in yet } | |
txScrapHndl := Nil; | |
txScrapSize := 0; | |
txJustItem := leftItem; | |
textJust := teFillLeft; | |
CheckItem(myMenus[styleMenu],plainItem,TRUE); | |
CheckItem(myMenus[styleMenu],txJustItem,TRUE); | |
fontSizes[1] := 9; | |
fontSizes[2] := 10; | |
fontSizes[3] := 12; | |
fontSizes[4] := 14; | |
fontSizes[5] := 18; | |
fontSizes[6] := 24; | |
fontSizes[7] := 36; | |
fontSizes[8] := 48; | |
fontSizes[9] := 72; | |
theFontSize := 3; { text size 12 point } | |
maskHandle := Nil; { so KillMask won't croak } | |
CheckItem(myMenus[sizeMenu],theFontSize,TRUE); | |
fontCmdHndl := GetString(fontCmdString); | |
prevSizeChar := fontCmdHndl^^[1]; | |
nextSizeChar := fontCmdHndl^^[2]; | |
theFont := 1; { in case not found } | |
GetFontName(1,fontName); | |
FOR i := 1 TO lastFont DO | |
BEGIN | |
MyGetItem(myMenus[fontMenu],i,itemString); | |
IF EqualString(fontName,itemString) THEN theFont := i; | |
END; | |
MenuCommand(fontMenu,theFont); { choose initial font, highlight real sizes } | |
inWindow := FALSE; | |
inSel := FALSE; | |
fatScroll := FALSE; | |
cursorFlag := TRUE; | |
hiResFlag := TRUE; { default for finder print } | |
rwShftDh := 0; | |
rwShftDv := 0; | |
rwResult := 0; | |
finderMsg := FinderDoc(docDrive,docVersion,@docName); { get file name from finder } | |
IF finderMsg = printMsg THEN EXIT(InitOnce); | |
workDrive := 0; | |
result := CreateFile(workDrive,0,'Paint1'); | |
rescueFlag := (result = fileExists); | |
result := OpenFile(workDrive,0,'Paint1',Nil,workFrom); | |
IF WorkError(result) THEN EXIT(InitOnce); | |
result := CreateFile(workDrive,0,'Paint2'); | |
rescueFlag := rescueFlag AND (result = fileExists); | |
result := OpenFile(workDrive,0,'Paint2',Nil,workTo); | |
IF WorkError(result) THEN EXIT(InitOnce); | |
IF Length(docName) <> 0 THEN rescueFlag := FALSE; | |
IF rescueFlag THEN | |
BEGIN | |
FileInfo(workDrive,0,'Paint1',date1,size1); | |
FileInfo(workDrive,0,'Paint2',date2,size2); | |
workSize := size1; | |
IF date2 > date1 THEN { use most recent file } | |
BEGIN | |
SwapWord(workTo,workFrom); | |
workSize := size2; | |
END; | |
END | |
ELSE BlankDoc(workFrom); | |
BlankDoc(workTo); | |
quitFlag := FALSE; { we made it } | |
CursorNormal; | |
END; | |
{$S } | |
PROCEDURE QuitProgram; | |
VAR result: INTEGER; | |
BEGIN | |
IF docDirty AND windOpen THEN | |
BEGIN | |
quitFlag := FALSE; { in case we cancel quit } | |
result := ShouldSave(quitDlog); | |
IF result = 3 { cancel } THEN EXIT(QuitProgram); | |
IF result = 1 { save } THEN | |
BEGIN | |
IF NOT SaveDoc(FALSE) THEN EXIT(QuitProgram); | |
END; | |
quitFlag := TRUE; | |
END; | |
BusyCursor; | |
InitWindows; { erase the screen } | |
result := CloseFile(workFrom); | |
result := CloseFile(workTo); | |
result := DeleteFile(workDrive,0,'Paint1'); | |
result := DeleteFile(workDrive,0,'Paint2'); | |
FlushVol(workDrive); | |
IF KeyIsDown(featureCode) THEN EjectReset; | |
END; | |
{$S } | |
BEGIN { main program } | |
tempWord := UnloadScrap; | |
MoreMasters; { allocate 2nd block of 64 master pointers } | |
MoreMasters; { allocate 3rd block of 64 master pointers } | |
MoreMasters; { allocate 4th block of 64 master pointers } | |
MoreMasters; { allocate 5th block of 64 master pointers } | |
InitGraf(@thePort); | |
InitFonts; | |
InitWindows; | |
InitOnce; | |
IF finderMsg = printMsg THEN | |
BEGIN | |
UnloadSeg(@InitOnce); | |
NewDocInit; | |
FinderPrint; | |
END; | |
IF quitFlag THEN EXIT(MacPaint); | |
NewDocInit; | |
OpenFirstDoc; | |
REPEAT | |
UnloadSeg(@InitOnce); { SegInit } | |
UnloadSeg(@PrintDoc); { SegPrint } | |
UnloadSeg(@CutOrCopy); { SegScrap } | |
UnloadSeg(@Paste); { SegPaste } | |
UnloadSeg(@Rotate); { SegFlip } | |
UnloadSeg(@ShowPage); { SegPage } | |
UnloadSeg(@DrawPat); { SegUpdate } | |
UnloadSeg(@EditPat); { SegPatEdit } | |
UnloadSeg(@ChooseBrush); { SegBrush } | |
UnloadSeg(@Symmetry); { SegSym } | |
UnloadSeg(@ShowPicture); { SegHelp } | |
IF heapJam THEN | |
BEGIN | |
tempLong := MaxMem(tempLong); { purge heap } | |
heapJam := FALSE; | |
END; | |
SystemTask; { give desk accessories a chance } | |
IF active THEN TrackCursor; | |
IF GetNextEvent(everyEvent,theEvent) THEN ProcessTheEvent; | |
IF active AND NOT quitFlag AND (DiskSpace(0) < minDiskSpace) THEN | |
BEGIN | |
tempWord := SaveAlert(diskAlrt); | |
quitFlag := TRUE; | |
END; | |
IF quitFlag THEN QuitProgram; | |
UNTIL quitFlag; | |
ExitToShell; | |
END. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Wow. This is a great find.