[comp.sys.atari.st] Read Screen Character

U211510@HNYKUN11.BITNET (Wil Groenen) (06/15/88)

Dear readers,
I have a problem which some of you probably have encountered before,
that is reading a character from screen at current cursor position.
Somehow I have not been able to find the proper gemdos (?) function
call for this. Does anyone knows how to handle this, preferably in
Fortran or Pascal??

          Wil Groenen

 CATHOLIC UNIVERSITY NYMEGEN            W           W      GGGGGGGG
 P.O. BOX 9108                           W         W      G
 6500 HK NIJMEGEN                         W   W   W       G    GGGG
 THE NETHERLANDS                           W W W W        G       G
      TEL : 080-516270/233021              w   w           GGGGGGGG
   BITNET : U211510 AT HNYKUN11

kurth@sco.COM (Kurt Hutchison) (06/17/88)

In article <8806151250.AA29397@ucbvax.Berkeley.EDU>, U211510@HNYKUN11.BITNET (Wil Groenen) writes:
> Dear readers,
> I have a problem which some of you probably have encountered before,
> that is reading a character from screen at current cursor position.
> Somehow I have not been able to find the proper gemdos (?) function
> call for this. Does anyone knows how to handle this, preferably in
> Fortran or Pascal??
> 
>           Wil Groenen

This can't be done easily.  The screen image is stored as graphics data.
No data that describes which character was used to generate the graphics
information is maintained.

Therefore, to find out which character was used, assuming
that you know what resolution you were in and which font table was
used, you could extract the graphics information from the screen
and compare it with every entry in the font table until
you found a match.

It would probably be easier just to save a local image
of the screen as you create it.  It *IS* possible to get the current cursor
location by sending the cursor save string to the roms and then
looking in the documented location for the saved cursor address.

At least that way you don't have to keep track of the cursor position
but you will probablyt have to keep track of the data.

		Good luck,
			- kurt

-- 
-------------------------------------------------------------------------
Kurt Hutchison		The Santa Cruz Operation	Software Engineer
Trumpet player, synth player, pianist, cyclist, philosopher at large
The above opinions (if any) are my own

wheels@mks.UUCP (Gerry Wheeler) (06/18/88)

In article <8806151250.AA29397@ucbvax.Berkeley.EDU>, U211510@HNYKUN11.BITNET (Wil Groenen) writes:
> I have a problem [...] reading a character from screen at current
> cursor position.

I do not have detailed knowledge about this (my manuals aren't here
at the moment), but I would theorise that this is not possible.
Remember, once the character is drawn on the screen it is just a
bunch of bits. This is quite unlike the usual video screens for
IBM-type computers. It would take quite a program to read the pattern
of bits and tell which character it was.
-- 
     Gerry Wheeler                           Phone: (519)884-2251
Mortice Kern Systems Inc.               UUCP: uunet!watmath!mks!wheels
   35 King St. North                             BIX: join mks
Waterloo, Ontario  N2J 2W9                  CompuServe: 73260,1043

rling@june.cs.washington.edu (Robert Ling) (06/19/88)

In article <478@mks.UUCP>, wheels@mks.UUCP (Gerry Wheeler) writes:
> In article <8806151250.AA29397@ucbvax.Berkeley.EDU>, U211510@HNYKUN11.BITNET (Wil Groenen) writes:
> > I have a problem [...] reading a character from screen at current
> > cursor position.
> 
>             ... but I would theorise that this is not possible.
> Remember, once the character is drawn on the screen it is just a
> bunch of bits. This is quite unlike the usual video screens for
> IBM-type computers. It would take quite a program to read the pattern
> of bits and tell which character it was.

If you use the BIOS/GEMDOS to write to the screen, the characters are
in fixed positions.  If you also had access to the font used, the problem
is one of (bit) pattern matching.  In high resolution, a screen character
is contained in 16 bytes, all you have to do is match this set of 16 bytes
against 256 sets in the font table.  This is actually what happens in
IBM-type computers when in graphics mode.

Things are a little bit more complicated if you use the DVI since the
area of the screen that contains the character might be "corrupted"
by other things and the character might not be normal sized.

- Robert Ling   <rling@june.cs.washington.edu>

leo@philmds.UUCP (Leo de Wit) (06/19/88)

In article <8806151250.AA29397@ucbvax.Berkeley.EDU> U211510@HNYKUN11.BITNET (Wil Groenen) writes:
>Dear readers,
>I have a problem which some of you probably have encountered before,
>that is reading a character from screen at current cursor position.
>Somehow I have not been able to find the proper gemdos (?) function
>call for this. Does anyone knows how to handle this, preferably in
>Fortran or Pascal??

    Sorry to disappoint you, but there is no trivial way to read a
character from the screen. The ST has only graphics modes, no text
modes as for instance the B.B.C or the MSX line of computers (storing
characters in ASCII form in Ram). The MSX uses this feature for its
screen editor.

    But, cheer up, there is a non-trivial way of doing it: you can match
the bytes that form the character image against the TOS font(s) and
return that character on a match or a space for instance if there is no
match. This method was used by good ol' Sinclair Spectrum; that had a
SCREEN$(row,col) function that returned the matching code for the image
at (row,col). The Spectrum knew only one (graphics) mode.

    I'm planning to mail a screen dump program next week to the moderator
of Comp.sources.atari.st; this program matches each character screen
position against the TOS font and sends it to the printer. Really nice
if you would like the compiler's output that is on the screen, or an
error message, or a screenfull while you are in the editor, being
dumped to the printer. It is as fast as just printing the text as a
file. It uses a function that matches the character bit image at the
position indicated. It is written in C (major 8-), so you could
translate the source to Pascal or link the compiled C module.

B.T.W. Speaking of languages, I thought you people in Nijmegen were all
dedicated C/Unix hackers?  
            Pascal ??????????  Fortran !"#$%^&*()_+=@~     %=)

        Leo.

jason@lakesys.UUCP (Jason) (06/20/88)

In article <5143@june.cs.washington.edu>, rling@june.cs.washington.edu (Robert Ling) writes:
> In article <478@mks.UUCP>, wheels@mks.UUCP (Gerry Wheeler) writes:
> > In article <8806151250.AA29397@ucbvax.Berkeley.EDU>, U211510@HNYKUN11.BITNET (Wil Groenen) writes:
> > > I have a problem [...] reading a character from screen at current
> > > cursor position.
> > [...Entire article deleted]
> [...]
> in fixed positions.  If you also had access to the font used, the problem
> is one of (bit) pattern matching.  In high resolution, a screen character
> [... Portion of article deleted]
> 
> - Robert Ling   <rling@june.cs.washington.edu>

	Another way to do it (not reading the character bit maps after on the
screen) would be to take over the character output routines (I don't recall
what this would take), and put all the characters into an array. Of course,
if your program was the only thing generating character output, it'd be more
efficient to just put the characters in the array immediately. I would think
that you'd have to handle the VT-52 stuff that the ST does in order to get an
accurate array...

	This entire approach would only be valid if the characters in question
had not yet been drawn on the screen.


	Jason
"Not your average iconoclast"

farren@gethen.UUCP (Michael J. Farren) (06/20/88)

In article <478@mks.UUCP> wheels@mks.UUCP (Gerry Wheeler) writes:
>> I have a problem [...] reading a character from screen at current
>> cursor position.
>
>I would theorise that this is not possible.

If it's that hard, how is it that IBM PC's can do it?  (And I do mean in
graphics mode, where the characters are, just as they are on the ST,
just bit patterns in memory.)

-- 
Michael J. Farren             | "INVESTIGATE your point of view, don't just 
{ucbvax, uunet, hoptoad}!     | dogmatize it!  Reflect on it and re-evaluate
        unisoft!gethen!farren | it.  You may want to change your mind someday."
gethen!farren@lll-winken.llnl.gov ----- Tom Reingold, from alt.flame 

ud@mutec.UUCP (Ulrich Dessauer) (06/20/88)

In article <8806151250.AA29397@ucbvax.Berkeley.EDU> U211510@HNYKUN11.BITNET (Wil Groenen) writes:
>I have a problem which some of you probably have encountered before,
>that is reading a character from screen at current cursor position.
>Somehow I have not been able to find the proper gemdos (?) function
>call for this. Does anyone knows how to handle this, preferably in
>Fortran or Pascal??
	The problem of the ST is his graphic-mode where also all text
will be put out. To get a charackter from the screen, you first have
to calculate the Postion in the graphic-screen, then compare the
current 8 * 16 (or 8 * 8) field with the current systemfont. You see,
it is a lot of work, so the (nearly) only possible language is assembler.

	As I know, gemdos doesn't support such a function, but perhaps
later it will do it :-).

		Greetings, U//i
-- 
UUCP:	..!unido!mutec!ud	ud@mutec.UUCP
Snail:	Ulrich Dessauer
	Markt&Technik Verlag AG, Hans-Pinsel-Strasse 2, D-8013 Haar
Voice:	+49 89 4613 745 (Office)

rosenkra@Alliant.COM (Bill Rosenkranz) (06/21/88)

---
In article <755@lakesys.UUCP> jason@lakesys.UUCP (Jason) writes:
>	Another way to do it (not reading the character bit maps after on the
>screen) would be to take over the character output routines (I don't recall
>what this would take), and put all the characters into an array. Of course,
>
>	Jason
>"Not your average iconoclast"

i have actually done something along these lines (replacing the bios trap 13
handler with my own - in a futile attempt to buffer alcyon output to a file
trouble is alcyon does not use trap13...waaahhh). it looks for any Bconout
call going to dev=2 (CON:) and tee's to either a file or a buffer. it works
well and _SHOULD_ be portable across ROM versions since i get the handler
pointer from a sys vector. it is still kind of a kludge since i am not a 68000
as wiz, but it does work well from C (alcyon, of course :^).

if anybody wants it, i'll post it here (it is short). actually i don't
know if i CAN post it since it is basically the code in ROM with 10 or 12
lines added...if atari is listening, give me the ok (it is in abacus internals
and you can easily look at it with dis2nd or any other disassembler, so this
should not be a problem...)

-bill
...!rutgers!mit-eddie!alliant!rosenkra

neil@cs.hw.ac.uk (Neil Forsyth) (06/21/88)

In article <272@scolex> kurth@sco.COM (Kurt Hutchison) writes:
>It *IS* possible to get the current cursor location by sending the cursor
>save string to the roms and then looking in the documented location for
>the saved cursor address.

Excuse me bt i have never seen this variable location documented anywhere.
Where is it? If it's not an official location just ignore this message.

 _____________________________________________________________________________
/ "I think all right thinking people in this country are sick and tired of    \
! being told that ordinary decent people are fed up in this country with      !
! being sick and tired. I'm certainly not and I'm sick and tired of being     !
! told that I am!" - Monty Python                                             !
!                                                                             !
! Neil Forsyth                           JANET:  neil@uk.ac.hw.cs             !
! Dept. of Computer Science              ARPA:   neil@cs.hw.ac.uk             !
! Heriot-Watt University                 UUCP:   ..!ukc!cs.hw.ac.uk!neil      !
! Edinburgh                                                                   !
! Scotland                                                                    !
\_____________________________________________________________________________/

leo@philmds.UUCP (Leo de Wit) (06/25/88)

In article <1871@brahma.cs.hw.ac.uk> neil@cs.hw.ac.uk (Neil Forsyth) writes:
>In article <272@scolex> kurth@sco.COM (Kurt Hutchison) writes:
>>It *IS* possible to get the current cursor location by sending the cursor
>>save string to the roms and then looking in the documented location for
>>the saved cursor address.
>
>Excuse me bt i have never seen this variable location documented anywhere.
>Where is it? If it's not an official location just ignore this message.

As far as I can judge it is a constant location (in fact two), but it
could probably vary from ROM to ROM (not being a system variable). But
anyway, there is a clean way of doing it (that does not destroy a
previous saved location): use the VDI ESC 15 function, fetch cursor
position, or if you use a C library, it is probably called:

vq_curaddress(handle,&row,&col); with WORD handle,row,col. This
requires a handle but in this case you can use 0 (Desktop's handle).

Furthermore I would like to offer the readers of this newsgroup the
source of a module that reads a character from the screen, using the
current TOS font.  The relevant function is copied with slight
modification from the fastdump program that was on the
comp.sources.atari.st newsgroup just a while ago.  If there are any
objections against me posting such a long article, I would also like to
hear (but then, you can always hit 'n'). As it is, the source
represents a tiny demo program (just to show that it works). By
removing main you get a module that can be linked with your program
(about 738 bytes in size). Enjoy!

    Leo

============================== C U T   H E R E ==============================
/*
 ******************************************************************************
 *                                                                            *
 *    vtchar.c    version 1.0 of 25 June 1988    (C) L.J.M. de Wit 1988       *
 *                                                                            *
 * This software may be used and distributed freely if not used commercially  *
 * and the originator (me) is mentioned.                                      *
 *                                                                            *
 ******************************************************************************
 *
 *     This program demonstrates the reading of characters from the screen.
 *  The upper left quadrant of the screen is copied to the other three using
 *  this technique.
 *     If you want to use get_schar() from your own programs, just remove the
 *  function main() from this file and compile it as a separate module. Then
 *  link it with your program.
 *     To use it, call prep_schar() first; this sets the correct parameters
 *  (need to be done only once). Then you can use get_schar(r,c) with r the
 *  row and c the column to read from.
 *     An unrecognized character will be presented by a space.
 *     Inverse video is not yet supported (most probably it becomes a space
 *  now), but this is not difficult to implement.
 */

#include <osbind.h>
#include <portab.h>

/* font definitions */
typedef struct font_header {
   WORD f_id;       /* font identifier; system font = 1 */
   WORD f_point;    /* font size in points */
   char f_name[32]; /* font name */
   WORD f_low;      /* lowest ascii code in font */
   WORD f_high;     /* highest ascii code in font */
   WORD f_top;      /* relative distance of top to base line */
   WORD f_ascent;   /* relative distance of ascent to base line */
   WORD f_half;     /* relative distance of half to base line */
   WORD f_descent;  /* relative distance of descent to base line */
   WORD f_bottom;   /* relative distance of bottom to base line */
   WORD f_maxcharw; /* maximal character width in font */
   WORD f_maxcellw; /* maximal cell width in font */
   WORD f_loffset;  /* left offset */
   WORD f_roffset;  /* right offset */
   WORD f_fatsiz;   /* degree of fattening */
   WORD f_ulsiz;    /* underline degree */
   WORD f_normask;  /* normal cancelled mask */
   WORD f_skewmask; /* skewing cancelled mask */
   WORD f_flag;     /* flag:
                     *  bit 0: system font;
                     *  bit 1: hor. offset;
                     *  bit 2: byte swap;
                     *  bit 3: non proportional font
                     */
   WORD *f_horoff;  /* pointer to horizontal offsets table */
   WORD *f_charoff; /* pointer to character offsets table */
   char *f_data;    /* pointer to font data table */
   WORD f_fontw;    /* total width of all chars in font */
   WORD f_fonth;    /* height of font (# scanlines) */
   struct font_header
          *f_next;  /* pointer to next font header */
} font_header;

static UWORD g_fheader[] = {  0xA000,        /* LineA exception 0   */
                              0x222F,0x0004, /* MOVE.L  4(SP),D1    */
                              0xE581,        /* ASL.L   #2,D1       */
                              0x2031,0x1800, /* MOVE.L  0(A1,D1),D0 */
                              0x4E75 };      /* RTS                 */

static WORD planes;
static font_header *fhp;
static WORD rows, cols;                   /* Rows & columns of screen    */
static int physbase;

BYTE get_schar();
void prep_schar();

main()
{
   int i, j, rows2, cols2;
   char line[82];

   prep_schar();
   cols2 = cols/2; rows2 = rows/2;
   Bconout(2,'\33');   Bconout(2,'f');
   for (i = 0; i < rows2; i++) {
      for (j = 0; j < cols2; j++) {
         line[j] = get_schar(i,j);
      }
      line[cols2] = '\0';
      Bconout(2,'\33');          Bconout(2,'Y');
      Bconout(2,' '+ i);         Bconout(2,' '+cols2);
      Cconws(line);
      Bconout(2,'\33');          Bconout(2,'Y');
      Bconout(2,' '+ i+rows2);   Bconout(2,' ');
      Cconws(line);
      Cconws(line);
   }
   Bconout(2,'\33');   Bconout(2,'e');
}

void prep_schar()
{
   BYTE rez;                              /* resolution 2 high 1 med 0 low*/

   rez = Getrez();
   fhp = (*(font_header *(*)())g_fheader)
         ((rez == 2) ? 2 : 1);            /* pointer to standard font    */
   planes = 4 >> rez;                     /* # of bit planes: 4, 2 or 1  */
   rows = 25;
   cols = (rez == 0) ? 40 : 80;
   physbase = Physbase();
}

BYTE get_schar(i,j)                       /* Find match in a font for    */
WORD i,j;                                 /* the character bit image at  */
{                                         /* position (i,j)              */
   register WORD l;                       /* line counter                */
   register BYTE *cpd,                    /* char ptr into font_data     */
                 *cps;                    /* char ptr into ch_img[]      */
   register WORD p, c;
   WORD *curadd,                          /* screen address of top word  */
        sval;                             /* will hold a word of image   */
   BYTE ch_img[16],                       /* will hold image as bytes    */
        or_all;                           /* OR of all bytes of image    */
   UWORD w_p_l,                           /* # words per line            */
         maxl;                            /* height of a char in lines   */

   w_p_l = (planes == 1) ? 40 : 80;
   maxl = (planes == 1) ? 16 : 8;
   curadd = (WORD *)(physbase + i * 1280 + (j & ~1) * planes);

   /* prepare ch_img[] to hold a adjusted copy of the bit image */
   or_all = 0;
   for (l = 0; l < maxl; l++) {
      sval = 0;
      for (p = 0; p < planes; p++) {      /* OR in all colour bit planes */
         sval |= curadd[l * w_p_l + p];
      }

      ch_img[l] = (j & 1) ? sval & 0xff   /* Take lower or upper byte    */
                   : (sval >> 8) & 0xff;  /* as appropriate              */
      or_all |= ch_img[l];                /* Keeps inclusive Or of all   */
   }

   /* search */
   if (or_all == 0) {                     /* Not a pixel set             */
      c = ' ';                            /* then space will be printed  */
   } else {                               /* else for each char in font  */
      for (c = fhp->f_low; c <= fhp->f_high; c++) {
         cpd = fhp->f_data + (fhp->f_charoff[c] >> 3);
         cps = ch_img;
         for (l = 0; l < maxl; l++) {     /* Compare each line (byte)    */
            if (*cps++ != *cpd) break;    /* Match failed at this line   */
            cpd += fhp->f_fontw;
         }
         if (l >= maxl) break;            /* All lines matched           */
      }

      if ((c == '\0') || (c > fhp->f_high)) { /* If no match             */
         c = ' ';                         /* use space instead           */
      }
   }

   return (BYTE)c;                        /* Return matched char or space*/
}