DIRECTORY
MathDisplayExpr,
MathExpr,
MathBox,
MathConstructors,
MathDB,
MathTypes,
MathRules,
Convert USING [RopeFromAtom],
Rope USING [ROPE, Length, Find, Replace, Cat],
Imager USING [Context, black, SetColor, MaskRectangle],
XRope;

MathDisplayExprImpl: CEDAR PROGRAM
IMPORTS MathBox, MathExpr, MathDB, MathConstructors, Imager, MathRules, Rope, Convert, XRope
EXPORTS MathDisplayExpr ~

BEGIN

ROPE: TYPE ~ Rope.ROPE;
BOX: TYPE ~ MathBox.BOX;
EXPR: TYPE ~ MathExpr.EXPR;
AtomEXPR: TYPE ~ MathExpr.AtomEXPR;
CompoundEXPR: TYPE ~ MathExpr.CompoundEXPR;
MatrixEXPR: TYPE ~ MathExpr.MatrixEXPR;
Style: TYPE ~ MathTypes.Style;
Argument: TYPE ~ MathExpr.Argument;
Symbol: TYPE ~ MathExpr.Symbol;
AtomClass: TYPE ~ MathExpr.AtomClass;
AtomFlavor: TYPE ~ MathExpr.AtomFlavor;
CompoundClass: TYPE ~ MathExpr.CompoundClass;
MatrixClass: TYPE ~ MathExpr.MatrixClass;

Size: TYPE ~ MathRules.Size;
Selection: TYPE ~ MathDisplayExpr.Selection;
ReplacePair: TYPE ~ MathDisplayExpr.ReplacePair;


DisplayExprRep: PUBLIC TYPE ~
RECORD [
tag: ATOM,  -- identifying tag such as $integrand
expression: DisplayObj,  -- atom, compound expr, or matrix
relativeBox: BOX,  -- bounding box in relative units
absoluteBox: BOX,  -- bounding box in absolute units
iconic: BOOL _ FALSE, -- TRUE iff expression is currently iconic (2/87apparentlyUnused)
parent: DisplayExpr _ NIL  -- enclosing parent expression
];

DisplayObj: TYPE ~ REF DisplayObjRep;  
DisplayObjRep: TYPE ~ RECORD [
SELECT type:* FROM
atom => [class: AtomClass, value: ROPE],
compound => [class: CompoundClass, subExprs: LIST OF DisplayExpr _ NIL],
matrix => [
class: MatrixClass,  -- type of matrix op, e.g. matrix, vector, determinant, etc.
nRows, nCols: INT,  -- matrix size, rows x cols
elements: LIST OF DisplayExpr _ NIL,  -- matrix elements
openSym: DisplayExpr, -- left bracket
closeSym: DisplayExpr, -- right bracket
space: DisplayExpr -- inter-element spacing
]
ENDCASE
];

AtomDisplayObj: TYPE ~ REF AtomDisplayObjRep;
AtomDisplayObjRep: TYPE ~ atom DisplayObjRep;
CompoundDisplayObj: TYPE ~ REF CompoundDisplayObjRep;
CompoundDisplayObjRep: TYPE ~ compound DisplayObjRep;
MatrixDisplayObj: TYPE ~ REF MatrixDisplayObjRep;
MatrixDisplayObjRep: TYPE ~ matrix DisplayObjRep;

DisplayExpr: TYPE ~ REF DisplayExprRep;  -- inside impl module, use rep
MakeAtomicDisplayExpr: PUBLIC PROC[tag: ATOM, class: AtomClass, value: ROPE, relBox, absBox: BOX, parent: DisplayExpr _ NIL]  RETURNS[DisplayExpr] ~ {
RETURN[NEW[DisplayExprRep _ [tag: tag, relativeBox: relBox, absoluteBox: absBox, parent: parent, expression: NEW[AtomDisplayObjRep _ [atom[class: class, value: value]]]]]];
};

MakeCompoundDisplayExpr: PUBLIC PROC[tag: ATOM, class: CompoundClass, subExprs: LIST OF DisplayExpr, relBox, absBox: BOX, parent: DisplayExpr _ NIL] RETURNS[DisplayExpr] ~ {
RETURN[NEW[DisplayExprRep _ [tag: tag, relativeBox: relBox, absoluteBox: absBox, parent: parent, expression: NEW[CompoundDisplayObjRep _ [compound[class: class, subExprs: subExprs]]]]]];
};

MakeMatrixDisplayExpr: PUBLIC PROC[tag: ATOM, class: MatrixClass, nRows, nCols: INT, elements: LIST OF DisplayExpr, relBox, absBox: BOX, openSym, closeSym, space: DisplayExpr, parent: DisplayExpr _ NIL] 
RETURNS[DisplayExpr] ~ {
RETURN[NEW[DisplayExprRep _ [tag: tag, relativeBox: relBox, absoluteBox: absBox, parent: parent, expression: NEW[MatrixDisplayObjRep _ [matrix[class: class, nRows: nRows, nCols: nCols, elements: elements, openSym: openSym, closeSym: closeSym, space: space]]]]]];
};

ASRopeFromDisplayExpr: PUBLIC PROC[expr: DisplayExpr, flavor: ATOM _ $AS] RETURNS[ROPE] ~ {
WITH expr.expression SELECT FROM

a: AtomDisplayObj => SELECT flavor FROM
$Reduce => IF a.class.cvtReduceRope # NIL THEN RETURN[a.class.cvtReduceRope[a.value]] ELSE RETURN[a.value];
$SMP => IF a.class.cvtSMPRope # NIL THEN RETURN[a.class.cvtSMPRope[a.value]] ELSE RETURN[a.value];
ENDCASE => IF a.class.cvtASRope # NIL THEN RETURN[a.class.cvtASRope[a.value]] ELSE RETURN[a.value];

c: CompoundDisplayObj => {
template: ROPE _ SELECT flavor FROM
$Reduce => c.class.cvtReduce,  -- template for return value
$SMP => c.class.cvtSMP,  -- template for return value
ENDCASE => c.class.cvtAS;  -- template for return value
argName: ROPE _ NIL;
position: INT _ -1;
IF Rope.Length[template] < 1 THEN RETURN[""];

FOR l: LIST OF Argument _ c.class.arguments, l.rest UNTIL l = NIL DO
argName _ Convert.RopeFromAtom[l.first.name];
position _ Rope.Find[template, argName];
IF position # -1 THEN template _ Rope.Replace[base: template, start: position, len: Rope.Length[argName], with: ASRopeFromDisplayExpr[GetDisplayExpr[l.first.name, c.subExprs], flavor] ];
ENDLOOP;  

IF c.class.name = $complex THEN {
position _ Rope.Find[template, "+ -"];
IF position # -1 THEN template _ Rope.Replace[base: template, start: position, len: 3, with: "- "];
};

RETURN[template];
};

m: MatrixDisplayObj => {
Element: TYPE ~ RECORD [
expr: DisplayExpr _ NIL
];
Row: TYPE ~ REF RowRec;
RowRec: TYPE ~ RECORD [
elements: SEQUENCE numberOfCols: NAT OF Element
];
Matrix: TYPE ~ REF MatrixRec;
MatrixRec: TYPE ~ RECORD[
rows: SEQUENCE numberOfRows: NAT OF Row
];

a: Matrix;
currentRow, currentCol: NAT;
result: ROPE _ NIL;  -- return value

a _ NEW[MatrixRec[m.nRows]];
FOR row:INT IN [0..m.nRows) DO
a[row] _ NEW[RowRec[m.nCols]];
ENDLOOP;
FOR l: LIST OF DisplayExpr _ m.elements, l.rest UNTIL l = NIL DO
[currentRow, currentCol] _ MathRules.RowColFromAtom[l.first.tag];
a[currentRow - 1][currentCol - 1].expr _ l.first;
ENDLOOP;

SELECT m.class.name FROM
$matrix => {
result _ "List[ ";
FOR r:INT IN [0..m.nRows) DO
result _ Rope.Cat[result, "List[ "];  -- row start char
FOR c:INT IN [0..m.nCols) DO
result _ Rope.Cat[result, ASRopeFromDisplayExpr[a[r][c].expr, flavor]];
IF c # (m.nCols - 1) THEN result _ Rope.Cat[result, ", "];  -- col separator
ENDLOOP;
result _ Rope.Cat[result, " ]"];  -- row end char
IF r # (m.nRows - 1) THEN result _ Rope.Cat[result, ", "];  -- row separator
ENDLOOP;
result _ Rope.Cat[result, " ]"];  -- end with matrix end char
};
$vector, $sequence, $set, $point => {
result _ "List[ ";  -- should select set, sequence, etc.
IF m.nRows = 1 THEN { -- row vector
FOR c: INT IN [0..m.nCols) DO
result _ Rope.Cat[result, ASRopeFromDisplayExpr[a[0][c].expr, flavor]];
IF c # (m.nCols - 1) THEN result _ Rope.Cat[result, ", "];  -- col separator
ENDLOOP;
}
ELSE { -- column vector
FOR r: INT IN [0..m.nRows) DO
result _ Rope.Cat[result, ASRopeFromDisplayExpr[a[r][0].expr, flavor]];
IF r # (m.nRows - 1) THEN result _ Rope.Cat[result, ", "];  -- row separator
ENDLOOP;
};
result _ Rope.Cat[result, " ]"]; 
};
ENDCASE => result _ "unknownMatrixType";
RETURN[result];
};
ENDCASE => ERROR;

};
 

DisplayExprFromExpr: PUBLIC PROC[expr: EXPR] RETURNS[DisplayExpr] ~ {
myDisplayExpr, tempDisplayExpr: DisplayExpr;

emptyAtom: ATOM _ $expr;  -- generic identifier
emptyRelBox: BOX _ MathBox.MakeBox[emptyAtom, NIL, other, relative];
emptyAbsBox: BOX _ MathBox.MakeBox[emptyAtom, NIL, other, absolute];

SELECT expr.GetType[] FROM

atom => {
a: AtomEXPR _ expr.GetAtomExpr[];

RETURN[MakeAtomicDisplayExpr[emptyAtom, MathExpr.GetAtomClass[a], MathExpr.GetValue[a], emptyRelBox, emptyAbsBox]];
};

compound => {

c: CompoundEXPR _ expr.GetCompoundExpr[];
compClass: CompoundClass _ MathExpr.GetCompoundClass[c];

displaySubExprs: LIST OF DisplayExpr _ NIL;  -- cons up list of display expressions 

FOR l: LIST OF Argument _ compClass.arguments, l.rest UNTIL l = NIL DO
tempDisplayExpr _ DisplayExprFromExpr[MathExpr.GetTaggedExpr[l.first.name, MathExpr.GetSubExprs[c] ! exprNotFound => {ERROR unable[$missingArg]}].expression];
tempDisplayExpr.tag _ l.first.name;  -- set name tag for display expr
displaySubExprs _ CONS[tempDisplayExpr, displaySubExprs];
ENDLOOP;

FOR l: LIST OF Symbol _ compClass.symbols, l.rest UNTIL l = NIL DO
tempDisplayExpr _ DisplayExprFromExpr[MathExpr.GetTaggedExpr[l.first.name, MathExpr.GetSubExprs[c] ! exprNotFound => {ERROR unable[$missingSym]}].expression];
tempDisplayExpr.tag _ l.first.name;  -- set name tag for display expr
displaySubExprs _ CONS[tempDisplayExpr, displaySubExprs];
ENDLOOP;

myDisplayExpr _ MakeCompoundDisplayExpr[emptyAtom, MathExpr.GetCompoundClass[c], displaySubExprs, emptyRelBox, emptyAbsBox];

FOR l: LIST OF DisplayExpr _ displaySubExprs, l.rest UNTIL l = NIL DO
l.first.parent _ myDisplayExpr;  -- set parent 
ENDLOOP;

RETURN[myDisplayExpr];
};
matrix => {

m: MatrixEXPR _ expr.GetMatrixExpr[];
elts: LIST OF MathExpr.TaggedMathExpr _ MathExpr.GetMatrixElements[m];
class: MatrixClass _ MathExpr.GetMatrixClass[m];
displayElts, displayEltsPointer: LIST OF DisplayExpr _ NIL;
nRows, nCols: NAT;
openSym, closeSym, space: DisplayExpr;

[nRows, nCols] _ MathExpr.GetMatrixSize[m];

FOR l: LIST OF MathExpr.TaggedMathExpr _ elts, l.rest UNTIL l = NIL DO
tempDisplayExpr _ DisplayExprFromExpr[l.first.expression];
tempDisplayExpr.tag _ l.first.id; -- set name tag for display expr
IF displayElts = NIL THEN displayElts _ displayEltsPointer _ LIST[tempDisplayExpr] ELSE displayEltsPointer _ displayEltsPointer.rest _ LIST[tempDisplayExpr];
ENDLOOP;

openSym _ DisplayExprFromExpr[class.openSym];
closeSym _ DisplayExprFromExpr[class.closeSym];
space _ DisplayExprFromExpr[class.space];

myDisplayExpr _ MakeMatrixDisplayExpr[emptyAtom, class, nRows, nCols, displayElts, emptyRelBox, emptyAbsBox, openSym, closeSym, space];

FOR l: LIST OF DisplayExpr _ displayElts, l.rest UNTIL l = NIL DO
l.first.parent _ myDisplayExpr; -- set parent
ENDLOOP;

RETURN[myDisplayExpr];
};
ENDCASE => ERROR;
};

ExprFromDisplayExpr: PUBLIC PROC[expr: DisplayExpr] RETURNS[EXPR] ~ {
WITH expr.expression SELECT FROM

a: AtomDisplayObj => {
RETURN[MathExpr.MakeAtomicExpr[a.class.name, a.value]];
};

c: CompoundDisplayObj => {
args: LIST OF MathExpr.TaggedMathExpr _ NIL;

FOR l: LIST OF DisplayExpr _ c.subExprs, l.rest UNTIL l = NIL DO
args _ CONS[[l.first.tag, ExprFromDisplayExpr[l.first]], args];
ENDLOOP;

RETURN[MathExpr.MakeCompoundExpr[c.class.name, args]];
};

m: MatrixDisplayObj => {
elts, eltsPointer: LIST OF MathExpr.TaggedMathExpr _ NIL;

FOR l: LIST OF DisplayExpr _ m.elements, l.rest UNTIL l = NIL DO -- changed 3/4/87
taggedMathExpr: MathExpr.TaggedMathExpr _ [l.first.tag, ExprFromDisplayExpr[l.first]];
IF elts = NIL THEN elts _ eltsPointer _ LIST[taggedMathExpr] ELSE eltsPointer _ eltsPointer.rest _ LIST[taggedMathExpr];
ENDLOOP;

RETURN[MathExpr.MakeMatrixExpr[m.class.name, m.nRows, m.nCols, elts]];
};

ENDCASE => ERROR;
};



Copy: PUBLIC PROC[expr: DisplayExpr] RETURNS[DisplayExpr] ~ {
WITH expr.expression SELECT FROM

a: AtomDisplayObj => {
RETURN[MakeAtomicDisplayExpr[expr.tag, a.class, a.value, expr.relativeBox, expr.absoluteBox]];
};

c: CompoundDisplayObj => {

exprCopy: DisplayExpr;  -- return value
copiedSubExprs: LIST OF DisplayExpr _ NIL;  -- cons up new list of copies

FOR l: LIST OF DisplayExpr _ c.subExprs, l.rest UNTIL l = NIL DO
copiedSubExprs _ CONS[Copy[l.first], copiedSubExprs];
ENDLOOP; 

exprCopy _ MakeCompoundDisplayExpr[expr.tag, c.class, copiedSubExprs, expr.relativeBox, expr.absoluteBox];
FOR l: LIST OF DisplayExpr _ copiedSubExprs, l.rest UNTIL l = NIL DO
l.first.parent _ exprCopy;  -- set parent pointers appropriately
ENDLOOP;

RETURN[exprCopy];
};

m: MatrixDisplayObj => {

exprCopy: DisplayExpr; -- return value
copiedElts, copiedEltsPtr: LIST OF DisplayExpr _ NIL;  -- cons up a new list of copied elements


FOR l: LIST OF DisplayExpr _ m.elements, l.rest UNTIL l = NIL DO
IF copiedElts = NIL THEN copiedElts _ copiedEltsPtr _ LIST[Copy[l.first] ] ELSE copiedEltsPtr _ copiedEltsPtr.rest _ LIST[Copy[l.first] ];
ENDLOOP;

exprCopy _ MakeMatrixDisplayExpr[expr.tag, m.class, m.nRows, m.nCols, copiedElts, expr.relativeBox, expr.absoluteBox, Copy[m.openSym], Copy[m.closeSym], Copy[m.space]];
FOR l: LIST OF DisplayExpr _ copiedElts, l.rest UNTIL l = NIL DO
l.first.parent _ exprCopy;  -- set parent pointers appropriately
ENDLOOP;

RETURN[exprCopy];
};

ENDCASE => ERROR;
};
Tag: PUBLIC PROC[expr: DisplayExpr] RETURNS[ATOM] ~ {
RETURN[expr.tag];
};

Class: PUBLIC PROC[expr: DisplayExpr] RETURNS[ATOM] ~ {
WITH expr.expression SELECT FROM
a: AtomDisplayObj => RETURN[a.class.name];
c: CompoundDisplayObj => RETURN[c.class.name];
m: MatrixDisplayObj => RETURN[m.class.name];
ENDCASE => ERROR;
};

GetSubExprs: PUBLIC PROC[expr: DisplayExpr] RETURNS[LIST OF DisplayExpr] ~ {
WITH expr.expression SELECT FROM
a: AtomDisplayObj => RETURN[NIL];  -- atoms don't have any children
c: CompoundDisplayObj => RETURN[c.subExprs];
m: MatrixDisplayObj => RETURN[m.elements];
ENDCASE => ERROR;
};
Format: PUBLIC PROC[expr: DisplayExpr, size: Size] RETURNS[BOX] ~ {
subExprBoxes: LIST OF BOX;
myBox, tempBox: BOX;

WITH expr.expression SELECT FROM

a: AtomDisplayObj => {
RETURN[MathBox.Scale[MathBox.MakeBox[tag: a.class.name, aliases: NIL, formatClass: a.class.formatClass, type: absolute, extents: a.class.boxRule[a.value, a.class.style]], MathRules.VecFromSize[size]]];
};


c: CompoundDisplayObj => {


subExprBoxes _ NIL;  -- cons up list of subexpression boxes

FOR l: LIST OF Argument _ c.class.arguments, l.rest UNTIL l = NIL DO
tempBox _ Format[GetDisplayExpr[l.first.name, c.subExprs ! exprNotFound => {ERROR unable[$missingArg]}], MathRules.ComputeSize[base: size, adjustment: l.first.size]];
subExprBoxes _ CONS[MathBox.MakeBox[l.first.name, l.first.aliases, tempBox.FormatClass[], tempBox.Type[], tempBox.Extents[], tempBox.Offset[], tempBox.SubscriptHint[], tempBox.SuperscriptHint[]], subExprBoxes];
ENDLOOP;

FOR l: LIST OF Symbol _ c.class.symbols, l.rest UNTIL l = NIL DO
tempBox _ Format[GetDisplayExpr[l.first.name, c.subExprs ! exprNotFound => {ERROR unable[$missingSym]}], MathRules.ComputeSize[base: size, adjustment: l.first.size]];
subExprBoxes _ CONS[MathBox.MakeBox[l.first.name, l.first.aliases, tempBox.FormatClass[], tempBox.Type[], tempBox.Extents[], tempBox.Offset[], tempBox.SubscriptHint[], tempBox.SuperscriptHint[]], subExprBoxes];
ENDLOOP;

subExprBoxes _ c.class.boxRule[subExprBoxes];

[myBox, subExprBoxes] _ c.class.compBox[subExprBoxes];
myBox _ MathBox.ChangeFormatClass[myBox, c.class.formatClass];

FOR l: LIST OF DisplayExpr _ c.subExprs, l.rest UNTIL l = NIL DO
IF l.first.relativeBox.Type # relative THEN ERROR unable[$wrongBoxType];
l.first.relativeBox _ MathBox.GetBox[l.first.tag, subExprBoxes ! MathBox.boxNotFound => {ERROR unable[$boxNotFound]}];  -- set box
ENDLOOP;

RETURN[myBox];
};

m: MatrixDisplayObj => {
elementBoxes, elementBoxesPtr: LIST OF BOX _ NIL;
tempBox, spaceBox, openSymBox, closeSymBox: BOX;


FOR l: LIST OF DisplayExpr _ m.elements, l.rest UNTIL l = NIL DO
tempBox _ Format[l.first, MathRules.ComputeSize[base: size, adjustment: script]];
IF elementBoxes = NIL THEN
elementBoxes _ elementBoxesPtr _ LIST[ MathBox.MakeBox[l.first.tag, NIL, tempBox.FormatClass[], tempBox.Type[], tempBox.Extents[], tempBox.Offset[], tempBox.SubscriptHint[], tempBox.SuperscriptHint[] ] ]
ELSE
elementBoxesPtr _ elementBoxesPtr.rest _ LIST[ MathBox.MakeBox[l.first.tag, NIL, tempBox.FormatClass[], tempBox.Type[], tempBox.Extents[], tempBox.Offset[], tempBox.SubscriptHint[], tempBox.SuperscriptHint[] ] ];
ENDLOOP;

spaceBox _ Format[m.space, MathRules.ComputeSize[base: size, adjustment: script]];
openSymBox _ Format[m.openSym, normal];
closeSymBox _ Format[m.closeSym, normal];

[myBox, elementBoxes, m.openSym.relativeBox, m.closeSym.relativeBox] _ MathRules.ComposeMatrix[m.nRows, m.nCols, elementBoxes, spaceBox, openSymBox, closeSymBox];
myBox _ MathBox.ChangeFormatClass[myBox, m.class.formatClass];

FOR l: LIST OF DisplayExpr _ m.elements, l.rest UNTIL l = NIL DO
IF l.first.relativeBox.Type # relative THEN ERROR unable[$wrongBoxType];
l.first.relativeBox _ MathBox.GetBox[l.first.tag, elementBoxes ! MathBox.boxNotFound => {ERROR unable[$boxNotFound]}];  -- set box
ENDLOOP;

RETURN[myBox];
};


ENDCASE => ERROR;
};

Paint: PUBLIC PROC[expr: DisplayExpr, context: Imager.Context, absBox: BOX, 
selections: LIST OF Selection] ~ {
currentDisplayExpr: DisplayExpr;
IF absBox.Type # absolute THEN ERROR unable[$wrongBoxType];
expr.absoluteBox _ absBox;

WITH expr.expression SELECT FROM

a: AtomDisplayObj => {
a.class.paintRule[a.value, a.class.style, context, absBox];
};

c: CompoundDisplayObj => {

FOR l: LIST OF Argument _ c.class.arguments, l.rest UNTIL l = NIL DO
currentDisplayExpr _ GetDisplayExpr[l.first.name, c.subExprs ! exprNotFound => {ERROR unable[$missingArg]}];
Paint[currentDisplayExpr, context, MathBox.RelToAbsBox[currentDisplayExpr.relativeBox, absBox], selections];
ENDLOOP;

FOR l: LIST OF Symbol _ c.class.symbols, l.rest UNTIL l = NIL DO
currentDisplayExpr _ GetDisplayExpr[l.first.name, c.subExprs ! exprNotFound => {ERROR unable[$missingArg]}];
Paint[currentDisplayExpr, context, MathBox.RelToAbsBox[currentDisplayExpr.relativeBox, absBox], selections];
ENDLOOP;
};

m: MatrixDisplayObj =>  {

FOR l: LIST OF DisplayExpr _ m.elements, l.rest UNTIL l = NIL DO
Paint[l.first, context, MathBox.RelToAbsBox[l.first.relativeBox, absBox], selections];
ENDLOOP;

Paint[m.openSym, context, MathBox.RelToAbsBox[m.openSym.relativeBox, absBox], selections];
Paint[m.closeSym, context, MathBox.RelToAbsBox[m.closeSym.relativeBox, absBox], selections];
};

ENDCASE => ERROR;

FOR l: LIST OF Selection _ selections, l.rest UNTIL l = NIL DO
IF (expr = l.first.expr) THEN {
context.SetColor[l.first.color];

Imager.MaskRectangle[context, [x: absBox.Offset[].x - (absBox.Extents[].leftExtent + 1), y: absBox.Offset[].y - (absBox.Extents[].descent + 1), w: absBox.Width[] + 1, h: absBox.Height[] + 2]];

context.SetColor[Imager.black];
};
ENDLOOP;
};

GetDisplayExpr: PUBLIC PROC[tag: ATOM, exprs: LIST OF DisplayExpr] RETURNS[DisplayExpr] ~ {

FOR l: LIST OF DisplayExpr _ exprs, l.rest UNTIL l = NIL DO
IF l.first.tag = tag THEN RETURN[l.first];
ENDLOOP;

ERROR exprNotFound;
};
DisplayExprFromCoords: PUBLIC PROC[expr: DisplayExpr, x, y: REAL] RETURNS[DisplayExpr] ~ {
IF expr = NIL THEN ERROR noSelection;
IF ~MathBox.Inside[expr.absoluteBox, x, y] THEN ERROR noSelection;

WITH expr.expression SELECT FROM

a: AtomDisplayObj => {
IF Selectable[expr] THEN RETURN[expr] ELSE ERROR noSelection;
};

c: CompoundDisplayObj => {
FOR l: LIST OF DisplayExpr _ c.subExprs, l.rest UNTIL l = NIL DO
IF MathBox.Inside[l.first.absoluteBox, x, y] THEN
RETURN[DisplayExprFromCoords[l.first, x, y ! noSelection => CONTINUE]];
ENDLOOP;

IF Selectable[expr] THEN RETURN[expr] ELSE ERROR noSelection;  
};

m: MatrixDisplayObj => {
FOR l: LIST OF DisplayExpr _ m.elements, l.rest UNTIL l = NIL DO
IF MathBox.Inside[l.first.absoluteBox, x, y] THEN
RETURN[DisplayExprFromCoords[l.first, x, y ! noSelection => CONTINUE]];
ENDLOOP;

IF Selectable[expr] THEN RETURN[expr] ELSE ERROR noSelection;  
};

ENDCASE => ERROR;

};

Selectable: PUBLIC PROC[expr: DisplayExpr] RETURNS[BOOL] ~ {
IF expr = NIL THEN RETURN[FALSE];
WITH expr.expression SELECT FROM
a: AtomDisplayObj => {
IF a.class.flavor = symbol THEN RETURN[FALSE] ELSE RETURN[TRUE];
};
c: CompoundDisplayObj => RETURN[TRUE];
m: MatrixDisplayObj => RETURN[TRUE];
ENDCASE => ERROR;
};
SelectableParent: PUBLIC PROC[expr: DisplayExpr] RETURNS[DisplayExpr] ~ {
IF (expr = NIL) OR (expr.parent) = NIL THEN ERROR noSelection; 
RETURN[expr.parent];
};

SelectableChild: PUBLIC PROC[expr: DisplayExpr] RETURNS[DisplayExpr] ~ {
childExpr: DisplayExpr _ NIL;
IF expr = NIL THEN ERROR noSelection;
WITH expr.expression SELECT FROM
a: AtomDisplayObj => ERROR noSelection;  -- atom has no children
c: CompoundDisplayObj => {
FOR l: LIST OF Argument _ c.class.arguments, l.rest UNTIL l = NIL DO
childExpr _ GetDisplayExpr[l.first.name, c.subExprs];
IF Selectable[childExpr] THEN RETURN[childExpr];  -- return selected expression
ENDLOOP;
ERROR noSelection;
};
m: MatrixDisplayObj => {
ERROR noSelection;
};
ENDCASE => ERROR;
};

ExtendFunctionSelectSibling: PROC [expr: DisplayExpr] RETURNS [DisplayExpr] ~ {
emptyAtom: ATOM _ $expr;  -- generic identifier
emptyRelBox: BOX _ MathBox.MakeBox[emptyAtom, NIL, other, relative];
emptyAbsBox: BOX _ MathBox.MakeBox[emptyAtom, NIL, other, absolute];
arg12Space: DisplayExpr _ MakeAtomicDisplayExpr[$arg12Space, MathDB.LookupAtomClass[$space],  Convert.RopeFromAtom[$medium, FALSE], emptyRelBox, emptyAbsBox];
arg23Space: DisplayExpr _ MakeAtomicDisplayExpr[$arg23Space, MathDB.LookupAtomClass[$space],  Convert.RopeFromAtom[$medium, FALSE], emptyRelBox, emptyAbsBox];
arg34Space: DisplayExpr _ MakeAtomicDisplayExpr[$arg34Space, MathDB.LookupAtomClass[$space],  Convert.RopeFromAtom[$medium, FALSE], emptyRelBox, emptyAbsBox];
comma12: DisplayExpr _ MakeAtomicDisplayExpr[$comma12, MathDB.LookupAtomClass[$italicSym],  XRope.FromChar[',] , emptyRelBox, emptyAbsBox];
comma23: DisplayExpr _ MakeAtomicDisplayExpr[$comma23, MathDB.LookupAtomClass[$italicSym],  XRope.FromChar[',] , emptyRelBox, emptyAbsBox];
comma34: DisplayExpr _ MakeAtomicDisplayExpr[$comma34, MathDB.LookupAtomClass[$italicSym],  XRope.FromChar[',] , emptyRelBox, emptyAbsBox];
newExprs: LIST OF DisplayExpr;
sibling: DisplayExpr _ DisplayExprFromExpr[MathConstructors.MakePlaceHolder[] ];
sibling.parent _ expr.parent;
WITH expr.parent.expression SELECT FROM
c: CompoundDisplayObj => SELECT c.class.name FROM
$nullaryFunction, $unaryFunction, $binaryFunction, $ternaryFunction => {
SELECT c.class.name FROM
$nullaryFunction => {
c.class _ MathDB.LookupCompoundClass[$unaryFunction];
sibling.tag _ $arg1;
newExprs _ LIST[sibling]
};
$unaryFunction => {
c.class _ MathDB.LookupCompoundClass[$binaryFunction];
sibling.tag _ $arg2;
newExprs _ LIST[sibling, arg12Space, comma12]
};
$binaryFunction => {
c.class _ MathDB.LookupCompoundClass[$ternaryFunction];
sibling.tag _ $arg3;
newExprs _ LIST[sibling, arg23Space, comma23]
};
$ternaryFunction => {
c.class _ MathDB.LookupCompoundClass[$quaternaryFunction];
sibling.tag _ $arg4;
newExprs _ LIST[sibling, arg34Space, comma34]
};
ENDCASE => ERROR; -- can't extend quaternaryFunction
IF c.subExprs = NIL THEN c.subExprs _ newExprs ELSE {
p: LIST OF DisplayExpr _ c.subExprs;
WHILE p.rest#NIL DO p _ p.rest ENDLOOP;
p.rest _ newExprs;
};
};
ENDCASE => ERROR noSelection;
ENDCASE => ERROR noSelection;
RETURN[sibling];
};

SelectableSibling: PUBLIC PROC[expr: DisplayExpr] RETURNS[DisplayExpr] ~ {
afterExpr: LIST OF Argument _ NIL;  -- sibling after expr in parent's subexpr list
siblingExpr: DisplayExpr _ NIL;

IF (expr = NIL) OR (expr.parent = NIL) THEN ERROR noSelection;

WITH expr.parent.expression SELECT FROM
a: AtomDisplayObj => ERROR noSelection;
c: CompoundDisplayObj => {
FOR l: LIST OF Argument _ c.class.arguments, l.rest UNTIL l = NIL DO
IF l.first.name = expr.tag THEN {afterExpr _ l.rest; EXIT};
ENDLOOP;
FOR l: LIST OF Argument _ afterExpr, l.rest UNTIL l = NIL DO
siblingExpr _ GetDisplayExpr[l.first.name, c.subExprs];
IF Selectable[siblingExpr] THEN RETURN[siblingExpr]; -- return selected expression
ENDLOOP;
SELECT c.class.name FROM
$nullaryFunction, $unaryFunction, $binaryFunction, $ternaryFunction => RETURN[ExtendFunctionSelectSibling[expr]]; -- hack
ENDCASE;

IF c.class.name=$paren THEN RETURN[SelectableSibling[expr.parent] ];
FOR l: LIST OF Argument _ c.class.arguments, l.rest UNTIL l = NIL DO
IF l.first.name = expr.tag THEN EXIT;  -- already looked thru entire list
siblingExpr _ GetDisplayExpr[l.first.name, c.subExprs];
IF Selectable[siblingExpr] THEN RETURN[siblingExpr]; -- return selected expression
ENDLOOP;
ERROR noSelection;
};
m: MatrixDisplayObj => {
ERROR noSelection;
};
ENDCASE => ERROR;
};

Replace: PUBLIC PROC[expr, old, new: DisplayExpr] RETURNS[DisplayExpr] ~ {
RETURN[ReplaceN[expr, LIST[[old: old, new: new]]]];
};

ReplaceN: PUBLIC PROC[expr: DisplayExpr, replacements: LIST OF ReplacePair] RETURNS[DisplayExpr] ~ {
FOR l: LIST OF ReplacePair _ replacements, l.rest UNTIL l = NIL DO
IF expr = l.first.old THEN {
parent: DisplayExpr _ l.first.old.parent;
new: DisplayExpr _ l.first.new;

IF FALSE THEN {
parenArgTag: ATOM = $a;
argDisplayExpr: DisplayExpr;

parenExpr: DisplayExpr _ DisplayExprFromExpr[MathExpr.MakeCompoundExpr[$paren, LIST[[parenArgTag, MathConstructors.MakePlaceHolder[] ]] ] ];
FOR l: LIST OF DisplayExpr _ GetSubExprs[parenExpr], l.rest UNTIL l = NIL DO
IF Tag[l.first] = parenArgTag THEN { argDisplayExpr _ l.first; EXIT };
ENDLOOP;

parenExpr _ Replace[parenExpr, argDisplayExpr, new];

parenExpr.tag _ l.first.old.tag;  -- replacement has same tag (e.g. $integrand, etc.)
parenExpr.parent _ parent; -- replacement has same parent as before
RETURN[parenExpr] 
}
ELSE {
new.tag _ l.first.old.tag;  -- replacement has same tag (e.g. $integrand, etc.)
new.parent _ parent; -- replacement has same parent as before
RETURN[new]
};
};
ENDLOOP;

WITH expr.expression SELECT FROM

a: AtomDisplayObj => {
RETURN[Copy[expr]];
};

c: CompoundDisplayObj => {

exprCopy: DisplayExpr;  -- return value
copiedSubExprs: LIST OF DisplayExpr _ NIL;  -- cons up new list of copies

FOR l: LIST OF DisplayExpr _ c.subExprs, l.rest UNTIL l = NIL DO
copiedSubExprs _ CONS[ReplaceN[l.first, replacements], copiedSubExprs];
ENDLOOP; 

exprCopy _ MakeCompoundDisplayExpr[expr.tag, c.class, copiedSubExprs, expr.relativeBox, expr.absoluteBox];
FOR l: LIST OF DisplayExpr _ copiedSubExprs, l.rest UNTIL l = NIL DO
l.first.parent _ exprCopy;  -- set parent pointers appropriately
ENDLOOP;

RETURN[exprCopy];
};

m: MatrixDisplayObj => {

exprCopy: DisplayExpr; -- return value
copiedElts, copiedEltsPtr: LIST OF DisplayExpr _ NIL;  -- cons up a new list of copied elements


FOR l: LIST OF DisplayExpr _ m.elements, l.rest UNTIL l = NIL DO
IF copiedElts = NIL THEN copiedElts _ copiedEltsPtr _ LIST[ReplaceN[l.first, replacements] ] ELSE copiedEltsPtr _ copiedEltsPtr.rest _ LIST[ReplaceN[l.first, replacements] ];
ENDLOOP;

exprCopy _ MakeMatrixDisplayExpr[expr.tag, m.class, m.nRows, m.nCols, copiedElts, expr.relativeBox, expr.absoluteBox, Copy[m.openSym], Copy[m.closeSym], Copy[m.space]];
FOR l: LIST OF DisplayExpr _ copiedElts, l.rest UNTIL l = NIL DO
l.first.parent _ exprCopy;  -- set parent pointers appropriately
ENDLOOP;

RETURN[exprCopy];
};

ENDCASE => ERROR;

};
unable: PUBLIC ERROR[reason: ATOM] = CODE;
noSelection: PUBLIC ERROR = CODE;
exprNotFound: PUBLIC ERROR = CODE;


END.
��!˜��MathDisplayExprImpl.mesa
Carl Waldspurger, August 29, 1986 2:58:56 pm PDT
Arnon, December 11, 1986 11:23:05 am PST
Type Abbreviations from Imported Interfaces

Private Type Rep
A DisplayExpr is a MUTABLE math expression which is mapped to a viewer.
useful type shorthands
Display Expression Constructors
effects:  Constructs and returns a new atomic display expression.
effects:  Constructs and returns a new compound display expression.
effects:  Constructs and returns a new matrix display expression.
Parse/UnParse Routines
effects:  Returns a ROPE in selected format

recursively copy subexpressions
Hack for complexes with negative imaginary part. December 11, 1986 11:24:18 am PST
convert boxes into a SEQUENCE (ugh!) matrix type
instantiate matrix "a"  (isn't CLU's array[]$create() much nicer, really?)
add a comma if not last col in row
add a comma if not last row in matrix
add a comma if not last col in vector
add a comma if not last row in vector
effects:  Constructs and returns a new display expression from expr.
          All Display formatting information is set to default values.

local declarations
should really combine passed in style with local atomic style
recursively generate displayexprs for all subexpressions (arguments & symbols)
generate all argument subexpressions
generate all symbol subexpressions

construct return value now so can set "parent" component of subexpressions
set parents of display subexpressions
convert elements from expr to displayexpr
FOR l: LIST OF MathExpr.TaggedMathExpr _ elts, l.rest UNTIL l = NIL DO
tempDisplayExpr _ DisplayExprFromExpr[l.first.expression];
tempDisplayExpr.tag _ l.first.id; -- set name tag for display expr
displayElts _ CONS[tempDisplayExpr, displayElts];
ENDLOOP;

convert elements from expr to displayexpr -- changed 3/4/87
construct return value now so can set "parent" component of subexpressions

effects:  Constructs and returns a new EXPR from expr.
2/87 - amounts to just stripping away the formatting info from the DisplayExpr, i.e. stripping relativeBox, absoluteBox, and parent pointers.

local declarations
recursively build a list of tagged arg exprs
local declarations
FOR l: LIST OF DisplayExpr _ m.elements, l.rest UNTIL l = NIL DO
elts _ CONS[[l.first.tag, ExprFromDisplayExpr[l.first]], elts];
ENDLOOP;

effects:  Returns a new, distinct copy of expr.
local declarations
recursively copy subexpressions
construct return value now so we can set parent pointers for subexprs
local declarations
recursively copy elements
FOR l: LIST OF DisplayExpr _ m.elements, l.rest UNTIL l = NIL DO
copiedElts _ CONS[Copy[l.first], copiedElts];
ENDLOOP;
recursively copy elements -- changed 3/4/87
construct return value now so we can set parent pointers for subexprs

Selectors
effects:  Returns tag associated with expr.
effects:  Returns class of expr.
effects:  Returns subexpressions for expr.
          Returns NIL if no subexpressions exist

Format and Paint
modifies: expr
effects:  expr is updated into a "paintable" form (dsa - perhaps in the sense that all subExprs have been given correct relative bounding boxes)
          Returns a bounding box for expr.
          SIGNALS unable[reason: ATOM] if Formatting can not be completed.

local declarations
recursively format all subexpressions (arguments & symbols)
format all argument subexpressions
format all symbol subexpressions
compute corrected boxes using sizing constraints
compose layout for boxes using alignment constraints
set format class for mybox
set relative boxes of display subexpressions
local declarations
recursively format all matrix elements
FOR l: LIST OF DisplayExpr _ m.elements, l.rest UNTIL l = NIL DO
tempBox _ Format[l.first, MathRules.ComputeSize[base: size, adjustment: script]];
elementBoxes _ CONS[MathBox.MakeBox[l.first.tag, NIL, tempBox.FormatClass[], tempBox.Type[], tempBox.Extents[], tempBox.Offset[], tempBox.SubscriptHint[], tempBox.SuperscriptHint[]], elementBoxes];
ENDLOOP;
recursively format all matrix elements
format openSym, closeSym, and space
compose layout for matrix by using alignment constraints
set format class for mybox
set relative boxes of matrix elements

requires: absBox is an absolute BOX
modifies: expr
effects:  Displays expr in context, bounded by absBox.
          Updates absolute bounding boxes (viewer coords).
          SIGNALS unable[reason: ATOM] if Painting cannot be completed.

local declarations

update absolute coordinates
paint all subexpressions

paint arguments
paint symbols
paint all matrix elements
paint open & close symbols
if selected, highlight region appropriately, using a one pixel border
set proper color depending on selection
highlight region
reset color to black
List Operations
effects: Returns the DisplayExpr in exprs associated with tag.
         SIGNALS exprNotFound if no association exists.
cdr down list looking for tag
not found, so signal error
Selection Operations
effects:  Returns the subexpression associated with coordinates [x, y] in expression expr.  
          SIGNALS noSelection if no association exists.

see if selection can be further narrowed
if above loop does not return, then can't narrow selection any more
see if selection can be further narrowed
if above loop does not return, then can't narrow selection any more
effects: Returns TRUE iff expr is selectable.


effects: Returns the parent (enclosing expression) of expr.
         SIGNALS noParent if no selectable parent exists.

complain if no expr or no parent
effects:  Returns a child expressions (subexpression) for expr.
          SIGNALS noSelection if no selectable child exists.

local declarations

keep looking for selectable child
if there are no selectable children, signal noSelection
** FOO FIX THIS **
Hack 7/10/87: Assuming expr is the last arg of a function, change its parent to be larger function class and select the new last arg.
effects:  Returns the "next" sibling expression from expr.
          SIGNALS noSelection if no selectable sibling exists.

local declarations
"cycle" thru parent's children and return "next" selectable sibling in list
find starting point to begin looking for next selectable sibling expr
look for next selectable sibling in exprs after expr in list (i.e. in afterExpr)
*** hack 7/16/87 to handle extra inserted parentheses
*** end hack

if no selectable sibling exists after expr, then wraparound list to before expr
if we haven't RETURNed yet, then there are no selectable siblings
** FOO FIX THIS **
effects:  Returns a copy of display expression expr with new substituted for old. 
caveats: Return value must be reformatted before Paint[]'ing.
          Note that new is used (not a copy).  Hence if expr = old, then new returned, i.e. a "copy" returned iff old is a proper subexpression of expr.
effects:  Returns a copy of display expression expr with new substituted for old for each pair in replacements [old, new].
If expr = old_i, then new_i i.e. a "copy" returned iff each old_i is a proper subexpression of expr.
Note that replacements can "interfere" with each other; outcome depends on their ordering.
caveats: Return value must be reformatted before Paint[]'ing.

Note that "old" components of replace pairs must be the actual pointers to the exprs we wish to replace, i.e. we only replace that actual expr, and not any other expr which is equivalent but physically distinct from it.   
Note that the "new" components of replace pairs are used (not copies).  Hence anyone who holds the pointer to a "new" component can e.g. later ask to have it replaced by something. 
Note that recursion terminates as soon as we find a match, i.e. if expr = one of the olds (i.e. expr is one of the things to be replaced), we won't examine any subexprs of expr for possible additional matches
Parenthesize replacement if its op has lower precedence than parent
IF parent #NIL AND MathDB.CompareOps[Class[new], Class[parent] ] = less THEN {
-- 7/10/87 -- turn off op precedence for functional notation parsing
Create skeleton for parenthesized expression (i.e. dummy arg)

Grab onto dummy arg
Stuff actual pointer to new into parenExpr
Update pointers
new.tag _ $a; new.parent _ parenExpr;
local declarations
recursively copy subexpressions
construct return value now so we can set parent pointers for subexprs
local declarations
recursively copy elements
FOR l: LIST OF DisplayExpr _ m.elements, l.rest UNTIL l = NIL DO
copiedElts _ CONS[ReplaceN[l.first, replacements], copiedElts];
ENDLOOP;
recursively copy elements - changed 3/4/87
construct return value now so we can set parent pointers for subexprs

Signals & Errors
Ê!ˆ��˜�Jšœ™Jšœ0™0Jšœ(™(J˜�šÏk	˜	J˜J˜	J˜J˜J˜J˜
Jšœ
˜
Jšœœ˜Jšœœœ˜.Jšœœ+˜7Jšœ˜—J˜�šÏnœœ˜"JšœU˜\Jšœ˜J˜�Jš˜J˜�—headšž+™+J™�Jšœœœ˜Jšœœœ˜Jšœœœ˜Jšœ
œ˜#Jšœœ˜+Jšœœ˜'Jšœœ˜Jšœ
œ˜#Jšœœ˜Jšœœ˜%Jšœœ˜'Jšœœ˜-Jšœ
œ˜)J˜�Jšœœ˜Jšœœ˜,Jšœ
œ˜0J˜�—šž™JšœG™GIcode˜�šœœœ˜šœ˜LšœœÏc%˜1LšœŸ!˜:Lšœ
œŸ!˜4Lšœ
œŸ!˜4LšœœœŸA˜WLšœœŸ˜9L˜—L˜�—Lšœœœ˜'šœœœ˜šœ˜Lšœ"œ˜(Lšœ-œœœ˜Hšœ˜LšœŸ<˜QLšœœŸ˜/Lšœ
œœœŸ˜8LšœŸ˜%LšœŸ˜'LšœŸ˜+Lšœ˜—Lš˜—L˜L˜�—Lšœ™Lšœœœ˜-Lšœœ˜-Lšœœœ˜5Lšœœ˜5Lšœœœ˜1Lšœœ˜1L˜�Lšœ
œœŸ˜G—šž™šžœœœœœœœœ˜–LšœA™ALšœœcœ<˜¬L˜L˜�—šžœœœœ"œœœœœ˜­LšœC™CLšœœcœJ˜ºL˜L˜�—šžœœœœ$œœœœ?œœ˜äLšœA™ALšœœcœ–˜†L˜L˜�——šž™šžœœœœœœ˜[Lšœ+™+L™�šœœ˜ L˜�šœœ˜'Lš
œœœœœ!œœ
˜kLš
œœœœœœœ
˜bLšœœœœœœœ
˜c—L˜�˜šœ
œœ˜#LšœŸ˜;LšœŸ˜5LšœŸ˜7—Lšœ	œœ˜Lšœ
œ˜Lšœœœ˜-L˜�Lšœ™šœœœ&œœ˜DL˜-L˜(Lšœœ¥˜ºLšœ˜
—L˜�LšœR™Ršœœ˜!L˜&LšœœN˜cL˜L˜�—Lšœ˜L˜—L˜�šœ˜šœ	œœ˜Lšœ˜L˜—Lšœœœ˜šœœœ˜Lšœ
œœœ˜/L˜—Lšœœœ˜šœœœ˜Lšœœœœ˜'L˜—L˜�L˜
Lšœœ˜LšœœœŸ˜$L˜�Lšœ0™0LšœBÏzœ™JLšœœ˜šœœœ˜Lšœ	œ˜Lšœ˜—šœœœ"œœ˜@L˜AL˜1Lšœ˜L˜�—šœ˜˜Lšœ˜šœœœ˜Lšœ&Ÿ˜7šœœœ˜L˜GLšœ"™"Lšœœ#Ÿ˜LLšœ˜—Lšœ"Ÿ˜1Lšœ%™%Lšœœ#Ÿ˜LLšœ˜—Lšœ"Ÿ˜=L˜—˜%LšœŸ%˜8šœ
œŸ
˜#šœœœ˜L˜GLšœ%™%Lšœœ#Ÿ˜LLšœ˜—L˜—šœŸ˜šœœœ˜L˜GLšœ%™%Lšœœ#Ÿ˜LLšœ˜—L˜—Lšœ!˜!L˜—Lšœ!˜(—Lšœ	˜L˜—Lšœœ˜L˜�—˜L˜—L˜�—š
žœœœœœ˜ELšœD™DL™FL™�Lšœ™L˜,L˜�LšœœŸ˜/Lšœ
œœ˜DLšœ
œœ˜DL˜�šœ˜L˜�šœ	˜	Lšœ!˜!L˜�Lšœ=™=Lšœm˜sL˜L˜�—šœ
˜
L˜�Lšœ)˜)L˜8LšœN™NL˜�LšœœœœŸ'˜TL˜�Lšœ$™$šœœœ(œœ˜FLšœvœ#˜žLšœ%Ÿ ˜ELšœœ#˜9Lšœ˜—L˜�Lšœ"™"šœœœ$œœ˜BLšœvœ#˜žLšœ%Ÿ ˜ELšœœ#˜9Lšœ˜—L˜�L™�LšœJ™JLšœ|˜|L˜�Lšœ%™%šœœœ'œœ˜ELšœ!Ÿ˜/Lšœ˜—L˜�Lšœ˜L˜—˜L˜�L˜%Lšœœœ9˜FL˜0Lšœ!œœœ˜;Lšœœ˜L˜&L˜�L˜+L˜�Lšœ)™)šœœœ(œœ™FLšœ:™:Lšœ"Ÿ ™BLšœœ™1Lšœ™L™�—Lšœ;™;šœœœ(œœ˜FLšœ:˜:Lšœ"Ÿ ˜BLšœœœ$œœ0œ˜Lšœ˜—L˜�L˜-L˜/˜)L˜�—LšœJ™JL˜‡L˜�šœœœ#œœ˜ALšœ Ÿ
˜-Lšœ˜—L˜�Lšœ˜L˜—Lšœœ˜—L™�L˜L˜�—š
žœœœœœ˜ELšœ6™6Lšœ™L™�šœœ˜ L˜�˜Lšœ1˜7L˜—L˜�˜Lšœ™Lšœœœœ˜,L˜�Lšœ,™,šœœœ"œœ˜@Lšœœ4˜?Lšœ˜—L˜�Lšœ0˜6L˜—L˜�˜Lšœ™Lšœœœœ˜9L˜�šœœœ"œœ™@Lšœœ4™?Lšœ™L™�—š
œœœ"œœœŸ˜RLšœV˜VLšœœœœœ"œ˜xLšœ˜—L˜�Lšœ@˜FL˜—L˜�Lšœœ˜—˜L˜�—L˜�L˜�—šžœœœœ˜=Lšœ/™/šœœ˜ L˜�šœ˜LšœX˜^L˜—L˜�L˜˜�Lšœ™LšœŸ˜'LšœœœœŸ˜IL˜�Lšœ™šœœœ"œœ˜@Lšœœ ˜5Lšœ˜	L˜�—LšœE™ELšœj˜jšœœœ&œœ˜DLšœŸ$˜@Lšœ˜—L˜�Lšœ˜L˜—L˜�˜L˜�Lšœ™LšœŸ˜&LšœœœœŸ(˜_L˜�Lšœ™šœœœ"œœ™@Lšœ
œ™-Lšœ™L˜�—Lšœ+™+šœœœ"œœ˜@Lšœœœœœ&œ˜ŠLšœ˜—L˜�LšœE™ELšœ¨˜¨šœœœ"œœ˜@LšœŸ$˜@Lšœ˜—L˜�Lšœ˜L˜L™�L˜�—Lšœœ˜—L˜——šž	™	š
žœœœœœ˜5Lšœ+™+Lšœ˜L˜L˜�—š
žœœœœœ˜7Lšœ ™ šœœ˜ Lšœœ˜*Lšœœ˜.Lšœœ˜,Lšœœ˜—L˜L˜�—šžœœœœœœ˜LLšœ*™*Lšœ0™0L™�šœœ˜ LšœœœŸ ˜CLšœœ
˜,Lšœœ
˜*Lšœœ˜—L˜——šž™š
žœœœ œœ˜CLšœ™Lšœ™Lšœ*™*LšœJ™JL™�Lšœ™Lšœœœœ˜Lšœœ˜L˜�šœœ˜ L˜�šœ˜Lšœ;œ…˜ÉL˜L˜�—L˜�šœ˜L˜�Lšœ;™;L˜�LšœœŸ&˜;L˜�Lšœ"™"šœœœ&œœ˜DLšœLœU˜¦Lšœœ¿˜ÒLšœ˜—L˜�Lšœ ™ šœœœ"œœ˜@LšœLœU˜¦Lšœœ¿˜ÒLšœ˜—L˜�Lšœ0™0L˜-L˜�Lšœ4™4L˜6Lšœ™L˜>L˜�Lšœ,™,šœœœ"œœ˜@Lšœ%œœ˜HLšœYœŸ
˜‚Lšœ˜—L˜�Lšœ˜L˜—L˜�˜Lšœ™Lš	œœœœœ˜1Lšœ,œ˜0L˜�Lšœ&™&šœœœ"œœ™@LšœQ™QLšœœœ‘™ÅLšœ™L˜�—Lšœ&™&šœœœ"œœ˜@LšœQ˜Qšœœ˜Lšœ!œœ„˜Ë—š˜Lšœ)œœ…˜Ô—Lšœ˜—L˜�Lšœ#™#L˜RL˜'L˜)L˜�Lšœ8™8L˜¢Lšœ™L˜>L˜�Lšœ%™%šœœœ"œœ˜@Lšœ%œœ˜HLšœYœŸ
˜‚Lšœ˜—L˜�Lšœ˜L˜L˜�—L˜�Lšœœ˜—L™�L˜L˜�—šžœœœ5œœœ˜oLšœ#™#Lšœ™Lšœ6™6Lšœ:™:LšœG™GL™�Lšœ™L˜ L™�Lšœ™Lšœœœ˜;L˜L˜�šœœ˜ L˜�˜L˜;L˜—L˜�˜L˜�Lšœ™L™�Lšœ™šœœœ&œœ˜DLšœPœ˜lLšœl˜lLšœ˜L˜�—Lšœ
™
šœœœ"œœ˜@LšœPœ˜lLšœl˜lLšœ˜—L˜—L˜�L˜˜�Lšœ™šœœœ"œœ˜@LšœV˜VLšœ˜L˜�—Lšœ™LšœZ˜ZLšœ\˜\L˜—L˜�Lšœœ˜L˜�—LšœE™Ešœœœ œœ˜>šœœ˜Lšœ'™'L˜ L˜�Lšœ™L˜ÀL˜�Lšœ™L˜L˜—Lšœ˜—L˜L˜�——šž™šžœœœœ	œœœ˜[Lšœ>™>Lšœ7™7L˜�Lšœ™šœœœœœ˜;Lšœœœ
˜*Lšœ˜—L˜�Lšœ™Lšœ˜L˜——šž™š
žœœœœœ˜ZLšœ\™\L™7L™�Lšœœœœ
˜%Lšœ)œœ
˜BL˜�šœœ˜ L˜�šœ˜Lš
œœœœœ
˜=L˜L˜�—˜Lšœ(™(šœœœ"œœ˜@šœ+˜1Lšœ6œ˜G—Lšœ˜—L˜�LšœC™CLš
œœœœœ˜?L˜—L˜�˜Lšœ(™(šœœœ"œœ˜@šœ+˜1Lšœ6œ˜G—Lšœ˜—L˜�LšœC™CLš
œœœœœ˜?L˜—L˜�Lšœœ˜—L˜�˜L˜�——š
ž
œœœœœ˜<Lšœ-™-L™�Lš
œœœœœ˜!šœœ˜ ˜Lšœœœœœœœ˜@L˜—Lšœœœ˜&Lšœœœ˜$Lšœœ˜—L˜L™�—šžœœœœ˜ILšœ;™;Lšœ9™9L™�Lšœ ™ Lšœ	œœœœœ˜?Lšœ˜L˜L˜�—šžœœœœ˜HLšœ?™?Lšœ<™<L™�Lšœ™Lšœœ˜L™�Lšœœœœ
˜%šœœ˜ LšœœŸ˜@˜šœœœ&œœ˜DLšŸ!™!Lšœ5˜5LšœœœŸ˜OLšœ˜—Lšœ7™7Lšœ
˜L˜—˜Lšœ™Lšœ
˜L˜—Lšœœ˜—L˜L˜�—šžœœœ˜OLšœ…™…LšœœŸ˜/Lšœ
œœ˜DLšœ
œœ˜DLšœ|œ˜žLšœ|œ˜žLšœ|œ˜žLšœ‹˜‹Lšœ‹˜‹Lšœ‹˜‹Lšœ
œœ
˜LšœP˜PLšœ˜šœœ˜'šœœ˜1šœH˜Hšœ˜šœ˜Lšœ5˜5Lšœ˜Lšœœ	˜Lšœ˜—šœ˜Lšœ6˜6Lšœ˜Lšœœ˜-Lšœ˜—šœ˜Lšœ7˜7Lšœ˜Lšœœ˜-Lšœ˜—šœ˜Lšœ:˜:Lšœ˜Lšœœ˜-Lšœ˜—LšœœŸ"˜4—šœœœœ˜5Lšœœœ˜$Lšœœœœ˜'Lšœ˜L˜—Lšœ˜—Lšœœ
˜—Lšœœ
˜—Lšœ
˜Lšœ˜L˜�—šžœœœœ˜JLšœ:™:Lšœ>™>L™�Lšœ™LšœœœœŸ.˜RLšœœ˜L˜�Lšœ	œœœœœ
˜>L˜�LšœK™Kšœœ˜'Lšœœ
˜'˜Lšœ) œ™Ešœœœ&œœ˜DLšœœœ˜;Lšœ˜—Lšœ* œ!™Pšœœœœœ˜<Lšœ7˜7LšœœœŸ˜RLšœ˜—šœ˜LšœGœ%Ÿ˜yLšœ˜L˜�—Lšœ5™5Lšœœœ"˜DL™L™�LšœD œ™Ošœœœ&œœ˜DLšœœœŸ"˜ILšœ7˜7LšœœœŸ˜RLšœ˜—LšœA™ALšœ
˜L˜—˜Lšœ™Lšœ
˜L˜—Lšœœ˜—L˜L˜�—šžœœœœ˜JLšœR™RL™=Lšœ˜™˜Lšœœ˜3L˜L˜�—šžœœœ"œœœ˜dLšœz™zLšœd™dL™ZL™=L™�LšœÞ™ÞLšœµ™µL™Ðšœœœ$œœ˜Bšœœ˜Lšœ)˜)Lšœ˜L˜�L™CLšœ	œœ4œ™NL™Dšœœœ˜Lšœ
œ˜Lšœ˜—˜�Lšœ=™=LšœOœ9˜ŒL™�Lšœ™šœœœ.œœ˜LLšœœœ˜FLšœ˜—L˜�Lšœ*™*Lšœ4˜4L˜�Lšœ™Lšœ%™%Lšœ"Ÿ3˜ULšœŸ(˜CLšœŸ˜L˜—šœ˜LšœŸ3˜OLšœŸ(˜=Lšœ˜L˜—L˜—Lšœ˜—L˜�šœœ˜ L˜�šœ˜Lšœ
˜L˜—L˜�L˜˜�Lšœ™LšœŸ˜'LšœœœœŸ˜IL˜�Lšœ™šœœœ"œœ˜@Lšœœ2˜GLšœ˜	L˜�—LšœE™ELšœj˜jšœœœ&œœ˜DLšœŸ$˜@Lšœ˜—L˜�Lšœ˜L˜—L˜�˜L˜�Lšœ™LšœŸ˜&LšœœœœŸ(˜_L˜�Lšœ™šœœœ"œœ™@Lšœ
œ.™?Lšœ™L˜�—Lšœ*™*šœœœ"œœ˜@Lšœœœœ#œ&œ#˜®Lšœ˜—L˜�LšœE™ELšœ¨˜¨šœœœ"œœ˜@LšœŸ$˜@Lšœ˜—L˜�Lšœ˜L˜L™�L˜�—Lšœœ˜—L˜�L˜——šž™Lš	œœœ	œœ˜*Lšœ
œœœ˜!Lšœœœœ˜"L˜�—J˜�Jšœ˜—�…—����fF��©f��