DIRECTORY CD, CDInstances, CDBasics, CDLayers USING [MakeAbstract], CDLRUCache, CDImports, CDIOExtras, CDOps, CDOrient, CDSymbolicObjects, CDPrivate, CDProperties, CDRects, Imager, ImagerPath, Rope; CDSymbolicObjectsImpl: CEDAR MONITOR IMPORTS CD, CDInstances, CDBasics, CDLayers, CDLRUCache, CDIOExtras, CDOps, CDOrient, CDPrivate, CDProperties, CDRects, Imager, ImagerPath, Rope EXPORTS CDSymbolicObjects SHARES CDLayers = BEGIN symNameProp: ATOM = $SignalName; symLayerProp: ATOM = $layerOfPin; symOwnerProp: ATOM = $ownerOfPin; markObject: CD.Object; markObjectPath: ImagerPath.Trajectory = CreateMarkObjectPath[]; dummySpecific: REF SymRec = NEW[SymRec]; SymRec: TYPE = RECORD [dummy: INT _ 17]; pinLayer: PUBLIC CD.Layer _ CD.NewLayer[NIL, $pinRepresentation]; segmentLayer: PUBLIC CD.Layer _ CD.NewLayer[NIL, $segmentRepresentation]; markLayer: CD.Layer _ CD.combined; pinCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 17, newProc: NewPin]; segmentCache: CDLRUCache.LRUCache = CDLRUCache.Create[size: 17, newProc: NewSegment]; pinClass: PUBLIC REF CD.ObjectClass _ CD.RegisterObjectClass[$PinOb0]; segmentClass: PUBLIC REF CD.ObjectClass _ CD.RegisterObjectClass[$SymbolicSegment]; markClass: PUBLIC REF CD.ObjectClass _ CD.RegisterObjectClass[$AlignmentMarkOb]; NewPin: PROC [] RETURNS [CD.Object] = { ob: CD.Object _ NEW[CD.ObjectRep]; ob.specificRef _ dummySpecific; ob.layer _ pinLayer; ob.class _ pinClass; RETURN [ob] }; NewSegment: PROC [] RETURNS [CD.Object] = { ob: CD.Object _ NEW[CD.ObjectRep]; ob.specificRef _ dummySpecific; ob.layer _ segmentLayer; ob.class _ segmentClass; RETURN [ob] }; CreateMarkObjectPath: PROC [] RETURNS [markObjectPath: ImagerPath.Trajectory] = BEGIN markObjectPath _ ImagerPath.MoveTo[[0, 0]]; markObjectPath _ ImagerPath.LineTo[markObjectPath, [0, 3]]; markObjectPath _ ImagerPath.LineTo[markObjectPath, [1, 2]]; markObjectPath _ ImagerPath.LineTo[markObjectPath, [3, 4]]; markObjectPath _ ImagerPath.LineTo[markObjectPath, [4, 3]]; markObjectPath _ ImagerPath.LineTo[markObjectPath, [2, 1]]; markObjectPath _ ImagerPath.LineTo[markObjectPath, [3, 0]]; markObjectPath _ ImagerPath.LineTo[markObjectPath, [0, 0]]; END; Init: PROC [] = BEGIN CDLayers.MakeAbstract[pinLayer]; pinClass.drawMe _ pinClass.quickDrawMe _ DrawPin; pinClass.showMeSelected _ ShowSelectedSymRL; pinClass.internalRead _ ReadPin; pinClass.internalWrite _ WritePinOrSegment; pinClass.wireTyped _ TRUE; pinClass.symbolic _ TRUE; pinClass.description _ "pin"; pinClass.describeInst _ DescribeInstance; CDRects.UseAsCreateRect[pinLayer, RCreatePin, pinClass]; CDLayers.MakeAbstract[segmentLayer]; segmentClass.drawMe _ segmentClass.quickDrawMe _ DrawSegment; segmentClass.showMeSelected _ ShowSelectedSymRL; segmentClass.internalRead _ ReadSegment; segmentClass.internalWrite _ WritePinOrSegment; segmentClass.wireTyped _ TRUE; segmentClass.symbolic _ TRUE; segmentClass.description _ "segment"; segmentClass.describeInst _ DescribeInstance; CDRects.UseAsCreateRect[segmentLayer, RCreateSegment, segmentClass]; markClass.drawMe _ markClass.quickDrawMe _ DrawMark; markClass.internalWrite _ WriteMark; markClass.internalRead _ ReadMark; markClass.description _ "mark"; markClass.symbolic _ TRUE; markObject _ NEW[CD.ObjectRep _ [ class: markClass, size: [4, 4], layer: markLayer, specificRef: $AlignmentMarkOb ]]; [] _ CDProperties.RegisterProperty[symLayerProp, $layer]; [] _ CDProperties.RegisterProperty[symOwnerProp, $atom]; CDProperties.InstallProcs[prop: symOwnerProp, new: [makeCopy: CDProperties.CopyVal]]; CDProperties.InstallProcs[prop: symLayerProp, new: [makeCopy: CDProperties.CopyVal]]; END; CreateMark: PUBLIC PROC [dummySize: CD.Number_0] RETURNS [CD.Object] = BEGIN RETURN [markObject] END; CreateSegment: PUBLIC PROC [length: CD.Number, dummyWidth: CD.Number_0] RETURNS [CD.Object] = BEGIN ob: CD.Object = segmentCache.UnusedOrNew[]; size: CD.Position; IF dummyWidth<=0 THEN dummyWidth _ 8; size _ [dummyWidth, length]; ob.size _ CDBasics.MaxPoint[size, [1, 1]]; RETURN [segmentCache.ReplaceByAequivalent[ob]]; END; RCreateSegment: PROC [size: CD.Position, l: CD.Layer] RETURNS [CD.Object] = BEGIN RETURN [CreateSegment[size.y, size.x]] END; CreatePin: PUBLIC PROC [size: CD.Position] RETURNS [CD.Object] = BEGIN ob: CD.Object = pinCache.UnusedOrNew[]; ob.size _ CDBasics.MaxPoint[size, [1, 1]]; RETURN [pinCache.ReplaceByAequivalent[ob]]; END; RCreatePin: PROC [size: CD.Position, l: CD.Layer] RETURNS [CD.Object] = BEGIN RETURN [CreatePin[size]] END; IsSymbolicOb: PUBLIC PROC [ob: CD.Object] RETURNS [BOOL] = { RETURN [ob.class=markClass OR ob.class=segmentClass OR ob.class=pinClass] }; IsMark: PUBLIC PROC [ob: CD.Object] RETURNS [BOOL] = { RETURN [ob.class=markClass] }; IsSegment: PUBLIC PROC [ob: CD.Object] RETURNS [BOOL] = { RETURN [ob.class=segmentClass] }; IsPin: PUBLIC PROC [ob: CD.Object] RETURNS [BOOL] = { RETURN [ob.class=pinClass] }; SymbolicKind: PUBLIC PROC [ob: CD.Object] RETURNS [k: CDSymbolicObjects.Kind] = { SELECT TRUE FROM ob.class=pinClass => k _ pin; ob.class=segmentClass => k _ segment; ob.class=markClass => k _ mark; ENDCASE => k _ notSymbolic }; SetOwner: PUBLIC PROC [symInst: CD.Instance, owner: ATOM_NIL] = BEGIN IF IsSymbolicOb[symInst.ob] THEN CDProperties.PutPropOnInstance[symInst, symOwnerProp, owner] END; GetOwner: PUBLIC PROC [symInst: CD.Instance] RETURNS [at: ATOM] = BEGIN WITH CDProperties.GetPropFromInstance[symInst, symOwnerProp] SELECT FROM a: ATOM => at _ a ENDCASE => at _ NIL END; SetName: PUBLIC PROC [symInst: CD.Instance, name: Rope.ROPE] = BEGIN IF IsSymbolicOb[symInst.ob] THEN CDProperties.PutPropOnInstance[symInst, symNameProp, name] END; GetName: PUBLIC PROC [symInst: CD.Instance] RETURNS [r: Rope.ROPE _ NIL] = BEGIN IF IsSymbolicOb[symInst.ob] THEN { WITH CDProperties.GetPropFromInstance[symInst, symNameProp] SELECT FROM n: Rope.ROPE => r _ n; rt: REF READONLY TEXT => r _ Rope.FromRefText[rt]; ENDCASE => NULL; } END; SetLayer: PUBLIC PROC [symInst: CD.Instance, layer: CD.Layer] = BEGIN IF IsSymbolicOb[symInst.ob] THEN CDProperties.PutPropOnInstance[symInst, symLayerProp, CDPrivate.layers[layer]] END; GetLayer: PUBLIC PROC [symInst: CD.Instance] RETURNS [layer: CD.Layer] = BEGIN WITH CDProperties.GetPropFromInstance[symInst, symLayerProp] SELECT FROM lp: CDPrivate.LayerRef => layer _ lp^.number ENDCASE => layer _ CD.combined END; DirectionFromOrient: PUBLIC PROC [o: CD.Orientation] RETURNS [dir: CDSymbolicObjects.Direction] = BEGIN SELECT o FROM CDOrient.original, CDOrient.rotate180X => dir _ west; CDOrient.rotate90, CDOrient.rotate90X => dir _ south; CDOrient.rotate180, CDOrient.mirrorX => dir _ east; CDOrient.rotate270, CDOrient.rotate270X => dir _ north; ENDCASE => ERROR; END; OrientFromDirection: PUBLIC PROC [dir: CDSymbolicObjects.Direction] RETURNS [o: CD.Orientation] = BEGIN SELECT dir FROM west => o _ CDOrient.original; south => o _ CDOrient.rotate90; east => o _ CDOrient.rotate180; north => o _ CDOrient.rotate270; ENDCASE => ERROR; END; CreateSymInst: PUBLIC PROC [name: Rope.ROPE, denotes: CD.Rect, dummySize: CD.Number, layer: CD.Layer, owner: ATOM, approachFrom: CDSymbolicObjects.Direction] RETURNS [symInst: CD.Instance] = BEGIN symOb: CD.Object; orient: CD.Orientation _ OrientFromDirection[approachFrom]; loc: CD.Position; denotes _ CDBasics.NormalizeRect[denotes]; IF denotes.x1#denotes.x2 AND denotes.y1#denotes.y2 THEN { loc _ CDBasics.BaseOfRect[denotes]; symOb _ CreatePin[CDOrient.OrientedSize[CDBasics.SizeOfRect[denotes], orient]]; } ELSE IF denotes.x1=denotes.x2 AND denotes.y1=denotes.y2 THEN { p: CD.Position; symOb _ CreateMark[dummySize]; p _ CDOrient.MapPoint[ pointInCell: [0, 0], cellSize: symOb.size, cellInstOrient: orient, cellInstPos: [0, 0] ]; loc _ [x: denotes.x1-p.x, y: denotes.y1-p.y]; } ELSE { l: CD.Number; IF denotes.x1=denotes.x2 THEN { l _ denotes.y2-denotes.y1; IF approachFrom=south OR approachFrom=north THEN { approachFrom _ west; orient _ OrientFromDirection[approachFrom]; } } ELSE { l _ denotes.x2-denotes.x1; IF approachFrom=west OR approachFrom=east THEN { approachFrom _ south; orient _ OrientFromDirection[approachFrom]; } }; symOb _ CreateSegment[length: l, dummyWidth: dummySize]; loc _ CDBasics.BaseOfRect[denotes]; SELECT approachFrom FROM west, south => NULL; east => loc.x _ loc.x-symOb.size.x; north => loc.y _ loc.y-symOb.size.x; ENDCASE => ERROR; }; symInst _ CDInstances.NewInstance[ob: symOb, location: loc, orientation: orient]; IF name#NIL THEN SetName[symInst, name]; IF layer#CD.combined THEN SetLayer[symInst, layer]; IF owner#NIL THEN SetOwner[symInst, owner]; END; Denotes: PUBLIC PROC [symInst: CD.Instance] RETURNS [CD.Rect] = BEGIN itemInCell: CD.Rect; SELECT TRUE FROM symInst.ob.class=pinClass => itemInCell _ [x1: 0, y1: 0, x2: symInst.ob.size.x, y2: symInst.ob.size.y]; symInst.ob.class=segmentClass => itemInCell _ [x1: 0, y1: 0, x2: 0, y2: symInst.ob.size.y]; symInst.ob.class=markClass => itemInCell _ [0, 0, 0, 0]; ENDCASE => ERROR; RETURN [CDOrient.MapRect[ itemInCell: itemInCell, cellInstPos: symInst.location, cellSize: symInst.ob.size, cellInstOrient: symInst.orientation ]] END; EnumerateSymbolicObs: PUBLIC PROC [cellOb: CD.Object_NIL, eachInst: CDSymbolicObjects.InstEnumerator] RETURNS [quit: BOOL_FALSE] = BEGIN cp: CD.CellPtr; WITH cellOb.specificRef SELECT FROM c: CD.CellPtr => cp _ c; ip: CDImports.ImportPtr => { -- HACK? until imports handle symbolic objects more reasonably IF ip.boundInstance=NIL THEN RETURN [TRUE]; quit _ EnumerateSymbolicObs[ip.boundInstance.ob, eachInst]; RETURN }; ENDCASE => RETURN [TRUE]; FOR list: CD.InstanceList _ cp.contents, list.rest WHILE (list#NIL AND ~quit) DO IF IsSymbolicOb[list.first.ob] THEN { quit _ eachInst[list.first]; -- do NOT catch errors }; ENDLOOP; END; FindSymbolicObs: PUBLIC PROC [cellOb: CD.Object_NIL, name: Rope.ROPE] RETURNS [il: CD.InstanceList_NIL]= BEGIN Enumerate: CDSymbolicObjects.InstEnumerator = { IF Rope.Equal[GetName[inst], name] THEN il _ CONS[inst, il]; }; [] _ EnumerateSymbolicObs[cellOb, Enumerate]; END; WritePinOrSegment: CD.InternalWriteProc -- PROC [me: Object] -- = BEGIN CDIOExtras.WritePos[me.size]; END; WriteMark: CD.InternalWriteProc --PROC [me: Object]-- = {}; ReadPin: CD.InternalReadProc --PROC [] RETURNS [Object]-- = BEGIN RETURN [CreatePin[CDIOExtras.ReadPos[]]] END; ReadSegment: CD.InternalReadProc --PROC [] RETURNS [Object]-- = BEGIN p: CD.Position _ CDIOExtras.ReadPos[]; RETURN [CreateSegment[p.y, p.x]] END; ReadMark: CD.InternalReadProc --PROC [] RETURNS [Object]-- = {RETURN [markObject]}; DescribeInstance: PROC[i: CD.Instance] RETURNS [Rope.ROPE] = BEGIN RETURN [Rope.Cat[CDOps.LayerName[GetLayer[i]], " ", i.ob.class.description]]; END; ShowSelectedSymRL: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN pr.drawRect[CDOrient.RectAt[pos, inst.ob.size, orient], CD.highLightShade, pr] END; DrawPin: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN DrawPinInContext: PROC [context: Imager.Context, ob: CD.Object, layer: CD.Layer] = BEGIN Imager.MaskVector[context, [0, 0], [ob.size.x, ob.size.y]]; Imager.MaskVector[context, [0, ob.size.y], [ob.size.x, 0]]; END; IF pr.symbolics AND (pr.scaleHint*MIN[inst.ob.size.y, inst.ob.size.x]>3 OR pr.scaleHint<=0) THEN { pr.drawContext[pr, DrawPinInContext, inst.ob, pos, orient, pinLayer]; pr.drawComment[r: CDOrient.RectAt[pos, inst.ob.size, orient], comment: GetName[inst], pr: pr] } END; DrawSegment: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN DrawSegmentInContext: PROC [context: Imager.Context, ob: CD.Object, layer: CD.Layer] = BEGIN Imager.MaskVector[context, [0, 0], [0, ob.size.y]]; Imager.MaskVector[context, [0, 0], [ob.size.x, ob.size.y/2]]; Imager.MaskVector[context, [0, ob.size.y], [ob.size.x, ob.size.y/2]]; END; IF pr.symbolics AND (pr.scaleHint*inst.ob.size.y>3 OR pr.scaleHint<=0) THEN { pr.drawContext[pr, DrawSegmentInContext, inst.ob, pos, orient, segmentLayer]; pr.drawComment[r: CDOrient.RectAt[pos, inst.ob.size, orient], comment: GetName[inst], pr: pr] } END; DrawMark: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = BEGIN DrawPath: PROC [context: Imager.Context, ob: CD.Object, layer: CD.Layer] = BEGIN Imager.MaskFillTrajectory[context, markObjectPath]; END; IF pr.symbolics AND (pr.scaleHint*inst.ob.size.y>2 OR pr.scaleHint<=0) THEN { pr.drawContext[pr, DrawPath, markObject, pos, orient, markLayer] } END; Init[]; END. ^CDSymbolicObjectsImpl.mesa (part of ChipNDale) Copyright c 1984, 1985 by Xerox Corporation. All rights reserved. by Christian Jacobi, August 8, 1984 12:41:50 pm PDT last edited Christian Jacobi, January 28, 1986 1:55:46 pm PST --rects --lines --points --common --pin --mark --segment -- erroneous parameters.. -- erroneous parameters.. ΚO˜codešœ/™/Kšœ Οmœ7™BKšœ5™5Kšœ>™>—K˜šΟk ˜ Kšžœ˜K˜ K˜ Kšœ žœ˜Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ ˜ Kšœ˜K˜ K˜ K˜Kšœ˜Kšœ ˜ Kšœ˜—K˜šΠblœžœžœ˜(Kšžœžœ†˜Kšžœ˜Kšžœ˜—Kšž˜K˜Kšœ žœ˜ Kšœžœ˜"Kšœžœ˜"K˜šœ žœ˜Kšœ?˜?—K˜šœžœ žœ ˜(Kšœžœžœ žœ˜(K˜—Kšœ ž œ žœ žœ˜AKšœž œ žœ žœ˜IKšœ žœ žœ ˜"K˜KšœM˜MKšœU˜UK˜Kš œ žœžœžœžœ˜FKš œžœžœžœžœ'˜Sš œ žœžœžœžœ'˜PK˜šΟnœžœžœžœ ˜'Kšœžœ žœžœ ˜"Kšœ˜Kšœ˜Kšœ˜Kšžœ˜ K˜—K˜š  œžœžœžœ ˜+Kšœžœ žœžœ ˜"Kšœ˜Kšœ˜Kšœ˜Kšžœ˜ K˜——˜š œžœžœ*˜OKšž˜Kšœ+˜+Kšœ;˜;Kšœ;˜;Kšœ;˜;Kšœ;˜;Kšœ;˜;Kšœ;˜;Kšœ;˜;Kšžœ˜——K˜š œžœ˜Kšž˜KšΟl™Kšœ ˜ Kšœ1˜1Kšœ,˜,Kšœ ˜ Kšœ+˜+Kšœžœ˜Kšœžœ˜Kšœ˜Kšœ)˜)Kšœ8˜8Kš‘™Kšœ$˜$Kšœ=˜=Kšœ0˜0Kšœ(˜(Kšœ/˜/Kšœžœ˜Kšœžœ˜Kšœ%˜%Kšœ-˜-KšœD˜DKš‘™Kšœ4˜4Kšœ$˜$Kšœ"˜"Kšœ˜Kšœžœ˜šœ žœžœ˜!Kšœ˜K˜ Kšœ˜Kšœ˜Kšœ˜—Kš‘™Kšœ9˜9Kšœ8˜8KšœU˜UKšœU˜UKšžœ˜—K˜K˜š   œžœžœ žœ žœžœ ˜FKšž˜Jšžœ ˜Kšžœ˜—K˜š  œžœžœ žœžœ žœžœ ˜]Kšž˜Kšœžœ%˜+Kšœžœ ˜Kšžœžœ˜%Kšœ˜Kšœ*˜*Kšžœ)˜/Kšžœ˜K˜š  œžœžœžœžœžœ ˜KKšžœ˜Kšžœ ˜&Kšžœ˜——K˜š   œžœžœžœ žœžœ ˜@Kšž˜Kšœžœ!˜'Kšœ*˜*Kšžœ%˜+Kšžœ˜K˜š   œžœžœžœžœžœ ˜GKšžœ˜Kšžœ˜Kšžœ˜——K˜K˜š   œžœžœžœ žœžœ˜Kšž˜šžœžœ˜!Kšœ:˜:—Kšžœ˜—K˜š  œž œ žœ žœ žœžœ˜JKšž˜šžœžœ˜"šžœ8žœž˜GKšœžœ ˜Kšœžœžœžœ˜2Kšžœž˜—K˜—Kšžœ˜—K˜š œž œ žœžœ ˜?Kšž˜šžœžœ˜!KšœN˜N—Kšžœ˜—K˜š  œž œ žœ žœ žœ ˜HKšž˜šžœ9žœž˜HKšœ,˜,Kšžœ žœ ˜—Kšžœ˜—K˜š  œžœžœžœžœ%˜aKšž˜šžœž˜ Jšœ5˜5Jšœ5˜5Jšœ3˜3Jšœ7˜7Jšžœžœ˜—Kšžœ˜—K˜š œž œ$žœžœ˜aKšž˜šžœž˜Jšœ˜Jšœ˜Jšœ˜Jšœ ˜ Jšžœžœ˜—Kšžœ˜—K˜K˜š  œžœžœ žœ žœžœžœžœ-žœ žœ ˜ΎKšž˜Jšœžœ˜Jšœžœ1˜;Jšœžœ ˜Jšœ*˜*šžœžœžœ˜9Jšœ™Kšœ#˜#JšœP˜PJ˜—šžœžœžœžœ˜>Jšœ™Jšœ˜Jšœ˜šœ˜Jšœ˜Jšœ˜Jšœ˜Jšœ˜J˜—Jšœ-˜-J˜—šžœ˜Jšœ ™ Jšœžœ˜ šžœžœ˜Jšœ˜šžœžœžœ˜2J™Jšœ˜Jšœ+˜+J˜—Jšœ˜—šžœ˜Jšœ˜šžœžœžœ˜0J™Jšœ˜Jšœ+˜+J˜—J˜—Jšœ9˜9Jšœ#˜#šžœž˜Jšœžœ˜Jšœ$˜$Jšœ$˜$Jšžœžœ˜—J˜—KšœQ˜QKšžœžœžœ˜(Kšžœžœ žœ˜3Kšžœžœžœ˜+Kšžœ˜—K˜š  œž œ žœ žœžœ˜?Kšž˜Kšœ žœ˜šžœžœž˜Kšœg˜gKšœ[˜[Kšœ8˜8Kšžœžœ˜—šžœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ#˜#Kšœ˜—Kšžœ˜—K™š œžœžœ žœžœ.žœžœžœ˜‚Kšž˜Kšœžœ ˜šžœžœž˜#Kšœžœ˜šœΟc>˜[Kš žœžœžœžœžœ˜+Kšœ;˜;Kšž˜Kšœ˜—Kšžœžœžœ˜—š žœžœ'žœžœžœž˜Pšžœžœ˜%Kšœ’˜3K˜—Kšžœ˜—Kšžœ˜—K˜š œžœžœ žœžœ žœžœžœžœ˜hKšž˜šΟb œ&˜/Kšžœ!žœžœ ˜Kšœžœžœ ˜)Kšž˜Kšœ8žœ˜NKšžœ˜—K˜š  œžœžœžœžœ ˜KKšœžœ ˜Kšž˜K˜š œžœžœžœ ˜RKšž˜Kšœ;˜;Kšœ;˜;Kšžœ˜—K˜š žœžœžœ#žœžœ˜bKšœE˜EKšœ]˜]K˜—Kšžœ˜—K˜š   œžœžœžœžœ ˜OKšœžœ ˜Kšž˜K˜š œžœžœžœ ˜VKšž˜Kšœ3˜3Kšœ=˜=KšœE˜EKšžœ˜—K˜šžœžœ žœžœ˜MKšœM˜MKšœ]˜]K˜—Kšžœ˜—K˜š £œžœžœžœžœ ˜LKšœžœ ˜Kšž˜K˜š œžœžœžœ ˜JKšž˜Kšœ3˜3Kšžœ˜—K˜šžœžœ žœžœ˜NKšœ@˜@K˜—Kšžœ˜—K˜Kšœ˜Kšžœ˜K˜—…—1"BΟ