<<>> <> <> <> <> DIRECTORY Ascii USING [BS, CR, DEL, LF], Rope USING [Concat, FromChar, Length, Substr, ROPE], Xl USING [ButtonReleaseEvent, CreateEventFilter, CreateTQ, currentTime, Details, DetailsRec, EventProcType, EventFilter, KeyPressEvent, KeySym, LastTime, MatchRep, SetInputFocus, TimeStamp, XError], XlAscii USING [Convert], XTk, XTkButtons USING [CreateButton], XTkInhibitableWidgets, XTkLabels USING [StyleSpec, TextWidget], XTkShellWidgets USING [IsShell, SetFocus], XTkWidgets USING [GetText, SetText]; XTkInhibitableWidgetsImpl: CEDAR MONITOR IMPORTS Rope, Xl, XlAscii, XTk, XTkButtons, XTkShellWidgets, XTkWidgets EXPORTS XTkInhibitableWidgets ~ { InhibitableWidget: TYPE = XTkLabels.TextWidget; StyleSpec: TYPE = XTkLabels.StyleSpec; sampleBool: REF BOOLEAN ¬ NEW[BOOLEAN ¬ TRUE]; events: Xl.EventFilter ~ Xl.CreateEventFilter[keyPress]; Create: PUBLIC PROC [widgetSpec: XTk.WidgetSpec ¬ [], text: Rope.ROPE ¬ NIL] RETURNS [w: InhibitableWidget] ~ { w ¬ XTkButtons.CreateButton[widgetSpec: widgetSpec, text: text, hitProc: Hit, registerData: NEW[BOOLEAN ¬ TRUE]]; XTk.AddPermanentMatch[w, [proc: EventProc, handles: events, tq: Xl.CreateTQ[], data: w], [keyPress: TRUE]]; }; flushButNoErrors: Xl.Details ¬ NEW[Xl.DetailsRec ¬ [flush: now, errorMatch: NEW[Xl.MatchRep ¬ [proc: IgnoreErrors, handles: NIL, tq: Xl.CreateTQ[]]]]]; IgnoreErrors: Xl.EventProcType = {}; MySetFocus: PROC [field: XTk.Widget, time: Xl.TimeStamp ¬ Xl.currentTime] = { <> IF field#NIL AND field.fastAccessAllowed=ok THEN { root: XTk.Widget ~ XTk.RootWidget[field]; IF time=Xl.currentTime THEN time ¬ Xl.LastTime[field.connection]; IF root#NIL AND XTkShellWidgets.IsShell[root] THEN XTkShellWidgets.SetFocus[shell: root, time: time, child: field] ELSE Xl.SetInputFocus[field.connection, field.window, parent, time, flushButNoErrors]; }; }; Hit: XTk.WidgetNotifyProc ~ { WITH event SELECT FROM br: Xl.ButtonReleaseEvent => MySetFocus[widget, br.timeStamp]; ENDCASE => {}; }; EventProc: Xl.EventProcType = { ENABLE { Xl.XError => GOTO oops; }; widget: XTk.Widget ~ NARROW[clientData]; WITH event SELECT FROM keyPress: Xl.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]; IF isModifier THEN RETURN; PushChar[widget, char]; }; ENDCASE => {}; EXITS oops => {}; }; SetEdittability: PROC [w: InhibitableWidget, edittable: BOOL] ~ { XTk.PutWidgetProp[w, sampleBool, NEW[BOOL ¬ edittable]]}; Edittable: PUBLIC PROC [w: InhibitableWidget] RETURNS [BOOLEAN] ~ { WITH XTk.GetWidgetProp[w, sampleBool] SELECT FROM b: REF BOOLEAN => RETURN[b­]; ENDCASE => RETURN[TRUE]; }; PushChar: PROC [widget: XTk.Widget, ch: CHAR] = { text: Rope.ROPE ¬ XTkWidgets.GetText[widget]; edittable: BOOLEAN ¬ Edittable[widget]; IF edittable THEN { SELECT ch FROM 4c, Ascii.LF, Ascii.CR, Ascii.DEL => {text ¬ NIL}; Ascii.BS => { leng: INT ¬ Rope.Length[text]; IF leng>0 THEN text ¬ Rope.Substr[text, 0, leng-1]; } ENDCASE => { text ¬ Rope.Concat[text, Rope.FromChar[ch]]; }; XTkWidgets.SetText[widget, text]; }; }; Inhibit: PUBLIC PROC [widget: InhibitableWidget] ~ { SetEdittability[widget, FALSE] }; Enable: PUBLIC PROC [widget: InhibitableWidget] ~ { SetEdittability[widget, TRUE] }; }.