/*->c.dbug */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <signal.h>
#include <ctype.h>
#include <time.h>

#include "h.os"
#include "h.wimp"
#include "h.bbc"
#include "h.flex"

#include "h.Drawlevel0"

#include "h.etc"
#include "h.def"
#include "h.wos"
#include "h.timex"
#include "h.xext"
#include "h.main"
#include "h.mym"
#include "h.strdef"
#include "h.fax"
#include "h.serial"
#include "h.ram"
#include "h.file"
#include "h.pr"
#include "h.key"
#include "h.script"
#include "h.dir"
#include "h.view"
#include "h.batch"
#include "h.fo"
#include "h.pic"
#include "h.vx"
#include "h.trans"
#include "h.rxfax"
#include "h.txfax"
#include "h.state"


#include "h.dbug"


/*****************************************************************************/

#define DBLINES 128
#define DBWIDTH 80

#define DBMASK (DBLINES-1)

#define DBLEFT 5


static FILE * dbfp;
static int debdir;

static int dbdata;       /* show data ?                     */
static int dbdatadir;
static int dbdataphase;  /* is data currently being shipped */
static int dbdisplay=1;


typedef struct dblinestr
{
 int  dir:1;
 char text[DBWIDTH];

} dblinestr;


static dblinestr * dbline;
static int         dbcury;  
static int         dbcurx;


                        /* step between each macro entry in window */
#define TDIRDY   40
                        /* step between top of window and first macro */
#define TDIRFY   12
                        /* height of macro definitions */
#define TDIRHY   32



/* open a 80 col text window */
/* format 0000 stuff         */

static void blankline(int line,int dir)
{
 dblinestr * ls;

 ls=dbline+line;

 memset(ls,0,sizeof(dblinestr));

 ls->dir=dir;
 sprintf(ls->text,"%04d ",clock() % 10000);
}



static os_error * dbuginit(void)
{
 os_error * err;
 int        i;

 err=NULL;

 if(!dbline)
    err=flex_alloce((flex_ptr)&dbline,sizeof(dblinestr)*DBLINES);
 if(!err)
 {
  for(i=0;i<DBLINES;i++)
  {
   blankline(i,0);
  }
 }

 dbcurx=DBLEFT;
 dbcury=(DBLINES-1);

 dbdisplay=1;

 return(err);
}


static void dbugfinit(void)
{
 if(dbline) flex_free((flex_ptr)&dbline);
}



static void setpopdbug(void)
{
 unshadest(dbug_menu,1,!dbfp);
 unshadest(dbug_menu,2,dbfp!=NULL);
 tickst(dbug_menu,3,dbdata);
}


void decodedb(int m)
{
 switch(m)
 {
  case 2:
         debugclose(0);
         break;

  case 3:
         dbdata^=1;
         break;
 }

 setpopdbug();
}


void dbicon(int icon)
{
 if(buttons==2) 
 {
  setpopdbug();
  popmenu(dbug_menu);
 }
 else
 if(buttons==4) setfocus(whandle[DBUG]);

 USE(icon);
}



static void dbredrawsub(wimp_redrawstr * redrawstr,int more)
{
 int oy;
 int ox;
 int ylo;
 int yhi;
 int n;
 int y;

 while(more)
 {
  ox=redrawstr->box.x0-redrawstr->scx;
  oy=redrawstr->box.y1-redrawstr->scy;

  ylo=-(redrawstr->g.y1-oy);            /* small number, top of window */
  yhi=-(redrawstr->g.y0-oy);            /* bigger, bottom of window */

  n=(ylo-TDIRFY)/TDIRDY;
  if(n<0) n=0;
  y=n*TDIRDY+TDIRFY;

  while(y<=yhi && n<DBLINES)
  {
   wimp_setcolour(dbline[(n+dbcury+1)&DBMASK].dir?0:9);
   bbc_move(ox,oy-y);
   bbc_stringprint(dbline[(n+dbcury+1)&DBMASK].text);

   y+=TDIRDY;
   n++;
  } 

  wimp_get_rectangle(redrawstr,&more);
 }
}




void dbredraw(void)
{
 wimp_redrawstr redrawstr;
 int            more;
 redrawstr.w=ewindow;
 wimp_redraw_wind(&redrawstr,&more);
 dbredrawsub(&redrawstr,more);
}


void dbclose(void)
{
 closedownt(DBUG);
 dbugfinit();
}



static void dbextent(void)
{
 int sety;

 sety=TDIRFY+TDIRDY*DBLINES;
 extent(whandle[DBUG],0,-sety,DBWIDTH*16,0);
}


void dbopen(void)
{
 os_error * err;
 int        handle;

 if(whandle[DBUG]) forward(whandle[DBUG]);
 else
 {
  handle=createwindow(DBUG);
  if(!handle) return;

  err=dbuginit();
  if(!err) 
  {
   popup(handle,0);
   dbextent();
   getw(handle);
   scy=-(TDIRFY+TDIRDY*DBLINES)+(y1-y0);
   open(handle,x0,y0,x1,y1,scx,scy,bhandle);
  }
  else
  {
   dbclose();
   report(err);
  }
 }
}


static void dbscroll(int n)
{
 wimp_box box;

 box.x0=0;
 box.x1=DBWIDTH*16;
 box.y0=-(TDIRFY+TDIRDY*DBLINES);
 box.y1=-(TDIRFY+TDIRDY*n);
 
 wimp_blockcopy(whandle[DBUG],&box,0,box.y0+n*TDIRDY);
}


static void dbrefresh(int n) /* refresh bottom n lines */
{
 wimp_redrawstr r;

 getw(whandle[DBUG]);

 r.box.x0=0;
 r.box.x1=DBWIDTH*16;
 r.box.y0=-(TDIRFY+TDIRDY*DBLINES);
 r.box.y1=r.box.y0+TDIRDY*n+deltay;
 r.w=whandle[DBUG];

 wimp_force_redraw(&r);
}


static void dbflush(void)
{
 if(dbline)
 {
  dbrefresh(1);
  dbscroll(1);
  dbcury=(dbcury+1) & DBMASK;
  blankline(dbcury,debdir);
  dbcurx=DBLEFT;
 }

 if(dbfp) 
 {
  if(debdir) fprintf(dbfp,"\nRX(%d):",clock());
  else       fprintf(dbfp,"\nTX(%d):",clock());
 }
}



static void dbputclo(int c)
{
 if(dbcurx==(DBWIDTH-1)) dbflush();
 dbline[dbcury].text[dbcurx++]=c;
}


static void dbputc(int c)
{
 if(dbdisplay) 
 {
  if(dbfp) putc(c,dbfp);

  if((dbdata || !dbdataphase || dbdatadir!=debdir) && dbline)
  {
   if(c<32)
   {
    if(c=='\n') dbflush();
    else
    if(c=='\r') dbcurx=DBLEFT;
    else
    {
     dbputclo('|');
     dbputclo(c+64);
    }
   }
   else
   if(c=='|')
   {
    dbputclo('|');
    dbputclo('|');
   }
   else
   if(c==127)
   {
    dbputclo('|');
    dbputclo('?');
   }
   else
   if(c>=128 && c<160)
   {
    dbputclo('|');
    dbputclo(c+64);
   }
   else dbputclo(c);
  }
 }
}




/* something like if in TX phase, stash data */
/* get Return send it out */


static char dbkbuff[DBWIDTH];
static int  dbkindex;


void dbkey(int * key)
{
 int ch;
 int i;

 ch=*key;
 if(ch>=0 && ch<=255)
 {
  dbputc(ch);

  dbkbuff[dbkindex]=ch;

  if(ch=='\r')
  {
   dbdisplay=0;

   for(i=0;i<=dbkindex;i++)
   {
    outbyte(dbkbuff[i]);
   }

   dbdisplay=1;
   dbkindex=0;
  }
  else
  {
   if(dbkindex<DBWIDTH) dbkindex++;

  }

  dbrefresh(1);

  *key=-1;
 }
}


int savedbbuffer(char * filename)
{
 FILE * fp;
 int    i;

 fp=ropen(filename,"wb");
 if(fp)
 {
  for(i=0;i<DBLINES;i++)
  {
   rfprintf(fp,"%c%s\n",dbline[(i+dbcury+1)&DBMASK].dir?'R':'T',
                        dbline[(i+dbcury+1)&DBMASK].text);
  }
  rclose(fp);
 }
 return(1);
}


int savedbspool(char * filename)
{
 if(!dbfp)
 {
  dbfp=fopen(filename,"wb");
 }
 return(1);
}


/*****************************************************************************/


void writetodebug(int fp)
{
 char * p;
 dbputc('[');
 p=stringptr(stack[fp]);
 while(*p) dbputc(*p++);
 dbputc(']');
}


void debugopen(int fp)
{
 savedbspool(stringptr(stack[fp]));
}


void debugclose(int fp)
{
 if(dbfp) fclose(dbfp);
 dbfp=NULL;
 fp=fp;
}


void debugputc(int c)
{
 if(dbdisplay)
 {
  if(debdir)
  {
   debdir=0;
   dbflush();
  }
  dbputc(c);
 }
}

void debuggetc(int c)
{
 if(!debdir)
 {
  debdir=1;
  dbflush();
 }

 dbputc(c);
}


void setdbdataphase(int enter,int rx)
{
 char * p;

 if(enter && !dbdata)
 {
  dbflush();
  if(rx) p="<receive data>";
  else   p="<transmit data>";

  while(*p) dbputc(*p++);

  dbflush();
 }

 dbdatadir=rx;
 dbdataphase=enter;
}


