{File name: LineBreak.mc Description: LineBreak opcode Author: JPM Created: December 17, 1986 Last Edited: JPM December 31, 1986 Fix bug in LBReadPriorIndex (wrong offset) JPM December 30, 1986 Add (and use) suffixHardHyphen; fix bug in LBTextCross (can't use r0100) JPM December 19, 1986 Revise algorithm per LineBreakImpl.mesa} { Copyright (C) 1986 by Xerox Corporation. All rights reserved.} {Link register use: L0 - returns from MapSrc and MapDst subroutines L1 - need to write prior U-regs into arg (1 = FALSE, 0 = TRUE) -- init after calls to MapSrc/MapDst L2 - hyphenate flag (2 = FALSE, 3 = TRUE) L3 - misc. flow control L4 - word.notPunctuation flag (2 = FALSE, 3 = TRUE)} {return reasons} Set[reasonMargin, 0]; Set[reasonNormal, 1]; Set[reasonChangeBase, 2]; Set[reasonInvalidCache, 3]; Set[reasonContiguousWords, 4]; Set[reasonUnableToBreak, 5]; Set[reasonSpecialGermanCase, 6]; {escape types} Set[escapeSpace, Or[Lshift[0,1],9]]; Set[escapeZeroWidthSpace, Or[Lshift[1,1],9]]; Set[escapeChangeBase, Or[Lshift[2,1],9]]; {state field constants} Set[spaceCountIncr, Lshift[1,4]]; Set[notPunctuationTRUE, Lshift[1,3]]; Set[suffixCharField, 7]; {suffixChar types} Set[suffixSpace, 0]; Set[suffixZeroWidthSpace, 1]; Set[suffixHyphen, 2]; Set[suffixHardHyphen, 3]; Set[suffixNull, 4]; @LINEBREAK: rhVirtualH ← TOS LRot0, c1, at[0E,10,ESCAn]; rVirtualL ← STK, pop, L0 ← L0.LineBreak, c2; rVirtualL ← rVirtualL + 2, fXpop, push, CALL[MapDst], c3; {get length 1st} {MapDst subroutine starts in c1, ends in c2} rCtMinusIx ← MD {text.LENGTH}, c3, MapDstRet[L0.LineBreak]; MAR ← [rhArgReal, rArgReal + 9], c1; {offset 0B - 2} uLBTextCount ← rCtMinusIx, CANCELBR[$,2], c2; Q ← MD {final.index}, c3; MAR ← rArgReal ← [rhArgReal, rArgReal - 2], c1; {start of arg} rCtMinusIx ← rCtMinusIx - Q, ZeroBr, CANCELBR[$,2], c2; uLBArgRealLo ← rArgReal, rVirtualL ← MD {text lo}, BRANCH[$,LBFastExit], c3; MAR ← [rhArgReal, rArgReal + 1], L3 ← 0, c1; rVirtualL ← rVirtualL + Q, CarryBr, CANCELBR[$,2], c2; uLBTextRealLo ← rVirtualL, rhVirtualH ← MD {text hi}, BRANCH[$,LBUpdateHigh], c3; MAR ← [rhArgReal, rArgReal + 0E], c1, at[0,10,LBUpdateHighRet]; Q ← ~suffixCharField, CANCELBR[$,2], c2; rhSuffixChar ← MD {final.suffixChar}, rSpCount ← MD and Q {final.count/notPunctuation}, c3; MAR ← [rhArgReal, rArgReal + 0D], c1; Q ← rhSuffixChar xor rSpCount, CANCELBR[$,2], c2; rBitLength ← MD {final.bitLength}, c3; MAR ← [rhArgReal, rArgReal + 3], c1; rhSuffixChar ← Q LRot0, CANCELBR[$,2], c2; Q ← MD {cache lo}, c3; MAR ← [rhArgReal, rArgReal + 4], c1; uLBCacheLo ← Q, CANCELBR[$,2], c2; Q ← MD {cache hi}, c3; MAR ← [rhArgReal, rArgReal + 5], c1; uLBCacheHi ← Q, CANCELBR[$,2], c2; Q ← MD {hyphenate/font}, XHDisp, c3; MAR ← [rhArgReal, rArgReal + 6], L2 ← 2, BRANCH[$,LBSetHyphenate,2], c1; CANCELBR[LBInitCont,2], c2; LBSetHyphenate: Q ← Q and ~u8000, CANCELBR[$,2], c2; {clear high bit} LBInitCont: rMargin ← MD {margin}, c3; MAR ← [rhArgReal, rArgReal + 7], c1; uLBFont ← Q, CANCELBR[$,2], c2; UrG ← G, rMinSpPLength ← MD {hyphenPixelLength/minSpacePixelLength}, c3; MAR ← [rhArgReal, rArgReal + 9], c1; rhLBHyphenPL ← rMinSpPLength LRot8, CANCELBR[$,2], c2; UrL ← L, rMinSpMLength ← MD {minSpaceMicaLength}, c3; MAR ← [rhArgReal, rArgReal + 0A], c1; rMinSpPLength ← rMinSpPLength and 0FF, CANCELBR[$,2], c2; UrPC ← PC, rWhiteSpaceIncr ← MD {whiteSpace}, c3; MAR ← [rhArgReal, rArgReal + 0C], c1; Q ← rhArgReal, CANCELBR[$,2], c2; rMicaLength ← MD {final.micaLength}, c3; MAR ← [rhArgReal, rArgReal + 12], c1; uLBArgRealHi ← Q, CANCELBR[$,2], c2; Q ← MD {prior.micaLength}, c3; MAR ← [rhArgReal, rArgReal + 16], c1; uLBPMicaLength ← Q, CANCELBR[$,2], c2; Q ← MD {prior.whiteSpace}, c3; MAR ← [rhArgReal, rArgReal + 10], c1; uLBPWhiteSpace ← Q, CANCELBR[$,2], c2; rWhiteSpace ← MD {final.whiteSpace}, CALL[MapSrc], c3; {MapSrc subroutine starts in c1, ends in c2} Q ← MD {text[index]}, XHDisp, L1 ← 1, c3, MapSrcRet[L0.LineBreak]; MAR ← [rhArgReal, rArgReal + 0F], L3 ← 2, BRANCH[$,LBFirstEsc,2], c1; rCacheObj ← u3FFF, CANCELBR[LBReadyToLoop,2], c2; LBFirstEsc: rCacheObj ← u3FFF, CANCELBR[$,2], c2; LBReadyToLoop: rByteCount ← MD {final.byteCount}, L3Disp, GOTO[LBMainLoopCont], c3; LBMainLoop: MAR ← rTextReal ← [rhTextReal, rTextReal + 1], BRANCH[$,LBNormalExit], c1; LBMainRead: rCacheObj ← u3FFF, BRANCH[$,LBTextCross,1], c2; Q ← MD {text[index]}, XHDisp, c3; LBMainLoopCont: rhLBFlags ← Q LRot4, XDisp, BRANCH[$,LBEscape,2], c1; Q ← Q and rCacheObj, rhCacheObj ← uLBCacheHi, CANCELBR[$,0F], c2; rCacheObj ← uLBCacheLo, c3; LBMapCache: Map ← Q ← [rhCacheObj, rCacheObj + Q], CarryBr, c1; rCacheObj ← rhCacheObj + 1, LOOPHOLE[byteTiming], BRANCH[LBMapCacheCont,$], c2; rhCacheObj ← rCacheObj LRot0, rCacheObj ← 0, GOTO[LBMapCache], c3; LBMapCacheCont: rhCacheObj ← rCacheObj ← MD, c3; MAR ← rCacheObj ← [rhCacheObj, Q + 0], c1; Q ← ~u8000, c2; Q ← MD and Q {font}, XHDisp, c3; MAR ← [rhCacheObj, rCacheObj + 1], L4 ← 2{/3}, BRANCH[$,LBClearNotify,2], c1; [] ← Q xor uLBFont, NZeroBr, CANCELBR[LBTestFont,2], c2; LBClearNotify: [] ← Q xor uLBFont, NZeroBr, CANCELBR[$,2], c2; LBTestFont: Q ← MD {wordMetrics.micaLength}, BRANCH[$,LBInvalidCacheExit], c3; rMicaLength ← rMicaLength + Q, c1; [] ← rMicaLength - rMargin, CarryBr, c2; Ybus ← rSpCount, YDisp, L4Disp, BRANCH[$,LBHyphenate], c3; MAR ← [rhCacheObj, rCacheObj + 2], DISP4[LBCheckPunct,6], c1; CANCELBR[LBUpdateMetrics,2], c2, at[6,10,LBCheckPunct]; rSpCount ← rSpCount or notPunctuationTRUE, CANCELBR[LBUpdateMetrics,2], c2, at[7,10,LBCheckPunct]; rSpCount ← rSpCount and ~notPunctuationTRUE, CANCELBR[$,2], c2, at[0E,10,LBCheckPunct]; LBUpdateMetrics: Q ← MD {wordMetrics.pixelLength}, c3; MAR ← [rhCacheObj, rCacheObj + 3], c1; rBitLength ← rBitLength + Q, L4 ← 3, CANCELBR[$,3], c2; Q ← MD {wordMetrics.byteCount}, c3; Xbus ← rhLBFlags, XDisp, L3 ← 9, c1; rByteCount ← rByteCount + Q, BRANCH[LBLoopCheck,$,0B], c2; rhSuffixChar ← suffixSpace, GOTO[LBSaveBreak], c3; LBEscape: L3 ← 9, DISP4[LBEsc,9], c2; rhSuffixChar ← suffixSpace, GOTO[LBSaveBreak], c3, at[escapeSpace,10,LBEsc]; rhSuffixChar ← suffixZeroWidthSpace, GOTO[LBSaveBreak], c3, at[escapeZeroWidthSpace,10,LBEsc]; rReason ← reasonChangeBase, GOTO[LBExit], c3, at[escapeChangeBase,10,LBEsc]; LBSaveBreak: uLBPMicaLength ← rMicaLength, c1; LBSvBkAtEnd: uLBPCtMinusIx ← rCtMinusIx, L1 ← 0, c2; uLBPBitLength ← rBitLength, c3; rSpCount ← rSpCount and ~notPunctuationTRUE, c1; Q ← rSpCount or rhSuffixChar, c2; uLBPSpCount ← Q, c3; uLBPByteCount ← rByteCount, L3Disp, c1; uLBPWhiteSpace ← rWhiteSpace, DISP4[LBSvBkRet], c2; LBSpace: rMicaLength ← rMicaLength + rMinSpMLength, c3, at[9,10,LBSvBkRet]; [] ← rMicaLength - rMargin - 1, CarryBr, c1; rBitLength ← rBitLength + rMinSpPLength, BRANCH[$,LBSimpleMarginExit], c2; rSpCount ← rSpCount + spaceCountIncr, c3; rByteCount ← rByteCount + 1, c1; rWhiteSpace ← rWhiteSpace + rWhiteSpaceIncr, c2; LBLoopCheck: rCtMinusIx ← rCtMinusIx - 1, ZeroBr, GOTO[LBMainLoop], c3, at[0B,10,LBSvBkRet]; LBHyphenate: MAR ← [rhCacheObj, rCacheObj + 4], L2Disp, BRANCH[$,LBUnableToBreakExit,7], c1; rMicaLength ← rMicaLength - Q, BRANCH[LBNoHyphen,$,2], c2; rSylCount ← MD {sylableCount}, L2 ← 1, c3; [] ← rSylCount, ZeroBr, c1; Q ← uLBPWhiteSpace, BRANCH[$,LBNoSylables], c2; rMinWidth ← rMargin - Q, c3; Q ← uLBPMicaLength, c1; [] ← Q - rMinWidth, CarryBr, c2; rMinWidth ← rMargin, BRANCH[$,LBBreakOK], c3; MAR ← rCacheObj ← [rhCacheObj, rCacheObj + 5], c1; rMinWidth ← rMinWidth - rWhiteSpace, CANCELBR[$,2], c2; LBSylableLoop: rSylType ← MD {thisSylable.type}, XHDisp, BRANCH[$,LBSylLoopEnd], c3; MAR ← [rhCacheObj, rCacheObj + 1], BRANCH[$,LBSpecialGermanExit,2], c1; rSylType ← rSylType LRot8, CANCELBR[$,2], c2; Q ← MD {thisSylable.micaLength}, c3; Q ← rMicaLength + Q, c1; [] ← rMargin - Q, CarryBr, c2; [] ← rSylType and 0F, ZeroBr, BRANCH[LBSkipSyl,$], c3; [] ← rFit - Q, NegBr, L2Disp, BRANCH[$,LBFoundHard], c1; [] ← Q - rMinWidth, CarryBr, BRANCH[$,LBSaveSyl], c2; BRANCH[LBNextSyl,LBFoundFit], c3; LBSaveSyl: uLBPendSyl ← rCacheObj, rFit ← Q, L2 ← 0, BRANCH[$,LBFoundFit], c3; LBNextSyl: MAR ← rCacheObj ← [rhCacheObj, rCacheObj + 3], GOTO[LBNextSylable], c1; LBSkipSyl: MAR ← rCacheObj ← [rhCacheObj, rCacheObj + 3], CANCELBR[$,1], c1; LBNextSylable: rSylCount ← rSylCount - 1, ZeroBr, CANCELBR[LBSylableLoop,2], c2; LBSylLoopEnd: Q ← rFit, L2Disp, CANCELBR[$,3], c1; rCacheObj ← uLBPendSyl, BRANCH[LBFoundSyl,$], c2; rCtMinusIx ← uLBPCtMinusIx, GOTO[LBWholeWordBreak], c3; LBFoundSyl: Noop, c3; LBFoundFit: Noop, c1; rhSuffixChar ← suffixHyphen, GOTO[LBHyphenateOK], c2; LBFoundHard: rhSuffixChar ← suffixHardHyphen, XLDisp, CANCELBR[$,1], c2; LBHyphenateOK: uLBPMicaLength ← rMicaLength ← Q, L3 ← 0{/1}, BRANCH[$,LBSetHard], c3; MAR ← [rhCacheObj, rCacheObj + 0], GOTO[LBHyphenateCont], c1; LBSetHard: MAR ← [rhCacheObj, rCacheObj + 0], c1; LBHyphenateCont: rSylByteCount ← 0FF, c2; rSylByteCount ← rSylByteCount and MD {thisSylable.byteCount}, c3; MAR ← [rhCacheObj, rCacheObj + 2], c1; rByteCount ← rByteCount + rSylByteCount, CANCELBR[$,2], c2; rSylBitLength ← MD {thisSylable.pixelLength}, c3; rBitLength ← rBitLength + rSylBitLength, CALL[LBSvBkAtEnd], c1; { uLBPCtMinusIx ← rCtMinusIx, L1 ← 0, c2; uLBPBitLength ← rBitLength, c3; rSpCount ← rSpCount and ~notPunctuationTRUE, c1; Q ← rSpCount or rhSuffixChar, c2; uLBPSpCount ← Q, c3; uLBPByteCount ← rByteCount, L3Disp, c1; uLBPWhiteSpace ← rWhiteSpace, DISP4[LBSvBkRet], c2;} Q ← rhLBHyphenPL, GOTO[LBComputeBackup], c3, at[0,10,LBSvBkRet]; Q ← 0, c3, at[1,10,LBSvBkRet]; LBComputeBackup: MAR ← [rhCacheObj, rCacheObj + 1], c1; rBitLength ← Q - rSylBitLength, CANCELBR[$,2], c2; rMicaLength ← MD {thisSylable.micaLength}, c3; rSpCount ← 0, rhSuffixChar ← suffixNull, c1; rArgReal ← uLBArgRealLo, c2; rhArgReal ← uLBArgRealHi, c3; MAR ← [rhArgReal, rArgReal + 8], L3Disp, c1; rByteCount ← - rSylByteCount, BRANCH[$,LBBackupHard,2], c2; Q ← MD {hyphenMicaLength}, GOTO[LBFinishBackup], c3; LBBackupHard: Q ← 0, c3; LBFinishBackup: rMicaLength ← Q - rMicaLength, c1; rWhiteSpace ← 0, c2; rReason ← reasonMargin, GOTO[LBStoreFinalCont], c3; LBNoSylables: rCtMinusIx ← uLBPCtMinusIx, CANCELBR[LBWholeWordBreak,1], c3; LBBreakOK: Noop, c1; Noop, c2; LBNoHyphen: rCtMinusIx ← uLBPCtMinusIx, GOTO[LBWholeWordBreak], c3; LBSimpleMarginExit: rCtMinusIx ← uLBPCtMinusIx, c3; LBWholeWordBreak: rCtMinusIx ← rCtMinusIx - 1, c1; rMicaLength ← 0, c2; rBitLength ← 0, c3; rSpCount ← 0, rhSuffixChar ← suffixNull, c1; rByteCount ← 0, c2; rWhiteSpace ← 0, c3; rReason ← reasonMargin, L1Disp, GOTO[LBStoreFinal], c1; LBInvalidCacheExit: rReason ← reasonInvalidCache, GOTO[LBStoreFinal], c1; LBContiguousExit: rReason ← reasonContiguousWords, CANCELBR[$,2], c2, at[0F,10,LBCheckPunct]; rMicaLength ← rMicaLength - Q, GOTO[LBExit], c3; LBUnableToBreakExit: rReason ← reasonUnableToBreak, CANCELBR[LBExit3,3], c2; LBNormalExit: rReason ← reasonNormal, CANCELBR[LBExit3,3], c2; LBSpecialGermanExit: rReason ← reasonSpecialGermanCase, CANCELBR[$,3], c2; LBExit3: Noop, c3; LBExit: Noop, c1; LBStoreFinal: rArgReal ← uLBArgRealLo, BRANCH[$,LBReadPriorIndex], c2; rhArgReal ← uLBArgRealHi, GOTO[LBStoreFinalCont], c3; LBReadPriorIndex: rhArgReal ← uLBArgRealHi, c3; MAR ← [rhArgReal, rArgReal + 11], c1; uLBTextCount ← 0, CANCELBR[$,2], c2; rCtMinusIx ← ~MD {prior.index}, c3; LBStoreFinalCont: MAR ← [rhArgReal, rArgReal + 0C], c1; MDR ← rMicaLength {final.micaLength}, CANCELBR[$,2], LOOPHOLE[wok], c2; rSpCount ← rSpCount or rhSuffixChar, c3; MAR ← [rhArgReal, rArgReal + 0D], c1; MDR ← rBitLength {final.bitLength}, CANCELBR[$,2], LOOPHOLE[wok], c2; Q ← uLBTextCount, c3; MAR ← [rhArgReal, rArgReal + 0E], c1; MDR ← rSpCount {final.count}, CANCELBR[$,2], LOOPHOLE[wok], c2; Q ← Q - rCtMinusIx, c3; MAR ← [rhArgReal, rArgReal + 0B], c1; MDR ← Q {final.index}, CANCELBR[$,2], LOOPHOLE[wok], c2; Q ← uLBTextCount, c3; MAR ← [rhArgReal, rArgReal + 0F], c1; MDR ← rByteCount {final.byteCount}, CANCELBR[$,2], LOOPHOLE[wok], c2; rCtMinusIx ← uLBPCtMinusIx, c3; MAR ← [rhArgReal, rArgReal + 10], L1Disp, c1; MDR ← rWhiteSpace {final.whiteSpace}, BRANCH[$,LBRestoreRegs,2], c2; Q ← Q - rCtMinusIx, c3; MAR ← [rhArgReal, rArgReal + 11], c1; MDR ← Q {prior.index}, CANCELBR[$,2], LOOPHOLE[wok], c2; Q ← uLBPMicaLength, c3; MAR ← [rhArgReal, rArgReal + 12], c1; MDR ← Q {prior.micaLength}, CANCELBR[$,2], LOOPHOLE[wok], c2; Q ← uLBPBitLength, c3; MAR ← [rhArgReal, rArgReal + 13], c1; MDR ← Q {prior.bitLength}, CANCELBR[$,2], LOOPHOLE[wok], c2; Q ← uLBPSpCount, c3; MAR ← [rhArgReal, rArgReal + 14], c1; MDR ← Q {prior.count}, CANCELBR[$,2], LOOPHOLE[wok], c2; Q ← uLBPByteCount, c3; MAR ← [rhArgReal, rArgReal + 15], c1; MDR ← Q {prior.byteCount}, CANCELBR[$,2], LOOPHOLE[wok], c2; Q ← uLBPWhiteSpace, c3; MAR ← [rhArgReal, rArgReal + 16], c1; MDR ← Q {prior.whiteSpace}, CANCELBR[$,3], LOOPHOLE[wok], c2; LBRestoreRegs: L ← UrL, c3; G ← UrG, c1; PC ← UrPC, push, GOTO[LBDone], c2; LBFastExit: rReason ← reasonNormal, c1; push, c2; LBDone: STK ← TOS, r0100 ← 0FF + 1, pop, GOTO[Bank1NxtInstc1], c3; {page cross handling} LBTextCross: rCacheObj ← rByteCount {save in temp, since rVirtualL = rByteCount}, c3; rVirtualL ← uLBTextRealLo, L3 ← 2, c1; Q ← 0FF + 1, c2; rVirtualL ← rVirtualL + Q, CarryBr, c3; LBTextRemap: Map ← uLBTextRealLo ← [rhVirtualH, rVirtualL], BRANCH[$,LBUpdateHighCont], c1, at[2,10,LBUpdateHighRet]; rByteCount ← rCacheObj, {restore from temp} c2; rhTextReal ← rTextReal ← MD, c3; MAR ← rTextReal ← [rhTextReal, 0+0], GOTO[LBMainRead], c1; LBUpdateHigh: Noop, c1; LBUpdateHighCont: Q ← rhVirtualH + 1, LOOPHOLE[byteTiming], L3Disp, c2; rhVirtualH ← Q LRot0, DISP4[LBUpdateHighRet], c3;