/* > c.cmndwind < */

#include <stdio.h>
#include "aim_stdlib.h"
#include <string.h>
#include <float.h>
#include <math.h>
#include <stdarg.h>
#include <setjmp.h>
#include <swis.h>
#include "flex.h"
#include "os.h"
#include "bbc.h"
#include "wimp.h"
#include "wimpt.h"
#include "win.h"
#include "sprite.h"
#include "werr.h"
#include "cmdwind.h"
#include "swis.h"

#define Rand 0
#define max(a,b) ((a) > (b) ? (a) : (b))
#define min(a,b) ((a) < (b) ? (a) : (b))


extern int max_row,max_col;
extern wimp_wstate cmd_st;
extern BOOL cmdwind_is_open;
int WprintfHeight; 
int WprintfWidth;  
int WprintfMode;   
int WprintfSize;
BOOL formfeed;
/* =(WprintfWidth*WprintfHeight)+sizeof(sprite_header)+sizeof(sprite_area) */

void wvdu(char ch);
void reinit_wprintf(int wimp_mode, BOOL init, BOOL display);
sprite_defines wsprite;
sprite_factors factors;
sprite_pixtrans pixtrans[256];

extern int cmd_window;
extern int OSx, OSy, OSbpp;
extern wimp_caretstr block;
extern int grey_level;

ForceRedrawBlock wblk;
wimp_winfo w;
wimp_wstate state;
static int x0,y0;

static int save0,save1,save2;
char *outf="Aim>";
char *outr="\rAim>";
char *outl="\nAim>";
char *colours="\x11\x80\x11\x07";
int bytecnt=4;

os_regset reg;
os_error *err;
change_box * sprite;

int wprintf_window;
sprite_area *wprintf_sprite_area;
char wprintf_sprite_name[20];
sprite_ptr wprintf_sprite_ptr;
int wprintf_vdu_save[1000];


void strcvrt(char *string,int lengte)
{
   int teller;

   teller = 0;
   while ((string[teller] != 13) && (teller < lengte)) ++teller;
   string[teller] = 0;
}


os_error *WimpCreateWindow(CreateWindowBlock *windowblock,int *wind_handle)
{
   os_regset reg;
   os_error *err;

   reg.r[1] = (int)windowblock;
   err = os_swix(Wimp_CreateWindow, &reg);
   *wind_handle = reg.r[0]; 
   return(err);
}

os_error *WimpCreateIcon(CreateIconBlock *iconblock,int *icon_handle)
{
   os_regset reg;
   os_error *err;

   reg.r[1] = (int)iconblock;
   err = os_swix(Wimp_CreateIcon, &reg);
   *icon_handle = reg.r[0]; 
   return(err);
}

os_error *WimpGetIconState(int wind_handle,int icon_handle,
                           GetIconStateBlock *block)
{
   os_regset reg;
   os_error *err;

   block->wind_handle = wind_handle;
   block->icon_handle = icon_handle;
   reg.r[1] = (int)block;
   err = os_swix(Wimp_GetIconState, &reg);
   return(err);
}



char *WimpGetIconName(int handle,int icon,const char *name)
{
   GetIconStateBlock blk1;
   int lengte;
   static char iname[256];
   wimpt_complain(WimpGetIconState(handle,icon,&blk1));

   if ((blk1.flags & INDIRECT)==0) {
      if (name == NULL)
         strncpy(iname,blk1.icon.text,12);
      else
         strncpy((char *)name,blk1.icon.text,12);
      lengte=12;
   }
   else {
      lengte=blk1.icon.write.bufflen;
      if (name == NULL)
         strncpy((char *)iname,blk1.icon.write.text_buff,lengte);
      else
         strncpy((char *)name,blk1.icon.write.text_buff,lengte);
   }
   if (name == NULL)
      strcvrt(iname,lengte);
   else
      strcvrt((char *)name,lengte);
   return(iname);
}

int WimpCreateIconEasy(int handle,int x0,int y0,int x1,int y1,int flag,
                       char c0,char c1,const char *tekst)
{
   CreateIconBlock block;

   block.wind_handle = handle;
   block.x0 = x0;
   block.y0 = y0;
   block.x1 = x1;
   block.y1 = y1;
   block.flags = flag + (c0 << 24) + (c1 << 28);
   strcpy(block.data.text,tekst);
   wimpt_complain(WimpCreateIcon(&block,&handle));
   return(handle);
}


int WimpCreateWindowEasy(int ix0,int iy0,int ix1,int iy1,int scx,int scy,
                         int flags,
                         char titfcol,char titbcol,char wafcol,char wabcol,
                         char sbicol,char sbocol,char highlcol,
                         int worklengte,int workhoogte,
                         int titelflags,int workflags,int sacb,
                         char *titel)
{
   CreateWindowBlock WindowBlock;
   int handle;

   WindowBlock.x0 = ix0;
   WindowBlock.y0 = iy0;
   WindowBlock.x1 = ix1;
   WindowBlock.y1 = iy1;
   WindowBlock.scx = scx;
   WindowBlock.scy = scy;
   WindowBlock.wind_behind = -1;
   WindowBlock.flags = flags;
   WindowBlock.colours[0] = titfcol;
   WindowBlock.colours[1] = titbcol;
   WindowBlock.colours[2] = wafcol;
   WindowBlock.colours[3] = wabcol;
   WindowBlock.colours[4] = sbicol;
   WindowBlock.colours[5] = sbocol;
   WindowBlock.colours[6] = highlcol;
   WindowBlock.reservedb = 0;
   WindowBlock.exx0 = 0;
   WindowBlock.exy0 = -workhoogte;
   WindowBlock.exx1 = worklengte;
   WindowBlock.exy1 = 0;
   WindowBlock.title_icon = titelflags;
   WindowBlock.work_icon = workflags;
   WindowBlock.reservedw[0] = sacb;
   WindowBlock.reservedw[1] = 0;
   strcpy(WindowBlock.title,titel);
   WindowBlock.initial_icons = 0;
   wimpt_complain(WimpCreateWindow(&WindowBlock,&handle));
   return(handle);
}

static os_error *sprite_Changedbox(int flag, change_box **cbox)
{
  os_regset r;
  os_error *e;

  r.r[0] = flag;
  e = os_swix(OS_ChangedBox, &r);
  if (e == 0)
    *cbox = (change_box *)(r.r[1]);
  return e;
}

void wprintf(const char *form,...)
{
   int wkey(void);
   void redo_wprintf(int handle);
   BOOL more,Redraw;
   wimp_eventstr *e;
   int del_x,ybot,i;
   va_list arg_ptr;
   va_start(arg_ptr,form);
   reg.r[0]=0x23c;
   reg.r[1]=(int)wprintf_sprite_area;
   reg.r[2]=(int)wprintf_sprite_ptr;
   reg.r[3]=(int)wprintf_vdu_save;
   err=os_swix(OS_SpriteOp,&reg);
   save0 = reg.r[0];
   save1 = reg.r[1];
   save2 = reg.r[2];
   sprite_Changedbox(1,&sprite);
   sprite_Changedbox(2,&sprite);
   vprintf(form,arg_ptr);
   va_end(arg_ptr);
   if (form[strlen(form)-1]=='\n')
   reg.r[1]=5;reg.r[0]=(int)outr;err=os_swix(OS_WriteN,&reg);
   sprite_Changedbox(-1,&sprite);
   wblk.x0=sprite->box.x0*OSx;
   wblk.x1=max(sprite->box.x1*OSx,0)+2;
   wblk.y0=(sprite->box.y0*OSy)-OSy*WprintfHeight+Rand;
   wblk.y1=max(sprite->box.y1*OSy,0)-OSy*WprintfHeight+Rand + 4;   


   del_x=1;
   if (form[strlen(form)-1]=='\n') del_x=-wblk.x1+(8*strlen(outf)+1)*OSx;
   block.w=wprintf_window;
   block.i = -1;
   block.x=wblk.x1+del_x;
   block.y=wblk.y0;
   block.height=9*OSy;
   block.index=0;
   reg.r[0] = save0;
   reg.r[1] = save1;
   reg.r[2] = save2;
   err=os_swix(OS_SpriteOp,&reg);

   wimpt_noerr(wimp_get_wind_state(cmd_window, &state));
   ybot=state.o.box.y0-state.o.box.y1+state.o.y;
   Redraw=FALSE;
   if (wblk.y0 < ybot) 
      {
       Redraw=TRUE;
       w.info.scy+=(wblk.y0-ybot);
       wblk.y1=0; 
       wblk.y0+=ybot;
       state.o.y=w.info.scy;
      }
    if (wblk.y0 < -1280) wblk.y0=-1280;
   x0=state.o.box.x0-state.o.x;
   y0=state.o.box.y1-state.o.y-OSy*WprintfHeight;

   err=wimp_set_caret_pos(&block);      
   wblk.wind_handle=wprintf_window;
   if (Redraw) 
     {
      wimp_open_wind(&state.o);
      redo_wprintf(cmd_window);
      i=wkey();  /* The neccesary polling */
     }
   else
     {
      wimp_update_wind((wimp_redrawstr *)&wblk,&more);
      while (more)
       {
        wimpt_complain(sprite_put_given(wprintf_sprite_area,&wsprite.id,0,
                    x0,y0));
        wimp_get_rectangle((wimp_redrawstr *)&wblk,&more);
       }
     }

}

void wvdu(char ch)
{
   int wkey(void);
   void redo_wprintf(int handle);
   BOOL more,Redraw;
   int ybot,i;
   reg.r[0]=0x23c;
   reg.r[1]=(int)wprintf_sprite_area;
   reg.r[2]=(int)wprintf_sprite_ptr;
   reg.r[3]=(int)wprintf_vdu_save;
   err=os_swix(OS_SpriteOp,&reg);
   save0 = reg.r[0];
   save1 = reg.r[1];
   save2 = reg.r[2];
   sprite_Changedbox(1,&sprite);
   sprite_Changedbox(2,&sprite);
   reg.r[1]=1;
   reg.r[0]=(int) &ch;
   err=os_swix(OS_WriteN,&reg);
   formfeed = TRUE;
   
     switch(ch)
      {
       case 13: reg.r[1]=5;reg.r[0]=(int)outl;err=os_swix(OS_WriteN,&reg);
                break; 
       case 10: reg.r[1]=5;reg.r[0]=(int)outr;err=os_swix(OS_WriteN,&reg);
                break; 
       case 12: reg.r[1]=bytecnt;reg.r[0]=(int)colours;
                err=os_swix(OS_WriteN,&reg);
                reg.r[1]=5;reg.r[0]=(int)outf;err=os_swix(OS_WriteN,&reg);
                formfeed = FALSE;
                break; 
      }
   sprite_Changedbox(-1,&sprite);
   wblk.x0=sprite->box.x0*OSx;
   wblk.x1=max(sprite->box.x1*OSx,0)+2;
   wblk.y0=max(sprite->box.y0*OSy,0)-OSy*WprintfHeight+Rand;
   wblk.y1=max(sprite->box.y1*OSy,0)-OSy*WprintfHeight+Rand + 4;   
   reg.r[0] = save0;
   reg.r[1] = save1;
   reg.r[2] = save2;
   err=os_swix(OS_SpriteOp,&reg);
   block.y=wblk.y0;
   block.x=wblk.x1+1;
     switch(ch)
      {
       case 12:   block.x=(8*strlen(outf)+1)*OSx;
                  block.y=wblk.y1-8*OSy; 
                  break;
       case 13:
       case 10:   block.x=(8*strlen(outf)+1)*OSx;
                  break; 
       case 0x7F: block.x=wblk.x1-8*OSx;
                  break;
       default:   break;
      }

   block.w=wprintf_window;
   block.i = -1;
   block.height=9*OSy;
   block.index=0;

   wblk.wind_handle=cmd_window;
   wimpt_noerr(wimp_get_wind_state(cmd_window, &state));
   ybot=state.o.box.y0-state.o.box.y1+state.o.y;
   Redraw=FALSE;
   if (wblk.y0 <= ybot) 
      {
       Redraw=TRUE;
       w.info.scy+=(wblk.y0-ybot);
       wblk.y1=0;
       state.o.y=w.info.scy*formfeed;
      }
   x0=state.o.box.x0-state.o.x;
   y0=state.o.box.y1-state.o.y-OSy*WprintfHeight;
   if (Redraw && cmdwind_is_open) wimp_open_wind(&state.o); 
   /* is window reeds open, voer scroll actie uit */
   err=wimp_set_caret_pos(&block);      
   wimp_update_wind((wimp_redrawstr *)&wblk,&more);
   while (more)
    {
     wimpt_complain(sprite_put_given(wprintf_sprite_area,&wsprite.id,0,
                    x0,y0));
     wimp_get_rectangle((wimp_redrawstr *)&wblk,&more);
    }
}

void wprintf_init(void)
{
 int action;
 WprintfMode=12;
 WprintfHeight=max_row*8; /* maximum height=480 pixels */
 WprintfWidth=max_col*8;  /* maximum width=500 pixels */
 WprintfSize=(WprintfWidth*WprintfHeight)+sizeof(sprite_header)+sizeof(sprite_area);
   wprintf_sprite_area=(sprite_area *)heap_alloc(WprintfSize);
   if (action == NULL) werr(1,"Malloc failed in CmdWindow \r"); 
   sprite_area_initialise(wprintf_sprite_area,WprintfSize);
   reinit_wprintf(wimpt_mode(),TRUE,FALSE);
}

void redo_wprintf(int handle)
{
  BOOL            more_to_do;
  wimp_redrawstr  r;
  r.w=handle;
  w.w=handle;
  wimp_get_wind_info(&w);
  x0=w.info.box.x0-w.info.scx;
  y0=w.info.box.y1-w.info.scy-OSy*WprintfHeight;
  wimp_redraw_wind(&r,&more_to_do);

  /* --- refresh the window's contents --- */
    while (more_to_do)
    {
     wimpt_complain(sprite_put_given(wprintf_sprite_area,&wsprite.id,0,
                    x0,y0));
      wimp_get_rectangle(&r, &more_to_do);
    }
}

void reinit_wprintf(int wimp_mode, BOOL init,BOOL display)
{
 int box[5];
 switch(OSbpp)
  {
  case 8:
   if (grey_level==16)
    {
     colours="\x11\xff\x11\x2a\x17\x11\x01\xc0\x00\x00\x00\x00\x00\x17\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
     bytecnt=27;
    }
   else
    { 
     colours="\x11\xff\x11\x00\x17\x11\x01\xc0\x00\x00\x00\x00\x00";
     bytecnt=13;
    }
   break;
 case 4:
   colours="\x11\x80\x11\x07";
   bytecnt=4;
   break;
 default:
   colours="\x11\x80\x11\x07";
   bytecnt=4;
   break;
 }

if (!init)
 {
  wimpt_noerr(wimp_get_wind_state(cmd_window, &state));
  wimpt_complain(wimp_delete_wind(wprintf_window));
  wimpt_complain(sprite_delete(wprintf_sprite_area,&wsprite.id));
/*  win_activedec(); */
  wimpt_complain(sprite_area_reinit(wprintf_sprite_area));
 }

 wprintf_window = WimpCreateWindowEasy(0,220,OSx*WprintfWidth,
                        OSy*WprintfHeight,0,0,0x0000000f,6,3,0,0xff,4,2,12,
                        OSx*WprintfWidth,OSy*WprintfHeight,
                                      0x62000019,0x00003080,
                                       (int)wprintf_sprite_area,
                                      "Aim");
 cmd_window = wprintf_window;

 wimpt_complain(sprite_create(wprintf_sprite_area, "CmdSprite",
           sprite_nopalette,WprintfWidth,WprintfHeight,wimp_mode));

 strcpy(wprintf_sprite_name,"CmdSprite");

 wsprite.id.tag=sprite_id_name;
 wsprite.id.s.name="CmdSprite";
 wimpt_complain(sprite_select_rp(wprintf_sprite_area,&wsprite.id,&wprintf_sprite_ptr));

 /* Reset savearea vdu-stream for default display */
 
 wprintf_vdu_save[0]=0;
 reg.r[0]=0x23c;
 reg.r[1]=(int)wprintf_sprite_area;
 reg.r[2]=(int)wprintf_sprite_ptr;
 reg.r[3]=(int)wprintf_vdu_save;
 err=os_swix(OS_SpriteOp,&reg);
 save0 = reg.r[0];
 save1 = reg.r[1];
 save2 = reg.r[2];
 reg.r[0]=1;
 reg.r[1]=(int)box;
 err=os_swix(OS_ChangedBox,&reg);
 reg.r[0] = save0;
 reg.r[1] = save1;
 reg.r[2] = save2;
 err=os_swix(OS_SpriteOp,&reg);
if (!init && display)
 {
 cmdwind_is_open=TRUE;
 cmd_st.o.w=cmd_window;
 cmd_st.o.behind =state.o.behind;
 cmd_st.flags=state.flags;
 wimp_open_wind(&cmd_st.o);
/* win_activeinc(); */
 }
 wvdu('\f');wvdu('\f');
}
