author | Claus Gittinger <cg@exept.de> |
Thu, 11 Jun 1998 19:11:45 +0200 | |
changeset 940 | 16c955286510 |
parent 938 | 3e65cc6f22cd |
child 942 | 1f4fa3a6faec |
permissions | -rw-r--r-- |
914 | 1 |
TextCollector subclass:#TerminalView |
2 |
instanceVariableNames:'inStream outStream readerProcess shellPid kbdSequences |
|
3 |
escapeSequenceTree currentSequence currentTree kbdMap |
|
926 | 4 |
escapeLeadingChars numberOfColumns numberOfLines' |
914 | 5 |
classVariableNames:'' |
6 |
poolDictionaries:'' |
|
7 |
category:'Views-TerminalViews' |
|
8 |
! |
|
9 |
||
10 |
!TerminalView class methodsFor:'documentation'! |
|
11 |
||
12 |
documentation |
|
13 |
" |
|
916 | 14 |
I provide terminal functionality, by forking a command interpreter |
15 |
and comunicating with it via a pty. |
|
16 |
I am abstract - concrete terminal characteristics are defined |
|
17 |
by concrete subclasses (see VT52TerminalView). |
|
914 | 18 |
|
19 |
[author:] |
|
20 |
Claus Gittinger |
|
915 | 21 |
|
22 |
[start with:] |
|
23 |
VT52TerminalView openShell |
|
919 | 24 |
VT100TerminalView openShell |
914 | 25 |
" |
26 |
! ! |
|
27 |
||
929 | 28 |
!TerminalView class methodsFor:'queries'! |
29 |
||
30 |
isVisualStartable |
|
31 |
"returns whether this application class can be started via #open" |
|
32 |
||
33 |
self == TerminalView ifTrue:[^ false]. |
|
34 |
^ true |
|
35 |
||
36 |
"Created: / 10.6.1998 / 15:48:43 / cg" |
|
37 |
! ! |
|
38 |
||
914 | 39 |
!TerminalView class methodsFor:'testing'! |
40 |
||
928 | 41 |
open |
42 |
self openShell |
|
43 |
||
44 |
" |
|
45 |
VT100TerminalView open |
|
46 |
" |
|
47 |
||
48 |
"Modified: / 10.6.1998 / 15:06:35 / cg" |
|
49 |
"Created: / 10.6.1998 / 15:47:25 / cg" |
|
50 |
! |
|
51 |
||
914 | 52 |
openDummy |
53 |
|in vt52| |
|
54 |
||
55 |
vt52 := self new. |
|
56 |
in := ForwardingStream on:''. |
|
57 |
||
58 |
in fwdStream:vt52. |
|
59 |
vt52 inStream:in. |
|
60 |
vt52 outStream:in. |
|
61 |
vt52 open |
|
62 |
||
63 |
" |
|
64 |
self openDummy |
|
65 |
" |
|
66 |
! |
|
67 |
||
68 |
openShell |
|
69 |
|in top scr vt52| |
|
70 |
||
71 |
top := StandardSystemView new. |
|
72 |
scr := HVScrollableView for:self in:top. |
|
917 | 73 |
scr autoHideHorizontalScrollBar:true. |
933
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
74 |
scr horizontalMini:true. |
914 | 75 |
scr origin:0.0@0.0 corner:1.0@1.0. |
76 |
vt52 := scr scrolledView. |
|
77 |
||
940 | 78 |
top extent:(scr preferredExtent). |
79 |
top label:'shell'. |
|
80 |
top openAndWait. |
|
81 |
||
914 | 82 |
vt52 startShell. |
917 | 83 |
|
914 | 84 |
|
85 |
" |
|
933
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
86 |
VT100TerminalView openShell |
914 | 87 |
" |
923 | 88 |
|
940 | 89 |
"Modified: / 11.6.1998 / 18:11:19 / cg" |
914 | 90 |
! ! |
91 |
||
92 |
!TerminalView methodsFor:'accessing'! |
|
93 |
||
94 |
inStream |
|
95 |
"return the value of the instance variable 'inStream' (automatically generated)" |
|
96 |
||
97 |
^ inStream! |
|
98 |
||
99 |
inStream:something |
|
100 |
"set the value of the instance variable 'inStream' (automatically generated)" |
|
101 |
||
102 |
inStream := something.! |
|
103 |
||
104 |
outStream |
|
105 |
"return the value of the instance variable 'outStream' (automatically generated)" |
|
106 |
||
107 |
^ outStream! |
|
108 |
||
109 |
outStream:something |
|
110 |
"set the value of the instance variable 'outStream' (automatically generated)" |
|
111 |
||
112 |
outStream := something.! ! |
|
113 |
||
114 |
!TerminalView methodsFor:'cursor handling'! |
|
115 |
||
116 |
cursorCol:col |
|
117 |
"check of col is a valid cursor position; return a new col-nr if not. |
|
118 |
Here, the linelength is enforced" |
|
119 |
||
926 | 120 |
^ super cursorCol:(col min:numberOfColumns) |
914 | 121 |
|
926 | 122 |
"Modified: / 10.6.1998 / 15:09:34 / cg" |
914 | 123 |
! |
124 |
||
933
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
125 |
cursorDown:n |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
126 |
cursorLine + n > list size ifTrue:[ |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
127 |
list := list , (Array new:n). |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
128 |
self textChanged. |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
129 |
]. |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
130 |
super cursorDown:n |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
131 |
|
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
132 |
"Modified: / 10.6.1998 / 17:18:41 / cg" |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
133 |
"Created: / 10.6.1998 / 17:18:50 / cg" |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
134 |
! |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
135 |
|
914 | 136 |
cursorLine:l col:col |
137 |
"check of col is a valid cursor position; return a new col-nr if not. |
|
138 |
Here, the linelength is enforced" |
|
139 |
||
926 | 140 |
^ super cursorLine:l col:(col min:numberOfColumns) |
914 | 141 |
|
926 | 142 |
"Modified: / 10.6.1998 / 15:09:38 / cg" |
914 | 143 |
! |
144 |
||
145 |
validateCursorCol:col inLine:line |
|
146 |
"check of col is a valid cursor position; return a new col-nr if not. |
|
147 |
Here, the linelength is enforced" |
|
148 |
||
926 | 149 |
^ col min:numberOfColumns |
914 | 150 |
|
926 | 151 |
"Modified: / 10.6.1998 / 15:09:41 / cg" |
914 | 152 |
! ! |
153 |
||
154 |
!TerminalView methodsFor:'event handling'! |
|
155 |
||
156 |
keyPress:aKey x:x y:y |
|
157 |
|rest rawKey seq| |
|
158 |
||
159 |
inStream isNil ifTrue:[^ self]. |
|
160 |
||
931 | 161 |
"/ Transcript showCR:'----'; show:'key:' ; showCR:aKey printString. |
914 | 162 |
|
163 |
aKey isCharacter ifTrue:[ |
|
164 |
"/ send it down to inStream ... |
|
165 |
inStream nextPut:aKey. |
|
166 |
^ self |
|
167 |
]. |
|
168 |
||
921 | 169 |
aKey == #Tab ifTrue:[ |
931 | 170 |
"/ Transcript show:'->' ; showCR:Character tab storeString. |
921 | 171 |
inStream nextPut:Character tab. |
172 |
^ self |
|
173 |
]. |
|
174 |
||
914 | 175 |
seq := kbdSequences at:aKey ifAbsent:nil. |
176 |
seq notNil ifTrue:[ |
|
931 | 177 |
"/ Transcript show:'->' ; showCR:seq storeString. |
914 | 178 |
inStream nextPutAll:(seq withEscapes). |
179 |
^ self |
|
180 |
]. |
|
181 |
||
182 |
rawKey := device keyboardMap keyAtValue:aKey ifAbsent:aKey. |
|
183 |
seq := kbdSequences at:rawKey ifAbsent:nil. |
|
184 |
seq notNil ifTrue:[ |
|
931 | 185 |
"/ Transcript show:'->' ; showCR:seq storeString. |
914 | 186 |
inStream nextPutAll:(seq withEscapes). |
187 |
^ self |
|
188 |
]. |
|
189 |
||
190 |
(rawKey startsWith:'Ctrl') ifTrue:[ |
|
191 |
rest := rawKey copyFrom:5. |
|
192 |
rest size == 1 ifTrue:[ |
|
193 |
rest := rest at:1. |
|
194 |
(rest >= $a and:[rest <= $z]) ifTrue:[ |
|
931 | 195 |
"/ Transcript show:'->' ; showCR:(Character value:(rest - $a + 1)) storeString. |
914 | 196 |
inStream nextPut:(Character value:(rest - $a + 1)). |
197 |
^ self |
|
198 |
]. |
|
199 |
(rest >= $A and:[rest <= $Z]) ifTrue:[ |
|
931 | 200 |
"/ Transcript show:'->' ; showCR:(Character value:(rest - $a + 1)) storeString. |
914 | 201 |
inStream nextPut:(Character value:(rest - $A + 1)). |
202 |
^ self |
|
203 |
]. |
|
204 |
] |
|
205 |
]. |
|
206 |
||
934 | 207 |
(rawKey startsWith:'Control') ifTrue:[ |
208 |
^ self |
|
209 |
]. |
|
210 |
(rawKey startsWith:'Shift') ifTrue:[ |
|
211 |
^ self |
|
212 |
]. |
|
213 |
(rawKey startsWith:'Alt') ifTrue:[ |
|
214 |
^ self |
|
215 |
]. |
|
216 |
(rawKey startsWith:'Cmd') ifTrue:[ |
|
217 |
^ self |
|
218 |
]. |
|
219 |
||
220 |
Transcript show:'unhandled: '; showCR:rawKey. |
|
914 | 221 |
|
222 |
"/ super keyPress:aKey x:x y:y |
|
921 | 223 |
|
934 | 224 |
"Modified: / 10.6.1998 / 17:51:21 / cg" |
914 | 225 |
! |
226 |
||
227 |
shellTerminated |
|
228 |
self warn:'shell terminated'. |
|
229 |
self closeDownShell. |
|
230 |
! ! |
|
231 |
||
232 |
!TerminalView methodsFor:'functions'! |
|
233 |
||
234 |
doBackspace |
|
235 |
self cursorLeft. |
|
236 |
self replaceCharAtCursor:(Character space). |
|
237 |
self cursorLeft. |
|
238 |
||
931 | 239 |
"Modified: / 10.6.1998 / 17:09:12 / cg" |
914 | 240 |
! |
241 |
||
926 | 242 |
doClearDisplay |
243 |
firstLineShown to:(list size) do:[:l | |
|
244 |
self at:l put:'' |
|
245 |
]. |
|
922 | 246 |
|
926 | 247 |
"Created: / 10.6.1998 / 14:43:06 / cg" |
248 |
"Modified: / 10.6.1998 / 14:58:07 / cg" |
|
249 |
! |
|
250 |
||
251 |
doClearToEnd |
|
252 |
self doClearToEndOfLine. |
|
922 | 253 |
cursorLine+1 to:(list size) do:[:l | |
254 |
self at:l put:'' |
|
255 |
]. |
|
256 |
||
926 | 257 |
"Modified: / 10.6.1998 / 14:45:43 / cg" |
258 |
! |
|
259 |
||
260 |
doClearToEndOfLine |
|
261 |
|l| |
|
262 |
||
263 |
l := self listAt:cursorLine. |
|
931 | 264 |
(l size >= (cursorCol-1)) ifTrue:[ |
926 | 265 |
l := l copyTo:cursorCol-1. |
266 |
self at:cursorLine put:l. |
|
267 |
] |
|
268 |
||
269 |
"Created: / 10.6.1998 / 14:45:01 / cg" |
|
931 | 270 |
"Modified: / 10.6.1998 / 17:08:23 / cg" |
922 | 271 |
! |
272 |
||
914 | 273 |
doCursorDown |
931 | 274 |
super cursorDown:1 |
275 |
||
276 |
"Modified: / 10.6.1998 / 16:55:17 / cg" |
|
914 | 277 |
! |
278 |
||
926 | 279 |
doCursorDown:n |
931 | 280 |
super cursorDown:n |
926 | 281 |
|
282 |
"Created: / 10.6.1998 / 15:15:05 / cg" |
|
931 | 283 |
"Modified: / 10.6.1998 / 16:55:25 / cg" |
926 | 284 |
! |
285 |
||
914 | 286 |
doCursorHome |
938 | 287 |
self cursorVisibleLine:1 col:1 |
288 |
"/ super cursorHome |
|
289 |
||
290 |
"Modified: / 10.6.1998 / 20:47:31 / cg" |
|
914 | 291 |
! |
292 |
||
293 |
doCursorLeft |
|
294 |
super cursorLeft |
|
295 |
! |
|
296 |
||
297 |
doCursorNewLine |
|
931 | 298 |
super cursorDown:1 |
299 |
||
300 |
"Modified: / 10.6.1998 / 16:55:57 / cg" |
|
914 | 301 |
! |
302 |
||
303 |
doCursorReturn |
|
304 |
super cursorToBeginOfLine |
|
305 |
! |
|
306 |
||
307 |
doCursorRight |
|
308 |
super cursorRight |
|
309 |
! |
|
310 |
||
926 | 311 |
doCursorRight:n |
312 |
self cursorCol:(cursorCol + n) |
|
313 |
||
314 |
"Created: / 10.6.1998 / 15:10:08 / cg" |
|
315 |
! |
|
316 |
||
914 | 317 |
doCursorUp |
318 |
super cursorUp |
|
926 | 319 |
! |
320 |
||
321 |
doSendInterrupt |
|
322 |
OperatingSystem sendSignal:(OperatingSystem sigINT) to:shellPid negated. |
|
323 |
||
934 | 324 |
"Modified: / 10.6.1998 / 17:49:49 / cg" |
914 | 325 |
! ! |
326 |
||
327 |
!TerminalView methodsFor:'initialization'! |
|
328 |
||
329 |
closeDownShell |
|
926 | 330 |
|pid| |
331 |
||
332 |
(pid := shellPid) notNil ifTrue:[ |
|
934 | 333 |
"/ Transcript print:'killing shell pid='; showCR:pid. |
334 |
||
926 | 335 |
OperatingSystem terminateProcessGroup:pid. |
336 |
OperatingSystem terminateProcess:pid. |
|
925 | 337 |
Delay waitForSeconds:1. |
338 |
shellPid notNil ifTrue:[ |
|
926 | 339 |
OperatingSystem killProcessGroup:pid. |
340 |
OperatingSystem killProcess:pid. |
|
925 | 341 |
shellPid := nil. |
342 |
]. |
|
926 | 343 |
OperatingSystem closePid:pid. |
914 | 344 |
]. |
345 |
||
346 |
readerProcess notNil ifTrue:[ |
|
347 |
readerProcess terminate. |
|
348 |
readerProcess := nil |
|
349 |
]. |
|
350 |
inStream notNil ifTrue:[ |
|
351 |
inStream close. |
|
352 |
inStream := nil |
|
353 |
]. |
|
354 |
outStream notNil ifTrue:[ |
|
355 |
outStream close. |
|
356 |
outStream := nil |
|
357 |
]. |
|
924 | 358 |
|
934 | 359 |
"Modified: / 10.6.1998 / 17:53:49 / cg" |
914 | 360 |
! |
361 |
||
362 |
destroy |
|
363 |
self closeDownShell. |
|
364 |
super destroy |
|
365 |
! |
|
366 |
||
367 |
escapeSequences:codes |
|
368 |
|tree| |
|
369 |
||
370 |
tree isNil ifTrue:[tree := escapeSequenceTree := IdentityDictionary new]. |
|
371 |
||
372 |
codes do:[:specEntry | |
|
373 |
|sequence function| |
|
374 |
||
375 |
sequence := (specEntry at:1) withEscapes. |
|
376 |
function := specEntry at:2. |
|
377 |
||
378 |
tree := escapeSequenceTree. |
|
379 |
||
380 |
sequence keysAndValuesDo:[:idx :char | |
|
381 |
|followup| |
|
382 |
||
383 |
idx == sequence size ifTrue:[ |
|
384 |
tree at:char put:function |
|
385 |
] ifFalse:[ |
|
386 |
followup := tree at:char ifAbsent:nil. |
|
387 |
followup isNil ifTrue:[ |
|
388 |
tree at:char put:(followup := IdentityDictionary new). |
|
389 |
]. |
|
390 |
tree := followup |
|
391 |
] |
|
392 |
] |
|
393 |
]. |
|
918 | 394 |
escapeLeadingChars := escapeSequenceTree keys asSet. |
395 |
escapeLeadingChars add:(Character cr). |
|
396 |
escapeLeadingChars add:(Character return). |
|
397 |
escapeLeadingChars add:(Character backspace). |
|
398 |
||
399 |
escapeLeadingChars := escapeLeadingChars asArray |
|
400 |
||
401 |
"Modified: / 9.6.1998 / 19:43:12 / cg" |
|
914 | 402 |
! |
403 |
||
404 |
initialize |
|
405 |
super initialize. |
|
406 |
||
407 |
showMatchingParenthesis := false. |
|
408 |
insertMode := false. |
|
936 | 409 |
alwaysAppendAtEnd := false. |
914 | 410 |
|
926 | 411 |
numberOfColumns := 80. |
412 |
numberOfLines := 25. |
|
413 |
||
914 | 414 |
self initializeEscapeSequences. |
415 |
self initializeKeyboardSequences. |
|
416 |
list := OrderedCollection new:24 withAll:''. |
|
417 |
||
418 |
self initializeKeyboardMap. |
|
419 |
||
420 |
" |
|
421 |
VT52TerminalView openShell |
|
926 | 422 |
VT100TerminalView openShell |
914 | 423 |
" |
926 | 424 |
|
936 | 425 |
"Modified: / 10.6.1998 / 19:21:57 / cg" |
914 | 426 |
! |
427 |
||
428 |
initializeEscapeSequences |
|
429 |
self subclassResponsibility. |
|
430 |
! |
|
431 |
||
432 |
initializeKeyboardMap |
|
433 |
|ctrlKeys cmdKeys| |
|
434 |
||
435 |
"/ setup my own keyboardMap, where control-keys are |
|
436 |
"/ not translated. |
|
437 |
kbdMap := device keyboardMap copy. |
|
438 |
||
439 |
ctrlKeys := kbdMap keys select:[:key | key startsWith:'Ctrl']. |
|
440 |
ctrlKeys do:[:key | kbdMap removeKey:key]. |
|
441 |
cmdKeys := kbdMap keys select:[:key | key startsWith:'Cmd']. |
|
442 |
cmdKeys do:[:key | kbdMap removeKey:key]. |
|
443 |
||
444 |
kbdMap removeKey:#Delete ifAbsent:[]. |
|
445 |
kbdMap removeKey:#BackSpace ifAbsent:[]. |
|
446 |
||
447 |
" |
|
448 |
VT52TerminalView openShell |
|
449 |
" |
|
450 |
! |
|
451 |
||
452 |
initializeKeyboardSequences |
|
453 |
self subclassResponsibility. |
|
454 |
! |
|
455 |
||
456 |
keyboardMap |
|
934 | 457 |
"return my keyboard map. This has control keys removed and |
458 |
those will be passed unchanged to the shell" |
|
459 |
||
914 | 460 |
^ kbdMap |
934 | 461 |
|
462 |
"Modified: / 10.6.1998 / 17:46:59 / cg" |
|
914 | 463 |
! |
464 |
||
465 |
startReaderProcess |
|
934 | 466 |
"Start a reader process, which looks for the commands output, |
467 |
and sends me #peocessInput:n: events whenever something arrives." |
|
468 |
||
914 | 469 |
readerProcess isNil ifTrue:[ |
470 |
readerProcess := [ |
|
471 |
[ |
|
926 | 472 |
|buffer n reading| |
473 |
||
474 |
reading := true. |
|
940 | 475 |
Stream streamErrorSignal handle:[:ex | |
476 |
Transcript showCR:ex errorString. |
|
477 |
Transcript showCR:OperatingSystem lastErrorString. |
|
478 |
] do:[ |
|
926 | 479 |
[true] whileTrue:[ |
480 |
Object abortSignal handle:[:ex | |
|
481 |
self showCursor. |
|
482 |
] do:[ |
|
483 |
outStream readWait. |
|
933
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
484 |
buffer := String new:1024. |
926 | 485 |
n := outStream nextAvailableBytes:1024 into:buffer startingAt:1. |
914 | 486 |
|
926 | 487 |
n > 0 ifTrue:[ |
933
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
488 |
self pushEvent:#processInput:n: with:buffer with:n. |
926 | 489 |
] ifFalse:[ |
490 |
n == 0 ifTrue:[ |
|
491 |
outStream atEnd ifTrue:[ |
|
492 |
outStream close. outStream := nil. |
|
493 |
inStream close. inStream := nil. |
|
494 |
||
495 |
Processor activeProcess terminate. |
|
496 |
] |
|
497 |
] |
|
914 | 498 |
] |
499 |
] |
|
500 |
] |
|
501 |
] |
|
502 |
] valueOnUnwindDo:[ |
|
503 |
readerProcess := nil |
|
504 |
] |
|
505 |
] fork. |
|
506 |
] |
|
507 |
||
508 |
" |
|
934 | 509 |
VT100TerminalView openShell |
914 | 510 |
" |
926 | 511 |
|
940 | 512 |
"Modified: / 11.6.1998 / 18:10:33 / cg" |
914 | 513 |
! |
514 |
||
515 |
startShell |
|
934 | 516 |
"start a shell on a pseudo terminal. |
517 |
Also fork a reader process, to read the shells output and |
|
518 |
pass it back to me." |
|
519 |
||
914 | 520 |
|p slaveFD execFdArray blocked exitStatus| |
521 |
||
522 |
p := ExternalStream makePTYPair. |
|
523 |
p isNil ifTrue:[ |
|
915 | 524 |
self warn:'cannot open pty'. |
914 | 525 |
^ self. |
526 |
]. |
|
527 |
||
528 |
"/ p at:1 is the master; |
|
529 |
"/ p at:2 is the slave |
|
530 |
inStream := outStream := (p at:1). |
|
531 |
inStream buffered:false. |
|
532 |
||
533 |
"/ fork a shell process on the slave-side |
|
534 |
slaveFD := (p at:2) fileDescriptor. |
|
535 |
||
536 |
execFdArray := Array with:slaveFD with:slaveFD with:slaveFD. |
|
537 |
||
538 |
blocked := OperatingSystem blockInterrupts. |
|
539 |
||
540 |
shellPid := Processor |
|
541 |
monitor:[ |
|
929 | 542 |
|e| |
543 |
||
544 |
e := IdentityDictionary new. |
|
545 |
e at:#TERM put:(self terminalType). |
|
546 |
||
914 | 547 |
OperatingSystem |
548 |
exec:'/bin/sh' |
|
549 |
withArguments:#('sh') |
|
929 | 550 |
environment:e |
914 | 551 |
fileDescriptors:execFdArray |
552 |
closeDescriptors:#() |
|
553 |
fork:true |
|
929 | 554 |
newPgrp:true. |
914 | 555 |
] |
556 |
action:[:status | |
|
935 | 557 |
"/ Transcript show:'pid:'; showCR:status pid. |
558 |
"/ Transcript show:'status:'; showCR:status status. |
|
559 |
"/ Transcript show:'code:'; showCR:status code. |
|
560 |
"/ Transcript show:'core:'; showCR:status core. |
|
914 | 561 |
status stillAlive ifFalse:[ |
562 |
exitStatus := status. |
|
563 |
OperatingSystem closePid:shellPid. |
|
564 |
shellPid := nil. |
|
565 |
self pushEvent:#shellTerminated |
|
566 |
]. |
|
567 |
]. |
|
568 |
||
569 |
shellPid isNil ifTrue:[ |
|
570 |
self halt. |
|
571 |
(p at:1) close. |
|
572 |
(p at:2) close. |
|
573 |
]. |
|
574 |
||
575 |
blocked ifFalse:[ |
|
576 |
OperatingSystem unblockInterrupts |
|
577 |
]. |
|
578 |
||
579 |
self startReaderProcess. |
|
580 |
||
581 |
" |
|
934 | 582 |
VT100TerminalView openShell |
914 | 583 |
" |
929 | 584 |
|
935 | 585 |
"Modified: / 10.6.1998 / 18:42:23 / cg" |
914 | 586 |
! ! |
587 |
||
588 |
!TerminalView methodsFor:'menu'! |
|
589 |
||
590 |
editMenu |
|
591 |
"return the views middleButtonMenu" |
|
592 |
||
593 |
<resource: #keyboard (#Copy #Paste #Print)> |
|
594 |
<resource: #programMenu> |
|
595 |
||
596 |
|items m sub shortKeys sensor| |
|
597 |
||
598 |
((sensor := self sensor) notNil and:[sensor ctrlDown]) ifTrue:[ |
|
599 |
items := #( |
|
600 |
('Interrupt' doSendInterrupt) |
|
601 |
). |
|
602 |
] ifFalse:[ |
|
603 |
items := #( |
|
604 |
('copy' copySelection Copy ) |
|
605 |
('paste' pasteOrReplace Paste ) |
|
606 |
('-' ) |
|
607 |
('save as ...' save SaveAs ) |
|
608 |
('print' doPrint Print ) |
|
609 |
). |
|
610 |
]. |
|
611 |
||
612 |
m := PopUpMenu itemList:items resources:resources. |
|
613 |
||
614 |
self hasSelection not ifTrue:[ |
|
615 |
m disable:#copySelection. |
|
616 |
]. |
|
617 |
^ m. |
|
618 |
||
619 |
"Modified: / 21.5.1998 / 15:52:38 / cg" |
|
620 |
||
621 |
||
622 |
! ! |
|
623 |
||
940 | 624 |
!TerminalView methodsFor:'misc'! |
914 | 625 |
|
626 |
removeTrailingBlankLines |
|
627 |
^ self |
|
628 |
! ! |
|
629 |
||
630 |
!TerminalView methodsFor:'processing - input'! |
|
631 |
||
933
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
632 |
processInput:buffer n:count |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
633 |
1 to:count do:[:i | |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
634 |
self nextPut:(buffer at:i). |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
635 |
]. |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
636 |
(self sensor hasEvent:#processInput:n: for:self) ifFalse:[ |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
637 |
self endEntry. |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
638 |
self makeCursorVisible. |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
639 |
]. |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
640 |
|
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
641 |
"Created: / 10.6.1998 / 17:26:09 / cg" |
de456e07697e
much better asynchronous display
Claus Gittinger <cg@exept.de>
parents:
931
diff
changeset
|
642 |
"Modified: / 10.6.1998 / 17:36:07 / cg" |
914 | 643 |
! ! |
644 |
||
645 |
!TerminalView methodsFor:'queries'! |
|
646 |
||
647 |
preferredExtent |
|
926 | 648 |
^ (fontWidth * numberOfColumns + (leftMargin * 2)) @ (self heightForLines:numberOfLines) |
649 |
||
650 |
"Modified: / 10.6.1998 / 14:47:03 / cg" |
|
929 | 651 |
! |
652 |
||
653 |
terminalType |
|
654 |
^ #dump |
|
655 |
||
656 |
"Modified: / 10.6.1998 / 14:47:03 / cg" |
|
657 |
"Created: / 10.6.1998 / 16:22:30 / cg" |
|
914 | 658 |
! ! |
659 |
||
660 |
!TerminalView methodsFor:'selection handling'! |
|
661 |
||
662 |
paste:someText |
|
663 |
"paste - redefined to send the chars to the shell instead |
|
664 |
of pasting into the view" |
|
665 |
||
666 |
someText asString string do:[:aChar | |
|
667 |
inStream nextPut:aChar |
|
668 |
] |
|
669 |
! ! |
|
670 |
||
671 |
!TerminalView class methodsFor:'documentation'! |
|
672 |
||
673 |
version |
|
940 | 674 |
^ '$Header: /cvs/stx/stx/libwidg2/TerminalView.st,v 1.21 1998-06-11 17:11:45 cg Exp $' |
914 | 675 |
! ! |