/*
        This file is part of the cFos project,
        Copyright (c) 1993 by Martin Winkler, Christoph Lders

        This file contains routines only used in the debug phase.


        You are allowed to use, copy, distribute, publish, redistribute
        and/or modify this program under the terms of the 'cFos public
        licence and warranty'.

        This program is distributed in the hope that it will be useful,
        but WITHOUT ANY WARRANTY; without even the implied warranty of
        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

        See COPYING.CF for the 'cFos public license and warranty'.
*/


#include <stdarg.h>
#include <string.h>

#include "vars.h"



static short disp_alternate=0, disp_ascroll=0;
static short disp_arows, disp_acols, disp_ascrlen;
static unsigned char disp_anow_atb, far *disp_ascrbuff, far *disp_ascrptr;
static short disp_anow_row, disp_anow_col;
static unsigned char *disp_atb_tab;

extern unsigned char disp_atb_mono[DISP_MAX_ATB];
extern unsigned char disp_atb_color[DISP_MAX_ATB];


int adisp_init (void)
{
   union REGS r;
   struct SREGS s;
   int old;
   byte buffer[64];

   mysegread (&s);
   r.h.ah = 0x1b;
   r.x.bx = 0;
   s.es = FP_SEG (buffer);
   r.x.di = FP_OFF (buffer);
   myint86x (0x10, &r, &r, &s);

   if (r.h.al != 0x1b)
      return 0;                 /* !! ok? */

   r.h.ah = 0x0f;                       /* get video mode */
   myint86 (0x10, &r, &r);
   disp_acols = r.h.ah;
   old = r.h.al;

   if (buffer[0x26] == 0)
      return 0;                 /* !! ok? */

   if (old == 7) {
       disp_ascrbuff = (unsigned char far *) 0xb8000000L;
       disp_atb_tab = disp_atb_color;
   } else {
       disp_ascrbuff = (unsigned char far *) 0xb0000000L;
       disp_atb_tab = disp_atb_mono;
   }

   disp_alternate = 1;
   disp_anow_row = 0;
   disp_anow_col = 0;
   disp_acols = 80;
   disp_arows = 25;

   disp_anow_atb = *disp_atb_tab;
   disp_ascrptr = disp_ascrbuff + disp_anow_row*disp_acols*2 + disp_anow_col*2;
   disp_ascrlen = disp_arows * disp_acols * 2;

   myaprintf ("\xc" "alternate screen routines initialized.\n");

   return 1;
}



/* --- alternate monitor display routine */

void _adisp_char (char c)
{
   unsigned char far *cp;
   short i;

   if (!disp_alternate)
      return;

   switch (c) {
      case 12:
         for (cp=disp_ascrbuff,i=0; i<disp_ascrlen; i++) {
            *cp++ = ' ';
            *cp++ = disp_anow_atb;
         }
         disp_anow_row = 0;
         disp_anow_col = 0;
         disp_ascrptr = disp_ascrbuff;
         break;

      case '\t':
         i = ((disp_anow_col/8)+1)*8;
         for (; i!=disp_anow_col;)
            _adisp_char (' ');
         disp_ascrptr += (i-disp_anow_col)*2;
         break;

      case '\n':
         if (disp_anow_col < 40) {
            i = ((disp_anow_col/40)+1)*40;
            for (; i!=disp_anow_col;)
               _adisp_char (' ');
            disp_ascrptr += (i-disp_anow_col)*2;
            c = 0;                      /* to avoid scrolling */
            break;
         }
         disp_ascrptr += disp_acols*2;
         disp_anow_row++;

      case '\r':
         disp_ascrptr -= disp_anow_col*2;
         disp_anow_col = 0;
         break;

      case '\b':
         if (disp_anow_col > 0) {
            disp_ascrptr -= 2;
            disp_anow_col--;
         }
         break;

      default:
         *disp_ascrptr++ = c;
         *disp_ascrptr++ = disp_anow_atb;
         disp_anow_col++;
         break;
   }
   if (disp_anow_col >= disp_acols) {
      disp_anow_col -= disp_acols;
      disp_anow_row++;
   }
   if (disp_anow_row >= disp_arows) {         /* gotta scroll */
      if (disp_ascroll) {
         memcpy3 (disp_ascrbuff, disp_ascrbuff+disp_acols*2, disp_ascrlen-disp_acols*2);
         disp_ascrptr -= disp_acols*2;
         disp_anow_row--;
         for (cp=disp_ascrbuff+disp_ascrlen-disp_acols*2,i=disp_acols; i>0; i--) {
            *cp++ = ' ';
            *cp++ = disp_anow_atb;
         }
      } else {
         disp_ascrptr -= disp_ascrlen;
         disp_anow_row -= disp_arows;
      }
   }
   if (!disp_ascroll && c == 10) {
      for (cp=disp_ascrptr, i=disp_acols; i>0; i--) {
         *cp++ = ' ';
         *cp++ = disp_anow_atb;
      }
   }
}



#if 0
void myagotoxy (short x, short y)
{
   if (x != -1)
      disp_anow_row = x;
   disp_anow_col = y;

   disp_ascrptr = disp_ascrbuff + (disp_anow_row*disp_acols + disp_anow_col)*2;
}
#endif



#if 0
void aset_atb (short atb)
{
   disp_anow_atb = disp_atb_tab[atb%DISP_MAX_ATB];
}
#endif


int myaprintf (const char *format, ...)
{
   va_list arg_ptr;
   int result;

   if (disp_alternate) {
      va_start (arg_ptr, format);
      result = _output ((int (*)(int, int)) _adisp_char, 0, NULL, format, arg_ptr);
      va_end (arg_ptr);

   } else
      result = 0;

   return (result);
}



void adisp (char *text)
{
   while (*text)
      _adisp_char (*text++);
}



/* --- eof debug.c */
