52: How do I avoid
scrolling in the last column of the last row?
A: If you use write or
writeln at the last column of the last row
(usually 80,25) the screen will scroll. If you wish to avoid the
scrolling you'll have to use an alternative write that does not move
the cursor. Here is a procedure to write without moving the cursor
uses Dos;
procedure WriteChar (Character : char; fgColor, bgColor : byte);
var r : registers;
begin
FillChar (r, SizeOf(r), 0);
r.ah := $09;
r.al := ord(Character);
r.bl := (bgColor shl 4) or fgColor;
r.cx := 1; { Number of repeats }
Intr ($10, r);
end; (* writechar *)
Thus, if you wish to write to the last column of the last row, you
must first move the cursor to that position. That can be done in
alternative ways. One might get there by having written previously
on the screen (with writeln and write routines) until one is in that
position. Another alternative is using GoToXY(80,20), but then you
have to use the Crt unit. If you don't want to use it, then you can
move the cursor by employing "GOATXY As the ordinary
GoToXY but no
Crt unit required" from ftp://garbo.uwasa.fi/pc/ts/tspa3470.zip.
There is an alternative interrupt service ($0A) which does the
same as service $09, but uses the default colors instead. Just
substitute $0A for $09, and leave the r.bl assignment out of the
WriteChar routine.
Another option for writing anyhere on the screen without
affecting the cursor is using direct screen writes:
uses Dos;
procedure WriteChar (c : char; x, y : byte; fg, bg : byte);
var vidstart : word;
regs : registers;
begin
FillChar (regs, SizeOf(regs), 0);
regs.ah := $0F;
Intr ($10, regs); { Color or MonoChrome video adapter }
if regs.al = 7 then vidstart := $B000 else vidstart := $B800;
mem[vidstart:((y-1)*80+x-1)*2] := ord(c);
mem[vidstart:((y-1)*80+x-1)*2+1] := (bg shl 4) or fg;
end;
To write to the last position simply apply e.g.
WriteChar ('X', 80, 25, 14, 0); { Yellow on black }
The foreground (fg) and the background (bg) color codes are
Black = 0
Blue = 1
Green = 2
Cyan = 3
Red = 4
Magenta = 5
Brown = 6
LightGray = 7
DarkGray = 8
LightBlue = 9
LightGreen = 10
LightCyan = 11
LightRed = 12
LightMagenta = 13
Yellow = 14
White = 15
Blink = 128
Yet another option is the following, but it needs the Crt unit. On
the other hand, it uses the default color. This is quite a good and
easy solution. I captured this fairly frequent idea from a posting
by Robert Buergi (nbuero@hslrswi.hasler.ascom.ch).
uses Crt;
procedure WriteToCorner (c : char);
begin
Inc (WindMax);
GotoXY (80, 25);
write (c);
Dec (WindMax);
end; (* writeToCorner *)