// IfsLeafWrite.bcpl - Leaf Write - SWAPPABLE
// Copyright Xerox Corporation 1979, 1982

// Last modified April 9, 1982 12:57 PM by Taft

get ecIllegalLeafWrite, ecLeafFileTooLong from "IfsLeafErrors.decl";
get "IfsLeaf.decl";

external
[
//outgoing procedures
WriteLeaf;

//incoming procedures
AnswerSetOp; ByteBlt; CheckHandle;
LeafError; LeafGetPage; MoveBlock;
SetModeLength;
]

//----------------------------------------------------------------------------
let WriteLeaf(sequin, answerPBI, op) = valof
//----------------------------------------------------------------------------
[
let fh = CheckHandle(sequin, answerPBI, op);
let address = lv op>>FileRequest.address;
let writeLength = op>>FileRequest.op.length - writeRequestOv & bytesPerPage-1
unless SetModeLength(op, fh, true, lv writeLength) do
resultis LeafError(answerPBI, op, ecIllegalLeafWrite);
let writeByte = address>>LeafAddress.low & bytesPerPage-1
let writePage = address>>LeafAddress.highAddr lshift logPagesPerWord +
address>>LeafAddress.low rshift logBytesPerPage
let firstLength = (writeByte + writeLength ule bytesPerPage ?
writeLength, bytesPerPage - writeByte)
let pageAddress = LeafGetPage(fh>>FH.lvmd, writePage + 1, dirtyPage);
if pageAddress eq 0 then resultis LeafError(answerPBI, op, ecLeafFileTooLong);
ByteBlt(pageAddress, writeByte, lv op>>FileRequest.words, 0, firstLength)
if writeLength ugr firstLength then
[
pageAddress = LeafGetPage(fh>>FH.lvmd, writePage + 2, dirtyPage);
if pageAddress eq 0 then resultis LeafError(answerPBI, op,
ecLeafFileTooLong);
ByteBlt(pageAddress, 0, lv op>>FileRequest.words, firstLength,
writeLength - firstLength)
]
//no thirds allowed (since bytesPerPage >= bytesPerPup)

let answer = AnswerSetOp(answerPBI, op, 2*lenWriteAnswer);
MoveBlock(lv answer>>FileAnswer.address, address,
size FileAnswer.address/bitsPerWord + size FileAnswer.length/bitsPerWord);
answer>>FileAnswer.rate = atAnyRate;
resultis leafOpComplete;
]