<> <> <> <> DIRECTORY Xl, XlCursor, XlPrivateResources, CardTab, Rope; XlCursorImpl: CEDAR MONITOR IMPORTS Xl, XlPrivateResources, CardTab EXPORTS XlCursor = BEGIN OPEN Xl, XlCursor; myPropKey: REF ATOM ¬ NEW[ATOM ¬ $XlCursorImpl]; cache: ConnectionCache ¬ NEW[ConnectionCacheRec]; --never NIL; caching is valuable because we will allways have lots of operation on very few connections ConnectionCache: TYPE = REF ConnectionCacheRec; ConnectionCacheRec: TYPE = RECORD [ connection: Connection ¬ NIL, cursorFont: Font ¬ nullFont, sharedStandardCursors: CardTab.Ref ¬ NIL ]; GetConnectionData: PROC [c: Connection] RETURNS [ca: ConnectionCache] = { ca ¬ cache; --local, immutable copy IF ca.connection#c THEN { ca ¬ NARROW[Xl.GetConnectionPropAndInit[c, myPropKey, InitConnection]]; cache ¬ ca; --atomic }; }; InitConnection: InitializeProcType = { ca: ConnectionCache ¬ NEW[ConnectionCacheRec ¬ [ connection: c, cursorFont: Xl.OpenFont[c, "cursor"], sharedStandardCursors: CardTab.Create[] ]]; RETURN [ca] }; StandardCursorFont: PUBLIC PROC [c: Connection] RETURNS [Font] = { data: ConnectionCache ¬ GetConnectionData[c]; RETURN [data.cursorFont]; }; SharedStandardCursor: PUBLIC PROC [c: Connection, source: StandardFontCursors] RETURNS [cursor: Cursor] = { data: ConnectionCache ¬ GetConnectionData[c]; WITH CardTab.Fetch[data.sharedStandardCursors, ORD[source]].val SELECT FROM cc: REF Cursor => RETURN [cc­]; ENDCASE => { cursor ¬ MutableStandardCursor[c, source]; XlPrivateResources.Attach[c, cursor, $immutableCursor]; [] ¬ CardTab.Store[data.sharedStandardCursors, ORD[source], NEW[Cursor ¬ cursor]] }; }; MutableStandardCursor: PUBLIC PROC [c: Xl.Connection, source: StandardFontCursors] RETURNS [cursor: Xl.Cursor] = { data: ConnectionCache ¬ GetConnectionData[c]; cursor ¬ CreateGlyphCursor[c: data.connection, sourceFont: data.cursorFont, sourceChar: ORD[source], maskFont: data.cursorFont, maskChar: ORD[source]+1]; }; <<>> END.