Terminal control/Preserve screen

From Rosetta Code
Task
Terminal control/Preserve screen
You are encouraged to solve this task according to the task description, using any language you may know.

The task is to clear the screen, output something on the display, and then restore the screen to the preserved state that it was in before the task was carried out. There is no requirement to change the font or kerning in this task, however character decorations and attributes are expected to be preserved. If the implementer decides to change the font or kerning during the display of the temporary screen, then these settings need to be restored prior to exit.

Applesoft BASIC[edit]

Restores 40 x 24 TEXT screen, cursor position, display mode, and speed. Adjusts HIMEM to make room to store 1024 bytes aligned to the 256 byte page boundary. POKEs a machine language "copy 4 pages of memory" routine into page 3.

 10  LET FF = 255:FE = FF - 1
11 LET FD = 253:FC = FD - 1
12 POKE FC, 0 : POKE FE, 0
13 LET R = 768:H = PEEK (116)
14 IF PEEK (R) = 162 GOTO 40
 
15 LET L = PEEK (115) > 0
16 LET H = H - 4 - L
17 HIMEM:H*256
18 LET A = 10:B = 11:C = 12
19 LET D = 13:E = 14:Z = 256
20 POKE R + 0,162: REMLDX
21 POKE R + 1,004: REM #$04
22 POKE R + 2,160: REMLDY
23 POKE R + 3,000: REM #$00
24 LET L = R + 4: REMLOOP
25 POKE L + 0,177: REMLDA
26 POKE L + 1,FC:: REM($FC),Y
27 POKE L + 2,145: REMSTA
28 POKE L + 3,FE:: REM($FE),Y
29 POKE L + 4,200: REMINY
30 POKE L + 5,208: REMBNE
31 POKE L + 6,Z - 7: REMLOOP
32 POKE L + 7,230: REMINC
33 POKE L + 8,FD:: REM $FD
34 POKE L + 9,230: REMINC
35 POKE L + A,FF:: REM $FF
36 POKE L + B,202: REMDEX
37 POKE L + C,208: REMBNE
38 POKE L + D,Z - E: REMLOOP
39 POKE L + E,096: REMRTS
 
40 POKE FD, 4 : POKE FF, H
41 CALL R : S = PEEK(241)
42 LET V = PEEK(37)
43 LET C = PEEK(36)
44 LET M = PEEK(50)
45 LET F = PEEK(243)
 
50 HOME : INVERSE
51 PRINT "ALTERNATE BUFFER"
52 FLASH : SPEED = 125
53 FOR I = 5 TO 1 STEP -1
54 PRINT "GOING BACK IN: "I
55 NEXT I
 
60 POKE FD, H : POKE FF, 4
61 CALL R : POKE 241, S
62 VTAB V + 1 : HTAB C + 1
63 POKE 50, M : POKE 243, F

BBC BASIC[edit]

The screen is saved as a bitmap:

      PRINT "This is the original screen"
OSCLI "GSAVE """ + @tmp$ + "bbcsave"""
WAIT 200
CLS
PRINT "This is the new screen, following a CLS"
WAIT 200
OSCLI "DISPLAY """ + @tmp$ + "bbcsave"""

C[edit]

For Xterm. "Allow alternate screen buffer" must be enabled by the popup menu.
#include <stdio.h>
#include <unistd.h>
 
int main()
{
int i;
printf("\033[?1049h\033[H");
printf("Alternate screen buffer\n");
for (i = 5; i; i--) {
printf("\rgoing back in %d...", i);
fflush(stdout);
sleep(1);
}
printf("\033[?1049l");
 
return 0;
}

Common Lisp[edit]

Translation of: C
 
(format t "~C[?1049h~C[H" (code-char #O33) (code-char #O33))
(format t "Alternate screen buffer~%")
(loop for i from 5 downto 1 do (progn
(format t "~%going back in ~a" i)
(sleep 1)
))
(format t "~C[?1049l" (code-char #O33))
 

JavaScript[edit]

(function() {
var orig= document.body.innerHTML
document.body.innerHTML= '';
setTimeout(function() {
document.body.innerHTML= 'something';
setTimeout(function() {
document.body.innerHTML= orig;
}, 1000);
}, 1000);
})();

This implementation assumes that Javascript is running in the browser.

This task does not admit sample output, but you can demonstrate this solution for yourself using the chrome browser: control-shift-J then copy and paste the above into the command line, and hit enter.

Mathematica[edit]

Run["tput smcup"]    (* Save the display *)
Run["echo Hello"]
Pause[5] (* Wait five seconds *)
Run["tput rmcup"]

Nim[edit]

Translation of: Python
import os
 
echo "\e[?1049h\e[H"
echo "Alternate buffer!"
 
for i in countdown(5, 1):
echo "Going back in: ", i
sleep 1000
 
echo "\e[?1049l"

Perl 6[edit]

print "\e[?1049h\e[H";
say "Alternate buffer!";
 
for 5,4...1 {
print "\rGoing back in: $_";
sleep 1;
}
 
print "\e[?1049l";

PicoLisp[edit]

#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
 
(call 'tput "smcup")
(prinl "something")
(wait 3000)
(call 'tput "rmcup")
 
(bye)

Python[edit]

Similar to the C example above:

#!/usr/bin/env python
 
import time
 
print "\033[?1049h\033[H"
print "Alternate buffer!"
 
for i in xrange(5, 0, -1):
print "Going back in:", i
time.sleep(1)
 
print "\033[?1049l"

Racket[edit]

 
#lang racket
 
(require racket/system)
(define (flash str)
(system "tput smcup")
(displayln str)
(sleep 2)
(system "tput rmcup")
(void))
 
(flash "Hello world.")
 

REXX[edit]

This version only works with PC/REXX and Personal REXX.

/*REXX pgm saves the screen contents, clear it, write +++, restore orig.*/
parse value scrsize() with sd sw . /*determine how big the screen is*/
parse value cursor(1,1) with r_ c_ /*find where the cursor is also. */
do original=1 for sd /*get the original screen content*/
@line.original=scrread(original,1,sw)
end
'CLS' /*start with a clean slate. */
do 20
say copies('$',60) /*write a score of sixty bucks. */
end
'CLS' /*start with a clean slate, again*/
do restore=1 for sd /*restore the original screen. */
call scrwrite restore,1,strip(@line.restore,'T')
end
call cursor r_,c_ /*restore the original cursor pos*/
/*stick a fork in it, we're done.*/

This REXX program makes use of   SCRSIZE   REXX program (or BIF) which is used to determine the screen size of the terminal (console).
The   SCRSIZE.REX   REXX program is included here ──► SCRSIZE.REX.

Scala[edit]

Similar to the C example above:

print("\033[?1049h\033[H")
println("Alternate buffer!")
 
for (i <- 5 to 0 by -1) {
println(s"Going back in: $i")
Thread.sleep(1000)
}
 
print("\033[?1049l")

Sidef[edit]

Translation of: Perl 6
print "\e[?1049h\e[H";
say "Alternate buffer!";
 
3.downto(1).each { |i|
say "Going back in: #{i}";
Sys.sleep(1);
}
 
print "\e[?1049l";

Tcl[edit]

On Unix terminals only, with the help of tput:

# A helper to make code more readable
proc terminal {args} {
exec /usr/bin/tput {*}$args >/dev/tty
}
 
# Save the screen with the "enter_ca_mode" capability, a.k.a. 'smcup'
terminal smcup
# Some indication to users what is happening...
puts "This is the top of a blank screen. Press Return/Enter to continue..."
gets stdin
# Restore the screen with the "exit_ca_mode" capability, a.k.a. 'rmcup'
terminal rmcup

UNIX Shell[edit]

Works with: Bourne Shell
Works with: bash
#!/bin/sh
tput smcup # Save the display
echo 'Hello'
sleep 5 # Wait five seconds
tput rmcup # Restore the display

XPL0[edit]

include c:\cxpl\codes;  \intrinsic 'code' declarations
 
proc SetPage(P); \Select active display page for video screen
int P;
int CpuReg;
[CpuReg:= GetReg; \access CPU registers
CpuReg(0):= $0500 + P; \call BIOS interrupt $10, function 5
SoftInt($10);
]; \SetPage
 
[SetPage(1); \enable page 1 text display screen
Clear; \clear screen and output something
Text(0, "Hit any key to restore original screen. ");
if ChIn(1) then []; \wait for keystroke
SetPage(0); \restore original, default text screen, page 0
]

Z80 Assembly[edit]

Using the Amstrad CPC firmware:

		org	$3000
 
txt_output: equ $bb5a
scr_clear: equ $bc14
wait_char: equ $bb06
scr_get_loc: equ $bc0b
scr_set_off: equ $bc05
 
push bc
push de
push hl
push af
 
call scr_get_loc ; save this value just in case the
push hl ; original screen has been scrolled vertically
 
ld hl,$c000 ; copy screen to block 1
ld de,$4000
ld bc,$4000
ldir
 
call scr_clear
ld hl,text
 
print: ld a,(hl)
cp 0
jr z,key
call txt_output
inc hl
jr print
 
key: call wait_char
pop hl
call scr_set_off
ld hl,$4000 ; restore screen
ld de,$c000
ld bc,$4000
ldir
pop af
pop hl
pop de
pop bc
ret
 
text: defm "This is some text. Please press a key.\0"