DIRECTORY CDTexts, CDTextsExtras, CDEvents, CDPrivate, CDProperties, CD, CDIO, CDOrient, FS, Imager, ImagerFont, ImagerTransformation, IO, LRUCache, Real, Rope, RuntimeError USING [UNCAUGHT], SymTab, TerminalIO, TokenIO, VFonts; CDTextsImpl: CEDAR MONITOR IMPORTS CD, CDIO, CDEvents, CDPrivate, CDProperties, FS, Imager, ImagerFont, ImagerTransformation, IO, LRUCache, Real, Rope, RuntimeError, SymTab, TerminalIO, TokenIO, VFonts EXPORTS CDTexts, CDTextsExtras = BEGIN TextPtr: TYPE = CDTexts.TextPtr; TextRec: TYPE = CDTexts.TextRec; FontRec: TYPE = CDTexts.FontRec; CDFont: TYPE = CDTexts.CDFont; convertClass: PUBLIC CD.ObjectClass _ CD.RegisterObjectClass[$Text, [ internalRead: ConvertRead ]]; rigidTextClass: PUBLIC CD.ObjectClass _ CD.RegisterObjectClass[$RigidText, [ drawMe: FixDraw, quickDrawMe: FixDraw, internalRead: Read, internalWrite: Write, describe: Describe, origin: Origin ]]; flipTextClass: PUBLIC CD.ObjectClass _ CD.RegisterObjectClass[$FlipText, [ drawMe: FlipDraw, quickDrawMe: FlipDraw, internalRead: Read, internalWrite: Write, describe: Describe, origin: Origin ]]; textClass: PUBLIC CD.ObjectClass _ flipTextClass; lruQueue: LRUCache.Handle _ LRUCache.Create[127, CDPrivate.Hash, Equal]; free: CD.Object _ NIL; GiveOb: ENTRY PROC [] RETURNS [ob: CD.Object] = { ob _ free; free _ NIL; IF ob=NIL THEN ob _ NEW[CD.ObjectRep_[specificRef: NEW[TextRec]]]; }; Equal: PROC[x, y: REF] RETURNS [BOOL] = { EqualSpec: PROC[x, y: CD.Object] RETURNS [BOOL] = { tp1: TextPtr = NARROW[x.specificRef]; tp2: TextPtr = NARROW[y.specificRef]; RETURN [ Rope.Equal[tp1.text, tp2.text, TRUE] AND Rope.Equal[tp1.cdFont.supposedKey, tp2.cdFont.supposedKey, TRUE] ] }; ob1: CD.Object = NARROW[x]; ob2: CD.Object = NARROW[y]; RETURN [ob1.class=ob2.class AND ob1.size=ob2.size AND ob1.layer=ob2.layer AND EqualSpec[ob1, ob2]] }; Up: PROC [r: REAL] RETURNS [i: INT] = { i _ Real.Fix[r]; IF Real.Float[i]#r THEN i _ i+1; }; Create: PUBLIC PROC [text: Rope.ROPE, font: REF READONLY ANY, layer: CD.Layer, flip: BOOL_TRUE] RETURNS [ob: CD.Object] = { ENABLE UNWIND => NULL; WITH font SELECT FROM cdFont: CDFont => { insert: BOOL; used: REF; e: ImagerFont.Extents _ ImagerFont.RopeBoundingBox[cdFont.font, text]; w: REAL _ ImagerFont.RopeWidth[cdFont.font, text].x; ob _ GiveOb[]; NARROW[ob.specificRef, TextPtr]^ _ [text: text, cdFont: cdFont]; ob.size _ [cdFont.origin.x+Up[e.rightExtent], cdFont.height]; ob.class _ IF flip THEN flipTextClass ELSE rigidTextClass; ob.layer _ layer; [insert: insert, used: used] _ LRUCache.Include[lruQueue, ob]; IF ~insert THEN { free _ ob; ob _ NARROW[used]; }; }; ENDCASE => NULL }; FixDraw: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = { DrawInContext: PROC [context: Imager.Context, ob: CD.Object, layer: CD.Layer] = { tp: CDTexts.TextPtr = NARROW[ob.specificRef]; IF pr.specialFonts THEN { --use substituted font font: CDTexts.CDFont; WITH CDProperties.GetListProp[pr.properties^, $FontExchange] SELECT FROM xp: REF PROC [CDTexts.CDFont] RETURNS [CDTexts.CDFont] => font _ xp^[tp.cdFont]; ENDCASE => font _ tp.cdFont; Imager.SetFont[context, font.font]; } ELSE Imager.SetFont[context, tp.cdFont.font]; --normal case Imager.SetXY[context, tp.cdFont.xy]; --always use original font offsets! Imager.ShowRope[context, tp.text]; }; pr.drawContext[pr, DrawInContext, inst.ob, pos, orient, inst.ob.layer] }; FlipDraw: PROC [inst: CD.Instance, pos: CD.Position, orient: CD.Orientation, pr: CD.DrawRef] = { DrawInContext: PROC [context: Imager.Context, ob: CD.Object, layer: CD.Layer] = { tp: CDTexts.TextPtr = NARROW[ob.specificRef]; IF pr.specialFonts THEN { --use substituted font font: CDTexts.CDFont; WITH CDProperties.GetListProp[pr.properties^, $FontExchange] SELECT FROM xp: REF PROC [CDTexts.CDFont] RETURNS [CDTexts.CDFont] => font _ xp^[tp.cdFont]; ENDCASE => font _ tp.cdFont; Imager.SetFont[context, font.font]; } ELSE Imager.SetFont[context, tp.cdFont.font]; --normal case SELECT orient FROM CDOrient.original, CDOrient.rotate270 => NULL; CDOrient.mirrorX, CDOrient.rotate90X => { Imager.Scale2T[context, [-1, 1]]; Imager.TranslateT[context, [-ob.size.x, 0]]; }; CDOrient.rotate180X, CDOrient.rotate270X => { Imager.Scale2T[context, [-1, 1]]; Imager.TranslateT[context, [-ob.size.x, 0]]; Imager.RotateT[context, 180]; Imager.TranslateT[context, [-ob.size.x, -ob.size.y]]; }; CDOrient.rotate180, CDOrient.rotate90 => { Imager.RotateT[context, 180]; Imager.TranslateT[context, [-ob.size.x, -ob.size.y]]; }; ENDCASE => NULL; Imager.SetXY[context, tp.cdFont.xy]; --always use original font offsets! Imager.ShowRope[context, tp.text]; }; pr.drawContext[pr, DrawInContext, inst.ob, pos, orient, inst.ob.layer] }; Origin: PROC [ob: CD.Object] RETURNS [o: CD.Position] = { o _ NARROW[ob.specificRef, TextPtr].cdFont.origin; }; Describe: PROC[me: CD.Object] RETURNS [r: Rope.ROPE] = { tp: TextPtr = NARROW[me.specificRef]; r _ Rope.Cat["text [", tp.text, "]"]; IF me.class#flipTextClass THEN r _ Rope.Concat["X-", r]; }; Write: CD.InternalWriteProc = { tp: TextPtr = NARROW[me.specificRef]; CDIO.WritePos[me.size]; TokenIO.WriteRope[tp.text]; WriteFont[tp.cdFont]; CDIO.WriteLayer[me.layer]; IF me.class=flipTextClass THEN TokenIO.WriteInt[1] ELSE TokenIO.WriteInt[0] }; Read: CD.InternalReadProc = { ob: CD.Object; sz: CD.Position; r: Rope.ROPE; i: INT; cdFont: REF CDTexts.FontRec; layer: CD.Layer; sz _ CDIO.ReadPos[]; r _ TokenIO.ReadRope[]; cdFont _ ReadFont[]; layer _ CDIO.ReadLayer[]; i _ TokenIO.ReadInt[]; ob _ Create[text: r, font: cdFont, layer: layer, flip: i=1]; IF sz#ob.size THEN FixSize[ob, sz]; RETURN [ob] }; changeTextSizeIfDifferent: BOOL _ FALSE; changeMsg: BOOL _ FALSE; FixSize: PROC [ob: CD.Object, sz: CD.Position] = { IF sz#ob.size THEN { TerminalIO.WriteRope["** size of text wrong; probably use of different font\n"]; IF ~changeMsg THEN { TerminalIO.WriteRope["** to change object sizes to the current font requirements type "" _ CDTextsImpl.changeTextSizeIfDifferent _ TRUE"" into an interpreter and read in the file again. Then set it again to FALSE\n"]; changeMsg _ TRUE; }; IF ~changeTextSizeIfDifferent THEN ob.size _ sz; }; }; ReadFont: PROC [] RETURNS [cdFont: REF CDTexts.FontRec] = { format: INT _ TokenIO.ReadInt[]; SELECT format FROM 1 => { name: Rope.ROPE; scale: INT; name _ TokenIO.ReadRope[]; scale _ TokenIO.ReadInt[]; cdFont _ InternalMakeFont[name, scale, $IO]; }; ENDCASE => ERROR }; WriteFont: PROC [cdFont: CDFont] = { TokenIO.WriteInt[cdFont.format]; IF cdFont.format#1 THEN ERROR ELSE { TokenIO.WriteRope[cdFont.supposedName]; TokenIO.WriteInt[cdFont.scaleI]; }; }; fontCache: SymTab.Ref _ SymTab.Create[mod: 31, case: FALSE]; MakeKey: PROC [name: Rope.ROPE, scale: INT] RETURNS [Rope.ROPE] = { RETURN [IO.PutFR["!%0g*%0g", IO.rope[name], IO.int[scale]]]; }; GetCachedFont: PROC [name: Rope.ROPE, scale: CD.Number] RETURNS [REF CDTexts.FontRec] = { WITH fontCache.Fetch[MakeKey[name, scale]].val SELECT FROM f: REF CDTexts.FontRec => RETURN [f]; ENDCASE => RETURN [NIL]; }; CreateFont: PROC [name: Rope.ROPE, scale: CD.Number, approx: ATOM _ NIL] RETURNS [cdFont: REF CDTexts.FontRec_NIL] = { FindFont: PROC [name: Rope.ROPE] RETURNS [font: Imager.Font_NIL] = { font _ ImagerFont.Find[name ! Imager.Error => { font _ NIL; TerminalIO.WriteRopes["**error while loading font ", name, ": "]; TerminalIO.WriteRopes[error.explanation, "\n"]; CONTINUE; }; RuntimeError.UNCAUGHT => { font _ NIL; TerminalIO.WriteRopes["**unknown error while loading font ", name, "\n"]; CONTINUE; } ]; }; IsIdentity: PROC [t: Imager.Transformation] RETURNS [BOOL] = { RETURN [t.a=1.0 AND t.b=0.0 AND t.c=0.0 AND t.d=0.0 AND t.e=1.0 AND t.f=0.0] }; Internalize: PROC [font: Imager.Font, scale: INT] RETURNS [cdf: REF CDTexts.FontRec_NIL] = { IF font#NIL THEN { e: ImagerFont.Extents; scale _ MAX[1, scale]; IF ~IsIdentity[font.charToClient] THEN ERROR; cdf _ NEW[CDTexts.FontRec _ [properties: CD.InitPropRef[], origin: [0, 0], xy: [0, 0], format: 1]]; cdf.scaleI _ scale; cdf.scaleR _ scale; CDProperties.PutProp[cdf.properties, $OriginalFont, font]; cdf.font _ ImagerFont.Modify[font, ImagerTransformation.Scale[scale]]; e _ ImagerFont.FontBoundingBox[cdf.font]; cdf.xy.x _ Up[e.leftExtent]; cdf.xy.y _ Up[e.descent]; cdf.height _ Up[e.ascent]+Up[e.descent]; cdf.origin.x _ Up[cdf.xy.x]; cdf.origin.y _ Up[cdf.xy.y]; } }; FindPlaceholderFont: PROC [name: Rope.ROPE] RETURNS [font: Imager.Font_NIL] = { TerminalIO.WriteRopes["**font ", name, " substituted\n"]; RETURN [VFonts.defaultFont]; }; isPlaceHolder: BOOL _ FALSE; font: Imager.Font _ FindFont[name]; IF font=NIL THEN { SELECT approx FROM NIL => RETURN [NIL]; $old => { font _ OldFindFont[name]; IF font#NIL THEN name _ font.name; --to prevent bad cache entries!! }; $IO => NULL; ENDCASE => TerminalIO.WriteRope["** bad font mode key\n"]; IF font=NIL THEN { isPlaceHolder _ TRUE; font _ FindPlaceholderFont[name]; }; }; IF font#NIL THEN { --exact font cdFont _ Internalize[font, scale]; cdFont.isPlaceHolder _ isPlaceHolder; cdFont.supposedKey _ MakeKey[name, scale]; cdFont.supposedName _ name; [] _ fontCache.Store[cdFont.supposedKey, cdFont]; RETURN }; }; InternalMakeFont: PROC [name: Rope.ROPE, scale: CD.Number, approx: ATOM] RETURNS [cdFont: REF FontRec] = { cdFont _ GetCachedFont[name, scale]; IF cdFont=NIL THEN cdFont _ CreateFont[name, scale, approx]; }; MakeFont: PUBLIC PROC [name: Rope.ROPE, scale: CD.Number] RETURNS [CDFont] = { RETURN [InternalMakeFont[name, scale, NIL]] }; CreateText: PUBLIC PROC [text: Rope.ROPE, font: REF READONLY ANY, layer: CD.Layer] RETURNS [ob: CD.Object_NIL] = { ob _ ConvertCreateText[text, font, layer, NIL]; }; ConvertCreateText: PROC [text: Rope.ROPE, font: REF READONLY ANY, layer: CD.Layer, key: ATOM] RETURNS [ob: CD.Object_NIL] = { WITH font SELECT FROM cdFont: CDFont => { flip: BOOL _ layer=CD.commentLayer; IF Rope.Match["*symbol*", cdFont.supposedName, FALSE] THEN flip _ FALSE; IF Rope.Match["*gate*", cdFont.supposedName, FALSE] THEN flip _ FALSE; IF key=$chipnsil OR key=$never THEN flip _ FALSE; ob _ Create[text, cdFont, layer, flip] }; ENDCASE => NULL }; neverFlip: BOOL _ FALSE; flipMsg: BOOL _ FALSE; ReadEvent: CDEvents.EventProc = { changeMsg _ flipMsg _ FALSE; }; ConvertRead: CD.InternalReadProc = { ob: CD.Object; sz: CD.Position; r: Rope.ROPE; cdFont: REF CDTexts.FontRec; layer: CD.Layer; IF CDIO.VersionKey[]<=8 THEN RETURN [VeryOldReadText[]]; r _ TokenIO.ReadRope[]; layer _ CDIO.ReadLayer[]; IF layer=CD.undefLayer AND CDIO.VersionKey[]<=14 THEN { layer _ CD.commentLayer; TerminalIO.WriteRope["** layer of text converted to comment\n"]; }; sz _ CDIO.ReadPos[]; cdFont _ ReadFont[]; ob _ ConvertCreateText[text: r, font: cdFont, layer: layer, key: IF neverFlip THEN $never ELSE CDIO.DesignInReadOperation[].technology.key ]; IF ~flipMsg THEN { flipMsg _ TRUE; TerminalIO.WriteRope["**did convert text to either rigid or flip text; you can guide the conversion with either\n _ CDTextsImpl.neverFlip _ TRUE\n _ CDTextsImpl.neverFlip _ FALSE\nand repeating the input\n"]; }; IF sz#ob.size THEN FixSize[ob, sz]; RETURN [ob] }; OldFindFont: PROC [name: Rope.ROPE] RETURNS [font: Imager.Font_NIL] = { FindFont: PROC [name: Rope.ROPE] RETURNS [font: Imager.Font_NIL] = { font _ ImagerFont.Find[name ! Imager.Error => {font _ NIL; CONTINUE}; RuntimeError.UNCAUGHT => {font _ NIL; CONTINUE} ]; }; BasePart: PROC [name: Rope.ROPE] RETURNS [Rope.ROPE] = { fName: Rope.ROPE; cp: FS.ComponentPositions; [fullFName: fName, cp: cp] _ FS.ExpandName[name: name]; RETURN [ Rope.Substr[fName, cp.base.start, cp.base.length] ] }; FindFontOrXFont: PROC [name: Rope.ROPE] RETURNS [font: Imager.Font_NIL] = { font _ FindFont[name]; IF font=NIL THEN font _ FindFont[Rope.Concat["Xerox/TiogaFonts/", name]]; }; TryAlso: PROC [name: Rope.ROPE] RETURNS [next: Rope.ROPE_NIL] = { IF name.Length[]>1 THEN { ch: CHAR _ name.Fetch[name.Length[]-1]; IF ch='B OR ch='I OR ch='N THEN next _ name.Substr[0, name.Length[]-1] } }; ok: BOOL _ TRUE; copy: Rope.ROPE _ BasePart[name]; name _ copy; DO font _ FindFontOrXFont[copy]; IF font#NIL THEN { IF copy#name THEN TerminalIO.WriteRope[ Rope.Cat["Font ", name, " not found; use ", copy, " instead\n"] ]; RETURN; }; copy _ TryAlso[copy]; IF copy.IsEmpty[] THEN RETURN; ENDLOOP; }; VeryOldReadText: CD.InternalReadProc = { OldReadFont: PROC [] RETURNS [font: REF CDTexts.FontRec] = { name: Rope.ROPE = TokenIO.ReadRope[]; scale: INT = MAX[TokenIO.ReadInt[]/8, 1]; --originally used a real ignoreHeight: CD.Number = TokenIO.ReadInt[]; ignoreWhiteBorder: CD.Number = TokenIO.ReadInt[]; ignoreLayerSubstitute: CD.Layer = CDIO.ReadLayer[]; ignoreBaseOffsetX: REAL = TokenIO.ReadInt[]/8.0; ignoreBaseOffsetY: REAL = TokenIO.ReadInt[]/8.0; ignoreScaleByReplacingFontAllowed: BOOL = (1=TokenIO.ReadInt[]); font _ InternalMakeFont[name: name, scale: scale, approx: $old]; }; ob: CD.Object; x: INT _ -1; y: INT _ -1; r: Rope.ROPE; f: ATOM; layer: CD.Layer _ CD.undefLayer; font: REF FontRec; token: TokenIO.Token _ TokenIO.ReadToken[]; IF token.kind=rope THEN { r _ NARROW[token.ref]; } ELSE { x _ NARROW[token.ref, REF INT]^; y _ TokenIO.ReadInt[]; layer _ CDIO.ReadLayer[]; r _ TokenIO.ReadRope[] }; f _ TokenIO.ReadAtom[]; IF f#NIL THEN ERROR; font _ OldReadFont[]; ob _ CreateText[text: r, font: font, layer: layer]; IF x>0 OR y>0 THEN IF x#ob.size.x OR y#ob.size.y THEN TerminalIO.WriteRope["** size of text wrong; probably use of different font\n"]; RETURN [ob] }; [] _ CDProperties.RegisterProperty[$OriginalFont, $CDTextsImpl]; CDProperties.PutProp[rigidTextClass, $SisyphExtractProc, $ExtractNull]; CDProperties.PutProp[rigidTextClass, $SinixCMosBExtractProc, $ExtractNull]; CDEvents.RegisterEventProc[$ReadTechnologyPrivate, ReadEvent]; END. \CDTextsImpl.mesa Copyright c 1983, 1986 by Xerox Corporation. All rights reserved. Created by Christian Jacobi, July 29, 1983 11:17 am gbb April 4, 1986 3:47:34 pm PST Last Edited by: Christian Jacobi, August 21, 1986 3:44:45 pm PDT -- returns integer i: i >= r; there exists no integer j such that j < i and j >= r --don't clip; speeeed; --Imager.ClipRectangle[context, [x: 0, y: 0, w: ob.size.x, h: ob.size.y]]; --don't clip; speeeed; --Imager.ClipRectangle[context, [x: 0, y: 0, w: ob.size.x, h: ob.size.y]]; -- Fonts ======================================== -- Old ======================================== --get rid of a B or I (for Bold or Italic) --we don't handle ropes of length 0 and 1 --for version<=8 -- very old -- less old --cheat while the conversion... gbb April 4, 1986 3:46:03 pm PST Added conversion of default layer for text ΚZ˜codešœ™Kšœ Οmœ7™BKšœ4™4K™ 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˜šΠln œžœžœ˜Kš žœžœžœ%žœ,žœI˜―Kšžœ˜#—Kšž˜K˜Kšœ žœ˜ Kšœ žœ˜ Kšœ žœ˜ Kšœžœ˜K˜šœžœžœžœ˜EKšœ˜Kšœ˜—šœžœžœžœ"˜LKšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—šœžœžœžœ!˜JKšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜—Kšœ žœžœ˜1K˜KšœH˜HKšœžœ žœ˜K˜š Οnœžœžœžœžœ ˜1Kšœžœ˜šžœžœžœ˜Kšœžœžœžœ ˜3—K˜—K˜š  œžœžœžœžœ˜)š   œžœžœ žœžœ˜3Kšœžœ˜%Kšœžœ˜%šžœ˜Kšœžœžœ˜)Kšœ;žœ˜@Kšœ˜—K˜—Kšœžœ žœ˜Kšœžœ žœ˜Kšžœžœžœžœ˜bKšœ˜—K˜š  œžœžœžœžœ˜'K™TKšœ˜Kšžœžœ ˜ K˜K˜—š œžœžœ žœžœžœžœ žœžœžœžœžœ ˜{Kšžœžœžœ˜šžœžœž˜šœ˜Kšœžœžœ˜KšœF˜FKšœžœ-˜4Kšœ˜Kšžœ:˜@Kšœ=˜=Kšœ žœžœžœ˜:Kšœ˜Kšœ>˜>šžœ žœ˜Kšœ ˜ Kšœžœ˜Kšœ˜—K˜—Kšžœž˜—Kšœ˜K˜—š  œžœžœžœžœ ˜KKšœžœ ˜K˜š  œžœžœžœ ˜QKšœžœ˜-Kšœ™KšœJ™JšžœžœΟc˜0Kšœ˜šžœ9žœž˜Hšœžœžœžœ˜:Kšœ˜—Kšžœ˜—Kšœ#˜#Kšœ˜—Kšžœ*‘ ˜;Kšœ%‘#˜HKšœ"˜"Kšœ˜—K˜KšœF˜FKšœ˜—K˜š  œžœžœžœžœ ˜LKšœžœ ˜K˜š  œžœžœžœ ˜QKšœžœ˜-Kšœ™KšœJ™Jšžœžœ‘˜0Kšœ˜šžœ9žœž˜Hšœžœžœžœ˜:Kšœ˜—Kšžœ˜—Kšœ#˜#Kšœ˜—Kšžœ*‘ ˜;šžœž˜Kšœ)žœ˜.šœ)˜)KšœP˜PKšœ˜—šœ-˜-KšœP˜PKšœU˜UK˜—šœ*˜*KšœU˜UK˜—Kšžœžœ˜—Kšœ%‘#˜HKšœ"˜"Kšœ˜—K˜KšœF˜FKšœ˜—K˜š Πbnœžœžœ žœžœ˜9Kšœžœ(˜2Kšœ˜K˜—š  œžœžœ žœ žœ˜8Kšœžœ˜%Kšœ%˜%Kšžœžœ˜8Kšœ˜—K˜š’œžœ˜Kšœžœ˜%Kšžœ˜Kšœ˜Kšœ˜Kšžœ˜Kšžœžœžœ˜KKšœ˜—K˜š’œžœ˜Kš œžœ žœžœžœ˜5Kšœžœžœ˜-Kšœžœ ˜Kšœ˜Kšœ˜Kšœžœ ˜Kšœ˜Kšœ<˜Kš žœ žœ žœ žœ žœ žœ ˜LKšœ˜—K˜š   œžœžœžœžœžœ˜\šžœžœžœ˜Kšœ˜Kšœžœ ˜Kšžœ žœžœ˜-Kšœžœ žœ8˜cKšœ˜Kšœ˜Kšœ:˜:KšœF˜FKšœ)˜)Kšœ˜Kšœ˜Kšœ(˜(Kšœ˜Kšœ˜K˜—Kšœ˜—K˜š  œžœ žœžœžœ˜OKšœ9˜9Kšžœ˜Kšœ˜—K˜Kšœžœžœ˜Kšœ#˜#šžœžœžœ˜šžœž˜Kšžœžœžœ˜šœ ˜ Kšœ˜Kšžœžœžœ‘ ˜CK˜—Kšœžœ˜ Kšžœ3˜:—šžœžœžœ˜Kšœžœ˜Kšœ!˜!K˜—K˜—šžœžœžœ‘ ˜Kšœ"˜"Kšœ%˜%Kšœ*˜*Kšœ˜Kšœ1˜1Kšž˜K˜—Kšœ˜—K˜š œžœ žœ žœžœžœ žœ ˜jKšœ$˜$Kšžœžœžœ*˜˜>Kšžœ˜K˜™ K™*—K™—…—5ΠL†