Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2000-09

Reading the screen

11 messages · 8 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Unknown author

Does anyone know how to read characters from a text-mode win32/go32 program? I need to gotoxy and read some information, but I can't figure out how.

TIA...

Jim

Matthew Bradford
to Unknown author

Jim,
I looked around the docs and couldn't find anything that would help you, however, I think I still may have a solution for you.

If you want to write something to the console you can write a wrapper for the writeln procedure that would do the following:
1. behave like the current write/writeln procedures do
2. in addition, keep track of all screen writes in an array eg. var Screen[1..80,1..25] of char;
Now, that could get kind of tricky when you start throwing in windows and such. But, for straight screen writing and no fancy stuff, that should do the trick. Also, it wouldn't be all that hard to write it so that the array would totally mimic the screen.

A second option, is pick up an assembler book and call the interupt that will return that info for you. (A word of caution on that though. Interupts are slow, so if speed is important, that would not be the way to go. Also, the use of assembler makes your program very non-portable. However, if neither of those are a concern for you it would probably be easier.)

Perhaps one of the more experienced people with FPC will have better insight into a way to do this that is already built into the language.

Matt

Show quoted text 13 lines
Does anyone know how to read characters from a text-mode win32/go32 program? I need to gotoxy and read some information, but I can't figure out how. TIA... Jim _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/mailman/listinfo/fpc-pascal
Kuba Ober
to Unknown author: Does anyone know how to read characters from a text-mode win32/go32 program? I need to…

Under win32: look at
http://msdn.microsoft.com/library/default.asp (only using IE5.0/5.5 or Netscape 4.76)
On left-hand-side TOC window, navigate to
Platform SDK
- Base services
-- Files and I/O
--- Consoles and Character-Mode Support
---- Using the Console

Below is the C example for reading and writing block of characters and attributes, using ReadConsoleInput and WriteConsoleOutput.

MSDN is a good source of Win32 info, alas I have no idea about GO32.

#include <windows.h>
VOID main(void)
{
     HANDLE hStdout, hNewScreenBuffer;
     SMALL_RECT srctReadRect;
     SMALL_RECT srctWriteRect;
     CHAR_INFO chiBuffer[160]; // [2][80];
     COORD coordBufSize;
     COORD coordBufCoord;
     BOOL fSuccess;
     // Get a handle to the STDOUT screen buffer to copy from and
     // create a new screen buffer to copy to.
     hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
     hNewScreenBuffer = CreateConsoleScreenBuffer(
        GENERIC_READ |           // read/write access
        GENERIC_WRITE,
        0,                       // not shared
        NULL,                    // no security attributes
        CONSOLE_TEXTMODE_BUFFER, // must be TEXTMODE
        NULL);                   // reserved; must be NULL
     if (hStdout == INVALID_HANDLE_VALUE ||
             hNewScreenBuffer == INVALID_HANDLE_VALUE)
     {
         MyErrorExit("CreateConsoleScreenBuffer");
     }
     // Make the new screen buffer the active screen buffer.
     if (! SetConsoleActiveScreenBuffer(hNewScreenBuffer) )
         MyErrorExit("SetConsoleActiveScreenBuffer");
     // Set the source rectangle.
     srctReadRect.Top = 0;    // top left: row 0, col 0
     srctReadRect.Left = 0;
     srctReadRect.Bottom = 1; // bot. right: row 1, col 79
     srctReadRect.Right = 79;
     // The temporary buffer size is 2 rows x 80 columns.
     coordBufSize.Y = 2;
     coordBufSize.X = 80;
     // The top left destination cell of the temporary buffer is
     // row 0, col 0.
     coordBufCoord.X = 0;
     coordBufCoord.Y = 0;
     // Copy the block from the screen buffer to the temp. buffer.
     fSuccess = ReadConsoleOutput(
        hStdout,        // screen buffer to read from
        chiBuffer,      // buffer to copy into
        coordBufSize,   // col-row size of chiBuffer
        coordBufCoord,  // top left dest. cell in chiBuffer
        &srctReadRect); // screen buffer source rectangle
     if (! fSuccess)
         MyErrorExit("ReadConsoleOutput");
     // Set the destination rectangle.
     srctWriteRect.Top = 10;    // top lt: row 10, col 0
     srctWriteRect.Left = 0;
     srctWriteRect.Bottom = 11; // bot. rt: row 11, col 79
     srctWriteRect.Right = 79;
     // Copy from the temporary buffer to the new screen buffer.
     fSuccess = WriteConsoleOutput(
         hNewScreenBuffer, // screen buffer to write to
         chiBuffer,        // buffer to copy from
         coordBufSize,     // col-row size of chiBuffer
         coordBufCoord,    // top left src cell in chiBuffer
         &srctWriteRect);  // dest. screen buffer rectangle
     if (! fSuccess)
         MyErrorExit("WriteConsoleOutput");
     Sleep(10000);
     // Restore the original active screen buffer.
     if (! SetConsoleActiveScreenBuffer(hStdout))
         MyErrorExit("SetConsoleActiveScreenBuffer");

}

Martin Hankovec

Hi,
I think, here is a solution for text console under DOS: .....
uses go32v2....
....
{reads ascii value and attribut from text console} {x,y - coordinates, returns ascii and attribut of char on position x,y}

procedure getscreenchar(x,y:integer;var ascii:char;var attribut:byte);
var
  segment,offset:word;
begin
    segment:=$a7f7+(10*y)+(x div 8);	{address of char}
    offset:=$ffee+((x mod 8)*2);
    dosmemget(segment,offset,ascii,1);	{read ascii}
    inc(offset);
    dosmemget(segment,offset,attribut,1);	{read attribut}
end;

Have a good day
Martin H.

Johann Glaser
to Martin Hankovec

Hi!

Hmm, I saw this way and I wonder why it is necessary to do such complicated segment calculations. Is there any reason?

Show quoted text 7 lines
begin segment:=$a7f7+(10*y)+(x div 8); {address of char} offset:=$ffee+((x mod 8)*2); dosmemget(segment,offset,ascii,1); {read ascii} inc(offset); dosmemget(segment,offset,attribut,1); {read attribut} end;

It would more clear and far easier when doing it that way:

Begin
  Segment := $B800;
  Offset  := 2*(Y*80 + X);
  DosMemGet(Segment,Offset,Ascii,1);
  Inc(Offset);
  DosMemGet(Segment,Offset,Attribut,1);
End;

The value $B800 is the start of the video memory in text mode.

Be careful with the value "80" for the line width. It is possible (e.g. in Windows DOS-Boxes or when using SVGATextMode that there are more or less than 80 chars per line.

A bit better way would be calling "DosMemGet" only once fetchig two bytes. Therefore "Ascii" and "Attribut" must be on two directly following memory adresses.

Bye
Hansi

Sent through GMX FreeMail - http://www.gmx.net
Martin Hankovec

Hi,
I just tried the code:

Show quoted text 7 lines
Begin Segment := $B800; Offset := 2*(Y*80 + X); DosMemGet(Segment,Offset,Ascii,1); Inc(Offset); DosMemGet(Segment,Offset,Attribut,1); End;

It's easier, but it works bad. I haven't test it in detail, but if I use it in my unit for text user interface, it doesn't work in all cases. As I tested the video RAM myself, it's not full linear sequence of bytes, but it has blocks of 8 characters (16 bytes). This code gets the bytes from linear address space. So some addresses are the same, but other addresses are different (You'll get another character !!).

Anybody tested this code and found it FULL working ? Maybe I'm wrong.

Bye

Martin

Florian Klaempfl
to Johann Glaser: Hi! Hmm, I saw this way and I wonder why it is necessary to do such complicated segment…
Show quoted text 24 lines
Hi! Hmm, I saw this way and I wonder why it is necessary to do such complicated segment calculations. Is there any reason? > begin > segment:=$a7f7+(10*y)+(x div 8); {address of char} > offset:=$ffee+((x mod 8)*2); > dosmemget(segment,offset,ascii,1); {read ascii} > inc(offset); > dosmemget(segment,offset,attribut,1); {read attribut} > end; It would more clear and far easier when doing it that way: Begin Segment := $B800; Offset := 2*(Y*80 + X); DosMemGet(Segment,Offset,Ascii,1); Inc(Offset); DosMemGet(Segment,Offset,Attribut,1); End;

It should working this way.

BTW: You can also use mem[seg:ofs].

Johann Glaser
to Martin Hankovec: I just tried the code: It's easier, but it works bad. I haven't test it in detail, but if…

Hi!

Show quoted text 19 lines
>Begin >Segment := $B800; > Offset := 2*(Y*80 + X); > DosMemGet(Segment,Offset,Ascii,1); > Inc(Offset); > DosMemGet(Segment,Offset,Attribut,1); >End; It's easier, but it works bad. I haven't test it in detail, but if I use it in my unit for text user interface, it doesn't work in all cases. As I tested the video RAM myself, it's not full linear sequence of bytes, but it has blocks of 8 characters (16 bytes). This code gets the bytes from linear address space. So some addresses are the same, but other addresses are different (You'll get another character !!).

Are you really sure? This shouldn't happen, because the character storage is _only_ dependant on the graphics card. And this does it scince CGA this way. If the Protected Mode Wrapper has unpredictable behavior, than you may be right. Or the hardware (too fast bus access, caching, ...) is unpredictable.

I used the video memory a lot when I was working on DOS a few years ago. And it worked properly. But this was on smaller machines. In Protected Mode it worked properly too. No characters were on the wrong place.

Bye
Hansi

Sent through GMX FreeMail - http://www.gmx.net
Martin Hankovec

Hi,
I have found the problem :-))) Your procedure takes coordinates from 0, but my procedure (and gotoxy too) takes it from 1.

It's worth more testing, I know. But I hadn't more time then get your procedure from mail and put it into my unit :-)

I'm not specialist in VideoRAM configuration and mapping. I only explained, how works my crazy procedure ;-))). Maybe me description was crazy, but functional (I hope).

Can it be done in some way under Win console for WIN32 target? Under Linux I can use consolebuf. Can it be used under Win32 ?

Have a good day.

Martin

Jeff Wormsley
to Martin Hankovec
AM Martin Hankovec wrote
Can it be done in some way under Win console for WIN32 target? Under Linux I can use consolebuf. Can it be used under Win32 ?

This is code snagged from a console mode windowing unit I did last year in Delphi. It should be failry easy to make work in FPC. There is a lot of crap you won't need, but it is complete enough that you should be able to pop it into a test program and run it.

Uses Windows;
Var
 DestRect       : TSmallRect;
 Win_MaxX       : Byte;             { Max Window X          }
 Win_MaxY       : Byte;             { Max Window Y          }
 Win_MinX       : Byte;             { Min Window X          }
 Win_MinY       : Byte;             { Min Window Y          }
 Win_Save       : Array[0..24, 0..79] of TCharInfo; { Window Save Buffer   }
 BuffSize       : TCoord;
 BuffCoord      : TCoord;
 hOut           : THandle;

{ Win_Height ---------------------------------------------------------------- }

Function Win_Height: Word;
Begin
 Win_Height := Win_MaxY - Win_MinY + 1                { Return Window Height  }
End;

{ Win_Width ----------------------------------------------------------------- }

Function Win_Width: Word;
Begin
 Win_Width := Win_MaxX - Win_MinX + 1                 { Return Window Width   }
End;

{ Win_Push ------------------------------------------------------------------ } { This code grabs a region of the screen and saves it in a buffer } { Screen region is defined by the coordinates in Win_MinX, Win_MinY, } { Win_MaxX, Win_MaxY. }

Procedure Win_Push;
Var
 Y                : Byte;
Begin
 DestRect.Left   := 1;
 DestRect.Top    := 1;
 DestRect.Right  := Win_Width;
 DestRect.Bottom := Win_Height;
 BuffSize.X      := Win_Width;
 BuffSize.Y      := Win_Height;
 BuffCoord.X     := 1;
 BuffCoord.Y     := 1;
 ReadConsoleOutput(hOut, @Win_Save, BuffSize, BuffCoord, DestRect);
End;

{ Win_Pull ------------------------------------------------------------------ } { This code puts the buffer back onto the screen } { Screen region is defined by the coordinates in Win_MinX, Win_MinY, } { Win_MaxX, Win_MaxY. }

Procedure Win_Pull;
Var
 Y                : Byte;
Begin
 DestRect.Left   := 1;
 DestRect.Top    := 1;
 DestRect.Right  := Win_Width;
 DestRect.Bottom := Win_Height;
 BuffSize.X      := Win_Width;
 BuffSize.Y      := Win_Height;
 BuffCoord.X     := 1;
 BuffCoord.Y     := 1;
 WriteConsoleOutput(hOut, @Win_Save, BuffSize, BuffCoord, DestRect);
End;
Gabor DEAK JAHN

At 09/29/2000 06:29, you wrote:

Dear Jim,

Does anyone know how to read characters from a text-mode win32/go32 program? I need to gotoxy and read some information, but I can't figure out

how.

Using ReadConsoleOutput, Win32 provides this function just for this purpose. You can read a character, a line or even a rectangular region with it. A related function, GetConsoleScreenBufferInfo can be used to get the size of the screen or the current position of the cursor. Naturally, there is a WriteConsoleOutput also to write to the console window.

Bye,
   Gábor

------------------------------------------------------------------- Gabor DEAK JAHN -- Budapest, Hungary.
E-mail: ,