DIRECTORY CharDisplays, DisplayControllers, DisplayControllerSteps, FS, Rope, TermProgs; EmVT100: CEDAR PROGRAM IMPORTS DisplayControllers, DisplayControllerSteps, FS, TermProgs = BEGIN OPEN DisplayControllers, DisplayControllerSteps, TermProgs; tipName: ROPE ~ FS.ExpandName["VT100.tip"].fullFName; CurrentCursor: TYPE = REF CurrentCursorRec; CurrentCursorRec: TYPE = RECORD [line: INT, column: INT]; cursor: CurrentCursor ¬ NIL; attributes: TYPE = {bold, uScore, blink, neg}; Attribute: TYPE = ARRAY attributes OF BOOL ¬ ALL[FALSE]; att, storedAtts: Attribute; vt52Mode: BOOL ¬ FALSE; MakeVT100: PROC RETURNS [t: Term] = { cursor ¬ NEW[CurrentCursorRec]; t ¬ NEW [TermRep ¬ [cp: NewControlProgram[], tipTableName: tipName]]; AddInstruction[t.cp, LIST["\000"], [Naught]]; AddInstruction[t.cp, LIST["\007"], [Beep]]; AddInstruction[t.cp, LIST["\010"], [SkipCursor, $left]]; AddInstruction[t.cp, LIST["\011"], [Tab, $dontTouch]]; AddInstruction[t.cp, LIST["\012"], [SkipCursor, $down]]; AddInstruction[t.cp, LIST["\015"], [CarriageReturn]]; AddInstruction[t.cp, LIST["\033[H"], [Home]]; AddInstruction[t.cp, LIST["\033f"], [Home]]; AddInstruction[t.cp, LIST["\033[f"], [Home]]; AddInstruction[t.cp, LIST["\033[A"], [SkipCursor, $up]]; AddInstruction[t.cp, LIST["\033A"], [Vt52CU]]; AddInstruction[t.cp, LIST["\033[B"], [SkipCursor, $down]]; AddInstruction[t.cp, LIST["\033B"], [Vt52CD]]; AddInstruction[t.cp, LIST["\033[C"], [SkipCursor, $right]]; AddInstruction[t.cp, LIST["\033C"], [Vt52CR]]; AddInstruction[t.cp, LIST["\033[D"], [SkipCursor, $left]]; AddInstruction[t.cp, LIST["\033D"], [Vt52CL]]; AddInstruction[t.cp, LIST["\033H"], [Vt52CH]]; AddInstruction[t.cp, LIST["\033I"], [Vt52RLF]]; AddInstruction[t.cp, LIST["\033[J"], [ClrTo, $eos]]; AddInstruction[t.cp, LIST["\033J"], [Vt52EOS]]; AddInstruction[t.cp, LIST["\033[K"], [ClrTo, $eol]]; AddInstruction[t.cp, LIST["\033K"], [Vt52EOL]]; AddInstruction[t.cp, LIST["\0337"], [SaveAll]]; AddInstruction[t.cp, LIST["\0338"], [RestoreAll]]; AddInstruction[t.cp, LIST["\033[m"], [AttsOff]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line]], "J"], [JDecode]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line]], "K"], [KDecode]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line]], "m"], [Att1Decode]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line]], ";", NEW [DecodeRep ¬ [reg: col]], "m"], [Att2Decode]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line]], ";", NEW [DecodeRep ¬ [reg: col]], ";", NEW [DecodeRep ¬ [reg: aux1]], ";", "m"], [Att3Decode]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line]], ";", NEW [DecodeRep ¬ [reg: col]], ";", NEW [DecodeRep ¬ [reg: aux1]], ";", NEW [DecodeRep ¬ [reg: aux2]], ";", "m"], [Att4Decode]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line]], ";", NEW [DecodeRep ¬ [reg: col]], ";", NEW [DecodeRep ¬ [reg: aux1]], ";", NEW [DecodeRep ¬ [reg: aux2]], ";", NEW [DecodeRep ¬ [reg: aux3]], ";", "m"], [Att5Decode]]; AddInstruction[t.cp,LIST["\033[", NEW [DecodeRep ¬ [reg: line]], ";", NEW [DecodeRep ¬ [reg: col]], "H"], [NormCursor]]; AddInstruction[t.cp, LIST["\033Y", NEW [DecodeRep ¬ [reg: line, base: NumChars, org: ' , len: 1]], NEW [DecodeRep ¬ [reg: col, base: NumChars, org: ' , len: 1]]], [Vt52CA]]; AddInstruction[t.cp,LIST["\033[", NEW [DecodeRep ¬ [reg: line]], ";", NEW [DecodeRep ¬ [reg: col]], "f"], [NormCursor]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line]], "A"], [JumpCursor, $v]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line]], "B"], [JumpCursor, $v]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line]], "C"], [CursorHn]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line]], "D"], [CursorHn]]; -- *** NoOp Traps *** -- -- Programmable LEDs AddInstruction[t.cp, LIST["\033[q"], [Naught]]; -- Line Size AddInstruction[t.cp, LIST["\033#", NEW [DecodeRep ¬ [reg: line, len: 1]]], [Naught]]; -- Indexing AddInstruction[t.cp, LIST["\033D"], [Naught]]; AddInstruction[t.cp, LIST["\033E"], [Naught]]; AddInstruction[t.cp, LIST["\033M"], [Naught]]; -- Alternate Characters/Keys AddInstruction[t.cp, LIST["\033F"], [Naught]]; AddInstruction[t.cp, LIST["\033G"], [Naught]]; AddInstruction[t.cp, LIST["\033>"], [Naught]]; AddInstruction[t.cp, LIST["\033<"], [Naught]]; AddInstruction[t.cp, LIST["\033="], [Naught]]; AddInstruction[t.cp, LIST["\033(A"], [Naught]]; AddInstruction[t.cp, LIST["\033(B"], [Naught]]; AddInstruction[t.cp, LIST["\033(", NEW [DecodeRep ¬ [reg: line, len: 1]]], [Naught]]; AddInstruction[t.cp, LIST["\033)A"], [Naught]]; AddInstruction[t.cp, LIST["\033)B"], [Naught]]; AddInstruction[t.cp, LIST["\033)", NEW [DecodeRep ¬ [reg: line, len: 1]]], [Naught]]; -- Scrolling Region AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line]], ";", NEW [DecodeRep ¬ [reg: col]], "r"], [Naught]]; -- Tabbing AddInstruction[t.cp, LIST["\033H"], [Naught]]; AddInstruction[t.cp, LIST["\033[g"], [Naught]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line, len: 1]], "g"], [Naught]]; -- Status Report AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line, len: 1]], "n"], [Naught]]; -- Interrogation AddInstruction[t.cp, LIST["\033c"], [Naught]]; AddInstruction[t.cp, LIST["\033Z"], [Naught]]; AddInstruction[t.cp, LIST["\033[c"], [Naught]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line, len: 1]], "c"], [Naught]]; AddInstruction[t.cp, LIST["\033[?l", NEW [DecodeRep ¬ [reg: line, len: 1]], "c"], [Naught]]; -- Tests AddInstruction[t.cp, LIST["\033[2", NEW [DecodeRep ¬ [reg: line, len: 1]], "y"], [Naught]]; -- Modes AddInstruction[t.cp, LIST["\033[?", NEW [DecodeRep ¬ [reg: line, len: 1]], "h"], [hDecode]]; AddInstruction[t.cp, LIST["\033[?", NEW [DecodeRep ¬ [reg: line, len: 1]], "l"], [lDecode]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line, len: 2]], "h"], [Naught]]; AddInstruction[t.cp, LIST["\033[", NEW [DecodeRep ¬ [reg: line, len: 2]], "l"], [Naught]]; }; NormCursor: ActionProc = { dc.cps.regs[line] ¬ dc.cps.regs[line]-1; dc.cps.regs[col] ¬ dc.cps.regs[col]-1; JumpCursor[dc, $hv]; }; Att1Decode: ActionProc = { SELECT dc.cps.regs[line] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; }; Att2Decode: ActionProc = { SELECT dc.cps.regs[line] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; SELECT dc.cps.regs[col] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; }; Att3Decode: ActionProc = { SELECT dc.cps.regs[line] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; SELECT dc.cps.regs[col] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; SELECT dc.cps.regs[aux1] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; }; Att4Decode: ActionProc = { SELECT dc.cps.regs[line] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; SELECT dc.cps.regs[col] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; SELECT dc.cps.regs[aux1] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; SELECT dc.cps.regs[aux2] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; }; Att5Decode: ActionProc = { SELECT dc.cps.regs[line] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; SELECT dc.cps.regs[col] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; SELECT dc.cps.regs[aux1] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; SELECT dc.cps.regs[aux2] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; SELECT dc.cps.regs[aux3] FROM 0 => { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; FOR a: attributes IN [bold..neg] DO att[a] ¬ FALSE ENDLOOP; }; 1 => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; 4 => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; 5 => {--no-op-- att[blink] ¬ TRUE}; 7 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; }; SaveAll: ActionProc = { cursor.line ¬ dc.cps.regs[line]; cursor.column ¬ dc.cps.regs[col]; FOR a: attributes IN [bold..neg] DO storedAtts[a] ¬ att[a] ENDLOOP; }; RestoreAll: ActionProc = { dc.cd.class.CursorMove[dc.cd, cursor.line, cursor.column, FALSE, TRUE, TRUE]; FOR a: attributes IN [bold..neg] DO SELECT TRUE FROM storedAtts[bold] => {SetEmph[dc, $boldOn]; att[bold] ¬ TRUE}; storedAtts[uScore] => {SetEmph[dc, $underlineOn]; att[uScore] ¬ TRUE}; storedAtts[blink] => {--no-op-- att[blink] ¬ TRUE}; storedAtts[neg] => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; ENDCASE; ENDLOOP; }; CursorHn: ActionProc = { dc.cps.regs[col] ¬ dc.cps.regs[line]; JumpCursor[dc, $h]; }; JDecode: ActionProc = { SELECT dc.cps.regs[line] FROM 0 => {ClrTo[dc, $eos]}; 1 => { --clear from Home to cursor-- }; 2 => {ClearScreen[dc, clientData]}; ENDCASE; }; KDecode: ActionProc = { SELECT dc.cps.regs[line] FROM 0 => {ClrTo[dc, $eol]}; 1 => { --clear from line start to cursor-- }; 2 => {Line[dc, $del]}; ENDCASE; }; hDecode: ActionProc = { SELECT dc.cps.regs[line] FROM 1 => { --cursor off-- }; 2 => {vt52Mode ¬ FALSE}; 3 => {--132 col--}; 4 => {--smooth scroll--}; 5 => {SetEmph[dc, $inverseOn]; att[neg] ¬ TRUE}; 6 => {--no-op--}; 7 => {--line-wrap--}; 8 => {--auto repeat--}; 9 => {--no-op--}; ENDCASE; }; lDecode: ActionProc = { SELECT dc.cps.regs[line] FROM 1 => { --cursor on-- }; 2 => {vt52Mode ¬ TRUE}; 3 => {-- 80 col--}; 4 => {--jump scroll--}; 5 => {SetEmph[dc, $inverseOff]; att[neg] ¬ FALSE}; 6 => {--no-op--}; 7 => {--line-wrap off--}; 8 => {--auto repeat off--}; 9 => {--no-op--}; ENDCASE; }; AttsOff: ActionProc = { SetEmph[dc, $boldOff]; SetEmph[dc, $underlineOff]; SetEmph[dc, $inverseOff]; }; Vt52CU: ActionProc = {IF vt52Mode THEN SkipCursor[dc, $up]}; Vt52CD: ActionProc = {IF vt52Mode THEN SkipCursor[dc, $down]}; Vt52CR: ActionProc = {IF vt52Mode THEN SkipCursor[dc, $right]}; Vt52CL: ActionProc = {IF vt52Mode THEN SkipCursor[dc, $left]}; Vt52CH: ActionProc = {IF vt52Mode THEN Home[dc, clientData]}; Vt52RLF: ActionProc = {IF vt52Mode THEN ScrollBack[dc, clientData]}; Vt52EOS: ActionProc = {IF vt52Mode THEN ClrTo[dc, $eos]}; Vt52EOL: ActionProc = {IF vt52Mode THEN ClrTo[dc, $eol]}; Vt52CA: ActionProc = {IF vt52Mode THEN JumpCursor[dc, $hv]}; RegTerm["vt100", MakeVT100[]]; END... 4 EMVT100.mesa Copyright Σ 1992 by Xerox Corporation. All rights reserved. Last Edited by: Neil Gunther, November 1, 1985 2:58:57 pm PST Last tweaked by Mike Spreitzer on July 25, 1988 6:18:03 pm PDT Spreitzer, February 19, 1986 8:51:31 pm PST Emulates a VT100. --to ranges of line[0..23] & col[0..79] Κ•NewlineDelimiter –(cedarcode) style™™ Jšœ Οeœ1™K™+—K˜KšΟk œ;žœ˜XK˜K™K˜šΠbxœžœž˜Kšžœ-žœž˜IK˜Kšžœ7˜;K˜Kšœ žœžœ#˜5K˜Kšœžœžœ˜+Kš œžœžœžœ žœ˜9šœžœ˜K˜—Kšœ žœ˜.Kš œ žœžœ žœžœžœžœ˜8Kšœ˜Kšœ žœžœ˜Kšœ˜šΟn œžœžœ˜%Kšœ žœ˜Kšœžœ>˜EKšœžœ˜-Kšœžœ˜+Kšœžœ˜8Kšœžœ˜6Kšœžœ˜8Kšœžœ˜5Kšœžœ˜-Kšœžœ˜,Kšœžœ˜-Kšœžœ˜8Kšœžœ˜.Kšœžœ!˜:Kšœžœ˜.Kšœžœ#˜Kšœ@žœ˜GKšœ€œžœ˜4Kšœ8žœ˜?—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šœ*žœ˜0K˜K˜K˜K˜—Kšžœ˜Kšœ˜K˜—šœ˜šžœžœ˜K˜Kšœžœ˜K˜K˜Kšœ+žœ˜2K˜K˜K˜K˜—Kšžœ˜Kšœ˜K˜—šœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—Kšœžœ žœ˜Kšœžœ žœ˜?Kšœžœ žœ˜>Kšœžœ žœ˜=Kšœžœ žœ˜DKšœžœ žœ˜9Kšœžœ žœ˜9šœžœ žœ˜