ObtainEmbeddedProfile:
PROC [oldIp:
ROPE]
RETURNS [ipToColorize, documentRopeSlice, stillToColorize:
ROPE ←
NIL] ~ {
PerOp: IPScan.ScanProc = {
[min: INT, max: INT, op: IPMaster.Op ← nil, seq: IPScan.Seq ← nil, num: INTEGER ← 0, punt: BOOL ← FALSE] RETURNS [quit: BOOL ← FALSE]
FoundKeep:
PROC []
RETURNS [
BOOL] ~ {
--searches for uncommented keepPassword
seq: ROPE ← oldIp.Substr[start: min+2, len: max-min-2];
commentPos: INT ← MIN[seq.Index[s2: "--"], seq.Index[s2: "<<"], seq.Index[s2: "\377\041\076\076\377\000" --extended char set dbldash--]];
RETURN [seq.Index[s2: keepPassword, case: FALSE] < commentPos];
};
IF punt THEN RETURN;
SELECT op
FROM
beginBody => {
IF bodyNest=0
THEN {
bodyStart ← min;
enabled ← enabledKeep ← FALSE;
};
bodyNest ← bodyNest+1;
};
endBody => {
IF (bodyNest ← bodyNest-1)=0
THEN
SELECT
TRUE
FROM
enabled, enabledKeep, everEnabled => {
--CustomColors found; abort scan, colorize, then go on
ipToColorize ← ipToColorize.Concat[oldIp.Substr[start: flushFrom, len: IF enabled THEN bodyStart-flushFrom ELSE --include CCPage-- max-flushFrom]];
IF oldIp.Substr[start: max].Equal["\240g"--END--] THEN ipToColorize ← ipToColorize.Concat["\240g"] ELSE stillToColorize ← oldIp.Substr[start: max];
quit ← TRUE; --will cause early abort of IPScan
profileAddition.PutChar['\n];
};
ENDCASE => NULL; -- just keep going
};
nil => {
--short sequenceString; actual sequence starts at min+2
IF oldIp.Fetch[index: min]#'\301 -- short sequenceString-- THEN ERROR; --System error!
SELECT
TRUE
FROM
enabled
OR enabledKeep => {
IF lookForKeep AND FoundKeep[] THEN {enabledKeep ← TRUE; enabled ← FALSE} --if <tab> is used, ("CustomColors <tab> (Keep)") VP uses SETXY for tabs and we catch SETXYs as newline; so lookForKeep allows us to check one more line for the keepPassword before it is reset to FALSE
ELSE
SELECT
TRUE
FROM
endPassword.Run[s2: oldIp, pos2: min+2, case:
FALSE]=endPasswordLength
--"EndCustom*"--
AND (enabled
OR enabledKeep) => {
ipToColorize ← ipToColorize.Concat[oldIp.Substr[start: flushFrom, len: IF enabled THEN passStart-flushFrom ELSE --include CC section-- max+1-flushFrom]];
enabled ← enabledKeep ← FALSE; --collect no more CC cmds
flushFrom ← max+1 --get past SHOW--
};
ENDCASE => {
--this line is a custom color command
profileAddition.PutRope[oldIp.Substr[start: min+2, len: max-min-2]];
profileAddition.PutRope["\377\000" --\377\000 ensures this is char set 0 since a hyphen sometimes changes the char set--];
};
lookForKeep ← FALSE;
};
embeddedProfilePassword.Run[s2: oldIp, pos2: min+2, case:
FALSE]=embeddedProfilePasswordLength
--"CustomColor*"-- => {
enabled ← lookForKeep ← ~(enabledKeep ← FoundKeep[]);
everEnabled ← TRUE;
passStart ← min;
};
ENDCASE => NULL;
};
setxy =>
IF enabled
OR enabledKeep
THEN {
--sameY=tab(add space); diffY=newLine(\n)
testY: INT ← ExtractY[oldIp.Substr[start: min, len: max-min]];
IF curY=testY THEN profileAddition.PutRope[" "]
ELSE {
prevY ← curY;
curY ← testY;
IF DifLineSpace[] THEN profileAddition.PutRope["\f"] ELSE profileAddition.PutRope["\n"]; --obscure problem. ViewPoint uses SETXY to do a newLine & also to spill a long line over. This is a hint to whether this is a completely newLine farther down on the page, like a footer, or a spill over (same y offset as used on prev line).
};
};
setxyrel, setyrel =>
IF enabled
OR enabledKeep
THEN {
testY: INT ← IF op=setxyrel THEN ExtractY[oldIp.Substr[start: min, len: max-min]] ELSE ExtractY[setxyFrag: oldIp.Substr[start: min, len: max-min], noX: TRUE];
IF testY=0 --same line-- THEN profileAddition.PutRope[" "]
ELSE {
--diff line
prevY ← curY;
curY ← curY+testY;
IF DifLineSpace[] THEN profileAddition.PutRope["\f"] ELSE profileAddition.PutRope["\n"];
};
};
ENDCASE => ERROR; --System error!
};
DifLineSpace:
PROC []
RETURNS [diff:
BOOL]~ {
curJump: INT ← ABS[curY-prevY];
diff ← prevJump#0 AND (curJump>prevJump+10); --10 is fudge allowed for line spacing
prevJump ← IF diff THEN 0 ELSE curJump; --every time there's a big jump, start over
};
embeddedProfilePasswordLength: INT ~ embeddedProfilePassword.Size;
endPasswordLength: INT ~ endPassword.Size;
lookForKeep: BOOL ← FALSE; --TRUE => found enabled, see if (Keep) on next line
enabled: BOOL ← FALSE; --TRUE => have found the password on this page
enabledKeep: BOOL ← FALSE; --TRUE => have found the keep password on this page
everEnabled: BOOL ← FALSE; --TRUE => at least one page had profile entries
bodyNest: INT ← 0;
flushFrom, bodyStart, passStart: INT ← 0;
curY, prevY: INT ← 0; --used to distinguish Tab SETXYs from \n SETXYs; used as vague hint to detect a big jump on page like a footer
prevJump: INT ← 0; --tracks the y-diff in the prev. line
profileAddition: IO.STREAM ~ IO.ROS[];
IPScan.ScanRope[ip: oldIp, ops: LIST[beginBody, endBody, setxy, setxyrel, setyrel], seqs: LIST[sequenceString], action: PerOp];
IF everEnabled THEN RETURN [ipToColorize: ipToColorize, documentRopeSlice: profileAddition.RopeFromROS, stillToColorize: stillToColorize]
ELSE RETURN [ipToColorize: oldIp, documentRopeSlice: NIL, stillToColorize: NIL];
};
ExtractY:
PROC [setxyFrag:
ROPE, noX:
BOOL ←
FALSE]
RETURNS [y:
INT ← 0] ~ {
startY: NAT ← IF noX THEN 0 ELSE 2; --2 is normal start of y in setxyFrag, if x encoded as short number
IF ~noX
THEN
SELECT setxyFrag.Fetch[0]
--start of x--
FROM
<= '\177 --using 2 byte short number encoding for x-- => NULL; --startY correct
'\302 --using multi-byte seqInteger encoding for x, # bytes found in next byte-- => startY ← startY + ORD[setxyFrag.Fetch[1]];
ENDCASE => ERROR; --system error; unknown encoding
SELECT setxyFrag.Fetch[startY]
--start of y--
FROM
<= '\177
--using 2 byte short number encoding for y, biased by 4000-- =>
y ← ORD[setxyFrag.Fetch[startY]]*256 + ORD[setxyFrag.Fetch[startY+1]] - 4000;
y ← IPMaster.IntFromSequenceData[text: Rope.ToRefText[setxyFrag], start: startY, len: 2];
'\302
--using multi-byte seqInteger encoding for y, # bytes found in next byte-- => {
bytes: NAT ← ORD[setxyFrag.Fetch[startY ← startY+1]]; --#bytes in y
IF bytes>4 THEN ERROR; --system error; would overflow INT boundaries
FOR i: NAT IN [1..bytes] DO
y ← y+ORD[setxyFrag.Fetch[startY+i]]*Real.Round[RealFns.Power[base: 256.0, exponent: bytes-i]];
ENDLOOP;
y ← IPMaster.IntFromSequenceData[text: Rope.ToRefText[setxyFrag], start: startY+1, len: bytes];
};
ENDCASE => ERROR; --system error; unknown encoding
};