/****************************************************************************
* msdostxt.c
*
* This module implements the text output routines for a 32-bit protected
* mode msdos verion of POV-Ray on various compilers.
*
* from Persistence of Vision(tm) Ray Tracer
* Copyright 1996 Persistence of Vision Team
*---------------------------------------------------------------------------
* NOTICE: This source code file is provided so that users may experiment
* with enhancements to POV-Ray and to port the software to platforms other
* than those supported by the POV-Ray Team. There are strict rules under
* which you are permitted to use this file. The rules are in the file
* named POVLEGAL.DOC which should be distributed with this file. If
* POVLEGAL.DOC is not available or for more info please contact the POV-Ray
* Team Coordinator by leaving a message in CompuServe's Graphics Developer's
* Forum. The latest version of POV-Ray may be found there as well.
*
* This program is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
*
*****************************************************************************/
#include <process.h>
#include <dos.h>
#include "frame.h"
#include "povproto.h"
#include "povray.h"
#include "optin.h"
#include "msdosall.h"
#define SCROLL_BACK_SIZE 10000
typedef struct W_Data_Struct WDATA;
struct W_Data_Struct
{
int CurX, CurY, Wy1, Wy2, Fcol, Bcol, Ovr, TabX, Init;
unsigned char Name[15];
WDATA *Prev ,*Next;
unsigned char *Buf;
int Wrap, Cur, Top;
};
static WDATA Bann_Data, Warn_Data, RInf_Data, SInf_Data, Fatl_Data, Stat_Data;
static WDATA Debug_Data;
static WDATA *OnTop, *Root;
static char *Saved_Text;
static void Do_Message(WDATA *Data,char *s);
static void Update_Tabs(WDATA *Data);
static void Do_Tab(WDATA *Data);
static void Slowit(void);
static int Scan_Back(unsigned char *Buf, int *Strt);
static int Scan_Front(unsigned char *Buf, int *Strt, int End);
static int Viewit(void);
static int Next_TabX, LastY;
#define Init_WData(d,y1,y2,f,b,cx,cy,ov,n) (d).CurX=(cx);(d).CurY=(cy);\
(d).Init=FALSE;(d).Wy1=(y1);(d).Wy2=(y2); (d).Fcol=(f);(d).Bcol=(b);\
(d).Ovr=(ov); (d).TabX=0; strcpy((d).Name,n); (d).Buf=NULL;
void MSDOS_Text_Init_Vars()
{
CON_init();
Init_WData(Bann_Data, 1,22,15,1,0, 0, TRUE,"About");
Init_WData(SInf_Data, 24,24,15,5,0, 0,FALSE,"");
Init_WData(RInf_Data, 2,22,15,2,0,20, TRUE,"Options");
Init_WData(Stat_Data, 2,22,15,3,0,20, TRUE,"Statistics");
Init_WData(Warn_Data, 2,22,14,6,0,20, TRUE,"Warning");
Init_WData(Fatl_Data, 2,22,14,4,0,20, TRUE,"Error");
Init_WData(Debug_Data, 2,22, 0,7,0,20, TRUE,"Debug");
if((Fatl_Data.Buf=malloc(SCROLL_BACK_SIZE))==NULL)
{
fprintf(stderr,"Cannot allocate error message buffer.\n");
exit(1);
}
Root=OnTop=NULL;
Next_TabX=2;
LastY=0;
CON_setForeColor(15);
CON_setBackColor(1);
CON_setBackground(CON_getAttr(),32);
CON_clrscr();
CON_writec( 0, 0,0x001f,201);
CON_writec(79, 0,0x001f,187);
CON_fillText( 1, 0,78, 0,0x001f,205);
CON_fillText( 1,23,78,23,0x001f,205);
CON_fillText( 0, 1, 0,24,0x001f,186);
CON_fillText(79, 1,79,24,0x001f,186);
CON_writec( 0,23,0x001f,204);
CON_writec(79,23,0x001f,185);
CON_setWindow(1,1,78,22);
CON_clrscr();
}
void MSDOS_Finish(n)
int n;
{
WDATA *Data;
if (opts.Options & PROMPTEXIT)
{
Viewit();
}
/* Note:Using free rather than POV_FREE because this is freed after the
* generic part of POV-Ray has already cleaned up all other memory.
*/
for (Data=Root; Data!=NULL; Data=Data->Next)
{
if(Data->Buf!=NULL)
{
free(Data->Buf);
Data->Buf=NULL;
}
}
CON_setForeColor(7);
CON_setBackColor(0);
CON_setBackground(CON_getAttr(),32);
CON_setWindow(0,0,79,24);
CON_gotoxy(79,24);
CON_printf("\n\r");
exit(n);
}
static void Do_Message(Data,s)
WDATA *Data;
char *s;
{
unsigned char *ptr = s;
register unsigned char c;
if (!(Data->Init))
{
Data->Next=Data->Prev=NULL;
Data->Wrap=Data->Cur=0;
if (Data->Ovr)
{
/* Note:Using malloc rather than POV_MALLOC because this
* is freed after the generic part of POV-Ray has already cleaned up
* all other memory.
*/
if(Data->Buf==NULL)
{
if((Data->Buf=malloc(SCROLL_BACK_SIZE))==NULL)
{
Error("Cannot allocate text message buffer.\n");
}
}
Data->Buf[0]=0;
Data->Cur=1;
Data->TabX=Next_TabX;
Next_TabX+=strlen(Data->Name)+5;
if (LastY<20)
{
Data->CurY=LastY;
}
/* Only Ovr gets linked */
Data->Init=TRUE;
Data->Next=Root;
if (Root!=NULL)
{
Root->Prev=Data;
}
Root=Data;
}
}
Update_Tabs(Data);
CON_setWindow(1,Data->Wy1,78,Data->Wy2);
CON_gotoxy(Data->CurX,Data->CurY);
CON_setForeColor(Data->Fcol);
CON_setBackColor(Data->Bcol);
CON_setBackground(CON_getAttr(),32);
if (Data->Ovr)
{
while ((c=*ptr++) != '\0')
{
if (c=='\n')
{
CON_putc('\r');
CON_putc(c);
c=0;
}
else
{
CON_putc(c);
}
/* This wraps 1 byte early but it'll make unwrapping easier */
if (Data->Cur==SCROLL_BACK_SIZE)
{
Data->Wrap=TRUE;
Data->Cur=0;
}
Data->Buf[Data->Cur++]=c;
}
}
else
{
while ((c=*ptr++) != '\0')
{
if (c=='\n')
{
CON_putc('\r');
}
CON_putc(c);
}
}
Data->CurX=CON_wherex();
Data->CurY=CON_wherey();
if (Data->Ovr)
{
LastY=Data->CurY;
}
}
void MSDOS_Banner(char *s)
{
Do_Message(&Bann_Data,s);
}
void MSDOS_Warning(char *s)
{
Do_Message(&Warn_Data,s);
}
void MSDOS_Render_Info(char *s)
{
if (In_Graph_Mode)
return;
Do_Message(&RInf_Data,s);
}
void MSDOS_Status_Info(char *s)
{
if (In_Graph_Mode)
return;
Do_Message(&SInf_Data,s);
}
void MSDOS_Fatal(char *s)
{
Do_Message(&Fatl_Data,s);
}
void MSDOS_Statistics(char *s)
{
Do_Message(&Stat_Data,s);
}
void MSDOS_Debug_Info(char *s)
{
if (In_Graph_Mode)
return;
Do_Message(&Debug_Data,s);
}
void MSDOS_Wait_Key(void)
{
MSDOS_getch();
}
int MSDOS_getch(void)
{
int Key;
if((Key=getch())==0)
Key=256+getch();
return(Key);
}
void MSDOS_Test_Abort (void)
{
if (opts.Options & EXITENABLE)
{
if (kbhit())
{
if (In_Graph_Mode)
{
Stop_Flag = TRUE; MSDOS_getch();
}
else
{
Status_Info("\n **** Paused **** Press 'C' to continue.");
MSDOS_getch();
if (!(Stop_Flag = Viewit()))
{
Status_Info("\n Program continued.");
}
}
}
}
}
static void Update_Tabs(Data)
WDATA *Data;
{
WDATA *Temp;
if (!(Data->Ovr))
return;
if (Data==OnTop)
return;
OnTop=Data;
Data->CurY=LastY;
if (LastY<20)
{
CON_setWindow(1,Data->CurY+Data->Wy1,78,Data->Wy2);
CON_setForeColor(Data->Fcol);
CON_setBackColor(Data->Bcol);
CON_setBackground(CON_getAttr(),32);
CON_clrscr();
}
else
{
if (LastY==20)
{
CON_setWindow(1,2,78,22);
CON_gotoxy(78,20);
CON_setForeColor(Data->Fcol);
CON_setBackColor(Data->Bcol);
CON_setBackground(CON_getAttr(),32);
CON_putc('\n');
}
}
CON_setWindow(0,0,79,24);
for(Temp=Root; Temp!=NULL; Temp=Temp->Next)
{
Do_Tab(Temp);
}
}
static void Do_Tab(Data)
WDATA *Data;
{
if (!(Data->Ovr))
return;
CON_gotoxy(Data->TabX,23);
if(Data==OnTop)
{
CON_setForeColor(Data->Fcol);
CON_setBackColor(Data->Bcol);
}
else
{
CON_setForeColor(7);
CON_setBackColor(1);
}
CON_setBackground(CON_getAttr(),32);
CON_printf("\\%s/",Data->Name);
}
static void Slowit(void)
{
time_t l, lt;
lt = l = time(&l);
while (time(&l) < lt + 1);
}
static int Scan_Back(Buf,Strt)
unsigned char *Buf;
int *Strt;
{
int i=(*Strt)-1;
if((*Strt)==0)
return(0);
while (Buf[i]!=0)
i--;
*Strt=i;
return (1);
}
static int Scan_Front(Buf,Strt,End)
unsigned char *Buf;
int *Strt;
int End;
{
int i=(*Strt)+1;
if ((*Strt)==End)
return(0);
while (Buf[i]!=0)
i++;
*Strt=i;
return (1);
}
static int Viewit(void)
{
WDATA *Data;
int i, j, k, Key, Flag;
unsigned char *tb;
for(Data=Root; Data!=NULL; Data=Data->Next)
{
if (Data->Wrap)
{
tb=malloc(SCROLL_BACK_SIZE);
i=SCROLL_BACK_SIZE - Data->Cur;
memcpy(tb,&(Data->Buf[Data->Cur]),i);
memcpy(&(tb[i]),Data->Buf,Data->Cur);
memcpy(Data->Buf,&(tb[1]),SCROLL_BACK_SIZE-1);
free(tb);
Data->Cur=SCROLL_BACK_SIZE-1;
Data->Buf[0]=0;
Data->Wrap=0;
}
Data->Buf[Data->Cur]=0;
Data->Top=Data->Cur;
for (i=0;i<21;i++)
{
Scan_Back(Data->Buf,&(Data->Top));
}
}
Key=99999; /* code to initalize */
Data=OnTop;
Flag=TRUE;
if (Data == NULL)
{
/* There's nothing to display. Just exit. */
return(Flag);
}
while (Key>0)
{
if (Key==99999)
{
Key=335; /* fake "End" key to initialize */
}
else
{
Key=MSDOS_getch();
}
switch(Key)
{
case 327: /* Home */
Data->Top=0;
break;
case 328: /* Up */
Scan_Back(Data->Buf,&(Data->Top));
break;
case 331: /* Left */
case 2: /* Shft Tab */
if (Data->Next==NULL)
{
while(Data->Prev!=NULL)
{
Data=Data->Prev;
}
}
else
{
Data=Data->Next;
}
break;
case 333: /* Right */
case 9: /* Tab */
if (Data->Prev==NULL)
{
while(Data->Next!=NULL)
{
Data=Data->Next;
}
}
else
{
Data=Data->Prev;
}
break;
case 335: /* End */
Data->Top=Data->Cur;
Scan_Back(Data->Buf,&(Data->Top));
case 329: /* Pg.Up. */
for (i=0;i<20;i++)
{
Scan_Back(Data->Buf,&(Data->Top));
}
break;
case 336: /* Down */
Scan_Front(Data->Buf,&Data->Top,Data->Cur);
break;
case 337: /* Pg.Dn. */
for (i=0;i<20;i++)
{
Scan_Front(Data->Buf,&Data->Top,Data->Cur);
}
break;
case 'c':
case 'C':
Flag=FALSE; /* fall through and exit */
default:
Key=-1;
}
if (Data->Top==Data->Cur)
{
Scan_Back(Data->Buf,&(Data->Top));
}
OnTop=NULL; /*force redisplay*/
Update_Tabs(Data);
CON_setWindow(1,Data->Wy1,78,Data->Wy2);
CON_setForeColor(Data->Fcol);
CON_setBackColor(Data->Bcol);
CON_setBackground(CON_getAttr(),32);
CON_clrscr();
j=Data->Top;
k=j+1;
for(i=0;i<21;i++)
{
CON_gotoxy(0,i);
if (Scan_Front(Data->Buf,&j,Data->Cur))
{
CON_puts(&(Data->Buf[k]));
k=j+1;
}
}
CON_setWindow(70,23,78,23);
CON_setForeColor(15);
CON_setBackColor(1);
CON_setBackground(CON_getAttr(),205);
CON_putc('\n');
CON_setForeColor(15);
CON_setBackColor(4);
CON_setBackground(CON_getAttr(),205);
CON_puts("\033\032");
if (Data->Top!=0)
{
CON_gotoxy(2,0);
CON_puts("\030More");
}
if (j!=Data->Cur)
{
CON_gotoxy(3,0);
CON_puts("More\031");
}
}
CON_setWindow(70,23,78,23);
CON_setForeColor(15);
CON_setBackColor(1);
CON_setBackground(CON_getAttr(),205);
CON_putc('\n');
return (Flag);
}
void MSDOS_Save_Text(void)
{
#ifdef FANCY_TEXT
Saved_Text=POV_MALLOC(80*25*2,"text screen");
CON_setWindow(0,0,79,24);
CON_saveText(0,0,79,24,Saved_Text);
#endif
}
void MSDOS_Restore_Text(void)
{
#ifdef FANCY_TEXT
CON_setWindow(0,0,79,24);
CON_restoreText(0,0,79,24,Saved_Text);
POV_FREE(Saved_Text);
#endif
}
int MSDOS_System(char *s)
{
int Code;
int i;
char *ARGS[20];
char *t;
char buf[POV_MAX_CMD_LENGTH];
Render_Info("\nExecuting '%s'",s);
strcpy(buf,s);
t = ARGS[0] = strtok(buf, " ");
i=1;
while ((t!=NULL)&&(i<20))
{
t = ARGS[i] = strtok(0, " ");
i++;
}
MSDOS_Save_Text();
CON_setForeColor(7);
CON_setBackColor(0);
CON_setBackground(CON_getAttr(),32);
CON_setWindow(0,0,79,24);
CON_gotoxy(79,24);
CON_printf("\n\r");
fprintf(stderr,"\nPOV-Ray shelling out to dos.\n%s\n",s);
Code=spawnvp(P_WAIT,ARGS[0],ARGS);
MSDOS_Restore_Text();
return(Code);
}
void MSDOS_Process_Povray_Ini(char *s)
{
char *buff;
char *t;
if (Option_String_Ptr != NULL)
{
return;
}
buff=POV_MALLOC(strlen(s)+13,"temp string");
strcpy(buff,s);
t=strrchr(buff,'\\');
if (t==NULL)
{
t=strrchr(buff,'/');
if (t==NULL)
{
t=strrchr(buff,':');
if (t==NULL)
{
t=buff;
}
}
}
strcpy(t,"\\povray.ini");
parse_ini_file(buff);
POV_FREE(buff);
}
void MSDOS_Process_Env(void)
{
if ((Option_String_Ptr = getenv("POVINI")) != NULL)
{
if (!parse_ini_file(Option_String_Ptr))
{
Warning(0.0,"Could not find '%s' as specified in POVINI environment.\n",
Option_String_Ptr);
}
}
}
void MSDOS_Other_Credits(void)
{
Banner("MS-Dos text & video: Chris Young, Chris Cason & Kendall Bennett\n");
#ifdef __CAUSEWAY__
Banner("CauseWay DOS Extender courtesy Michael Devore");
#endif
}