Can someone tell me a good way to clear one line of displayed text.

I want to erase the very bottom line of the dos window (row 25, column 80), but I don't want to scroll the entire screen to do it. In fact, the only thing I can alter is the bottom line; everything else must remain intact.

What I was thinking about doing was just filling the bottom line with blanks and then reseting the cursor to column 0 row 25. Actually I think I tried that once but after clearing it jadvanced the cursor to the next row so it scrolled the screen up once which I can't have.

Any other ways to do this more efficiently where a beginner can understand?

Thanks
Posted on 2002-04-08 20:48:34 by freedumb87
i guess the most logical way, without calling any interrupts (which are slower, anyway) is to simply write to video memory. something along the lines (no pun intended) of:

push 0b800h ;load video segment @ b800h
pop ds ;into data seg
mov bx,80*24*2 ;beginning of 25th row - two bytes for each char
mov dx,2007h ;space 32, + default colour attribute (07 egal gris)
mov cx,-79 ;80 spaces
@@:
mov ,dx ;move stuff into memory
dec cx ;decrease count
jne @B
int 20h ;quit

sorry if this doesn't work - haven't tried it. hope you get the idea.
no need to reposition the cursor or anything.

or you could use like repne movsw
Posted on 2002-04-08 21:23:15 by jademtech
If you're working in DOS mode you can write directly to the textmode video memory. I'm a little rusty on real mode asm, but I'll give it a go.



push 0B800h ;textmode ram starts at B800:0000
pop es
mov di, 24 * 80 * 2 ;last line * screen width * 2
xor ax, ax ;going to fill it with 0s
mov cx, 80 ;screen width
rep stosw




I don't know if that works, but that's the general idea. Maybe a little C will help you visualize better
Here's something that will let you output to anywhere on the screen.



#define SCRWIDTH 80
#define SCRHEIGHT 25

void WriteToTextMode( int x, int y, char ascii, char color )
{
unsigned char far* screen = (unsigned char far*)0xB8000000L;
int offset = y * ( SCRWIDTH << 1 ) + ( x << 1 );
screen[ offset ] = color;
screen[ offset+1 ] = ascii;
}
Posted on 2002-04-08 21:36:16 by iblis
Doh, sorry jademtech... you posted while I was writing ;)
Posted on 2002-04-08 21:37:30 by iblis
Wow two replies at one time :alright:. I don't mind that..heh.

I am going to try it now...

Thanks guys.
Posted on 2002-04-08 21:58:01 by freedumb87
Yes that does work. It clears the last line of my window. But now when I try to rewrite in that area it remains blank. Got any clues why? :eek:

Thanks
Posted on 2002-04-08 22:18:00 by freedumb87

Doh, sorry jademtech... you posted while I was writing ;)


haha... freedumb87 is right... nothing wrong wit dat ;)

freedumb87:
if you were using iblis' method, i think it's because the attribute (in the low byte of ax) was set to 0, which is black. so black text is being written there.

so instead of:
xor eax,eax

you might want to try:
mov eax,2007h
or
mov eax,7
or some variation.
Posted on 2002-04-08 22:27:31 by jademtech
whoops. terribly sorry. using ibilis' code, this is how to do it:

-u 100
0B30:0100 B800B8 MOV AX,B800
0B30:0103 50 PUSH AX
0B30:0104 07 POP ES
0B30:0105 BF000F MOV DI,0F00
0B30:0108 B82007 MOV AX,0720
0B30:010B B98000 MOV CX,0080
0B30:010E F3 REPZ
0B30:010F AB STOSW
0B30:0110 CD20 INT 20

(just a screen cap from debug)

mixed up byte ordering for ax.
Posted on 2002-04-08 22:47:14 by jademtech
Yes, set the high byte of ax (or the low byte? i forget which) to the color you want. The color byte is divided into 2 4bit values. My memory may be a bit off, but I think the colors go like so:




mov al, ascii_character
mov ah, 0XYh

where

X = background color
Y = foreground color

X Y
_______|_______ _______|_______
{ }{ }
[7] [6] [5] [4] [3] [2] [1] [0] <--- ah
| { } | { }
| | | |
| color | color
| |
| |
blink bit intensity bit


-------color------- ----blink bit----
| | | |
| 0 Black | | 0 normal |
| 1 Blue | | 1 blinking |
| 2 Green | -----------------
| 3 Cyan |
| 4 Red | --intensity bit--
| 5 Purple | | |
| 6 Brown | | 0 normal |
| 7 Grey | | 1 bright |
------------------- -----------------



So for example if you wanted bright green blinking text on a blue background, then mov ah, 9A.
Hope that helps. Traditionally, text mode uses 07 as the color.
Posted on 2002-04-08 22:58:23 by iblis
Man I don't know what's wrong. I can't seem to get it to work.

Let me explain to you what I am aiming for.

I am displaying a message at the bottom of the screen which is prompt that waits for the user to enter a key combination. For example, an option is to press ctrl+E which ends the program. Another is to Crtl+C to clear the entire screen except for the last row.

So, once a user presses a proper key combo the initial prompt should disappear and a new prompt or message should appear. For instance, when the user presses Ctrl+E I want the prompt to be rewritten over by another message that says something like "press any key to end the program." So what I thought of doing was just to have a function that was called everytime a new key combo was pressed. But with the code that Iblis provided it allows me to clear it but the prompt that should be displayed isn't showing up. The only way to get a new message to appear is to press another key combo that doesn't use the clear function.

Understand?


Maybe I should be clearing only the text that is left after the new message is displayed. I don't konw how to go about that either. I like the way you guys are telling me but I just can't implement it.

I am posting a picture of the dos window that I am getting once I press a key combo that uses the clear function.

Here is the code that I used...Maybe I am doing something wrong(probably so) :

push 0B800h
pop es
mov di, 24 * 80 * 2
MOV AH,9Ah
mov cx, 80
rep stosw
Posted on 2002-04-08 23:48:26 by freedumb87
Freedumb,

First, "mov ah, 9A" was just an example. Typically the color for text mode is 07.

Secondly, you need to "mov al, 0" or "mov al, 20". Those two values are null and whitespace respectively. They both work.

Thirdly, every time you output to stdout, the cursor will advance to the end of your prompt, so after clearing the bottom line, you will need to set the cursor position back to the beginning of the line before you output anything else.

Fourthly, you really should make efforts to understand how text mode works with respect to video memory. It will make your job so much easier.


Here's some code to set the cursor position:


; INT 10h, function AH = 02h - set cursor position.
;
SetCursor proc
; Before calling set dl = xpos, dh = ypos on the screen
; i.e. mov dh, column
; i.e mov dl, row
mov ah, 02h ; function 2
xor bh, bh ; vidpage 0
int 10h ; call bios
ret

SetCursor endp



Good luck!
Posted on 2002-04-09 01:19:30 by iblis
Thanks again,

One thing that I do know how to do is set the cursor. I just wasn't setting it after clearing directly from the video segment. I thought I read in the post there was no need to set the cursor position. At the moment I am able to clear the line using a line of blank spaces and then reseting the cursor. But I will ieep trying the other way too.

Thanks so much for the help. I really appreciate it.
Posted on 2002-04-09 10:23:18 by freedumb87

Thanks again,

One thing that I do know how to do is set the cursor. I just wasn't setting it after clearing directly from the video segment. I thought I read in the post there was no need to set the cursor position. At the moment I am able to clear the line using a line of blank spaces and then reseting the cursor. But I will ieep trying the other way too.

Thanks so much for the help. I really appreciate it.


that was me (about setting the cursor). but do you need to? the cursor should stay in the same position after writing to vid. memory. isn't that correct?! aack.
Posted on 2002-04-09 18:29:35 by jademtech
Originally posted by jademtech that was me (about setting the cursor). but do you need to? the cursor should stay in the same position after writing to vid. memory. isn't that correct?! aack.


Jademtech,

Yes but what if he's using stdout to ouput his text? Either printf or the DOS calls. That's what I figured he was doing, since he didn't know how to clear the bottom line of text.
Posted on 2002-04-09 19:59:23 by iblis