/* screen - screen update functions
 */

#include "screen.h"
#include <string.h>
#include <roslib.h>

int init_screen(Screendata *screendata) {
 static long vars_in[5],vars_out[5];
 static os_regset r;
 os_cursor(0);
 vars_in[0]=256;                                       /* text window width */
 vars_in[1]=257;                                      /* text window height */
 vars_in[2]=155;                                  /* text foreground colour */
 vars_in[3]=156;                                  /* text background colour */
 vars_in[4]=-1;
 r.r[0]=vars_in; r.r[1]=vars_out; os_swi(0x31,&r);
 if (strcmp(getenv("Wimp$State"),"desktop")==0) {
  vars_out[2]=2;
  vars_out[3]=7;
 }
 if (screendata->width==-1) screendata->width=vars_out[0];
 if (screendata->height==-1) screendata->height=vars_out[1];
 if (screendata->foreground==-1) screendata->foreground=vars_out[2];
 if (screendata->background==-1) screendata->background=vars_out[3];
 screendata->standout=0;
 screendata->redraw=0;
 screendata->screen=NULL; screendata->curscr=NULL;
 screendata->x=0; screendata->y=0;
 screendata->screen=
  (short *)malloc(sizeof(short)*(screendata->width)*(screendata->height));
 if (screendata->screen==NULL) {return(1);}
 screendata->curscr=
  (short *)malloc(sizeof(short)*(screendata->width)*(screendata->height));
 if (screendata->curscr==NULL) {free(screendata->screen); return(1);}
 os_cls();
 memset(screendata->screen,0,
        sizeof(short)*(screendata->width)*(screendata->height));
 memset(screendata->curscr,0,
        sizeof(short)*(screendata->width)*(screendata->height));
 screendata->oldx=1; screendata->oldy=0;
 os_byte(4,&(screendata->oldx),&(screendata->oldy));
 screendata->cminx=1000; screendata->cminy=1000;
 screendata->cmaxx=0; screendata->cmaxy=0;
 return(0);
}

void end_screen(Screendata *screendata) {
 if (screendata->screen!=NULL) free(screendata->screen);
 if (screendata->curscr!=NULL) free(screendata->curscr);
 os_colour(screendata->foreground);
 os_colour(screendata->background+128);
 os_vduq(31,0,screendata->height,10,13);
 os_byte(4,&(screendata->oldx),&(screendata->oldy));
 os_cursor(1);
}

void refresh(Screendata *screendata) {
 static int a,x,y;
 static char c,s,t;
 static long count;
 os_cursor(0);
 os_colour(screendata->foreground);
 os_colour((screendata->background)+128);
 if (screendata->redraw) {
  screendata->cminx=0; screendata->cminy=0;
  screendata->cmaxx=1000; screendata->cmaxy=1000;
 }
 s=0;
 if (screendata->cmaxx>screendata->width)
  screendata->cmaxx=screendata->width;
 if (screendata->cmaxy>screendata->height)
  screendata->cmaxy=screendata->height;
 for(y=screendata->cminy; y<screendata->cmaxy; y++) {
  c=0; count=y*(screendata->width)+screendata->cminx;
  for(x=screendata->cminx; x<screendata->cmaxx; x++) {
   if (screendata->screen[count]!=screendata->curscr[count]) {
    a=screendata->screen[count]; screendata->curscr[count]=a;
    if (a>255) {t=1; a-=256;} else {t=0;}
    if (s!=t) {
     s=t;
     os_colour((screendata->foreground)+128*s);
     os_colour((screendata->background)+128-(128*s));
    }
    if (c==0) os_vduq(31,x,y);
    c=1;
    if (a==0) a=32;
    if ((a<32) || (a==127)) a='.';
    os_vdu(a);
   } else {c=0;}
   count++;
  }
 }
 screendata->cminx=1000; screendata->cminy=1000;
 screendata->cmaxx=0; screendata->cmaxy=0;
 os_cursor(1);
 os_vduq(31,screendata->x,screendata->y);
}

void redraw(Screendata *screendata) {
 screendata->redraw=1;
 refresh(screendata);
}

void addstr(Screendata *screendata,char *string) {
 static int i;
 for(i=0; i<strlen(string); i++) {addch(screendata,string[i]);}
}

void addch(Screendata *screendata,int c) {
 static long count;
 if (((screendata->x)<0) || ((screendata->y)<0) ||
    ((screendata->x)>=screendata->width) ||
    ((screendata->y)>=screendata->height))
  return;
 if (c==32) c=0;
 c+=256*screendata->standout;
 count=screendata->x+(screendata->y)*(screendata->width);
 if (screendata->screen[count]==c) {(screendata->x)++; return;}
 screendata->screen[count]=c;
 if (screendata->cminx>screendata->x) screendata->cminx=screendata->x;
 if (screendata->cminy>screendata->y) screendata->cminy=screendata->y;
 (screendata->x)++;
 if (screendata->cmaxx<screendata->x) screendata->cmaxx=screendata->x;
 if (screendata->cmaxy<(screendata->y+1))
  screendata->cmaxy=(screendata->y)+1;
}

void move(Screendata *screendata,int x,int y) {
 if ((x<0) || (y<0) || (x>=screendata->width) || (y>=screendata->height))
  return;
 screendata->x=x; screendata->y=y;
}

int standout(Screendata *screendata,char status) {
 static int a;
 a=screendata->standout; screendata->standout=status; return(a);
}

int readchar(void) {return(os_get());}
