home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
CPROG
/
GCONIO.ZIP
/
GCONIO.CPP
next >
Wrap
C/C++ Source or Header
|
1991-03-30
|
14KB
|
562 lines
/*
gconio.cpp
3-30-91
graphics console class for Borland C++
Copyright 1991
John W. Small
All rights reserved
Use freely but acknowledge authorship and copyright.
CIS: 73757,2233
PSW / Power SoftWare
P.O. Box 10072
McLean, Virginia 22102 8072
(703) 759-3838
*/
#include <gconio.hpp>
#include <stdio.h>
#include <stdarg.h>
#include <dos.h>
GraphicsConsole::GraphicsConsole()
{
ColumnLeft = 0;
InputWriteMode = COPY_PUT;
InputRewrite = 0;
InputDone = 0;
OutputWriteMode = COPY_PUT;
ClearTextBk = 0;
TextBkPattern = SOLID_FILL;
TextBkColor = 0; // 0 = current bkcolor
CursorChar[0] = '\124'; // 0 = no getch/gets cursor
CursorChar[1] = '\0';
CursorOnMsec = 100;
CursorOffMsec = 100;
}
void GraphicsConsole::ProportionalBackSpace(int& lastchX,
int& lastchY, int chX, int chY, char lastch,
char ch, struct textsettingstype& TS)
{
char lastchs[2];
char chs[2];
struct textsettingstype tmpTS;
lastchX = chX;
lastchY = chY;
lastchs[0] = lastch;
lastchs[1] = '\0';
chs[0] = ch;
chs[1] = '\0';
gettextsettings(&tmpTS);
settextstyle(TS.font,TS.direction,TS.charsize);
if (TS.direction == HORIZ_DIR)
switch (TS.horiz) {
case LEFT_TEXT:
lastchX -= textwidth(lastchs);
break;
case CENTER_TEXT:
lastchX -= (textwidth(chs) >> 1);
lastchX -= (textwidth(lastchs) >> 1);
break;
case RIGHT_TEXT:
lastchX -= textwidth(chs);
break;
}
else
switch (TS.vert) {
case BOTTOM_TEXT:
lastchY += textwidth(lastchs);
break;
case CENTER_TEXT:
lastchY += (textwidth(chs) >> 1);
lastchY += (textwidth(lastchs) >> 1);
break;
case TOP_TEXT:
lastchY += textwidth(chs);
break;
}
settextstyle(tmpTS.font,tmpTS.direction,tmpTS.charsize);
}
void GraphicsConsole::ProportionalSpace(int chX, int chY,
int& nextchX, int& nextchY, char ch, char nextch,
struct textsettingstype& TS)
{
char chs[2];
char nextchs[2];
struct textsettingstype tmpTS;
nextchX = chX;
nextchY = chY;
chs[0] = ch;
chs[1] = '\0';
nextchs[0] = nextch;
nextchs[1] = '\0';
gettextsettings(&tmpTS);
settextstyle(TS.font,TS.direction,TS.charsize);
if (TS.direction == HORIZ_DIR)
switch (TS.horiz) {
case LEFT_TEXT:
nextchX += textwidth(chs);
break;
case CENTER_TEXT:
nextchX += (textwidth(chs) >> 1);
nextchX += (textwidth(nextchs) >> 1);
break;
case RIGHT_TEXT:
nextchX += textwidth(nextchs);
break;
}
else
switch (TS.vert) {
case BOTTOM_TEXT:
nextchY -= textwidth(chs);
break;
case CENTER_TEXT:
nextchY -= (textwidth(chs) >> 1);
nextchY -= (textwidth(nextchs) >> 1);
break;
case TOP_TEXT:
nextchY -= textwidth(nextchs);
break;
}
settextstyle(tmpTS.font,tmpTS.direction,tmpTS.charsize);
}
void GraphicsConsole::TextBox(int x, int y, char *s,
struct textsettingstype& TS,
int& x1, int& y1, int& x2, int& y2)
{
int dx, dy;
struct textsettingstype tmpTS;
gettextsettings(&tmpTS);
settextstyle(TS.font,TS.direction,TS.charsize);
if (TS.direction == HORIZ_DIR) {
dx = textwidth(s);
dy = textheight(s);
// Stroked fonts have long decenders!
if (TS.font != DEFAULT_FONT)
y += (dy >> 2);
}
else {
dx = textheight(s);
dy = textwidth(s);
// Stroked fonts have long decenders!
if (TS.font != DEFAULT_FONT) {
x += (dx >> 2);
// Correct quirk in outtext[xy]
if (TS.horiz == CENTER_TEXT)
if ((dx % 2) != 0)
x += 2;
else
x++;
}
}
settextstyle(tmpTS.font,tmpTS.direction,tmpTS.charsize);
x1 = x; x2 = x1;
y1 = y; y2 = y1;
switch (TS.horiz) {
case LEFT_TEXT:
x2 += dx;
break;
case CENTER_TEXT:
x1 -= (dx >> 1);
x2 += (dx >> 1);
break;
case RIGHT_TEXT:
x1 -= dx;
break;
}
switch (TS.vert) {
case BOTTOM_TEXT:
y1 -= dy;
break;
case CENTER_TEXT:
y1 -= (dy >> 1);
y2 += (dy >> 1);
break;
case TOP_TEXT:
y2 += dy;
break;
}
}
int GraphicsConsole::cprintf(const char *format,...)
{
va_list argv;
int cnt;
char buf[GC_BUF_SIZE];
va_start(argv,format);
cnt = vsprintf(buf,format,argv);
va_end(argv);
if (cnt)
cputs(buf);
return cnt;
}
int GraphicsConsole::cputs(const char *str)
{
int i, j, x, y, x1, y1, x2, y2;
int bkcolor;
struct textsettingstype TS;
struct fillsettingstype FS;
char buf[GC_BUF_SIZE];
int ch;
if (!str)
return 0;
x = getx(); y = gety();
gettextsettings(&TS);
if (ClearTextBk) {
getfillsettings(&FS);
bkcolor = TextBkColor? TextBkColor : getbkcolor();
}
setwritemode(OutputWriteMode);
for (i = j = 0; j >= 0; i++) {
switch (str[i]) {
case '\r':
case '\n':
// fall thru and output buf
case '\0':
buf[j] = '\0';
if (ClearTextBk) {
setfillstyle(TextBkPattern,bkcolor);
TextBox(x,y,buf,TS,x1,y1,x2,y2);
bar(x1,y1,x2,y2);
setfillstyle(FS.pattern,FS.color);
}
outtextxy(x,y,buf);
if (TS.direction == HORIZ_DIR)
switch (str[i]) {
case '\r':
if (!ColumnLeft &&
(TS.horiz == LEFT_TEXT))
x = 0;
break;
case '\n':
y += 1 + textheight(buf);
break;
default:
if (TS.horiz == LEFT_TEXT)
x += textwidth(buf);
break;
}
else // TS.direction == VERT_DIR
switch (str[i]) {
case '\r':
if (!ColumnLeft &&
(TS.vert == BOTTOM_TEXT))
y = getmaxy();
break;
case '\n':
x += 1+textheight(buf);
break;
default:
if (TS.horiz == BOTTOM_TEXT)
y -= textwidth(buf);
break;
}
moveto(x,y);
j = (str[i])? 0 : -1;// terminate when ready
break;
default:
if (j < GC_BUF_SIZE - 1)
ch = buf[j++] = str[i];
break;
}
}
return ch;
}
int GraphicsConsole::putch(int c)
{
char chs[2];
chs[0] = c; chs[1] = '\0';
return cputs(chs);
}
void GraphicsConsole::rubout(int ch)
{
int x1, y1, x2, y2, lastchX, lastchY;
struct textsettingstype TS;
struct fillsettingstype FS;
char chs[2];
gettextsettings(&TS);
// Only works for left justified text!
if (TS.direction == HORIZ_DIR) {
if (TS.horiz != LEFT_TEXT)
return;
}
else if (TS.horiz != BOTTOM_TEXT)
return;
setwritemode(OutputWriteMode);
ProportionalBackSpace(lastchX,lastchY,
getx(),gety(),ch,ch,TS);
moveto(lastchX,lastchY);
chs[0] = ch;
chs[1] = '\0';
// Only erase XOR_PUT, stroked fonts!
if ((OutputWriteMode == COPY_PUT) ||
(TS.font == DEFAULT_FONT)) {
getfillsettings(&FS);
if (!TextBkColor)
setfillstyle(TextBkPattern,getbkcolor());
else
setfillstyle(TextBkPattern,TextBkColor);
TextBox(getx(),gety(),chs,TS,x1,y1,x2,y2);
bar(x1,y1,x2,y2);
setfillstyle(FS.pattern,FS.color);
}
else {
outtextxy(getx(),gety(),chs);
moveto(lastchX,lastchY);
}
}
int GraphicsConsole::cscanf(const char *format,...)
{
va_list argv;
int cnt;
char buf[GC_BUF_SIZE];
buf[0] = GC_BUF_SIZE - 2;
cgets(buf);
va_start(argv,format);
cnt = vsscanf(&buf[2],format,argv);
va_end(argv);
return cnt;
}
char * GraphicsConsole::cgets(char *str)
{
int i, imax, x, y, x1, y1, x2, y2;
int lastchX, lastchY, nextchX, nextchY;
struct textsettingstype TS;
struct fillsettingstype FS;
if (!str)
return str;
if ((imax = str[0]) < 2)
return (char *) 0;
x = getx(); y = gety();
gettextsettings(&TS);
setwritemode(InputWriteMode);
getfillsettings(&FS);
if (!TextBkColor)
setfillstyle(TextBkPattern,getbkcolor());
else
setfillstyle(TextBkPattern,TextBkColor);
InputDone = 0;
str[i = 2] = '\0';
while (!InputDone) {
// Cursor only for stroked fonts!
if (CursorChar[0] && (TS.font != DEFAULT_FONT))
while (!kbhit() && !InputDone) {
setwritemode(XOR_PUT);
if (i > 2)
ProportionalSpace(getx(),gety(),
nextchX,nextchY,str[i-1],
CursorChar[0],TS);
else {
nextchX = getx();
nextchY = gety();
}
outtextxy(nextchX,nextchY,CursorChar);
if (!kbhit())
delay(CursorOnMsec);
outtextxy(nextchX,nextchY,CursorChar);
if (!kbhit())
delay(CursorOffMsec);
setwritemode(InputWriteMode);
}
// InputDone is also used to interrupt cgets()
// e.g. by mouse interrupt handler etc.
while (!kbhit() && !InputDone);
if (InputDone)
str[i] = '\13';
else
str[i] = getch();
switch (str[i]) {
case 13: // Carriage Return
if (TS.direction == HORIZ_DIR)
if (!ColumnLeft && (TS.horiz == LEFT_TEXT))
moveto(0,1+y+textheight("a"));
else
moveto(x,1+y+textheight("a"));
else
if (!ColumnLeft && (TS.vert == BOTTOM_TEXT))
moveto(1+x+textheight("a"),getmaxy());
else
moveto(1+x+textheight("a"),y);
str[i] = '\0';
str[1] = i - 2;
InputDone = 1;
break;
case 8: // Back Space
if (i > 2) {
str[i--] = '\0';
// Only erase XOR_PUT, stroked fonts!
if ((InputWriteMode == COPY_PUT) ||
(TS.font == DEFAULT_FONT)) {
TextBox(getx(),gety(),&str[i],TS,x1,y1,x2,y2);
bar(x1,y1,x2,y2);
}
else
outtextxy(getx(),gety(),&str[i]);
if (i > 2) {
ProportionalBackSpace(lastchX,lastchY,
getx(),gety(),str[i-1],str[i],TS);
moveto(lastchX,lastchY);
}
str[i] = '\0';
}
break;
default:
if (i - 2 >= imax) {
str[i] = '\0';
break;
}
if (i > 2) {
ProportionalSpace(getx(),gety(),
nextchX,nextchY,str[i-1],str[i],TS);
moveto(nextchX,nextchY);
}
else {
nextchX = getx();
nextchY = gety();
}
str[i+1] = '\0';
if (ClearTextBk) {
TextBox(nextchX,nextchY,&str[i],TS,x1,y1,x2,y2);
bar(x1,y1,x2,y2);
}
outtextxy(nextchX,nextchY,&str[i]);
i++;
break;
}
}
if (InputRewrite && str[1]) {
setwritemode(COPY_PUT);
outtextxy(x,y,&str[2]);
}
setfillstyle(FS.pattern,FS.color);
return &str[2];
}
// comment out next line to use gconio in your applications
#define TEST_GCONIO_CPP
#ifdef TEST_GCONIO_CPP
#include <stdio.h>
#include <stdlib.h>
#define MAXS 40
main()
{
int gdriver, gmode, gerror;
int dx, dy, c;
char s[MAXS];
GraphicsConsole GC;
gdriver = DETECT;
initgraph(&gdriver, &gmode, "..\\bgi");
gerror = graphresult();
if (gerror != grOk) /* an error occurred */
{
printf("Graphics error: %s\n", grapherrormsg(gerror));
printf("Press any key to halt:");
getchar();
exit(1);
}
dx = getmaxx() / (getmaxcolor()+1);
clearviewport();
for (c = 0; c <= getmaxcolor(); c++) {
setfillstyle(XHATCH_FILL,c);
bar3d(c*dx,0,(c+1)*dx,getmaxy(),0,0);
}
settextjustify(LEFT_TEXT,TOP_TEXT);
settextstyle(TRIPLEX_FONT,HORIZ_DIR,1);
GC.cputs("Test getche(): ");
GC.getche();
GC.cputs("\r\nTest cscanf(\"Hello %s \",s): ");
GC.cscanf("Hello %s ",s);
GC.cprintf("\r\ns: %s",s);
GC.cputs("\r\n\r\nAnd rubout: ");
GC.rubout(GC.getche());
GC.ColumnLeft = 1;
moveto(30,gety());
GC.cprintf("\r\nHello graphics %s!\r\n\r\n","world");
GC.cputs("Include gconio.hpp in your application.\r\n");
GC.cputs("Instantiate the GraphicsConsole class\r\n");
GC.cputs("to have complete text i/o capabilities\r\n");
GC.cputs("in all graphics modes.\r\n\r\n");
GC.cputs("Let's try cgets(). Enter: ");
s[0] = MAXS-2;
GC.cgets(s);
GC.ColumnLeft = 0;
setbkcolor(BLUE);
setcolor(WHITE);
clearviewport();
settextstyle(SANS_SERIF_FONT,VERT_DIR,4);
settextjustify(LEFT_TEXT,BOTTOM_TEXT);
moveto(0,getmaxy());
GC.cputs("It even works with\r\n");
GC.cputs("vertical text.\r\n\r\n");
GC.cputs("\r\n");
GC.cputs("And cgets(): ");
s[0] = MAXS-2;
GC.cgets(s);
clearviewport();
settextstyle(GOTHIC_FONT,HORIZ_DIR,4);
settextjustify(CENTER_TEXT,TOP_TEXT);
moveto(getmaxx()/2,10);
GC.cputs("Besure to call GraphicsConsole member\r\n");
GC.cputs("functions only after calling initgraph()\r\n");
GC.cputs("and before calling closegraph().");
settextstyle(SMALL_FONT,HORIZ_DIR,8);
settextjustify(CENTER_TEXT,TOP_TEXT);
moveto(getmaxx() / 2,getmaxy() / 2);
GC.cputs("Goodbye time - \r\n");
GC.cputs("consuming graphic\r\n");
GC.cputs("text programming!\r\n");
GC.cputs("\n");
GC.cputs("Press any key to continue ...");
GC.getch();
closegraph();
puts("If you find gconio useful and are using it in your");
puts("applications, how about telling a friend about it.");
puts("Gconio is freeware - I only ask that you leave my");
puts("copyright notice untouched! I will try to answer");
puts("as many of your questions and/or comments (time ");
puts("and money permitting). Thanks! John CIS: 73757,2233");
puts("");
puts("PSW / Power SoftWare");
puts("P.O. Box 10072");
puts("McLean, Virginia 22102 8072");
puts("(703) 759-3838");
puts("");
puts("That's all folks!");
puts("");
puts("Press enter to quit.");
getchar();
}
#endif