1 terminals define: #CursesConsole &parents: {StructuredConsole}.
3 CursesConsole traits `>> [
5 [ExternalInterface newForLibrary: 'ncurses-console' primitives:
6 q{(Boolean isAvailable ())
7 (Boolean enterStructuredMode ())
8 (Boolean leaveStructuredMode ())
9 (CString keySequenceOf (CString))
12 (Boolean write (Bytes Int Int))
14 (Boolean clearToEOS ())
15 (Boolean clearToEOL ())
16 (Boolean scroll (Int))
17 (Boolean moveToXY (Int Int))
23 (Boolean deleteChar ())
24 (Boolean deleteLines (Int))
25 (Boolean insertLines (Int))
28 (Void setAttributes (Int Int))
29 (Int maxColorPairs ())
30 (Boolean initColorPair (Int Int Int))
32 addSlot: #maxColorPairs.
33 addSlot: #currentColorPair.
34 addSlot: #colorToPairs valued: Dictionary new.
36 "Create new prorotypes for the streams for methods we install on them"
37 define: #EventStream &parents: {CursesConsole EventStream}.
38 "define: #ReadStream &parents: {CursesConsole ReadStream}. we don't override anything for now"
39 define: #WriteStream &parents: {CursesConsole WriteStream}.
40 define: #ReadWriteStream &parents: {CursesConsole ReadStream. CursesConsole WriteStream}.
43 w@(CursesConsole WriteStream traits) next: n putAll: seq startingAt: start
44 "Override the generic cursor tracking mechanism with reading the cursor position
49 c moveCursorTo: {c actualCursorColumn. c actualCursorRow}.
53 c@(CursesConsole traits) updateCursorPositionFrom: col@(Collection traits)
55 "Hide implementation, we will read the curses cursor position after the write"
58 _@(CursesConsole traits) elementType
61 _@(CursesConsole traits) collectionType
64 c@(CursesConsole traits) isAvailable
67 c Lib primitives isAvailable do
70 c@(CursesConsole traits) enterStructuredMode
72 (c Lib primitives enterStructuredMode do)
74 [c maxColorPairs := c Lib primitives maxColorPairs do.
75 c currentColorPair := 0.
76 c colorToPairs := c colorToPairs new.
77 c Lib primitives clear do.
80 [error: 'Curses console plugin failed to switch to structured mode'.
84 c@(CursesConsole traits) leaveStructuredMode
86 result := c Lib primitives leaveStructuredMode do.
87 c Lib primitives slotNamesAndValuesDo: [| :name :value |
88 (value is: ExternalMethod) ifTrue:
89 [value close. c Lib primitives removeSlot: name]].
94 c@(CursesConsole traits) initKeyMappings
96 c keyCodeToKeyName clear.
97 c sequenceToKeyName clear.
113 } do: [| :entry keyName cursesName |
114 keyName := entry first.
115 cursesName := entry second.
117 (c Lib primitives keySequenceOf applyTo: {cursesName as: String})
119 c ; 'Warning: Can\'t find TerminInfo entry for "' ; cursesName ; '" which is key "' ; keyName ; '"\n'.
121 ifNotNilDo: [| :sequence char |
122 entry size >= 3 ifTrue: [char := entry third].
124 ifTrue: [c keyCodeToKeyName at: (sequence first as: Integer) put: {keyName. char}]
126 sequence size = 2 /\ [sequence first = $^]
129 at: ((sequence second as: Integer) bitOr: 2r01000000)
130 put: {keyName. char}]
131 ifFalse: [| keyCode |
132 sequence size = 4 /\ [sequence first = $\\]
133 /\ [(keyCode := ((sequence copyFrom: 1) as: Integer &radix: 8)) ~= 0]
134 ifTrue: [c keyCodeToKeyName at: keyCode put: {keyName. Nil}]
135 ifFalse: [c sequenceToKeyName at: sequence put: keyName]]]].
139 0 to: 63 do: [| :index indexStr |
140 indexStr := (index as: String).
141 (c Lib primitives keySequenceOf applyTo: {'kf' ; indexStr})
142 ifNotNilDo: [| :sequence |
143 c sequenceToKeyName at: sequence put: ('Function' ; indexStr as: Symbol)].
146 "Fill the holes with defaults"
150 "The exported primitives as methods"
152 c@(CursesConsole traits) actualColumns
154 c assumeStructuredMode.
155 c Lib primitives columns do
158 c@(CursesConsole traits) actualRows
160 c assumeStructuredMode.
161 c Lib primitives rows do
164 c@(CursesConsole traits) clear
166 c assumeStructuredMode.
167 c Lib primitives clear do
170 c@(CursesConsole traits) clearToEOS
172 c assumeStructuredMode.
173 c Lib primitives clearToEOS do
176 c@(CursesConsole traits) clearToEOL
178 c assumeStructuredMode.
179 c Lib primitives clearToEOL do
182 c@(CursesConsole traits) moveCursorTo: pos
184 c assumeStructuredMode.
185 c Lib primitives moveToXY applyTo: {pos first. pos second}.
189 c@(CursesConsole traits) actualCursorColumn
191 c assumeStructuredMode.
192 c Lib primitives cursorX do
195 c@(CursesConsole traits) actualCursorRow
197 c assumeStructuredMode.
198 c Lib primitives cursorY do
201 c@(CursesConsole traits) scroll &lines: lines
203 c assumeStructuredMode.
204 lines `defaultsTo: 1.
205 c Lib primitives scroll applyTo: {lines}
208 c@(CursesConsole traits) readEscapedKeyInto: event
209 [| keyCode seq count |
212 "Read up to 4 key codes without blocking"
213 [(keyCode := (c Lib primitives nextEvent applyTo: {0})) > 0 /\
215 whileTrue: [| result |
217 "Reenter for double escaped keys like alt+right arrow"
218 count = 1 /\ [keyCode = 27]
220 event leftAltState := True.
221 ^ (c readEscapedKeyInto: event)].
222 seq nextPut: (keyCode as: ASCIICharacter).
223 (c translateEscapedSequence: seq contents into: event)
225 "If nothing was read unblockingly then it's a simple Escape"
226 count isZero ifTrue: [event keyName := #Escape].
229 c@(CursesConsole traits) write: n to: handle from: array startingAt: start
231 c assumeStructuredMode.
232 c Lib primitives write applyTo: {array. n. start}.
236 c@(CursesConsole traits) flush
238 c assumeStructuredMode.
239 c Lib primitives flush do
242 c@(CursesConsole traits) deleteChar
244 c assumeStructuredMode.
245 c Lib primitives deleteChar do
248 c@(CursesConsole traits) deleteLines: n
250 c assumeStructuredMode.
251 c Lib primitives deleteLines applyTo: {n}
254 c@(CursesConsole traits) insertLines: n
256 c assumeStructuredMode.
257 c Lib primitives insertLines applyTo: {n}
260 c@(CursesConsole traits) hideCursor
262 c assumeStructuredMode.
263 c Lib primitives hideCursor do
266 c@(CursesConsole traits) showCursor
268 c assumeStructuredMode.
269 c Lib primitives showCursor do
272 c@(CursesConsole traits) ensurePairForFg: fg forBg: bg
274 c colorToPairs at: fg <> bg ifAbsentPut:
276 (oldPair := c currentColorPair) >= c maxColorPairs ifTrue:
277 [error: 'Ran out of terminal color pairs (this is how lame ncurses is with its color pairs)'].
278 c currentColorPair := oldPair + 1.
279 c Lib primitives initColorPair applyTo: {oldPair. fg. bg}.
283 c@(CursesConsole traits) attributeMode: mode
285 c setAttributeMode: mode withFg: c currentFgColor withBg: c currentBgColor.
289 c@(CursesConsole traits) foregroundColor: fg
291 c setAttributeMode: c currentMode withFg: fg withBg: c currentBgColor.
295 c@(CursesConsole traits) backgroundColor: bg
297 c setAttributeMode: c currentMode withFg: c currentFgColor withBg: bg.
301 c@(CursesConsole traits) setAttributeMode: mode withFg: fg withBg: bg
302 "This is the primitive"
304 c assumeStructuredMode.
305 c Lib primitives setAttributes applyTo: {mode. c ensurePairForFg: fg forBg: bg}.
310 s@(CursesConsole EventStream traits) hasNext
312 (c := s console) assumeStructuredMode.
313 c Lib primitives hasEvent do
316 s@(CursesConsole EventStream traits) next
318 (c := s console) assumeStructuredMode.
319 (keyCode := c Lib primitives nextEvent apply*, -1) caseOf: {
322 127 -> [(c KeyDownEvent newForKeyCode: 8) `>>
323 [keyName := #BackSpace.
324 leftControlState := True. ]].
326 event := c KeyDownEvent newForKeyCode: keyCode.
327 c readEscapedKeyInto: event.
328 "event keyName ifNil: [error: 'unknown key sequence']."
330 } otherwise: [c resolveEvent: (c KeyDownEvent newForKeyCode: keyCode)]