[comp.os.msdos.programmer] Direct output in C

gandalf@valnet.UUCP (Andrew Davenport) (03/14/91)

    I am writing a program on an IBM AT compatible computer, and I want to
use direct input/output.  I wrote the following function, but it doesn't
work.  Can anyone give me a pointer as to why not?

--------------------------------- Cut Here ----------------------------------

int far *screen = (int far *)0xB8000000;

void dir_scr_write(int x, int y, char *str, char fore, char back)
{
    int c=0, temp=0, string[80];
    unsigned int attr=0;
    int far *tmp = screen;

    temp = strlen(str);
    attr = (((((int)back & 0x0f) << 4) | ((int)fore & 0x0f)) & 0x00ff);
    for(c = 0; c <= temp; c++)
    {
        string[c] = (int)str[c];
        string[c] <<= 8;
        string[c] &= attr;
    }
    tmp += (y * 80) + x;
    memcpy(tmp, string, (temp * 2));
}

--------------------------------- Cut Here ----------------------------------

Also, I want to read/write the cursor position directly...how might that be
done?

Please help!!!

Thanks in advance, and please e-mail responses to gandalf@valnet.UUCP, I'll be
happy to post a summary of replys if there's any interest...

Gandalf (a.k.a. Andrew Davenport)

jlr1801@aim1.tamu.edu (Jeff Rife) (03/14/91)

In article <J4gRy2w163w@valnet> gandalf@valnet.UUCP (Andrew Davenport) writes:
>
>    I am writing a program on an IBM AT compatible computer, and I want to
>use direct input/output.  I wrote the following function, but it doesn't
>work.  Can anyone give me a pointer as to why not?
>
	[code deleted]
>
>Please help!!!
>
>Thanks in advance, and please e-mail responses to gandalf@valnet.UUCP, I'll be
>happy to post a summary of replys if there's any interest...
>
>Gandalf (a.k.a. Andrew Davenport)

Massive apologies here, but my mailer bounced the e-mail to Andrew, and so
I will now proceed to waste some bandwidth.

Ok, I didn't really examine your code, but this works for me....  It's in
MSC 6.0; if you have TC, sorry.

I also have some stuff that I deleted that saves and restores areas of the
screen (hence the filename) and also some that draws and fills boxes.  Let
me know if you want that, too.

Sorry it's not commented very well, but you know the old saying, if it
was hard to write, it should be hard to read.

-------- cut here --------

/**************************************************************************/
/*                                                                        */
/*  savearea.h - declarations for savearea.c                              */
/*                                                                        */
/**************************************************************************/
#include <stddef.h>

#define _MONOTEXT_BUF   0xb0000000L
#define _COLORTEXT_BUF  0xb8000000L

#define _PAGE_SIZE      0x1000
#define _PAGE_EXTRA_43  0x0be0
#define _PAGE_EXTRA_50  0x1040

#define _SET_ATTRIBUTE  0x01
#define _SET_CHARACTER  0x02
#define _SET_FILL       (_SET_ATTRIBUTE | _SET_CHARACTER)

boolean   RestoreArea(void *buffer,short TopRow,short LeftCol,short Page);
void     *SaveArea(short TopRow,short LeftCol,short High,short Wide,short Page);
boolean   SetScreenArea(short TopRow,short LeftCol,short High,short Wide,short Page,unsigned short SetVal,unsigned short SetAction);
boolean   SetScreenLoc(short Row,short Col,short Page,unsigned short SetVal,unsigned short SetAction);
void far  WordMove(char far *Source,char far *Dest,short Count);

--------- cut here ----------
/****************************************************************************/
/*  savearea.c                                                              */
/****************************************************************************/

#include <graph.h>
#include <malloc.h>
#include "savearea.h"

unsigned short _CalcOffset(short,short);
unsigned short _CalcPageStart(short);
char far *_GetVideoBuffer(void);
boolean _InitBox(short *,short *,short *,short *,short *,short *);

static struct videoconfig vc;
static char far *far_buffer;
static char far *screen;
static unsigned short Offset;
static short i;


boolean SetScreenArea(TopRow,LeftCol,High,Wide,Page,SetVal,SetAction)
short TopRow,LeftCol,High,Wide,Page;
unsigned short SetVal;
unsigned short SetAction;
{
short BotRow,RightCol;
short x,y,j;
unsigned char  SetChar;

if (_InitBox(&TopRow,&LeftCol,&High,&Wide,&BotRow,&RightCol))
  {
  Offset = _CalcPageStart(Page);
  if ((SetAction & _SET_FILL) != _SET_FILL)
    {
    y = SetAction & _SET_ATTRIBUTE;
    SetChar = SetVal & 0xff;
    }

  Wide += Wide;

  for (i = TopRow; i <= BotRow; i++)
    {
    x = _CalcOffset(i,LeftCol) + Offset;
    for (j = 0; j < Wide; j += 2)
      {
      if ((SetAction & _SET_FILL) == _SET_FILL)
        *((short far *) ((screen) + x + j)) = SetVal;
      else
        *((screen) + x + j + y) = SetChar;
      }
    }
  return(TRUE);
  }
else
  return(FALSE);
}


boolean SetScreenLoc(Row,Col,Page,SetVal,SetAction)
short Row,Col,Page;
unsigned short SetVal;
unsigned short SetAction;
{
unsigned short x;

_getvideoconfig(&vc);

screen = _GetVideoBuffer();
if (screen == NULL)
  return(FALSE);

x = _CalcPageStart(Page) + _CalcOffset(Row,Col);

if ((SetAction & _SET_FILL) == _SET_FILL)
  *((short far *) ((screen) + x)) = SetVal;
else
  *((screen) + x + (SetAction & _SET_ATTRIBUTE)) = (SetVal & 0xff);

return(TRUE);

}


/****************************************************************************/
/*  _InitBox -  check for text video mode, and calculate true screen limits */
/*              support function for SaveArea, RestoreArea, and             */
/*              SetScreenArea                                               */
/*                                                                          */
/*  Returns:  TRUE, if in a text mode                                       */
/*            FALSE, if graphics                                            */
/*            Also changes some of it's parameters to reflect actual        */
/*            screen size.                                                  */
/****************************************************************************/

boolean _InitBox(TopRow,LeftCol,High,Wide,BotRow,RightCol)
short *TopRow,*LeftCol,*High,*Wide,*BotRow,*RightCol;
{
if (*High < 1 || *Wide < 1)
  return(FALSE);

screen = _GetVideoBuffer();
if (screen == NULL)
  return(FALSE);

*BotRow = *TopRow + *High - 1;
*RightCol = *LeftCol + *Wide - 1;

if (*TopRow < 1)
  {
  *High += (1 - *TopRow);
  *TopRow = 1;
  }
if (*LeftCol < 1)
  {
  *Wide += (1 - *LeftCol);
  *LeftCol = 1;
  }

if (*BotRow > vc.numtextrows)
  {
  *High += (vc.numtextrows - *BotRow);
  *BotRow = vc.numtextrows;
  }
if (*RightCol > vc.numtextcols)
  {
  *Wide += (vc.numtextcols - *RightCol);
  *RightCol = vc.numtextcols;
  }

return(TRUE);
}


/****************************************************************************/
/*  _GetVideoBuffer - find the current text video buffer location           */
/*                                                                          */
/*  Returns:  a far pointer to the current video memory                     */
/*            or NULL if the current video mode is not text.                */
/****************************************************************************/

char far *_GetVideoBuffer(void)
{
char far *temp;
_getvideoconfig(&vc);

if (vc.mode == _TEXTBW40 || vc.mode == _TEXTC40 ||
    vc.mode == _TEXTBW80 || vc.mode == _TEXTC80)
  temp = (char far *) _COLORTEXT_BUF;
else
  {
  if (vc.mode == _TEXTMONO)
    temp = (char far *) _MONOTEXT_BUF;
  else
    temp = (char far *) NULL;
  }
return(temp);
}


/****************************************************************************/
/*  _CalcPageStart -  get the start of a video page, as an offset from the  */
/*                    start of video memory.                                */
/*                    assumes vc is an initialized videoconfig structure    */
/*                                                                          */
/*  Returns:  the offset into the video memory of the start of the page.    */
/****************************************************************************/

unsigned short _CalcPageStart(Page)
short Page;
{
unsigned short Start;

Start = Page * _PAGE_SIZE;

if (vc.numtextrows == 43)
  Start += Page * _PAGE_EXTRA_43;
if (vc.numtextrows == 50)
  Start += Page * _PAGE_EXTRA_50;

return(Start);
}


/****************************************************************************/
/*  _CalcOffset - calculates the offset of a character position from the    */
/*                start of the given page.                                  */
/*                assumes vc is an initialized videoconfig structure        */
/*                                                                          */
/*  Returns:  the offset into the page of the given row/column position.    */
/****************************************************************************/

unsigned short _CalcOffset(Row,Col)
short Row,Col;
{
return(((Row - 1) * vc.numtextcols + Col - 1) * 2);
}

--
Jeff Rife   P.O. Box 3836   |   "Because he was human; because he had goodness;
College Station, TX 77844   |    because he was moral they called him insane.
(409) 823-2710              |    Delusions of grandeur; visons of splendor;
jlr1801@aim1.tamu.edu       |    A manic-depressive, he walks in the rain."