DIRECTORY KeySymsSun, KeySymsOSF, KeySymsHP, Process, Rope, Xl, XlAscii, XlAsciiInput, XlCutBuffers; XlAsciiInputImpl: CEDAR MONITOR IMPORTS Process, Rope, XlAscii, Xl, XlCutBuffers EXPORTS XlAsciiInput = BEGIN OPEN Xl, XlAsciiInput; events: EventFilter = CreateEventFilter[destroyNotify, keyPress]; check: CONDITION; BroadCast: ENTRY PROC[] = { ENABLE UNWIND => NULL; BROADCAST check; }; WindowDestroyed: PUBLIC ERROR = CODE; bufferSize: INT ~ 120; Buffer: TYPE = RECORD [ in, out: INT ¬ 0, data: PACKED ARRAY [0..bufferSize) OF CHAR, next: REF Buffer ¬ NIL ]; HandleRec: TYPE = MONITORED RECORD [ connection: Xl.Connection ¬ NIL, window: Window ¬ nullWindow, buffer: REF Buffer ¬ NIL, lastBuffer: REF Buffer ¬ NIL, alive: BOOL ¬ TRUE ]; cnt: INT ¬ 0; unused: REF Buffer ¬ NIL; GetBuffer: INTERNAL PROC [] RETURNS [buff: REF Buffer] = { IF unused=NIL THEN buff ¬ NEW[Buffer] ELSE { buff ¬ unused; unused ¬ buff.next; buff.in ¬ buff.out ¬ 0; buff.next ¬ NIL; cnt ¬ cnt-1; }; }; DisposeBuffer: INTERNAL PROC [buff: REF Buffer] = { IF buff#NIL AND cnt<4 THEN {cnt ¬ cnt+1; buff.next ¬ unused; unused ¬ buff; }; }; EnableAsciiInput: PUBLIC PROC [c: Xl.Connection, w: Xl.Window] RETURNS [Handle] = { h: REF HandleRec ¬ NEW[HandleRec ¬ [connection: c, window: w]]; match: Match ¬ NEW[MatchRep ¬ [proc: EventProc, handles: events, tq: CreateTQ[], data: h]]; Xl.AddDispatch[c, w, match, [keyPress: TRUE, keyRelease: TRUE, structureNotify: TRUE]]; RETURN [h]; }; listWithPaste: LIST OF Xl.KeySym = LIST[KeySymsSun.Paste, KeySymsOSF.Paste, KeySymsHP.Paste]; EventProc: EventProcType = { ENABLE Xl.XError => GOTO oops; h: REF HandleRec ~ NARROW[clientData]; WITH event SELECT FROM keyPress: KeyPressEvent => { char: CHAR; keysym: Xl.KeySym; matched: Xl.KeySym; isModifier: BOOL; [char: char, keysym: keysym, matched: matched, isModifier: isModifier] ¬ XlAscii.Convert[event.connection, keyPress.keyCode, keyPress.state, listWithPaste]; IF isModifier THEN RETURN; IF matched = KeySymsSun.Paste OR matched = KeySymsOSF.Paste OR matched = KeySymsHP.Paste THEN { r: ROPE ¬ XlCutBuffers.Get[event.connection]; TypeIn[h, r]; RETURN }; IF char#0c THEN QueueChar[h, char]; }; destroyNotify: DestroyNotifyEvent => { IF destroyNotify.window=h.window THEN { h.alive ¬ FALSE; BroadCast[]; } }; ENDCASE => {}; EXITS oops => {}; }; TypeIn: PUBLIC ENTRY PROC [handle: Handle, chars: REF] = { ENABLE UNWIND => NULL; WITH handle SELECT FROM h: REF HandleRec => { WITH chars SELECT FROM ch: REF CHAR => InternalQueueChar[h, ch­]; r: Rope.ROPE => { EachChar: INTERNAL Rope.ActionType = {InternalQueueChar[h, c]}; [] ¬ Rope.Map[base: r, action: EachChar]; }; ENDCASE => {}; }; ENDCASE => {}; }; QueueChar: ENTRY PROC [h: REF HandleRec, ch: CHAR] = { ENABLE UNWIND => NULL; InternalQueueChar[h, ch] }; InternalQueueChar: INTERNAL PROC [h: REF HandleRec, ch: CHAR] = { IF ORD[ch]=0 THEN {BROADCAST check; RETURN}; IF h.buffer=NIL THEN { buff: REF Buffer ¬ GetBuffer[]; h.lastBuffer ¬ h.buffer ¬ buff; }; IF h.lastBuffer.in>=bufferSize THEN { h.lastBuffer.next ¬ GetBuffer[]; h.lastBuffer ¬ h.lastBuffer.next; }; h.lastBuffer.data[h.lastBuffer.in] ¬ ch; h.lastBuffer.in ¬ h.lastBuffer.in+1; BROADCAST check; }; CharAvailable: PUBLIC PROC [handle: Handle, wait: BOOL ¬ FALSE] RETURNS [n: INT ¬ 0] = { EntryCharAvailable: ENTRY PROC [] = { ENABLE { UNWIND => NULL; ABORTED => GOTO oops; }; IF wait THEN { WHILE h.buffer=NIL OR h.buffer.out>=h.buffer.in DO WAIT check; IF ~h.alive OR ~Xl.Alive[h.connection] THEN RETURN WITH ERROR WindowDestroyed; Process.CheckForAbort[]; ENDLOOP; n ¬ ABS[h.buffer.in-h.buffer.out]; } ELSE { IF h.buffer=NIL OR h.buffer.out>=h.buffer.in THEN n ¬ 0 ELSE n ¬ ABS[h.buffer.in-h.buffer.out]; }; EXITS oops => RETURN WITH ERROR ABORTED; }; h: REF HandleRec ¬ NARROW[handle]; IF ~h.alive OR ~Xl.Alive[h.connection] THEN ERROR WindowDestroyed; IF h.buffer=NIL AND ~wait THEN RETURN [0]; EntryCharAvailable[] }; GetChar: PUBLIC PROC [handle: Handle, wait: BOOL ¬ TRUE] RETURNS [ch: CHAR¬0c] = { EntryGetChar: ENTRY PROC [] = { ENABLE { UNWIND => NULL; ABORTED => GOTO oops; }; IF wait THEN { WHILE h.buffer=NIL OR h.buffer.out>=h.buffer.in DO WAIT check; IF ~h.alive OR ~Xl.Alive[h.connection] THEN RETURN WITH ERROR WindowDestroyed; Process.CheckForAbort[]; ENDLOOP } ELSE { IF h.buffer=NIL OR h.buffer.out>=h.buffer.in THEN RETURN; }; ch ¬ h.buffer.data[h.buffer.out]; h.buffer.out ¬ h.buffer.out+1; IF h.buffer.out>=bufferSize THEN { buf: REF Buffer ¬ h.buffer; h.buffer ¬ h.buffer.next; IF h.buffer=NIL THEN h.lastBuffer ¬ NIL; DisposeBuffer[buf]; }; EXITS oops => RETURN WITH ERROR ABORTED; }; h: REF HandleRec ¬ NARROW[handle]; IF ~h.alive OR ~Xl.Alive[h.connection] THEN ERROR WindowDestroyed; EntryGetChar[]; }; ResetBuffer: PUBLIC ENTRY PROC [handle: Handle] = { ENABLE UNWIND => NULL; WITH handle SELECT FROM h: REF HandleRec => { DisposeBuffer[h.buffer]; h.buffer ¬ h.lastBuffer ¬ NIL; }; ENDCASE => {}; }; InitCond: ENTRY PROC [] = TRUSTED { ENABLE UNWIND => NULL; Process.InitializeCondition[@check, Process.MsecToTicks[10000]]; }; InitCond[]; END. Κ XlAsciiInputImpl.mesa Copyright Σ 1988, 1989, 1991, 1992 by Xerox Corporation. All rights reserved. Christian Jacobi, July 4, 1988 1:01:32 pm PDT Christian Jacobi, February 26, 1992 1:04 pm PST Κ :–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ ΟeœC™NKšœ*Οk™-Kšœ/™/—K˜šž œ˜ Kšœ ˜ Kšœ ˜ Kšœ ˜ Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ ˜ Kšœ ˜ K˜—šΟnœžœžœ˜ Kšžœ)˜0Kšžœ˜—šžœžœžœ ˜K˜—KšœA˜AK˜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˜š Ÿ œžœžœžœžœ ˜:Kšžœžœžœžœ˜%šžœ˜Kšœ"˜"Kšœ$žœ˜5K˜—K˜—K˜šŸ œžœžœžœ ˜3šžœžœžœžœ˜(Kšœ#˜#K˜—K˜—K˜š Ÿœžœžœžœžœ žœ ˜SKšœžœ žœ)˜?KšœžœI˜[Kšœ'žœžœžœ˜WKšžœ˜ Kšœ˜—K˜Kšœžœžœ žœ6˜]K˜šŸ œ˜Kšžœžœ˜Kšœžœ žœ ˜&šžœžœž˜šœ˜Kšœžœ5žœ˜DKšœœ˜œ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˜—š Ÿ œžœžœžœžœ˜6Kšžœžœžœ˜Kšœ˜Kšœ˜—K˜š Ÿœžœžœžœžœ˜AKš žœžœžœž œžœ˜,šžœ žœžœ˜Kšœžœ˜Kšœ˜Kšœ˜—šžœžœ˜%Kšœ ˜ Kšœ!˜!K˜—Kšœ(˜(Kšœ$˜$Kšž œ˜K˜—K˜šŸ œžœžœžœžœžœžœ ˜XšŸœžœžœ˜%šžœ˜Kšžœžœ˜Kšžœžœ˜K˜—šžœ˜šžœ˜šžœ žœžœž˜2Kšžœ˜ Kšžœ žœžœžœžœžœžœ˜NKšœ˜Kšžœ˜—Kšœžœ˜"K˜—šžœ˜šžœ žœžœ˜-Kšžœ˜ Kšžœžœ˜(—K˜——Kš žœ žœžœžœžœ˜(Kšœ˜—Kšœžœ žœ ˜"Kš žœ žœžœžœžœ˜BKš žœ žœžœžœžœ˜*Kšœ˜K˜—K˜š Ÿœž œžœžœžœžœ˜RšŸ œžœžœ˜šžœ˜Kšžœžœ˜Kšžœžœ˜K˜—šžœ˜šžœ˜šžœ žœžœž˜2Kšžœ˜ Kšžœ žœžœžœžœžœžœ˜NKšœ˜Kšž˜—K˜—šžœ˜Kš žœ žœžœžœžœ˜:K˜——Kšœ!˜!Kšœ˜šžœžœ˜"Kšœžœ˜Kšœ˜Kšžœ žœžœžœ˜(Kšœ˜K˜—Kš žœ žœžœžœžœ˜(Kšœ˜—Kšœžœ žœ ˜"Kš žœ žœžœžœžœ˜BKšœ˜K˜—K˜šŸ œž œžœ˜3Kšžœžœžœ˜šžœžœž˜šœžœ˜Kšœ˜Kšœžœ˜Kšœ˜—Kšžœ˜—K˜K˜—šŸœžœžœžœ˜#Kšžœžœžœ˜Kšœ@˜@K˜—K˜Kšœ ˜ Kšžœ˜K˜—…—ΰδ