/*_______________________________________________________________
tc-010.c
Function: This program demonstrates how to animate business
charts by using the high speed techniques of frame animation.
Compatibility: Supports all graphics adapters and monitors.
The software uses the 640x200 16-color mode if a VGA or an
EGA is present. The 640x200 2-color mode is used if a
CGA is present.
Remarks: The 640x200 16-color mode is used with the VGA and
EGA because four graphics pages are required by this animated
program. Only one page is available in the VGA's 640x480
16-color mode. Only two pages are available in the EGA's
640x350 16-color mode. Eight pages are available in the
320x200 16-color mode, but Turbo C 1.5 does not provide graphics
support for that mode.
If a CGA or MCGA is present, the extra graphics pages required by
this program are stored in user RAM, where care must be taken
in order to avoid overwriting the C compiler, the user's
source code, or the operating system.
Copyright 1988 Lee Adams and TAB BOOKS Inc.
_________________________________________________________________
I N C L U D E F I L E S */
#include <stdio.h> /* supports the printf function */
#include <graphics.h> /* supports the graphics functions */
#include <process.h> /* supports the exit() function */
#include <mem.h> /* supports memory moves */
/*_______________________________________________________________
D E C L A R A T I O N S */
void keyboard(void);void quit_pgm(void);
void notice(float x,float y);
void coords(void);void graphics_setup(void);
void scales(void);void labels(void);void blocks(void);
void animVGAEGA(void); /* EGA and VGA only */
void animCGA(void); /* CGA only */
void pagemove(unsigned source,unsigned target); /* CGA only */
float sx,sy,sx1,sy1,sx2,sy2;float x_res,y_res;
int C0=0,C1=1,C2=2,C3=3,C4=4,C5=5,C6=6,C7=7,C8=8,C9=9,C10=10,
C11=11,C12=12,C13=13,C14=14,C15=15,mode_flag=0;
int t1=1,t2=2;
/* coordinates for analytic graphics */
float x1=151,x2=262,x3=194,x4=219,x5=245,x6=462;
float y1=105,y2=140,y3=145,y4=180,y5=185,y6=220,
y7=225,y8=259,y9=264,y10=298,y11=303,y12=335,
y13=339,y14=373,y15=377,y16=410;
/*_______________________________________________________________
M A I N R O U T I N E */
main(){
graphics_setup(); /* establish graphics mode */
if (mode_flag==3) /* if VGA or EGA */
{setvisualpage(0);setactivepage(0);};
cleardevice();
scales(); /* create the scale for the chart */
labels(); /* create the alphanumeric labels */
setcolor(C3);sx=5;sy=460;coords();notice(sx,sy); /* notice */
blocks(); /* draw the analytic graphics */
if (mode_flag==4) {pagemove(0xB800,0x8800);} /* if CGA */
if (mode_flag==3) /* if VGA or EGA */
{setvisualpage(1);setactivepage(1);};
cleardevice();
x6=479;x2=265;x3=192;x4=218;
scales(); /* create the scale for the chart */
labels(); /* create the alphanumeric labels */
setcolor(C3);sx=5;sy=460;coords();notice(sx,sy); /* notice */
blocks(); /* draw the analytic graphics */
if (mode_flag==4) {pagemove(0xB800,0x8C00);} /* if CGA */
if (mode_flag==3) /* if VGA or EGA */
{setvisualpage(2);setactivepage(2);};
cleardevice();
x6=492;x2=268;x3=190;x4=217;
scales(); /* create the scale for the chart */
labels(); /* create the alphanumeric labels */
setcolor(C3);sx=5;sy=460;coords();notice(sx,sy); /* notice */
blocks(); /* draw the analytic graphics */
if (mode_flag==4) {pagemove(0xB800,0x9000);} /* if CGA */
if (mode_flag==3) /* if VGA or EGA */
{setvisualpage(3);setactivepage(3);};
cleardevice();
x6=502;x2=271;x3=188;x4=216;
scales(); /* create the scale for the chart */
labels(); /* create the alphanumeric labels */
setcolor(C3);sx=5;sy=460;coords();notice(sx,sy); /* notice */
blocks(); /* draw the analytic graphics */
if (mode_flag==4) {pagemove(0xB800,0x9400);} /* if CGA */
if (mode_flag==3) {setvisualpage(0);setactivepage(0);};
for (t1=1;t1<=30000;t1++); /* pause before animating */
if (mode_flag==3) animVGAEGA(); /* animation for VGA and EGA */
if (mode_flag==4) animCGA(); /* animation for CGA and MCGA */
quit_pgm();} /* end the program gracefully */
/*_______________________________________________________________
SUBROUTINE: frame animation manager for VGA and EGA */
void animVGAEGA(void){
for (t1=1;t1<=20;t1++){ /* animate 20 cycles of 6 frames each */
setvisualpage(1);for (t2=1;t2<=6000;t2++);
setvisualpage(2);for (t2=1;t2<=6000;t2++);
setvisualpage(3);for (t2=1;t2<=30000;t2++);
setvisualpage(2);for (t2=1;t2<=6000;t2++);
setvisualpage(1);for (t2=1;t2<=6000;t2++);
setvisualpage(0);for (t2=1;t2<=30000;t2++);};
setactivepage(0);setvisualpage(0);
return;}
/*_______________________________________________________________
SUBROUTINE: frame animation manager for CGA */
void animCGA(void){
for (t1=1;t1<=20;t1++){ /* animate 20 cycles of 6 frames each */
pagemove(0x8C00,0xB800);for (t2=1;t2<=6000;t2++);
pagemove(0x9000,0xB800);for (t2=1;t2<=6000;t2++);
pagemove(0x9400,0xB800);for (t2=1;t2<=30000;t2++);
pagemove(0x9000,0xB800);for (t2=1;t2<=6000;t2++);
pagemove(0x8C00,0xB800);for (t2=1;t2<=6000;t2++);
pagemove(0x8800,0xB800);for (t2=1;t2<=30000;t2++);};
return;}
/*_______________________________________________________________
SUBROUTINE: pagemove for CGA
This subroutine is called during the graphics drawing process
in order to store the frames in user RAM. This subroutine is
also called during the frame animation process in order to
flip the previously-stored pages onto the CGA display buffer
at B8000 hex. */
void pagemove(unsigned source, unsigned target){
movedata(source,0x0000,target,0x0000,16000);
return;}
/*_______________________________________________________________
SUBROUTINE: draw the scales */
void scales(void){
setcolor(C7);
sx=150;sy=420;coords();moveto(sx,sy);
sx=150;sy=82;coords();lineto(sx,sy);
sx=620;sy=82;coords();lineto(sx,sy);
sx=150;sy=82;coords();moveto(sx,sy);
sx=150;sy=78;coords();lineto(sx,sy);
sx=262;sy=82;coords();moveto(sx,sy);
sx=262;sy=78;coords();lineto(sx,sy);
sx=375;sy=82;coords();moveto(sx,sy);
sx=375;sy=78;coords();lineto(sx,sy);
sx=482;sy=82;coords();moveto(sx,sy);
sx=482;sy=78;coords();lineto(sx,sy);
sx=599;sy=82;coords();moveto(sx,sy);
sx=599;sy=78;coords();lineto(sx,sy);
return;}
/*_______________________________________________________________
SUBROUTINE: alphanumeric labels */
void labels(void){
setcolor(C3);moveto(264,192);
if (mode_flag==3) {outtext("640x200 16-color VGA and EGA mode");}
if (mode_flag==4) {outtext("640x200 2-color CGA and MCGA mode");}
moveto(248,0);
outtext("USING C TO ANIMATE BUSINESS GRAPHICS");
setcolor(C7);
moveto(24,24);outtext("$ in millions");
moveto(96,48);outtext("Sales");
moveto(32,64);outtext("Cost of Sales");
moveto(88,80);outtext("Profit");
moveto(8,96);outtext("Selling Expenses");
moveto(8,112);outtext("Operating Income");
moveto(32,128);outtext("Interest Paid");
moveto(40,144);outtext("Income Taxes");
moveto(56,160);outtext("Net Profit");
moveto(152,24);outtext("0");
moveto(240,24);outtext("5000");
moveto(360,24);outtext("10000");
moveto(464,24);outtext("15000");
moveto(568,24);outtext("20000");
moveto(360,120);outtext("GRAPHIC INCOME STATEMENT");
moveto(424,128);outtext("FOR 1988");
return;}
/*_______________________________________________________________
SUBROUTINE: draw the analytic graphics */
void blocks(void){
setfillstyle(SOLID_FILL,C4);
sx=x1;sy=y1;coords();sx1=sx;sy1=sy;
sx=x6;sy=y2;coords();sx2=sx;sy2=sy;
bar(sx1,sy1,sx2,sy2); /* sales */
setfillstyle(SOLID_FILL,C7);
sx=x2;sy=y3;coords();sx1=sx;sy1=sy;
sx=x6;sy=y4;coords();sx2=sx;sy2=sy;
bar(sx1,sy1,sx2,sy2); /* cost of sales */
setfillstyle(SOLID_FILL,C7);
sx=x1;sy=y5;coords();sx1=sx;sy1=sy;
sx=x2;sy=y6;coords();sx2=sx;sy2=sy;
bar(sx1,sy1,sx2,sy2); /* profit */
setfillstyle(SOLID_FILL,C1);
sx=x3;sy=y7;coords();sx1=sx;sy1=sy;
sx=x2;sy=y8;coords();sx2=sx;sy2=sy;
bar(sx1,sy1,sx2,sy2); /* selling expenses */
setfillstyle(SOLID_FILL,C1);
sx=x1;sy=y9;coords();sx1=sx;sy1=sy;
sx=x3;sy=y10;coords();sx2=sx;sy2=sy;
bar(sx1,sy1,sx2,sy2); /* operating income */
setfillstyle(SOLID_FILL,C2);
sx=x3;sy=y11;coords();sx1=sx;sy1=sy;
sx=x4;sy=y12;coords();sx2=sx;sy2=sy;
bar(sx1,sy1,sx2,sy2); /* interest paid */
setfillstyle(SOLID_FILL,C2);
sx=x4;sy=y13;coords();sx1=sx;sy1=sy;
sx=x5;sy=y14;coords();sx2=sx;sy2=sy;
bar(sx1,sy1,sx2,sy2); /* income taxes */
setfillstyle(SOLID_FILL,C2);
sx=x5;sy=y15;coords();sx1=sx;sy1=sy;
sx=x2;sy=y16;coords();sx2=sx;sy2=sy;
bar(sx1,sy1,sx2,sy2); /* net profit */
return;}
/*_______________________________________________________________
SUBROUTINE: GRACEFUL EXIT FROM THE PROGRAM */
void quit_pgm(void){
cleardevice();restorecrtmode();exit(0);}
/*______________________________________________________________
SUBROUTINE: VGA/EGA/CGA/MCGA compatibility module */
void graphics_setup(void){
int graphics_adapter,graphics_mode;
detectgraph(&graphics_adapter,&graphics_mode);
if (graphics_adapter==VGA) goto VGA_EGA_mode; /* if VGA */
if (graphics_mode==EGAHI) goto VGA_EGA_mode; /* if EGA and ECD */
if (graphics_mode==EGALO) goto VGA_EGA_mode; /* if EGA and SCD */
if (graphics_adapter==CGA) goto CGA_mode; /* if CGA */
if (graphics_adapter==MCGA) goto CGA_mode; /* if MCGA */
goto abort_message; /* if no VGA, EGA, CGA, or MCGA */
VGA_EGA_mode: /* establish 640x480 16-color mode */
graphics_adapter=EGA;graphics_mode=EGALO;
initgraph(&graphics_adapter,&graphics_mode,"");
x_res=640;y_res=200;mode_flag=3;
return;
CGA_mode: /* establish 640x200 2-color mode */
graphics_adapter=CGA;graphics_mode=CGAHI;
initgraph(&graphics_adapter,&graphics_mode,"");
x_res=640;y_res=200;C0=0;C1=1;C2=1;C3=1;C4=1;C5=1,C6=1;C7=1;
C8=1;C9=1;C10=1;C11=1;C12=1;C13=1;C14=1;C15=1;
mode_flag=4;
return;
abort_message:
printf("\n\nUnable to proceed.\n");
printf("Requires VGA, EGA, MCGA, or CGA adapter\n");
printf(" with appropriate monitor.\n");
printf("Please refer to the book.\n\n");
exit(0);
}
/*_______________________________________________________________
SUBROUTINE: coords()
This subroutine accepts sx,sy device-independent display
coordinates and returns sx,sy device-dependent screen
coordinates scaled to fit the 640x480, 640x350, 640x200, or
320x200 screen, depending upon the graphics mode being used. */
void coords(void){
sx=sx*(x_res/640);sy=sy*(y_res/480);return;}
/*_______________________________________________________________
SUBROUTINE: Copyright Notice
This subroutine displays the standard copyright notice.
If you are typing in this program from the book you can
safely omit this subroutine, provided that you also remove
the instruction "notice()" from the main routine. */
int copyright[][3]={0x7c00,0x0000,0x0000,0x8231,
0x819c,0x645e,0xba4a,0x4252,0x96d0,0xa231,0x8252,0x955e,0xba4a,
0x43d2,0xf442,0x8231,0x825c,0x945e,0x7c00,0x0000,0x0000};
void notice(float x, float y){
int a,b,c; int t1=0;
for (t1=0;t1<=6;t1++){a=copyright[t1][0];b=copyright[t1][1];
c=copyright[t1][2];
setlinestyle(USERBIT_LINE,a,NORM_WIDTH);
moveto(x,y);lineto(x+15,y);
setlinestyle(USERBIT_LINE,b,NORM_WIDTH);
moveto(x+16,y);lineto(x+31,y);
setlinestyle(USERBIT_LINE,c,NORM_WIDTH);
moveto(x+32,y);lineto(x+47,y);y=y+1;};
setlinestyle(USERBIT_LINE,0xFFFF,NORM_WIDTH);
return;}
/*_______________________________________________________________
End of source code */