DIRECTORY Keys USING [KeyBits], PrincOps USING [BBTable]; Terminal: CEDAR DEFINITIONS LOCKS terminalLock = BEGIN terminalLock: PRIVATE MONITORLOCK; Virtual: TYPE = REF Object; Object: TYPE = RECORD [ keyboard: PRIVATE LONG POINTER TO READONLY Keys.KeyBits, mouse: PRIVATE LONG POINTER TO READONLY Position, hasBlackAndWhiteDisplay: --READONLY-- BOOL, bwWidth: --READONLY-- NAT, bwHeight: --READONLY-- NAT, bwHasBorder: --READONLY-- BOOL, bwPixelsPerInch: --READONLY-- NAT, bwCursor: PRIVATE LONG POINTER TO Position, hasColorDisplay: --READONLY-- BOOL, colorWidth: --READONLY-- NAT, colorHeight: --READONLY-- NAT, colorPixelsPerInch: --READONLY-- NAT, colorDisplayType: --READONLY-- ColorDisplayType, colorMode: PRIVATE ColorMode, colorBitmapA: --READONLY-- LONG POINTER, -- channel A bitmap base colorBitmapB: --READONLY-- LONG POINTER, -- channel B bitmap base colorWordsPerLineA: --READONLY-- NAT, -- channel A bitmap width colorWordsPerLineB: --READONLY-- NAT, -- channel B bitmap width impl: PRIVATE REF ANY ]; SwapAction: TYPE = {coming, here, going, gone}; SwapNotifier: TYPE = PROC [Virtual, SwapAction]; Position: TYPE = MACHINE DEPENDENT RECORD [x, y: INTEGER]; BitmapState: TYPE = {none, allocated, displayed}; BWBackground: TYPE = {white, black}; BWBorder: TYPE = [0..256); BWCursorBitmap: TYPE = ARRAY [0..16) OF WORD; ColorDisplayType: TYPE = {ramtek525, hitachi3619}; ChannelValue: TYPE = [0..256); maxBitsPerChannelValue: NAT = --Log2 ChannelValue.LAST+1-- 8; ColorMode: TYPE = RECORD [ full: BOOL, bitsPerPixelChannelA: [0..maxBitsPerChannelValue], bitsPerPixelChannelB: [0..maxBitsPerChannelValue] ]; ChannelsVisible: TYPE = {none, aOnly, bOnly, all}; Color: TYPE = [0..256); bitsPerColorValue: NAT = --Log2 Color.LAST+1-- 8; ColorCursorBitmap: TYPE = ARRAY [0..16) OF WORD; ColorCursorPresentation: TYPE = {onesAreWhite, onesAreBlack}; ColorCursorBitmapState: TYPE = {visible, invisible}; Create: PROC RETURNS [vt: Virtual]; Select: PROC [vt: Virtual _ NIL, lock: BOOL _ FALSE] RETURNS [worked: BOOL]; Current: PROC RETURNS [vt: Virtual, lockCount: NAT]; PreventSwaps: PROC [vt: Virtual]; PermitSwaps: PROC [vt: Virtual]; RegisterNotifier: PROC [vt: Virtual, notifier: SwapNotifier]; UnregisterNotifier: PROC [vt: Virtual, notifier: SwapNotifier]; GetKeys: ENTRY PROC [vt: Virtual] RETURNS [Keys.KeyBits] = TRUSTED INLINE {RETURN[vt.keyboard^]}; GetKeysRef: ENTRY PROC [vt: Virtual, keys: REF Keys.KeyBits] = TRUSTED INLINE {keys^ _ vt.keyboard^}; GetMousePosition: ENTRY PROC [vt: Virtual] RETURNS [Position] = TRUSTED INLINE {RETURN[vt.mouse^]}; SetMousePosition: PROC [vt: Virtual, position: Position]; GetBWCursorPosition: ENTRY PROC [vt: Virtual] RETURNS [Position] = TRUSTED INLINE {RETURN[vt.bwCursor^]}; SetBWCursorPosition: ENTRY PROC [vt: Virtual, position: Position] = TRUSTED INLINE {vt.bwCursor^ _ position}; GetBWCursorPattern: PROC [vt: Virtual] RETURNS [pattern: BWCursorBitmap]; SetBWCursorPattern: PROC [vt: Virtual, pattern: BWCursorBitmap]; GetBWBitmapState: PROC [vt: Virtual] RETURNS [BitmapState]; SetBWBitmapState: PROC [vt: Virtual, new: BitmapState] RETURNS [old: BitmapState]; GetBWBackground: PROC [vt: Virtual] RETURNS [BWBackground]; SetBWBackground: PROC [vt: Virtual, new: BWBackground] RETURNS [old: BWBackground]; GetBWBorder: PROC [vt: Virtual] RETURNS [oddPairs, evenPairs: BWBorder]; SetBWBorder: PROC [vt: Virtual, oddPairs, evenPairs: BWBorder]; GetBitBltTable: UNSAFE PROC [vt: Virtual] RETURNS [bbt: PrincOps.BBTable]; WaitForBWVerticalRetrace: PROC [vt: Virtual]; BlinkBWDisplay: PROC [vt: Virtual]; GetColorBitmapState: PROC [vt: Virtual] RETURNS [BitmapState]; SetColorBitmapState: PROC [ vt: Virtual, newState: BitmapState, newMode: ColorMode, newVisibility: ChannelsVisible] RETURNS [oldState: BitmapState, oldMode: ColorMode, oldVisibility: ChannelsVisible]; GetColorMode: ENTRY PROC [vt: Virtual] RETURNS [ColorMode] = TRUSTED INLINE {RETURN[vt.colorMode]}; SetColorMode: PROC [vt: Virtual, new: ColorMode] RETURNS [old: ColorMode] = INLINE {RETURN[SetColorBitmapState[vt, allocated, new, all].oldMode]}; LegalColorMode: PROC [vt: Virtual, mode: ColorMode] RETURNS [BOOL]; TurnOnColorDisplay: PROC [vt: Virtual] = INLINE {[] _ SetColorBitmapState[vt, displayed, GetColorMode[vt], all]}; TurnOffColorDisplay: PROC [vt: Virtual] = INLINE {[] _ SetColorBitmapState[vt, allocated, GetColorMode[vt], none]}; GetVisibility: PROC [vt: Virtual] RETURNS [ChannelsVisible]; SetVisibility: PROC [vt: Virtual, visibility: ChannelsVisible] = INLINE {[] _ SetColorBitmapState[vt, GetColorBitmapState[vt], GetColorMode[vt], visibility]}; GetRedMap: PROC [vt: Virtual, in: Color] RETURNS [Color]; GetGreenMap: PROC [vt: Virtual, in: Color] RETURNS [Color]; GetBlueMap: PROC [vt: Virtual, in: Color] RETURNS [Color]; SetRedMap: PROC [vt: Virtual, in: Color, out: Color]; SetGreenMap: PROC [vt: Virtual, in: Color, out: Color]; SetBlueMap: PROC [vt: Virtual, in: Color, out: Color]; GetColor: PROC [vt: Virtual, aChannelValue, bChannelValue: ChannelValue _ 0] RETURNS [red, green, blue: Color]; SetColor: PROC [ vt: Virtual, aChannelValue, bChannelValue: ChannelValue _ 0, red, green, blue: Color]; GetColorCursorPosition: PROC [vt: Virtual] RETURNS [Position]; SetColorCursorPosition: PROC [vt: Virtual, position: Position]; GetColorCursorPattern: PROC [vt: Virtual] RETURNS [pattern: ColorCursorBitmap]; SetColorCursorPattern: PROC [vt: Virtual, pattern: ColorCursorBitmap]; GetColorCursorPresentation: PROC [vt: Virtual] RETURNS [ColorCursorPresentation]; SetColorCursorPresentation: PROC [vt: Virtual, new: ColorCursorPresentation] RETURNS [old: ColorCursorPresentation]; GetColorCursorState: PROC [vt: Virtual] RETURNS [ColorCursorBitmapState]; SetColorCursorState: PROC [vt: Virtual, new: ColorCursorBitmapState] RETURNS [old: ColorCursorBitmapState]; CantDoIt: ERROR; END. >ˆTerminal.mesa last edited by: Levin on: June 30, 1983 3:49 pm Types characteristics of the keyboard and mouse characteristics of the black-and-white display (if any) characteristics of the color display (if any) The following may change whenever the colorMode changes and are not valid if the color bitmap state is "none". implementation data This state applies to both black-and-white and color display bitmaps. Note: This type is presently defined in such a way that it is type-compatible with BWCursorBitmap. This is because the client is expected to treat the black-and-white and color cursors as a single logical entity, which moves between screens without being transformed. However, since the color cursor is implemented in software, it is not limited to a 16x16 bit array, as the black-and-white cursor is. We are willing to risk an interface change to make the two cursors different, since such a change will have more serious ramifications for the client than for us. Virtual Terminal Creation/Selection This interface provides a facility for multiplexing virtual terminals on a single physical terminal. The interface is designed for an arbitrary number of virtual terminals and is intended to be used to support debugging of new versions of terminal-handling code. This multiplexing facility has the following primary features: 1) The human user at the keyboard can cycle through the extant virtual terminals by a particular key combination (control-shift-shift). (This is equivalent to an implicit call of Select[NIL]; see below.) 2) A client program can select which virtual terminal is to be connected to the physical terminal, and can prevent a change of virtual terminal by clients or the user. 3) Clients may register procedures to be invoked whenever the virtual-to-physical terminal correspondance changes. The implementation initially supplies a single virtual terminal, available through Current. This procedure creates a new virtual terminal. If the hardware includes a black-and-white display, vt.hasBlackAndWhiteDisplay is TRUE and the border, screen dimensions, and resolution values are set to the characteristics of the hardware. Analogous remarks apply to the color display information in vt. The initial state of this terminal, in terms of the procedures below, is: GetKeys[vt] = ALL[up] GetMousePosition[vt] = [0,0] GetBWCursorPosition[vt] = [0,0] GetBWCursorPattern[vt] = ALL[0] GetBWBitmapState[vt] = none GetBWBackground[vt] = white Errors: CantDoIt is raised if insufficient virtual memory exists to create the virtual terminal. This procedure causes the indicated virtual terminal to be "connected" to the physical terminal; that is, its keyboard, mouse display(s) and cursor(s) interact directly with the hardware. If "lock" is TRUE, Select executes an implicit PreventSwaps (see below) after connecting the requested virtual terminal to the physical terminal. If the lock count (see PreventSwaps, below) is positive, Select has no effect (and "lock" is ignored). In this case, the return value is FALSE; otherwise, it is TRUE. (Note: if vt = NIL, the "next" virtual terminal, in an unspecified order, is selected. Thus, repeated calls of Select[NIL] cause each virtual terminal to be connected in succession.) Errors: It is illegal to invoke Select from a SwapNotifier procedure. This procedure returns the identity of the presently selected virtual terminal (lockCount is described under PreventSwaps, below). Errors: It is illegal to invoke Current from a SwapNotifier procedure. If the specified virtual terminal is not presently selected, PreventSwaps waits until it becomes selected. It then increments a global "lock count" which may be interrogated by Current. When this count is positive, Select and control-shift-shift are disabled (i.e., have no effect). Errors: It is illegal to invoke PreventSwaps from a SwapNotifier procedure. This procedure decrements the global lock count that may be interrogated by Current. If the specified virtual terminal is not presently selected or if PermitSwaps is called when the lock count is zero, it has no effect. This procedure registers a client procedure with the specified virtual terminal. The registered procedure will be invoked whenever a swap of virtual terminals occurs. When a terminal swap occurs, the following client-visible steps occur: 1) Notifiers for current terminal are called with SwapAction[going]. 2) Notifiers for the new terminal are called with SwapAction[coming]. 3) The actual terminal swap occurs. 4) Notifiers for the former current terminal are called with SwapAction[gone]. 5) Notifiers for the new current terminal are called with SwapAction[here]. The SwapNotifiers are invoked in the order of their registration in steps 2 and 5, and in the reverse order of their registration in steps 1 and 4. Unless otherwise noted, all the procedures in this interface may be invoked from a SwapNotifier. Errors: It is illegal to invoke RegisterNotifier from a SwapNotifier procedure. The specified SwapNotifier is disassociated from the specified virtual terminal. If it is not presently registered, UnregisterNotifier has no effect. Errors: It is illegal to invoke UnregisterNotifier from a SwapNotifier procedure. Access to keys (keyboard, mouse buttons, ... ) If the specified virtual terminal is presently selected (see Select, above), GetKeys returns the state of the actual hardware keys. If the terminal is not presently selected, GetKeys returns the state of the hardware at the time the terminal was most recently selected (or, if it has never been selected, the initial state as defined by Create, above). This procedure is functionally identical to GetKeys, but somewhat more efficient. Mouse If the specified virtual terminal is presently selected (see Select, above), GetMousePosition returns the position of the actual hardware mouse. If the terminal is not presently selected, GetMousePosition returns the position of the mouse at the time the terminal was most recently selected (or, if it has never been selected, the initial state as defined by Create, above). SetMousePosition redefines the present mouse position. Subsequent mouse motion (while the specified virtual terminal is selected) will be computed relative to this position. Black-and-White Cursor All of the procedures in this section are valid only if vt.hasBlackAndWhiteDisplay is TRUE. GetBWCursorPosition returns the position of the virtual cursor associated with the black-and-white display on the specified virtual terminal. This position changes only as a result of calls on SetBWCursorPosition. SetBWCursorPosition sets the cursor position of the specified virtual terminal to the indicated value. This position will be reflected on the screen when the virtual terminal is next selected (or, if it is presently selected, immediately). It is the responsibility of the client to clip the position, if desired, to ensure that the cursor remains on the visible area of the display. GetBWCursorPattern returns the bitmap of the virtual cursor associated with the black-and-white display on the specified virtual terminal. This bitmap changes only as a result of calls on SetBWCursorPattern. SetBWCursorPattern sets the cursor bitmap of the specified virtual terminal to the indicated value. This bitmap will be reflected on the screen when the virtual terminal is next selected (or, if it is presently selected, immediately). Black-and-White Display All of the procedures in this section are valid only if vt.hasBlackAndWhiteDisplay is TRUE. These procedures manage the virtual memory used for the black-and-white display's bitmap. These manipulations occur whether or not the virtual terminal is presently selected, but their effect, if any, on the display can only be observed when the terminal is selected. BitmapState[none] means that the display has no associated bitmap; if the virtual terminal is selected, the appearance of black-and-white screen is determined by the background value (see GetBWBackground and SetBWBackground below). BitmapState[allocated] means that virtual memory has been allocated for the display's bitmap, but is not presently associated with the screen. That is, even if the virtual terminal is selected, the contents of the bitmap will not be displayed. They may, however, be manipulated via GetBitBltTable and PrincOpsUtils.BITBLT. BitmapState[displayed] means that, when the specified virtual terminal is selected, its associated bitmap will appear on the black-and-white display. The background and border values (see below) will affect the appearance of the bitmap. If GetBWBitmapState[vt] = BitmapState[none] and SetBWBitmapState[vt, allocated] is called and there is insufficient virtual memory to allocate a bitmap, the error CantDoIt is raised. These procedures control the interpretation of bits in the black-and-white display's bitmap. (For the purposes of these procedures, a non-existent bitmap is equivalent to a bitmap containing all zeros.) BWBackground[white] causes zeros in the bitmap to appear white and ones to appear black. BWBackground[black] causes zeros in the bitmap to appear black and ones to appear white. These procedures may be invoked whether or not the virtual terminal is presently selected, but their effect, if any, on the display can only be observed when the terminal is selected. These procedures control the appearance of the region of the black-and-white display that is not occupied by the bitmap. These procedures may be invoked whether or not the virtual terminal is presently selected, but their effect, if any, on the display can only be observed when the terminal is selected. This procedure returns a BITBLT table for the black-and-white display bitmap of the specified virtual terminal. This table is properly aligned for use with PrincOpsUtils.BITBLT. Its contents are as follows: PrincOps.BBTable[ dst: IF GetBWBitmapState[vt] = none THEN NIL ELSE base of bitmap dstBpl: an appropriate width (at least vt.bwWidth) src: IF GetBWBitmapState[vt] = none THEN NIL ELSE base of bitmap srcDesc: [srcBpl[an appropriate width (at least vt.bwWidth)]] width: vt.bwWidth, height: vt.bwHeight, flags: [ direction: forward, disjoint: FALSE, disjointItems: FALSE, gray: FALSE, srcFunc: null, dstFunc: null ] ] If the specified virtual terminal is not presently selected, WaitForVerticalRetrace waits until the terminal becomes selected. It then waits until the next back-and-white display scan begins and returns. This procedure blinks the black-and-white display if the specified virtual terminal is presently selected. Otherwise, it has no effect. Color Display All of the procedures in this section are valid only if vt.hasColorDisplay is TRUE. These procedures manage the virtual memory used for the color display's bitmap and colormap. These manipulations occur whether or not the virtual terminal is presently selected, but their effect, if any, on the display can only be observed when the terminal is selected. BitmapState[none] means that the display has no associated bitmap; if the virtual terminal is selected, the color screen will appear black. BitmapState[allocated] means that virtual memory has been allocated for the display's bitmap and colormap, but is not presently associated with the screen. That is, even if the virtual terminal is selected, the contents of the bitmap will not be displayed. They may be (indeed, they are expected to be) manipulated by software through the appropriate bitmap pointers in "vt". Several arrangements of storage for the bitmap and colormap are supported; the "newMode" parameter specifies the way in which the display will be used. BitmapState[displayed] means that, when the specified virtual terminal is selected, its associated bitmap will appear on the color display. If newState = none, the mode and visibility settings are remembered (and can be accessed by GetColorMode and GetVisibility, respectively). Note that there is there is no formal distinction between and . However, these two situtions have different performance characteristics. When newMode = displayed, the bitmap and colormap are pinned in memory; that is, the real memory they occupy cannot be stolen by the virtual memory machinery. In other modes, the bitmap and colormap (if any) can be swapped out. Therefore, should be used only for short-term disabling of the display, since the bitmap and colormap remained pinned. If SetColorBitmapState is invoked with newMode equal to the previous ColorMode, the previously allocated bitmap and colormap (if any) is undisturbed. Invoking SetColorBitmapState with newMode such that ~LegalColorMode[vt, newMode] raises CantDoIt. This procedure returns TRUE if the color display implements the indicated mode. These procedures manipulate the visibility of the bitmaps accessed on the color channels. The effect of SetVisibility can be seen only when vt is selected and GetColorBitmapState[vt] = displayed, but it can be invoked in any state. These procedures are defined only if GetColorBitmapState[vt] ~= none and GetColorMode[vt].full is TRUE. They support gamma correction. These procedures are defined only if GetColorBitmapState[vt] ~= none and GetColorMode[vt].full is FALSE. They permit inspection and manipulation of the colormap. Color Cursor All of the procedures in this section are valid only if vt.hasColorDisplay is TRUE. GetColorCursorPosition returns the position of the virtual cursor associated with the color display on the specified virtual terminal. This position changes only as a result of calls on SetColorCursorPosition. SetColorCursorPosition sets the cursor position of the specified virtual terminal to the indicated value. This position will be reflected on the screen when the virtual terminal is next selected (or, if it is presently selected, immediately). It is the responsibility of the client to clip the position, if desired, to ensure that the cursor remains on the visible area of the display. GetColorCursorPattern returns the bitmap of the virtual cursor associated with the color display on the specified virtual terminal. This bitmap changes only as a result of calls on SetColorCursorPattern and/or SetColorCursorPresentation. SetColorCursorPattern sets the cursor bitmap of the specified virtual terminal to the indicated value. This bitmap will be reflected on the screen when the virtual terminal is next selected (or, if it is presently selected, immediately). These procedures control the manner in which the cursor bitmap is presented on the color display. "onesAreWhite" means a one-bit in the ColorCursorBitmap is mapped to a color value of all ones (conventionally white) and a zero-bit is mapped to a color value of all zeros (conventionally black). "onesAreBlack" reverses this interpretation. These procedures control the visibility of the cursor bitmap on the color display. When the state is "visible", the cursor bitmap (supplied by SetColorCursorPattern and influenced by SetColorCursorPresentation) is displayed at the position determined by SetColorCursorPosition. When the state is "invisible", no cursor appears on the color display. In the "visible" state, the cursor is merged into the color display bitmap by software, which caches the contents of the display bitmap that lie "under" the cursor. If the cursor moves (as a result of SetColorCursorPosition), the display bitmap is restored to the cached value. The procedures used to modify the display bitmap do not check to see if this cache should be invalidated. Therefore, if the client wants to change the display bitmap under the cursor, it must first flush the cache by setting the cursor state to "invisible". The effect of these procedures can only be observed when vt is selected and GetColorBitmapState[vt] = displayed. Errors Ê x˜Jšœ ™ Jšœ/™/J˜šÏk ˜ Jšœœ ˜Jšœ œ ˜J˜—Jšœ œ œœ˜0J˜Jš˜˜Jšœœ œ˜"—J™Jšœ™˜Jšœ œœ˜šœœœ˜šœ)™)Jš œ œœœœœ˜8Jš œœœœœœ ˜1—šœ7™7JšœÏc œœ˜+Jšœ ž œœ˜Jšœ ž œœ˜Jšœ ž œœ˜Jšœž œœ˜"Jš œ œœœœ ˜+—šœ-™-Jšœž œœ˜#Jšœ ž œœ˜Jšœ ž œœ˜Jšœž œœ˜%Jšœž œ˜0Jšœ œ ˜Jšœo™oJšœž œœœž˜BJšœž œœœž˜BJšœž œœž˜@Jšœž œœž˜@—šœ™Jšœœœ˜—J˜J˜—Jšœ œ˜/Jšœœœ˜0J˜Jš œ œœ œœœ˜:J˜šœ œ ˜1JšœE™E—J˜Jšœœ˜$Jšœ œ ˜J˜Jš œœœ œœ˜-J˜Jšœœ˜2Jšœœ ˜JšœœžÐcdžœ˜=šœ œœ˜Jšœœ˜ Jšœ2˜2Jšœ1˜1Jšœ˜—Jšœœ˜2Jšœœ ˜JšœœžŸžœ˜1J˜š œœœ œœ˜0Jšœ¸™¸—Jšœœ ˜=Jšœœ˜4J˜—J™#™šœÇ™ÇJšœÌ™ÌJšœ§™§Jšœr™r—J™[J™šÏnœœœ˜#šœû™ûJ™J™J™J™J™J™—J™a—J˜š œœœœœœ œ˜LJšœÊœŒœœ»™±J™F—J˜š œœœœ˜4Jšœ‚™‚J™G—J˜š  œœ˜!Jšœœ™œJ™L—J˜š  œœ˜ JšœÜ™Ü—J˜š œœ'˜=šœï™ïJšœE™EJšœF™FJ™$JšœO™OJšœL™L—Jšœ“™“J™`J™P—J˜š œœ'˜?Jšœ–™–J™R—J˜—Jšœ.™.˜š œœœœ˜:Jšœâ™âJšœœ˜&—J™š  œœœœ˜>JšœQ™QJšœ˜&—J˜—J™˜š œœœœ ˜?Jšœø™øJšœœ ˜#—J˜š œœ#˜9Jšœ®™®—J˜—Jšœ™™Jšœ[™[J˜š œœœœ ˜BJšœÖ™ÖJšœœœ˜&—J˜š œœœ$˜CJšœÿ™ÿJšœ˜)—J˜š œœœ˜IJšœÐ™Ð—J˜š œœ(˜@Jšœë™ë—J˜—Jšœ™˜Jšœ[™[J˜Jš œœœ˜;š œœ!œ˜RšœŒ™ŒJšœç™çJšœÄ™ÄJšœí™í—Jšœ¶™¶—J˜Jš œœœ˜;š œœ"œ˜SJšœ¸™¸—J˜Jš  œœœ!˜Hš  œœ.˜?Jšœ±™±—J˜š œ œœ˜JšœÐ™Ð™Jšž@™@J™2Jšœž;™@J™=J™J™™J™J™J™J™ J™J™ J™—J™———J˜š œœ˜-JšœÌ™Ì—J˜š œœ˜#Jšœˆ™ˆ—J˜—Jšœ ™ ˜JšœS™SJ˜Jš œœœ˜>š œœ˜JšœW˜WJšœM˜Tšœ™Jšœ‹™‹Jšœ“™“Jšœ‹™‹—J™ŠJ™ëJ™•J™a—J˜š  œœœœ˜˜LJšœ˜"—š œœ˜JšœV˜VJšœ¢™¢—™J™——Jšœ ™ ˜JšœS™SJ˜š œœœ ˜>JšœÒ™Ò—J˜š œœ#˜?Jšœ‚™‚—J˜š œœœ˜OJšœî™î—J˜š œœ+˜FJšœî™î—J˜Jš œœœ˜Qš œœ,˜LJšœ ˜'JšœÕ™Õ—J™Jš œœœ˜Iš œœ+˜DJšœ˜&Jšœú™úJ™p—J™—J™™Jšœ œ˜J˜—Jšœ˜J˜J˜J˜—…—`