When a TAB character is displayed in the screen, the Windows screen driver translates it to a series of blank spaces (usually 8 ), so in this case the TAB is destructive: any text previously displayed in the screen is overwritten by the spaces when the TAB is displayed.
The number of spaces vary accordingly to the position of the cursor when the TAB is displayed, so the final cusor position after the spaces is always multiple of 8. For example, if the cursor is at first column in a line, a TAB is displayed as 8 spaces, but if the cursor is at column 1, the TAB is displayed as 7 spaces, etc.
A behavior that may seems logical at first is that a BS character displayed after the TAB move the cursor back the same number of spaces displayed by the TAB, that is, the BS deletes the action of the TAB. What IMHO is a bug is that another BS displayed after the first one also move the cursor back the same number of spaces, and, if the cursor reach the left margin of the screen, the cursor wrap-around to end of the previous screen line!
For example, if the cursor is at first column in a line, a sequence of <TAB><BS><BS> characters move the cursor one line above and 7 columns at left of the right screen margin. If the screen have 80 characters wide, each additional group of 10 BS characters moves the cursor one line up more. After that, each additional BS character move the cursor 8 characters more to left in the same line. Finally, if another single standard character is displayed, then the following BS characters will move the cursor just one character to the left.
In this way, the cursor can be placed at any previous line and column in the screen by just calculating the proper number of BS characters to show after a TAB one, and after an additional standard char. If the desired position is below the current cursor position, just first place the cursor at the bottom of the screen via several ECHO/ commands, and after that move the cursor up and left to the desired location with this method.
The Batch file below is an example of previous procedure. The calculation of the number of BS characters and the ECHO command is really simple and can be added to any program in a very simple way, but this program is large and complex because it display a screen full of coordinates and allows you to enter the position of several marks, that will be displayed in the screen in the proper positions.
EDIT 2017-05-28: I added the method to correctly get a TAB character in both Windows XP and newer versions.
Code: Select all
@echo off
setlocal EnableDelayedExpansion
echo Enter coordinates in line,col order to move the cursor and show a mark
echo/
echo The valid ranges are: 0 ^<= line ^<= 30 and 0 ^<= column ^<= 71;
echo if a value is out of range, the bell will ring.
echo/
pause
rem Get a BEL, BS and a TAB characters
set "BEL="
for /F %%a in ('echo prompt $H ^| cmd') do set "BS=%%a"
set "TAB="
rem First, try the method for Windows XP
for /F "skip=4 delims=pR tokens=2" %%a in ('reg query hkcu\environment /v temp' ) do set "TAB=%%a"
rem Then, the method for newer versions
rem http://www.dostips.com/forum/viewtopic.php?f=3&t=1733&p=6840#p6853
for /F "tokens=2 delims=0" %%a in ('shutdown /? ^| findstr /BC:E') do if not defined TAB set "TAB=%%a"
rem Get a string with 162 BS characters, the maximum used in this program
set "BSs="
for /L %%i in (1,1,162) do set "BSs=!BSs!!BS!"
mode 80,32
set "line1="
for /L %%i in (1,1,8) do set "line1=!line1!0123456789"
set "line2="
for /L %%i in (1,1,8) do set "line2=!line2!^!l^! "
set "line2=!line2:~0,-1!^!l^!"
set "line3="
for /L %%i in (1,1,8) do set "line3=!line3!^!l^! 2 4 6 8 "
set "line3=!line3:~0,-1!^!l^!"
set "twoORthree=23"
< NUL (
for /L %%a in (1,1,3) do (
set /P "=%line1%" & set "l=1"
set /P "=%line2%" & set /A "l+=1"
for /L %%b in (1,1,4) do (
if %%a neq 2 (
set /P "=%line3%"
) else if "!twoORthree:%%b=!" equ "%twoORthree%" (
set /P "=%line3%"
) else (
echo %line3:~0,-15%
)
set /A "l+=1"
set /P "=%line2%" & set /A "l+=1"
)
)
set /P "=%line1:~0,-1%"
)
rem Initialize cursor position at middle of screen, to read input there
echo 9%TAB%!BSs!
set "currLine=16"
set "letters=_ABCDEFGHIJKLMNOPQRSTUVWXYZ"
set "num=1"
:loop
set "position="
set /P "position=Enter line,col for mark !letters:~%num%,1!: !BSs:~0,5!"
if not defined position goto end
for /F "tokens=1,2 delims=, " %%x in ("%position%") do set /A y=%%x, x=%%y, error=1
if 0 leq %y% if %y% leq 30 if 0 leq %x% if %x% leq 71 set "error="
if defined error (
echo %TAB%!BSs:~0,12!!BEL!
goto loop
)
if %y% leq %currLine% (
rem New position above: move cursor up and show point
call :MoveCursorupAndShow "(currLine-y-1)" x "!letters:~%num%,1!(%y%,%x%)"
rem And move cursor down, back to original input line
set /A down=currLine-y-2, cntBSup+=10
for /L %%i in (1,1,!down!) do echo/
if !down! lss 0 for /F %%i in ("!cntBSup!") do echo %TAB%!BSs:~0,%%i!
) else (
rem New position below: first, move cursor to last line
for /L %%i in (1,1,15) do echo/
rem Then, move cursor up and show point
call :MoveCursorupAndShow "(30-y)" x "!letters:~%num%,1!(%y%,%x%)"
rem And move cursor up, back to original input line, using the same method
set /A down=30-y
for /L %%i in (1,1,!down!) do echo/
echo %TAB%!BSs!
)
set /A num+=1
if %num% leq 26 goto loop
:end
cls
goto :EOF
:MoveCursorupAndShow Linesup Column "Text"
set /A "cntBSup = 2 + 10 * %~1 + (9-(%2+6)/8), cntBSleft = 8-(%2+6)%%8"
set "BSsLeft="
if %cntBSleft% gtr 0 set "BSsLeft=_!BSs:~0,%cntBSleft%!"
echo %TAB%!BSs:~0,%cntBSup%!!BSsLeft!%~3
exit /B
The image below is an output example of previous program after 8 marks were displayed at various positions.
Tested on Windows 8.1
Antonio