DIRECTORY AMBridge, AMTypes, Atom, RTTypesBasic, RTMiniModel, BBApply, Rope, ViewerClasses, ViewerOps, ViewerTools, ViewRec, ViewRecInsides, VFonts, Buttons, Containers, Labels, Rules, Process, UserTerminal, MessageWindow, IO, Icons, Real, ShowTime, Menus, TiogaOps; ViewRecOther: CEDAR MONITOR IMPORTS AMBridge, AMTypes, Atom, RTTypesBasic, BBApply, VO:ViewerOps, VT:ViewerTools, TiogaOps, Buttons, Labels, Rope, RTMiniModel, Process, UserTerminal, MessageWindow, IO, Real, ShowTime, ViewRec, ViewRecInsides EXPORTS ViewRec, ViewRecInsides SHARES Atom = BEGIN OPEN ViewRecInsides; NotARecord: PUBLIC ERROR = CODE; NoSelectedProc: PUBLIC ERROR = CODE; BadID: PUBLIC ERROR [id: ViewRec.Id] = CODE; NotFound: PUBLIC ERROR [name: ViewRec.Path] = CODE; Event: TYPE = {Call, Return, Abort, Edit}; Pending: TYPE = RECORD [f: FinishProc _ NIL, data: REF ANY _ NIL]; FinishProc: TYPE = ViewRec.FinishProc; behavior: PUBLIC ViewRec.BehaviorOptions _ []; delayed: PUBLIC REAL _ 0; roots: PUBLIC DataList _ NIL; z: PUBLIC REAL _ 0; transitions: ARRAY GregState OF ARRAY Event OF GregState; nvDocFmt, recDocFmt, nvcDocFmt: ROPE; procDoc, selDoc, butDoc: ROPE _ NIL; doitDocFmt: ARRAY BOOLEAN OF ROPE _ ALL[NIL]; abortDocFmt: ROPE _ NIL; toFinish: Pending; activeCount, extantCount, eltCount: CARDINAL _ 0; experimental: BOOLEAN _ FALSE; clearMessagePlace: PUBLIC ROPE _ "flush here"; mwTotal: ROPE _ ""; OKProc: PUBLIC PROC [pt: Type, argSpecs, retSpecs: BindingList, doAllRecords: BOOLEAN] RETURNS [ok, hasDom, hasRange: BOOLEAN] = BEGIN dom: Type _ AMTypes.Domain[pt]; range: Type _ AMTypes.Range[pt]; domArgs, rangeArgs: CARDINAL; SELECT AMTypes.TypeClass[dom] FROM structure, record => [ok, domArgs] _ SimpleEnough[dom, argSpecs, doAllRecords]; nil => {ok _ TRUE; domArgs _ 0}; ENDCASE => ok _ FALSE; IF NOT ok THEN RETURN [FALSE, FALSE, FALSE]; SELECT AMTypes.TypeClass[range] FROM structure, record => [ok, rangeArgs] _ SimpleEnough[range, retSpecs, doAllRecords]; nil => {ok _ TRUE; rangeArgs _ 0}; ENDCASE => ok _ FALSE; IF NOT ok THEN RETURN [FALSE, FALSE, FALSE]; RETURN [ok, domArgs > 0, rangeArgs > 0]; END; SimpleEnough: PUBLIC PROC [rt: Type, specs: BindingList, doAllRecords: BOOLEAN] RETURNS [ok: BOOLEAN, count: CARDINAL] = BEGIN count _ 0; FOR i: INTEGER IN [1..AMTypes.NComponents[rt]] DO tt: Type _ AMTypes.IndexToType[rt, i]; t: Type _ AMTypes.GroundStar[tt]; val: TypedVariable; sublist: BindingList; ok, visible: BOOLEAN; recers: RList; [sublist, ,val, ok, visible, , , recers] _ SelectBindings[specs, AMTypes.IndexToName[rt, i], i]; count _ count + 1; IF ok AND NOT visible THEN count _ count - 1 ELSE BEGIN exception: BOOLEAN _ FALSE; IF Recognize[t: t, specials: recers, onlyRecognize: TRUE].recognized THEN ok _ TRUE ELSE SELECT AMTypes.TypeClass[t] FROM record, structure => BEGIN presentable: CARDINAL; [ok, presentable] _ SimpleEnough[t, sublist, doAllRecords]; exception _ exception OR presentable < 1; END; ENDCASE => ok _ FALSE; IF doAllRecords THEN {IF exception OR NOT ok THEN count _ count - 1} ELSE IF NOT ok THEN RETURN [FALSE, 0] ELSE IF exception THEN count _ count - 1; END; ENDLOOP; ok _ TRUE; END; Recognize: PUBLIC PROC [t: Type, specials: RList, onlyRecognize: BOOLEAN] RETURNS [recognized: BOOLEAN, handler, handlerData: REF ANY] = BEGIN TryRecognizers: PROC [rl: RList] RETURNS [found: BOOLEAN] = BEGIN WHILE rl # NIL DO [found, handler, handlerData] _ rl.first[t, onlyRecognize]; IF found THEN {recognized _ TRUE; RETURN}; rl _ rl.rest; ENDLOOP; found _ FALSE; END; gt: Type; tc: AMTypes.Class; IF TryRecognizers[specials] THEN RETURN; IF TryRecognizers[befores[EquivalenceClass]] THEN RETURN; IF TryRecognizers[NARROW[Atom.TypeGetProp[type: t, prop: ecHandlerProp]]] THEN RETURN; IF TryRecognizers[befores[StripSubranges]] THEN RETURN; gt _ AMTypes.GroundStar[t]; IF TryRecognizers[NARROW[Atom.TypeGetProp[type: gt, prop: gtHandlerProp]]] THEN RETURN; IF TryRecognizers[befores[TypeClass]] THEN RETURN; tc _ AMTypes.TypeClass[gt]; IF TryRecognizers[classRecers[tc]] THEN RETURN; IF TryRecognizers[afterAlls] THEN RETURN; recognized _ FALSE; END; SelectBindings: PUBLIC PROC [bl: BindingList, name: ROPE, pos: INT] RETURNS [sublist, altSublist: BindingList, val: TypedVariable, found, visible, editable: BOOLEAN, notifies: NotifyList, recers: RList] = BEGIN sublist _ altSublist _ NIL; found _ FALSE; visible _ editable _ TRUE; notifies _ NIL; recers _ NIL; FOR bl _ bl, bl.rest WHILE bl # NIL DO WITH bl.first.name SELECT FROM r: ROPE => IF NOT r.Equal[name] THEN LOOP; i: Int => IF i^ # pos THEN LOOP; rt: REF TEXT => IF NOT Rope.FromRefText[rt].Equal[name] THEN LOOP; ENDCASE => ERROR BadID[bl.first.name]; WITH bl.first SELECT FROM v: Binding[Value] => {val _ v.val; visible _ v.visible; editable _ v.editable; found _ TRUE}; e: Binding[Editable] => editable _ e.editable; n: Binding[Notify] => notifies _ CONS[[n.notify, n.clientData], notifies]; r: Binding[TryRecognizer] => recers _ CONS[r.recognizer, recers]; g: Binding[Group] => {sublist _ BindingListAppend[g.sublist, sublist]; altSublist _ BindingListAppend[g.altSublist, altSublist]}; ENDCASE => ERROR; ENDLOOP; saver _ recers; --make sure GC don't take it END; saver: RList _ NIL; --to combat UNSAFEty of long REF-containing arg/return record BindingListAppend: PUBLIC PROC [a, b: BindingList] RETURNS [c: BindingList] = BEGIN IF a = NIL THEN RETURN [b]; c _ a; WHILE a.rest # NIL DO a _ a.rest ENDLOOP; a.rest _ b; END; Sample: PROCEDURE = BEGIN oldPriority: ViewRec.DelayPriority _ behavior.delayParms.priority; TRUSTED {Process.SetPriority[DPToP[oldPriority]]}; WHILE TRUE DO parm: REAL; asCard: CARDINAL; start: ShowTime.Microseconds _ ShowTime.GetMark[]; IF behavior.delayParms.priority # oldPriority THEN TRUSTED {Process.SetPriority[DPToP[oldPriority _ behavior.delayParms.priority]]}; activeCount _ extantCount _ eltCount _ 0; FOR r: DataList _ roots, r.rest WHILE r # NIL DO SampleData[r.first]; ENDLOOP; BEGIN OPEN behavior.delayParms; parm _ MIN[max, MAX[min, offset + dActive*activeCount + dExtant*extantCount + dElt*eltCount + dMicroseconds*ShowTime.SinceMark[start] ]]; END; IF (z > 0) AND (z < 1) THEN delayed _ (parm*(1-z) + delayed*z) ELSE delayed _ parm; asCard _ Real.RoundC[ABS[parm]]; IF behavior.delayParms.interp = Milliseconds THEN Process.Pause[Process.MsecToTicks[asCard]] ELSE FOR i: CARDINAL _ 0, i+1 WHILE i < asCard DO TRUSTED {UserTerminal.WaitForScanLine[0]}; ENDLOOP; ENDLOOP; END; DPToP: PROC [dp: ViewRec.DelayPriority] RETURNS [Process.Priority] = INLINE {RETURN [SELECT dp FROM Normal => Process.priorityNormal, Background => Process.priorityBackground, Foreground => Process.priorityForeground, ENDCASE => ERROR]}; RedisplayElt: PUBLIC PROC [eh: REF ANY] = BEGIN ed: EltData _ NARROW[eh]; IF ed.update # NIL THEN ed.update[ed, TRUE]; END; SampleData: PROC [d: Data] = BEGIN IF d.destroyed OR d.v.iconic THEN {extantCount _ extantCount + 1; RETURN}; activeCount _ activeCount + 1; FOR ed: EltData _ d.last, ed.prev WHILE ed # NIL DO IF ed.update # NIL THEN {eltCount _ eltCount + 1; ed.update[ed, FALSE]}; ENDLOOP; END; SampleRV: PUBLIC PROC [rv: RecordViewer] = {SampleData[RVToData[rv]]}; GetEltHandle: PUBLIC PROC [rv: RecordViewer, name: ViewRec.Path] RETURNS [eh: REF ANY] = BEGIN d: Data _ RVToData[rv]; e: Data _ NIL; IF name = NIL THEN ERROR NotFound[name]; DO ed: EltData _ Find[d, name.first]; IF ed = NIL AND e # NIL THEN ed _ Find[e, name.first]; IF ed = NIL THEN ERROR NotFound[name]; name _ name.rest; IF name = NIL THEN RETURN [ed]; WITH ed SELECT FROM pd: ProcData => {d _ pd.argRV; e _ pd.retRV}; rd: RecordData => {d _ rd.d; e _ NIL}; ENDCASE => ERROR NotFound[name]; ENDLOOP; END; Find: PROC [d: Data, name: REF ANY] RETURNS [ed: EltData] = BEGIN idx: INT _ 1; WITH name SELECT FROM r: ROPE => FOR ed _ d.first, ed.next WHILE ed # NIL DO IF r.Equal[ed.name] THEN RETURN [ed]; ENDLOOP; rt: REF TEXT => BEGIN r: ROPE _ Rope.FromRefText[rt]; FOR ed _ d.first, ed.next WHILE ed # NIL DO IF r.Equal[ed.name] THEN RETURN [ed]; ENDLOOP; END; ri: REF INT => FOR ed _ d.first, ed.next WHILE ed # NIL DO IF idx = ri^ THEN RETURN [ed]; idx _ idx + 1; ENDLOOP; ENDCASE => ERROR BadID[name]; RETURN [NIL]; END; Open: PROC [ed: EltData] = BEGIN ed.opened _ TRUE; ShowState[ed]; END; DeOpen: PROC [ed: EltData] = BEGIN ed.opened _ FALSE; ShowState[ed]; END; Poke: PROC [ed: EltData, how: Event] = BEGIN WITH ed SELECT FROM pd: ProcData => BEGIN oldState: GregState _ pd.gregState; pd.gregState _ transitions[pd.gregState][how]; IF pd.gregState # oldState AND pd.stateLabel # NIL THEN Labels.Set[pd.stateLabel, StateToRope[pd.gregState]]; END; ENDCASE => BEGIN IF ed.parent.edParent # NIL THEN Poke[ed.parent.edParent, how]; END; END; StateToRope: PROC [s: GregState] RETURNS [ROPE] = {RETURN [SELECT s FROM Other => "", Dispatched => "working", DispatchedAndEdited => "working on old", Returned => "done", Aborted => "aborted", ENDCASE => ERROR]}; FinishPendingBusiness: PUBLIC PROC RETURNS [okToProceed: BOOLEAN] = BEGIN IF toFinish.f # NIL THEN okToProceed _ toFinish.f[toFinish.data] ELSE okToProceed _ TRUE; END; SetPendingBusiness: PUBLIC PROC [proc: FinishProc _ NIL, data: REF ANY _ NIL] = {toFinish _ [proc, data]}; ShowState: PUBLIC PROC [ed: EltData, paint: BOOLEAN _ TRUE] = BEGIN style: ATOM; IF ed.b = NIL THEN {Scream["ViewRec: This can't happen #2"]; RETURN}; SELECT ed.et FROM Proc => BEGIN pd: ProcData _ NARROW[ed]; style _ IF pd.running THEN nameStyles.running ELSE IF pd.parent.highlightSelectedProc AND pd.parent.curProc = pd THEN nameStyles.beingShown ELSE nameStyles.quiescent; END; ENDCASE => style _ IF NOT ed.variable THEN nameStyles.invariant ELSE IF ed.opened THEN nameStyles.opened ELSE nameStyles.quiescent; Buttons.SetDisplayStyle[ed.b, style, paint]; END; SendMsg: PROC [rv: Data, to: ROPE] = BEGIN old: ROPE; FOR rv _ rv, rv.rvParent WHILE rv # NIL DO IF rv.feedBack # NIL THEN EXIT; ENDLOOP; IF (IF rv = NIL THEN TRUE ELSE rv.feedBack = NIL OR rv.destroyed) THEN BEGIN IF to=clearMessagePlace THEN to _ "" ELSE BEGIN IF mwTotal.Length[] > 0 THEN to _ mwTotal.Cat["; ", to]; END; MessageWindow.Append[message: mwTotal _ to, clearFirst: TRUE]; RETURN; END; IF to = clearMessagePlace THEN {VT.SetContents[rv.feedBack, ""]; RETURN}; old _ VT.GetContents[rv.feedBack]; IF old.Length[] > 0 THEN to _ old.Cat["; ", to]; VT.SetContents[rv.feedBack, to]; END; SetMsg: PROC [ed: EltData, to: ROPE] = BEGIN SendMsg[IF ed = NIL THEN NIL ELSE ed.parent, to]; END; DisplayMessage: PUBLIC PROC [rv: RecordViewer, msg: ROPE] = BEGIN d: Data _ RVToData[rv]; SendMsg[d, msg]; END; Scream: PROC [msg: ROPE] = BEGIN MessageWindow.Append[msg, TRUE]; MessageWindow.Blink[]; END; Runnable: ENTRY PROC [ed: EltData] RETURNS [BOOLEAN] = BEGIN pd: ProcData _ NARROW[ed]; IF pd.parent.running THEN RETURN [FALSE]; pd.parent.runningProc _ pd; RETURN [pd.parent.running _ pd.running _ TRUE]; END; UnRun: ENTRY PROC [ed: EltData] = BEGIN pd: ProcData _ NARROW[ed]; pd.parent.runningProc.runningProcess _ NIL; pd.parent.runningProc _ NIL; pd.parent.running _ pd.running _ FALSE; pd.userAbort _ 0; END; ProcessAbort: PUBLIC ENTRY PROC [rv: RecordViewer] RETURNS [found: BOOLEAN] = BEGIN data: Data; IF rv = NIL THEN RETURN [FALSE]; data _ RVToData[rv]; IF data.runningProc = NIL THEN RETURN [FALSE]; TRUSTED {Process.Abort[data.runningProc.runningProcess]}; RETURN [TRUE]; END; TestAndResetUserAbort: PUBLIC ENTRY PROC [rv: RecordViewer, threshold: CARDINAL] RETURNS [abort: CARDINAL --will be 0 or >= threshold--] = BEGIN data: Data; IF rv = NIL THEN RETURN [0]; data _ RVToData[rv]; IF data.runningProc = NIL THEN RETURN [0]; IF data.runningProc.userAbort >= threshold THEN BEGIN abort _ data.runningProc.userAbort; data.runningProc.userAbort _ 0; END ELSE abort _ 0; END; TestUserAbort: PUBLIC ENTRY PROC [rv: RecordViewer] RETURNS [abort: CARDINAL] = BEGIN data: Data; IF rv = NIL THEN RETURN [0]; data _ RVToData[rv]; IF data.runningProc = NIL THEN RETURN [0]; abort _ data.runningProc.userAbort; END; SetUserAbort: PUBLIC ENTRY PROC [rv: RecordViewer, newLevel: CARDINAL _ 100] = BEGIN data: Data; IF rv = NIL THEN RETURN; data _ RVToData[rv]; IF data.runningProc = NIL THEN RETURN; data.runningProc.userAbort _ newLevel; END; IncrementUserAbortBy: PROC [pd: ProcData, deltaLevel: INTEGER] = BEGIN old: CARDINAL _ pd.userAbort; pd.userAbort _ INT[MAX[MIN[INT[deltaLevel] + pd.userAbort, LAST[CARDINAL]], 0]]; SetMsg[pd, IF old = pd.userAbort THEN "UserAbort pegged" ELSE IF deltaLevel > 0 THEN IO.PutFR["UserAbort incremented to %g", IO.card[pd.userAbort]] ELSE IF pd.userAbort > 0 THEN IO.PutFR["UserAbort decremented to %g", IO.card[pd.userAbort]] ELSE "UserAbort cancelled"]; END; IncrementUserAbort: PUBLIC PROC [rv: RecordViewer, deltaLevel: INTEGER] = BEGIN data: Data; IF rv = NIL THEN RETURN; data _ RVToData[rv]; IF data.runningProc = NIL THEN RETURN; data.runningProc.userAbort _ INT[MAX[MIN[INT[deltaLevel] + data.runningProc.userAbort, LAST[CARDINAL]], 0]]; END; CallClient: PROC [pd: ProcData] = BEGIN Use: PROC [ret: TypedVariable] = {IF pd.hasRet THEN AMTypes.Assign[pd.retInst, ret]}; event: Event _ Return; IF pd = NIL THEN ERROR; IF pd.parent = NIL THEN ERROR; TRUSTED {Process.SetPriority[Process.priorityNormal]}; Use[BBApply.ApplyProcToRecord[proc: pd.proc, args: pd.domainInst ! ABORTED => BEGIN SetMsg[pd, "Aborted"]; event _ Abort; CONTINUE; END; UNWIND => BEGIN SetMsg[pd, "Unwound"]; UnRun[pd]; ShowState[pd]; END]]; UnRun[pd]; Poke[pd, event]; ShowState[pd]; END; ProcButtonProc: PUBLIC Menus.ClickProc = BEGIN pd: ProcData _ NARROW[clientData]; old: ProcData _ pd.parent.curProc; new: ProcData _ pd; SetMsg[pd, clearMessagePlace]; IF NOT FinishPendingBusiness[] THEN RETURN; IF control THEN BEGIN SetMsg[pd, IF pd.hasDom OR pd.hasRet THEN procDoc ELSE IF pd.parent.holdOff THEN selDoc ELSE butDoc]; RETURN; END; IF old # new THEN BEGIN IF (IF old # NIL THEN old.argret # NIL ELSE FALSE) THEN BEGIN VO.MoveViewer[viewer: old.argret, x: nowhere, y: 0, w: old.argret.ww, h: old.argret.wh, paint: new.argret = NIL]; old.argsShown _ FALSE; END; IF new.argret # NIL THEN BEGIN VO.MoveViewer[viewer: new.argret, x: 0, y: 0, w: new.argret.ww, h: new.argret.wh]; new.argsShown _ TRUE; END; pd.parent.curProc _ new; IF old # NIL THEN ShowState[old]; ShowState[new]; END; IF pd.parent.holdOff THEN NULL ELSE IF NOT (pd.hasDom OR pd.hasRet) THEN TryToCall[pd]; END; TryToCall: PROC [pd: ProcData] = TRUSTED BEGIN IF AMBridge.TVToProc[pd.proc] = NIL THEN SetMsg[pd, "Procedure Unbound!"] ELSE IF Runnable[pd] THEN BEGIN Poke[pd, Call]; ShowState[pd]; Process.Detach[pd.runningProcess _ FORK CallClient[pd]]; END ELSE SetMsg[pd, "Busy"]; END; InnerProcButtonProc: PUBLIC Menus.ClickProc = BEGIN pd: ProcData _ NARROW[clientData]; SetMsg[pd, clearMessagePlace]; IF pd = NIL THEN {SetMsg[pd, "InnerProcButtonProc invoked on NIL ProcData!"]; RETURN}; IF NOT FinishPendingBusiness[] THEN RETURN; IF control THEN BEGIN IF NOT shift THEN SetMsg[pd, IO.PutFR[doitDocFmt[pd.hasDom], IO.rope[pd.name]]] ELSE SELECT mouseButton FROM red => {IncrementUserAbortBy[pd, 100]; IF pd.userAbort >= 300 THEN [] _ ProcessAbort[pd.parent.asRV]}; blue => IncrementUserAbortBy[pd, -100]; yellow => SetMsg[pd, IO.PutFR[abortDocFmt, IO.card[pd.userAbort]]]; ENDCASE => ERROR; END ELSE TryToCall[pd]; END; ProcDoit: PUBLIC DoitProc = BEGIN ed: EltData _ RVToData[rv].edParent; WHILE NOT ISTYPE[ed, ProcData] DO ed _ ed.parent.edParent ENDLOOP; TryToCall[NARROW[ed]]; END; ProcUpdate: PUBLIC UpdateProc = BEGIN pd: ProcData _ NARROW[ed]; IF pd.argsShown THEN BEGIN IF pd.hasDom THEN SampleData[pd.argRV]; IF pd.hasRet THEN SampleData[pd.retRV]; END; END; CallSelectedProc: PUBLIC PROC [in: RecordViewer] RETURNS [refused: BOOLEAN] = TRUSTED BEGIN d: Data; IF in = NIL THEN RETURN [TRUE]; d _ RVToData[in]; IF (refused _ NOT FinishPendingBusiness[]) THEN RETURN; IF d.curProc = NIL THEN ERROR NoSelectedProc[]; IF AMBridge.TVToProc[d.curProc.proc] = NIL THEN RETURN [TRUE]; IF (refused _ NOT Runnable[d.curProc]) THEN RETURN; Poke[d.curProc, Call]; ShowState[d.curProc]; Process.Detach[d.curProc.runningProcess _ FORK CallClient[d.curProc]]; END; NotherElt: PROC [ed: EltData, forward, mustBeMutable: BOOLEAN] RETURNS [new: EltData] = BEGIN Next: PROC [ed: EltData] RETURNS [fd: EltData] = BEGIN WHILE TRUE DO IF ed = NIL THEN RETURN [NIL]; fd _ IF forward THEN ed.next ELSE ed.prev; IF fd = NIL THEN ed _ ed.parent.edParent ELSE RETURN; ENDLOOP; END; starting: BOOLEAN _ TRUE; WHILE TRUE DO IF ed = NIL THEN RETURN [NIL]; WITH ed SELECT FROM sd: SimpleData => IF starting THEN {starting _ FALSE; ed _ Next[ed]} ELSE IF ed.variable OR NOT mustBeMutable THEN RETURN [ed] ELSE ed _ Next[ed]; rd: RecordData => ed _ IF forward THEN rd.d.first ELSE rd.d.last; cd: ComplexData => ed _ Next[ed]; pd: ProcData => ed _ Next[ed]; ENDCASE => ERROR; ENDLOOP; END; TiogaDoit: TiogaOps.CommandProc = BEGIN eda: REF ANY _ VO.FetchProp[viewer: viewer, prop: $EltData]; ed: EltData; IF (IF eda = NIL THEN TRUE ELSE NOT ISTYPE[eda, EltData]) THEN RETURN [recordAtom: FALSE, quit: FALSE]; recordAtom _ FALSE; quit _ TRUE; ed _ NARROW[eda]; SetMsg[ed, clearMessagePlace]; IF NOT FinishPendingBusiness[] THEN RETURN; IF ed.parent.toDo # NIL THEN TRUSTED {Process.Detach[FORK CallToDo[ed]]}; END; CallToDo: PROC [ed: EltData] = BEGIN TRUSTED {Process.SetPriority[Process.priorityNormal]}; ed.parent.toDo[ed.parent.asRV, ed.parent.toDoData !ABORTED => BEGIN SetMsg[ed, "Aborted"]; CONTINUE END]; END; TiogaClose: TiogaOps.CommandProc = BEGIN eda: REF ANY _ VO.FetchProp[viewer: viewer, prop: $EltData]; ed: EltData; IF (IF eda = NIL THEN TRUE ELSE NOT ISTYPE[eda, EltData]) THEN RETURN [recordAtom: FALSE, quit: FALSE]; recordAtom _ FALSE; quit _ TRUE; ed _ NARROW[eda]; SetMsg[ed, clearMessagePlace]; [] _ FinishPendingBusiness[]; END; TiogaNext: TiogaOps.CommandProc = BEGIN eda: REF ANY _ VO.FetchProp[viewer: viewer, prop: $EltData]; ed, ned: EltData; IF (IF eda = NIL THEN TRUE ELSE NOT ISTYPE[eda, EltData]) THEN RETURN [recordAtom: FALSE, quit: FALSE]; recordAtom _ FALSE; quit _ TRUE; ed _ NARROW[eda]; SetMsg[ed, clearMessagePlace]; IF NOT FinishPendingBusiness[] THEN RETURN; ned _ NotherElt[ed, TRUE, TRUE]; IF ned = NIL THEN SetMsg[ed, "Ran off end!"] ELSE BEGIN Open[ned]; VT.EnableUserEdits[ned.t]; VT.SetSelection[ned.t]; toFinish _ [FinishNV, ned]; END; END; TiogaPrev: TiogaOps.CommandProc = BEGIN eda: REF ANY _ VO.FetchProp[viewer: viewer, prop: $EltData]; ed, ned: EltData; IF (IF eda = NIL THEN TRUE ELSE NOT ISTYPE[eda, EltData]) THEN RETURN [recordAtom: FALSE, quit: FALSE]; recordAtom _ FALSE; quit _ TRUE; ed _ NARROW[eda]; SetMsg[ed, clearMessagePlace]; IF NOT FinishPendingBusiness[] THEN RETURN; ned _ NotherElt[ed, FALSE, TRUE]; IF ned = NIL THEN SetMsg[ed, "Ran off end!"] ELSE BEGIN Open[ned]; VT.EnableUserEdits[ned.t]; VT.SetSelection[ned.t]; toFinish _ [FinishNV, ned]; END; END; TiogaGiveUp: TiogaOps.CommandProc = BEGIN eda: REF ANY _ VO.FetchProp[viewer: viewer, prop: $EltData]; ed: EltData; IF (IF eda = NIL THEN TRUE ELSE NOT ISTYPE[eda, EltData]) THEN RETURN [recordAtom: FALSE, quit: FALSE]; recordAtom _ FALSE; quit _ TRUE; ed _ NARROW[eda]; SetMsg[ed, clearMessagePlace]; IF NOT ed.opened THEN ERROR; SetMsg[ed, "OK, I give up!"]; VT.InhibitUserEdits[ed.t]; DeOpen[ed]; VT.SetContents[ed.t, ed.ToRope[ed]]; toFinish _ [NIL, NIL]; END; NVButtonProc: PUBLIC Menus.ClickProc = BEGIN ed: EltData _ NARROW[clientData]; SetMsg[ed, clearMessagePlace]; IF NOT FinishPendingBusiness[] THEN RETURN; IF control THEN SetMsg[ed, IF shift THEN ed.typeDoc ELSE IF NOT ed.variable THEN IO.PutFR[nvcDocFmt, IO.rope[ed.typeDoc]] ELSE WITH ed SELECT FROM sd: SimpleData => IO.PutFR[nvDocFmt, IO.rope[sd.handler.blueDoc], IO.rope[sd.typeDoc]], rd: RecordData => IO.PutFR[recDocFmt, IO.rope[rd.typeDoc]], ENDCASE => ERROR] ELSE IF ed.variable THEN SELECT mouseButton FROM red => BEGIN IF shift OR ed.t = NIL THEN SetMsg[ed, "Don't do that"] ELSE BEGIN Open[ed]; VT.EnableUserEdits[ed.t]; VT.SetSelection[ed.t]; toFinish _ [FinishNV, ed]; END; END; yellow => BEGIN IF shift OR ed.t = NIL THEN SetMsg[ed, "Don't do that"] ELSE [] _ Try[ed, VT.GetSelectionContents[], FALSE]; END; blue => WITH ed SELECT FROM sd: SimpleData => BEGIN new: TypedVariable; msg: ROPE; IF sd.handler.Butt = NIL THEN SetMsg[ed, "Don't do that"] ELSE BEGIN [new, msg] _ sd.handler.Butt[sd.var, sd.targType, sd.handler, sd.handlerData, shift]; IF msg # NIL THEN SetMsg[ed, msg]; IF msg = NIL THEN BEGIN AMTypes.Assign[sd.var, new]; Poke[ed, Edit]; FOR nl: NotifyList _ ed.notifyRequests, nl.rest WHILE nl # NIL DO nl.first.proc[nl.first.clientData]; ENDLOOP; END; END; END; ENDCASE => SetMsg[ed, "Don't do that"]; ENDCASE => ERROR ELSE SetMsg[ed, "You can't change that!"]; END; FinishNV: FinishProc = BEGIN ed: EltData _ NARROW[data]; [] _ Try[ed, VT.GetContents[ed.t], TRUE]; okToProceed _ TRUE; VT.InhibitUserEdits[ed.t]; DeOpen[ed]; toFinish _ [NIL, NIL]; END; Try: PROC [ed: EltData, asRope: ROPE, mightNeedRefresh: BOOLEAN] RETURNS [success: BOOLEAN] = BEGIN Quick: ENTRY PROC RETURNS [success: BOOLEAN] = BEGIN IF (success _ ed.AssignRope[ed, asRope]) THEN BEGIN AMTypes.Assign[ed.old, ed.var]; IF ed.t # NIL THEN VT.SetContents[ed.t, ed.ToRope[ed]]; END ELSE BEGIN IF mightNeedRefresh AND ed.t # NIL THEN VT.SetContents[ed.t, ed.ToRope[ed]]; END; END; IF (success _ Quick[]) THEN BEGIN Poke[ed, Edit]; FOR nl: NotifyList _ ed.notifyRequests, nl.rest WHILE nl # NIL DO nl.first.proc[nl.first.clientData]; ENDLOOP; END ELSE BEGIN SetMsg[ed, Rope.Cat["That should have been a ", ed.typeDoc]]; END; END; SetRope: PUBLIC PROC [ed: EltData, to: ROPE, paint: BOOLEAN _ TRUE] = {IF NOT ed.destroyed THEN VT.SetContents[viewer: ed.t, contents: to, paint: paint]}; UpdateNV: PUBLIC ENTRY UpdateProc = BEGIN IF (IF AMTypes.TVEqual[ed.old, ed.var] THEN always ELSE TRUE) THEN BEGIN AMTypes.Assign[ed.old, ed.var]; IF ed.t # NIL THEN SetRope[ed, ed.ToRope[ed]]; END; END; UpdateComplex: PUBLIC UpdateProc = BEGIN News: ENTRY PROC RETURNS [news: BOOLEAN] = {IF (news _ NOT AMTypes.TVEqual[ed.old, ed.var]) THEN AMTypes.Assign[ed.old, ed.var]}; IF (IF News[] THEN TRUE ELSE always) THEN BEGIN cd: ComplexData _ NARROW[ed]; cd.updater[tv: cd.var, v: cd.t, handlerData: cd.handlerData, clientData: cd.clientData]; END; END; SimpleToRope: PUBLIC ToRopeProc = BEGIN sd: SimpleData _ NARROW[ed]; asRope _ sd.handler.UnParse[sd.var, sd.targType, sd.handlerData]; END; SimpleAssignRope: PUBLIC AssignRopeProc = BEGIN sd: SimpleData _ NARROW[ed]; IF NOT (success _ sd.handler.Parse[asRope, sd.wideAsTV, sd.targType, sd.handlerData]) THEN RETURN; AMTypes.Assign[sd.var, AMTypes.Coerce[sd.wideAsTV, sd.targType ! AMTypes.Error => {success _ FALSE; CONTINUE}]]; END; UpdateRecord: PUBLIC UpdateProc = BEGIN rd: RecordData _ NARROW[ed]; IF (IF AMTypes.TVEqual[rd.old, rd.var] THEN always ELSE TRUE) THEN BEGIN AMTypes.Assign[rd.old, rd.var]; SampleData[rd.d]; END; END; BindAllOfATypeFromTVs: PUBLIC PROC [recType: Type, handle: TypedVariable, name: ROPE _ NIL, visible, editable: BOOLEAN _ FALSE] RETURNS [bl: BindingList] = BEGIN NameTest: PROC [i: CARDINAL] RETURNS [BOOLEAN] = {RETURN [IF name = NIL THEN TRUE ELSE name.Equal[AMTypes.IndexToName[recType, i]]]}; handsType: Type _ AMTypes.TVType[handle]; SELECT AMTypes.TypeClass[recType] FROM record, structure => NULL; ENDCASE => ERROR NotARecord[]; bl _ NIL; FOR i: CARDINAL IN [1..AMTypes.NComponents[recType]] DO Doit: PROC [t: Type] = BEGIN b: BindingList _ BindAllOfATypeFromTVs[t, handle, name, visible, editable]; IF b # NIL THEN bl _ CONS[[ii, Group[b]], bl]; END; ii: Int _ NEW [INT _ i]; cType: Type _ AMTypes.UnderType[AMTypes.IndexToType[recType, i]]; IF RTTypesBasic.EquivalentTypes[cType, handsType] AND NameTest[i] THEN bl _ CONS[[ii, Value[handle, visible, editable]], bl] ELSE SELECT AMTypes.TypeClass[cType] FROM procedure => BEGIN domType: Type _ AMTypes.Domain[cType]; rangeType: Type _ AMTypes.Range[cType]; argBL, retBL: BindingList; SELECT AMTypes.TypeClass[domType] FROM nil => argBL _ NIL; record, structure => argBL _ BindAllOfATypeFromTVs[domType, handle, name, visible, editable]; ENDCASE => ERROR; SELECT AMTypes.TypeClass[rangeType] FROM nil => retBL _ NIL; record, structure => retBL _ BindAllOfATypeFromTVs[rangeType, handle, name, visible, editable]; ENDCASE => ERROR; IF argBL # NIL OR retBL # NIL THEN bl _ CONS[[ii, Group[argBL, retBL]], bl]; END; record, structure => Doit[cType]; ENDCASE; ENDLOOP; END; BindAllOfATypeFromRefs: PUBLIC PROC [rec, handle: REF ANY, name: ROPE, visible, editable: BOOLEAN _ FALSE] RETURNS [BindingList] = TRUSTED BEGIN RETURN [BindAllOfATypeFromTVs[ recType: AMTypes.UnderType[AMTypes.TVType[AMBridge.TVForReferent[rec]]], handle: AMBridge.TVForReferent[handle], name: name, visible: visible, editable: editable]]; END; ViewRef: PUBLIC PROC [rec: REF ANY, specs: BindingList _ NIL, label: Rope.ROPE _ NIL, otherStuff: OtherStuffProc _ NIL, toDo: DoitProc _ NIL, toDoData: REF ANY _ NIL, parent: RecordViewer _ NIL, sample: BOOLEAN _ TRUE, holdOff: BOOLEAN _ FALSE, highlightSelectedProc: BOOLEAN _ TRUE, createOptions: CreateOptions _ [], viewerInit: ViewerClasses.ViewerRec _ [], paint: BOOLEAN _ TRUE] RETURNS [rv: RecordViewer] = TRUSTED BEGIN RETURN [ViewRec.ViewTV[rec: AMBridge.TVForReferent[rec], specs: specs, label: label, otherStuff: otherStuff, toDo: toDo, toDoData: toDoData, parent: parent, sample: sample, holdOff: holdOff, highlightSelectedProc: highlightSelectedProc, createOptions: createOptions, viewerInit: viewerInit, paint: paint]]; END; ViewInterface: PUBLIC PROC [name: ROPE, specs: BindingList _ NIL, label: ROPE _ NIL, otherStuff: OtherStuffProc _ NIL, toDo: DoitProc _ NIL, toDoData: REF ANY _ NIL, parent: RecordViewer _ NIL, sample: BOOLEAN _ TRUE, holdOff: BOOLEAN _ FALSE, highlightSelectedProc: BOOLEAN _ TRUE, createOptions: CreateOptions _ [], viewerInit: ViewerClasses.ViewerRec _ [], paint: BOOLEAN _ TRUE] RETURNS [RecordViewer] = BEGIN RETURN [ViewRec.ViewTV[rec: RTMiniModel.AcquireIRInstance[name], specs: specs, label: label, otherStuff: otherStuff, toDo: toDo, toDoData: toDoData, parent: parent, sample: sample, holdOff: holdOff, highlightSelectedProc: highlightSelectedProc, createOptions: createOptions, viewerInit: viewerInit, paint: paint]]; END; ViewSelf: PUBLIC PROC = TRUSTED BEGIN ift: Type _ AMTypes.TVType[RTMiniModel.AcquireIRInstance["ViewRec"]]; [] _ ViewInterface[name: "ViewRec", specs: BindAllOfATypeFromTVs[ift, AMBridge.TVForReferent[NEW [BOOLEAN _ FALSE]], "iconic", TRUE, TRUE], createOptions: [doAllRecords: TRUE], viewerInit: [name: "ViewRec", iconic: FALSE, column: right]]; END; SetBehavior: PUBLIC PROC [newBehavior: ViewRec.BehaviorOptions _ []] = {behavior _ newBehavior}; Help: PUBLIC PROC = BEGIN [] _ VT.MakeNewTextViewer[info: [name: "ViewRec.doc", file: "ViewRec.doc", iconic: FALSE]]; END; DestroyEltViewer: PUBLIC ENTRY ViewerClasses.DestroyProc = BEGIN ed: EltData _ NARROW[self.data]; ed.destroyed _ TRUE; END; Setup: PROC = BEGIN nvDocFmt _ "Red => Open this component for editing, Yellow => Take current Tioga Selection, and try to use it, %gControl Shift Red, Yellow, or Blue => Gives the following description of what this should be: \"%g\""; recDocFmt _ "Control Shift Red, Yellow, or Blue => Describe the TYPE of this component (%g)"; nvcDocFmt _ "Control Shift Red, Yellow, or Blue => Gives the following description of what this should be: \"%g\""; procDoc _ "Hitting me will cause this PROCEDURE's Arguments and Results to be displayed"; selDoc _ "Hitting me selects this PROCEDURE"; butDoc _ "Hitting me will invoke this PROCEDURE"; doitDocFmt[FALSE] _ "Control Shift Red => increment UserAbort (Process.Abort when 300 reached), Control Shift Blue => decrement UserAbort, Control Shift Yellow => inquire about UserAbort, Red, Yellow, or Blue => invoke %g (it takes no arguments)"; doitDocFmt[TRUE] _ "Control Shift Red => increment UserAbort (Process.Abort when 300 reached), Control Shift Blue => decrement UserAbort, Control Shift Yellow => inquire about UserAbort, Red, Yellow, or Blue => invoke %g with the given arguments"; abortDocFmt _ "UserAbort is %g"; transitions _ [ Other: [Edit: Other, Call: Dispatched, Return: Other, Abort: Other], Dispatched: [Edit: DispatchedAndEdited, Call: Dispatched, Return: Returned, Abort: Aborted], DispatchedAndEdited: [Edit: DispatchedAndEdited, Call: Dispatched, Return: Other, Abort: Other], Returned: [Edit: Other, Call: Dispatched, Return: Other, Abort: Other], Aborted: [Edit: Other, Call: Dispatched, Return: Other, Abort: Other]]; TRUSTED {Process.Detach[FORK Sample[]]}; TiogaOps.RegisterCommand[name: $NextPlaceholder, proc: TiogaNext]; TiogaOps.RegisterCommand[name: $PreviousPlaceholder, proc: TiogaPrev]; TiogaOps.RegisterCommand[name: $CtrlPrevPlaceholder, proc: TiogaGiveUp]; TiogaOps.RegisterCommand[name: $CtrlNextPlaceholder, proc: TiogaClose]; TiogaOps.RegisterCommand[name: $InsertLineBreak, proc: TiogaClose]; TiogaOps.RegisterCommand[name: $Break, proc: TiogaDoit]; END; Setup[]; END. ‚FILE: ViewRecOther.Mesa last edited by Spreitzer March 10, 1983 4:46 pm Last Edited by: Maxwell, November 16, 1982 3:29 pm Κ)Y˜J˜Jšœ™Jšœ/™/Jšœ2™2J˜codešΟk ˜ KšœΥœ)˜€K˜—šΠbx œœ˜Kšœ1œ œbœ)˜ΥKšœ˜Kšœ˜ K˜—Kšœœ˜K˜Kšœ œœœ˜ Kšœœœœ˜$Kšœœœœ˜,Kšœ œœœ˜3K˜Kšœœ˜*K˜Kš œ œœœœœœ˜BKšœ œ˜&K˜Kšœ œ˜.Kšœ œœ˜Kšœœ œ˜Kšœœœ˜K˜Kš œ œ œœœ ˜9Kšœ œ˜%Kšœœœ˜$Kš œ œœœœœœ˜-Kšœ œœ˜K˜Kšœ$œ˜1Kšœœœ˜Kšœœœ˜.Kšœ œ˜K˜š Οnœœœ;œœœ˜€Kš˜K˜K˜ Kšœœ˜šœ˜"˜$K˜*—Kšœ œ˜ Kšœ œ˜—Kšœœœœœœœ˜,šœ˜$˜&Kšœ,˜,—Kšœ œ˜"Kšœ œ˜—Kšœœœœœœœ˜,Kšœ"˜(Kšœ˜K˜—šŸ œœœ.œœœ œ˜xKš˜K˜ šœœœ˜1K˜&K˜!K˜K˜Kšœ œ˜K˜K˜`K˜Kšœœœ œ˜,š ˜ Kšœ œœ˜Kšœ2œ œ˜Sšœœ˜%šœ˜Kšœ œ˜K˜;Kšœœ˜)Kšœ˜—Kšœ œ˜—šœ˜Kš œœ œœœ˜/—Kš œœœœœœ˜%Kšœœ œ˜)Kšœ˜—Kšœ˜—Kšœœ˜ Kšœ˜—K˜šŸ œœœ+œœœœœ˜ˆKš˜šŸœœ œ œ˜;Kš˜šœœ˜Kšœ;˜;Kšœœœœ˜*K˜ Kšœ˜—Kšœœ˜Kšœ˜—K˜K˜ K˜K˜Kšœœœ˜(K˜Kšœ+œœ˜9K˜Kšœœ2œœ˜VK˜Kšœ)œœ˜7K˜K˜Kšœœ3œœ˜WK˜Kšœ$œœ˜2K˜K˜Kšœ!œœ˜/K˜Kšœœœ˜)K˜Kšœ œ˜Kšœ˜—K˜š Ÿœœœœœ˜CKšœRœ(˜ˆKš˜Kšœœ˜Kšœœ˜Kšœœ˜Kšœ œ˜Kšœ œ˜ šœœœ˜&šœœ˜Kš œœœœœœ˜*Kšœ œ œœ˜ Kš œœœœœ"œœ˜BKšœœ˜&—šœ œ˜šœ"˜"Kšœ˜Kšœ˜Kšœœ˜—K˜.Kšœ!œ%˜JKšœ&œ˜A˜FK˜:—Kšœœ˜—Kšœ˜—KšœΟc˜,Kšœ˜—K˜Kšœœ =˜QK˜šŸœœœœ˜MKš˜Kšœœœœ˜K˜Kšœ œœ œ˜)K˜ Kšœ˜—K˜šŸœ œ˜Kš˜K˜BKšœ+˜2šœœ˜ Kšœœ˜ Kšœœ˜K˜2Kšœ,œœJ˜„K˜)šœœœ˜0K˜Kšœ˜Kšœœ˜šœœœ˜˜4K˜;——Kšœ˜—šœ œ ˜K˜"—Kšœ˜Kšœœ˜ šœ+˜1K˜*—š œœœ œ ˜1Kšœ#˜*Kšœ˜—Kšœ˜—Kšœ˜K˜—šŸœœœ˜Kšœœœ˜K˜!K˜)K˜)Kšœœ˜—K˜—š Ÿ œœœœœ˜)Kš˜Kšœœ˜Kšœ œœœ˜,Kšœ˜—K˜šŸ œœ ˜Kš˜Kšœ œ œ!œ˜JK˜šœœœ˜3Kšœ œœ)œ˜HKšœ˜—Kšœ˜K˜—šŸœœœ˜*K˜K˜—š Ÿ œœœ(œœœ˜XKš˜K˜Kšœ œ˜Kšœœœœ˜(š˜K˜"Kš œœœœœ˜6Kšœœœœ˜&K˜Kšœœœœ˜šœœ˜K˜-Kšœ!œ˜&Kšœœ˜ —Kšœ˜—Kšœ˜—K˜š Ÿœœœœœ˜;Kš˜Kšœœ˜ šœœ˜š œœœœœ˜6Kšœœœ˜%Kšœ˜—šœœœ˜Kšœœ˜šœœœ˜+Kšœœœ˜%Kšœ˜—Kšœ˜—š œœœœœœ˜:Kšœ œœ˜Kšœ˜Kšœ˜—Kšœœ ˜—Kšœœ˜ Kšœ˜—K˜šŸœœ˜Kš˜Kšœ œ˜K˜Kšœ˜K˜—šŸœœ˜Kš˜Kšœ œ˜K˜Kšœ˜K˜—šŸœœ˜&Kš˜šœœ˜šœ˜K˜#K˜.šœœœ˜7K˜5—Kšœ˜—šœ˜šœœ˜ K˜—Kšœ˜——Kšœ˜K˜—šŸ œœœœ˜1šœœœ˜K˜ K˜K˜(K˜K˜Kšœœ˜K˜——š Ÿœœœœœ˜CKš˜šœœ˜K˜'—Kšœœ˜Kšœ˜K˜—šŸœœœœœœœ˜OK˜—K˜š Ÿ œœœœœ˜=Kš˜Kšœœ˜ Kšœœœ+œ˜Ešœ˜šœ˜ Kšœœ˜Kšœœ œ˜-šœœ ˜'Kšœœ˜5—Kšœ˜Kšœ˜—šœ œœ œ˜?Kšœœ œ˜(Kšœ˜——K˜,Kšœ˜K˜—šŸœœœ˜$Kš˜Kšœœ˜ šœœœ˜*Kšœœœœ˜Kšœ˜—šœœœœœœœœ˜FKš˜Kšœœ˜$šœ˜ Kšœœ˜8Kšœ˜—Kšœ8œ˜>Kšœ˜Kšœ˜—Kšœœœœ˜IKšœœ˜"K˜0Kšœ˜ Kšœ˜K˜—šŸœœœ˜&Kš˜Kš œœœœœœ˜1Kšœ˜K˜—šŸœœœœ˜;Kš˜K˜K˜Kšœ˜K˜—šŸœœœ˜Kš˜Kšœœ˜ K˜Kšœ˜K˜—š Ÿœœœœœ˜6Kš˜Kšœœ˜Kšœœœœ˜)K˜Kšœ#œ˜/Kšœ˜K˜—šŸœœœ˜!Kš˜Kšœœ˜Kšœ'œ˜+Kšœœ˜Kšœ!œ˜'Kšœ˜Kšœ˜—K˜š Ÿ œœœœœ œ˜MKš˜K˜ Kš œœœœœ˜ K˜Kš œœœœœ˜.Kšœ2˜9Kšœœ˜Kšœ˜—K˜šŸœœœœœœ œ œ˜ŠKš˜K˜ Kšœœœœ˜K˜Kšœœœœ˜*šœ)˜/Kš˜Kšœ#˜#Kšœ˜Kš˜—Kšœ ˜Kšœ˜—K˜š Ÿ œœœœœ œ˜OKš˜K˜ Kšœœœœ˜K˜Kšœœœœ˜*Kšœ#˜#Kšœ˜—K˜š Ÿ œœœœœ ˜NKš˜K˜ Kšœœœœ˜K˜Kšœœœœ˜&Kšœ&˜&Kšœ˜—K˜šŸœœœ˜@Kš˜Kšœœ˜Kš œœœœœœœ˜P˜ Kšœœ˜-Kš œœœœ&œ˜ZKš œœœœ&œ˜\Kšœ˜—Kšœ˜—K˜šŸœœœ œ˜IKš˜K˜ Kšœœœœ˜K˜Kšœœœœ˜&Kš œœœœœ+œœ˜lKšœ˜—K˜šŸ œœ˜!Kš˜šŸœœ˜ Kšœœ œ"˜4—K˜Kšœœœœ˜Kšœ œœœ˜Kšœ/˜6˜Bšœ˜ Kš˜K˜K˜Kšœ˜ Kšœ˜—šœ˜ Kš˜K˜K˜ K˜Kšœ˜——K˜ K˜K˜Kšœ˜K˜—šŸœœ˜(Kš˜Kšœœ ˜"K˜"K˜Kšœ˜Kšœœœœ˜+šœ ˜Kš˜šœ œ œ œ˜1Kšœœœœ ˜3—Kšœ˜Kšœ˜—šœ ˜Kš˜šœœœœœœœ˜7Kš˜šœ1˜3Kšœ8œ˜=—Kšœœ˜Kšœ˜—šœœ˜Kš˜šœ+˜-K˜$—Kšœœ˜Kšœ˜—K˜Kšœœœ˜!K˜Kšœ˜—Kšœœ˜Kš œœœ œ œ˜8Kšœ˜K˜—šŸ œœ˜(Kš˜Kšœœœ!˜Išœœœ˜K˜K˜Kšœ#œ˜8Kš˜—Kšœ˜Kšœ˜K˜—šŸœœ˜-Kš˜Kšœœ ˜"Kšœ˜Kšœœœ>œ˜VKšœœœœ˜+šœ ˜Kš˜Kš œœœ œœ˜Ošœœ ˜Kšœ'œœ$˜fKšœ'˜'Kšœœœ˜CKšœœ˜—Kš˜—Kšœ˜Kšœ˜—K˜šŸœœ ˜Kš˜Kšœ$˜$Kš œœœœœ˜BKšœ œ˜Kšœ˜—K˜šŸ œœ ˜Kš˜Kšœœ˜šœ˜Kš˜Kšœ œ˜'Kšœ œ˜'Kšœ˜—Kšœ˜K˜—š Ÿœœœœ œ˜UKš˜K˜Kš œœœœœ˜K˜Kšœ œœœ˜7Kšœ œœœ˜/Kš œ%œœœœ˜>Kšœ œœœ˜3K˜K˜Kšœ*œ˜FKšœ˜K˜—šŸ œœ'œœ˜WKš˜šŸœœœ˜0Kš˜šœœ˜ Kš œœœœœ˜Kšœœ œ œ ˜*Kš œœœœœ˜5Kšœ˜—Kšœ˜—Kšœ œœ˜šœœ˜ Kš œœœœœ˜šœœ˜šœœ œ œ˜DKš œœ œœœœ˜9Kšœ˜—Kšœœ œ œ ˜AK˜!K˜Kšœœ˜—Kšœ˜—Kšœ˜—K˜šŸ œ˜!Kš˜Kšœœœœ+˜