/***************************************************************************
 *                                                                         *
 *   VIDAPI.C                                                              *
 *                                                                         *
 *   Copyright (c) 1996-1997 Galacticomm, Inc.    All Rights Reserved.     *
 *                                                                         *
 *   This is the cross-platform Galacticomm video API as implemented for   *
 *   DOS.  Much code for this flavor of the video API also resides in the  *
 *   VAPIASM.ASM file.                                                     *
 *                                                                         *
 *                                                   - T. Stryker 2/8/89   *
 *                                                     C. Robert  3/12/96  *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "vapiasm.h"

#define FILREV "$Revision: 8 $"

INT pxoff,pyoff;                   /* proff() offsets for edtval() & prat  */
GBOOL color=TRUE;                  /* flag indicating color display avail  */

static CHAR *prtbuf=NULL;          /* temp buf to store printf()-style stgs*/
static CHAR *vidmem=NULL;          /* pointer to actual video memory       */

static INT hbstk[GVIDCSZSTK]={     /* cursiz()/rstcur() stack              */
     GVIDLILCURS,GVIDLILCURS,GVIDLILCURS,GVIDLILCURS,GVIDLILCURS,
     GVIDLILCURS,GVIDLILCURS,GVIDLILCURS,GVIDLILCURS,GVIDLILCURS
};

static VOID vidbomb(VOID);

static INT TimesInited=0;

static VOID
vidbomb(VOID)                      /* initvid not called error             */
{
     initvid();
     fprintf(stderr,"WARNING: VIDEO NOT INITIALIZED PROPERLY\n\007");
}

/*****************************************************************************
*                 Application Program Interface (API)                        *
*****************************************************************************/

VOID
initvid(VOID)                      /* initialize video subsystem           */
{
     TimesInited++;
     if (TimesInited > 1) {
          return;
     }
     vidmem=prxset();
     if (prtbuf == NULL) {
          prtbuf=alcmem(MAXPFSIZ);
     }
}

VOID
clsvid(VOID)                       /* shut down video subsystem            */
{
     if (TimesInited == 0) {
          return;
     }
     TimesInited--;
     if (TimesInited != 0) {
          return;
     }
     vidmem=NULL;
     if (prtbuf != NULL) {
          free(prtbuf);
          prtbuf=NULL;
     }
}

VOID
scn2mem(                           /* move real screen memory to other mem */
VOID *dest,                        /*   pointer to destination memory      */
UINT offset,                       /*   offset from start of the video scr */
UINT count)                        /*   number of bytes to move            */
{
     if (vidmem == NULL) {
          vidbomb();
     }
     ASSERT((offset+count) <= GVIDSCNSIZ);
     movmemb(&vidmem[offset],dest,count);
}

VOID
mem2scn(                           /* move other memory to the real screen */
VOID *src,                         /*   pointer to source memory           */
UINT offset,                       /*   offset into the video screen       */
UINT count)                        /*   number of bytes to move            */
{
     if (vidmem == NULL) {
          vidbomb();
     }
     ASSERT(offset+count <= GVIDSCNSIZ);
     movmemb(src,&vidmem[offset],count);
}

VOID
scn2scn(                           /* move real screen to real screen      */
UINT srcoff,                       /*   source offset for move             */
UINT dstoff,                       /*   destination offset for move        */
UINT count)                        /*   number of bytes to move            */
{
     if (vidmem == NULL) {
          vidbomb();
     }
     ASSERT(srcoff+count <= GVIDSCNSIZ);
     ASSERT(dstoff+count <= GVIDSCNSIZ);
     movmemb(&vidmem[srcoff],&vidmem[dstoff],count);
}

CHAR
scngetc(                           /* read a char/attr from the "REAL" scr */
UINT offset)                       /*   offset into the video screen       */
{
     if (vidmem == NULL) {
          vidbomb();
     }
     ASSERT(offset < GVIDSCNSIZ);
     return(vidmem[offset]);
}

VOID
scnputc(                           /* change a char/attr on the "REAL" scr */
UINT offset,                       /*   offset into the video screen       */
CHAR byt)                          /*   new byte to be written to the scr  */
{
     if (vidmem == NULL) {
          vidbomb();
     }
     ASSERT(offset < GVIDSCNSIZ);
     vidmem[offset]=byt;
}

VOID
scnputw(                           /* change a char/attr pair on "REAL" scr*/
UINT offset,                       /*   offset into the video screen       */
CHAR byt,                          /*   new character                      */
CHAR atr,                          /*   new attribute                      */
UINT nwords)                       /*   number of char/attr pairs to put   */
{
     UINT i;
     CHAR *ptr;

     if (vidmem == NULL) {
          vidbomb();
     }
     ASSERT(offset+nwords*2 <= GVIDSCNSIZ);
     for (i=0,ptr=&vidmem[offset] ; i < nwords ; i++) {
          *ptr++=byt;
          *ptr++=atr;
     }
}

CHAR *
scblank(                           /* clear a screen to blanks             */
CHAR *buf,                         /*   ptr to buffer to clear 0=real vid  */
CHAR attrib)                       /*   attribute to clear to              */
{
     UINT i;
     CHAR *actbuf;

     if (vidmem == NULL) {
          return(0);
     }
     attrib=scncolor(attrib);
     actbuf=(buf == NULL ? vidmem : buf);
     for (i=0 ; i < GVIDSCNSIZ ; i+=2) {
          *actbuf++=' ';
          *actbuf++=attrib;
     }
     return(buf);
}

CHAR
scncolor(                          /* get scn attrib equiv if monochrome   */
INT attrib)
{
     CHAR retval;

     retval=(CHAR)attrib;
     if (!color) {
          if ((retval&0x70) == 0x70) {
               retval=0x70;
          }
          else {
               retval=((retval&0x88)|0x07);
          }
     }
     return(retval);
}

VOID
monorcol(VOID)                     /* set 'color' flag based on CNF setting*/
{                                  /*   (or auto-sense if no MSG file)     */
     CHAR *opt;

     if (vidmem == NULL) {
          vidbomb();
     }
     if ((opt=msgscan("wgsmajor.msg","CRT")) != NULL) {
          if (sameas(opt,"AUTO")) {
               imonorcol();
          }
          else if (sameas(opt,"COLOR")) {
               color=TRUE;
          }
          else {
               color=FALSE;
          }
     }
     else {
          imonorcol();
     }
}

VOID
imonorcol(VOID)                    /* set 'color' flag on based on system  */
{
     USHORT crtseg;

     if (vidmem == NULL) {
          vidbomb();
     }
     crtseg=FP_SEG(vidmem);
     color=(crtseg != 0xB000 && crtseg != 0xB0 && crtseg != monseg);
}

VOID
cursiz(                            /* set cursor size                      */
INT howbig)                        /*   off, little or block               */
{
     union REGS regs;
     static CHAR startl[2][3]={{32,6,4},{32,11, 6}};
     static CHAR endlin[2][3]={{ 0,7,7},{ 0,12,12}};

     movmemb(hbstk,hbstk+1,sizeof(INT)*(GVIDCSZSTK-1));
     hbstk[0]=howbig;
     regs.h.ah=0x0F;
     int86(0x10,&regs,&regs);
     regs.h.ah=1;
     regs.h.ch=startl[regs.h.al == 7][howbig];
     regs.h.cl=endlin[regs.h.al == 7][howbig];
     int86(0x10,&regs,&regs);
}

VOID
rstcur(VOID)                       /* restore cursor from cursor-size stack*/
{
     movmemb(hbstk+1,hbstk,sizeof(INT)*(GVIDCSZSTK-1));
     cursiz(hbstk[0]);
}

INT
curcurs(VOID)                      /* return current cursor size code      */
{
     return(hbstk[0]);
}

INT
printfat(                          /* Galacticomm printf at position x,y   */
INT x,                             /*   x position to print at             */
INT y,                             /*   y position to print at             */
CHAR *fmt,                         /*   format string                      */
...)                               /*   variable number of parameters      */
{
     va_list ap;
     INT nprnt;

     if (prtbuf == NULL) {
          vidbomb();
     }
     locate(x,y);
     va_start(ap,fmt);
     nprnt=vsprintf(prtbuf,fmt,ap);
     va_end(ap);
     fastprintf(prtbuf);
     return(nprnt);
}

VOID
proff(                             /* set offsets for certain printing     */
INT x,                             /*   the x offset                       */
INT y)                             /*   the y offset                       */
{
     pxoff=x;
     pyoff=y;
}

VOID
prat(                              /* print at a location relative to proff*/
INT x,                             /*   x offset to start at               */
INT y,                             /*   y offset to start at               */
CHAR *ctlstg,                      /*   control string                     */
...)                               /*   variable arguments                 */
{
     va_list ap;

     if (prtbuf == NULL) {
          vidbomb();
     }
     locate(x+pxoff,y+pyoff);
     va_start(ap,ctlstg);
     vsprintf(prtbuf,ctlstg,ap);
     va_end(ap);
     fastprintf(prtbuf);
}

INT
gprintf(                           /* Galacticomm flavor of printf()       */
CHAR *fmt,
...)
{
     va_list ap;
     INT nprnt;

     if (prtbuf == NULL) {
          vidbomb();
     }
     va_start(ap,fmt);
     nprnt=vsprintf(prtbuf,fmt,ap);
     va_end(ap);
     fastprintf(prtbuf);
     return(nprnt);
}

