home *** CD-ROM | disk | FTP | other *** search
/ World of Shareware - Software Farm 2 / wosw_2.zip / wosw_2 / CPROG / GCONIO.ZIP / GCONIO.CPP next >
C/C++ Source or Header  |  1991-03-30  |  14KB  |  562 lines

  1. /*
  2.  
  3.     gconio.cpp
  4.     3-30-91
  5.     graphics console class for Borland C++
  6.  
  7.     Copyright 1991
  8.     John W. Small
  9.     All rights reserved
  10.     Use freely but acknowledge authorship and copyright.
  11.     CIS: 73757,2233
  12.  
  13.     PSW / Power SoftWare
  14.     P.O. Box 10072
  15.     McLean, Virginia 22102 8072
  16.     (703) 759-3838
  17.  
  18. */
  19.  
  20. #include <gconio.hpp>
  21. #include <stdio.h>
  22. #include <stdarg.h>
  23. #include <dos.h>
  24.  
  25. GraphicsConsole::GraphicsConsole()
  26. {
  27.     ColumnLeft = 0;
  28.     InputWriteMode = COPY_PUT;
  29.     InputRewrite = 0;
  30.     InputDone = 0;
  31.     OutputWriteMode = COPY_PUT;
  32.     ClearTextBk = 0;
  33.     TextBkPattern = SOLID_FILL;
  34.     TextBkColor = 0; // 0 = current bkcolor
  35.     CursorChar[0] = '\124'; // 0 = no getch/gets cursor
  36.     CursorChar[1] = '\0';
  37.     CursorOnMsec = 100;
  38.     CursorOffMsec = 100;
  39. }
  40.  
  41. void GraphicsConsole::ProportionalBackSpace(int& lastchX,
  42.     int& lastchY, int chX, int chY, char lastch,
  43.     char ch, struct textsettingstype& TS)
  44. {
  45.     char lastchs[2];
  46.     char chs[2];
  47.     struct textsettingstype tmpTS;
  48.  
  49.     lastchX = chX;
  50.     lastchY = chY;
  51.     lastchs[0] = lastch;
  52.     lastchs[1] = '\0';
  53.     chs[0] = ch;
  54.     chs[1] = '\0';
  55.     gettextsettings(&tmpTS);
  56.     settextstyle(TS.font,TS.direction,TS.charsize);
  57.     if (TS.direction == HORIZ_DIR)
  58.     switch  (TS.horiz)  {
  59.     case LEFT_TEXT:
  60.         lastchX -= textwidth(lastchs);
  61.         break;
  62.     case CENTER_TEXT:
  63.         lastchX -= (textwidth(chs) >> 1);
  64.         lastchX -= (textwidth(lastchs) >> 1);
  65.         break;
  66.     case RIGHT_TEXT:
  67.         lastchX -= textwidth(chs);
  68.         break;
  69.     }
  70.     else
  71.     switch (TS.vert)  {
  72.     case BOTTOM_TEXT:
  73.         lastchY += textwidth(lastchs);
  74.         break;
  75.     case CENTER_TEXT:
  76.         lastchY += (textwidth(chs) >> 1);
  77.         lastchY += (textwidth(lastchs) >> 1);
  78.         break;
  79.     case TOP_TEXT:
  80.         lastchY += textwidth(chs);
  81.         break;
  82.     }
  83.     settextstyle(tmpTS.font,tmpTS.direction,tmpTS.charsize);
  84. }
  85.  
  86. void GraphicsConsole::ProportionalSpace(int chX, int chY,
  87.     int& nextchX, int& nextchY, char ch, char nextch,
  88.     struct textsettingstype& TS)
  89. {
  90.     char chs[2];
  91.     char nextchs[2];
  92.     struct textsettingstype tmpTS;
  93.  
  94.     nextchX = chX;
  95.     nextchY = chY;
  96.     chs[0] = ch;
  97.     chs[1] = '\0';
  98.     nextchs[0] = nextch;
  99.     nextchs[1] = '\0';
  100.     gettextsettings(&tmpTS);
  101.     settextstyle(TS.font,TS.direction,TS.charsize);
  102.     if (TS.direction == HORIZ_DIR)
  103.     switch (TS.horiz)  {
  104.     case LEFT_TEXT:
  105.         nextchX += textwidth(chs);
  106.         break;
  107.     case CENTER_TEXT:
  108.         nextchX += (textwidth(chs) >> 1);
  109.         nextchX += (textwidth(nextchs) >> 1);
  110.         break;
  111.     case RIGHT_TEXT:
  112.         nextchX += textwidth(nextchs);
  113.         break;
  114.     }
  115.     else
  116.     switch (TS.vert)  {
  117.     case BOTTOM_TEXT:
  118.         nextchY -= textwidth(chs);
  119.         break;
  120.     case CENTER_TEXT:
  121.         nextchY -= (textwidth(chs) >> 1);
  122.         nextchY -= (textwidth(nextchs) >> 1);
  123.         break;
  124.     case TOP_TEXT:
  125.         nextchY -= textwidth(nextchs);
  126.         break;
  127.     }
  128.     settextstyle(tmpTS.font,tmpTS.direction,tmpTS.charsize);
  129. }
  130.  
  131. void GraphicsConsole::TextBox(int x, int y, char *s,
  132.     struct textsettingstype& TS,
  133.     int& x1, int& y1, int& x2, int& y2)
  134. {
  135.     int dx, dy;
  136.     struct textsettingstype tmpTS;
  137.  
  138.     gettextsettings(&tmpTS);
  139.     settextstyle(TS.font,TS.direction,TS.charsize);
  140.     if (TS.direction == HORIZ_DIR)  {
  141.     dx = textwidth(s);
  142.     dy = textheight(s);
  143.     // Stroked fonts have long decenders!
  144.     if (TS.font != DEFAULT_FONT)
  145.         y += (dy >> 2);
  146.     }
  147.     else  {
  148.     dx = textheight(s);
  149.     dy = textwidth(s);
  150.     // Stroked fonts have long decenders!
  151.     if (TS.font != DEFAULT_FONT)  {
  152.         x += (dx >> 2);
  153.         // Correct quirk in outtext[xy]
  154.         if (TS.horiz == CENTER_TEXT)
  155.         if ((dx % 2) != 0)
  156.             x += 2;
  157.         else
  158.             x++;
  159.         }
  160.     }
  161.     settextstyle(tmpTS.font,tmpTS.direction,tmpTS.charsize);
  162.     x1 = x; x2 = x1;
  163.     y1 = y; y2 = y1;
  164.     switch (TS.horiz)  {
  165.     case LEFT_TEXT:
  166.     x2 += dx;
  167.     break;
  168.     case CENTER_TEXT:
  169.     x1 -= (dx >> 1);
  170.     x2 += (dx >> 1);
  171.     break;
  172.     case RIGHT_TEXT:
  173.     x1 -= dx;
  174.     break;
  175.     }
  176.     switch (TS.vert)  {
  177.     case BOTTOM_TEXT:
  178.     y1 -= dy;
  179.     break;
  180.     case CENTER_TEXT:
  181.     y1 -= (dy >> 1);
  182.     y2 += (dy >> 1);
  183.     break;
  184.     case TOP_TEXT:
  185.     y2 += dy;
  186.     break;
  187.     }
  188. }
  189.  
  190. int GraphicsConsole::cprintf(const char *format,...)
  191. {
  192.     va_list argv;
  193.     int cnt;
  194.     char buf[GC_BUF_SIZE];
  195.  
  196.     va_start(argv,format);
  197.     cnt = vsprintf(buf,format,argv);
  198.     va_end(argv);
  199.     if (cnt)
  200.     cputs(buf);
  201.     return cnt;
  202. }
  203.  
  204. int GraphicsConsole::cputs(const char *str)
  205. {
  206.     int i, j, x, y, x1, y1, x2, y2;
  207.     int bkcolor;
  208.     struct textsettingstype TS;
  209.     struct fillsettingstype FS;
  210.     char buf[GC_BUF_SIZE];
  211.     int ch;
  212.  
  213.     if (!str)
  214.     return 0;
  215.     x = getx(); y = gety();
  216.     gettextsettings(&TS);
  217.     if (ClearTextBk)  {
  218.     getfillsettings(&FS);
  219.     bkcolor = TextBkColor? TextBkColor : getbkcolor();
  220.     }
  221.     setwritemode(OutputWriteMode);
  222.     for (i = j = 0; j >= 0; i++)  {
  223.     switch (str[i])  {
  224.     case '\r':
  225.     case '\n':
  226.         //  fall thru and output buf
  227.     case '\0':
  228.         buf[j] = '\0';
  229.         if (ClearTextBk)  {
  230.         setfillstyle(TextBkPattern,bkcolor);
  231.         TextBox(x,y,buf,TS,x1,y1,x2,y2);
  232.         bar(x1,y1,x2,y2);
  233.         setfillstyle(FS.pattern,FS.color);
  234.         }
  235.         outtextxy(x,y,buf);
  236.         if (TS.direction == HORIZ_DIR)
  237.         switch (str[i])  {
  238.         case '\r':
  239.             if (!ColumnLeft &&
  240.             (TS.horiz == LEFT_TEXT))
  241.             x = 0;
  242.             break;
  243.         case '\n':
  244.             y += 1 + textheight(buf);
  245.             break;
  246.         default:
  247.             if (TS.horiz == LEFT_TEXT)
  248.                 x += textwidth(buf);
  249.             break;
  250.         }
  251.         else // TS.direction == VERT_DIR
  252.         switch (str[i])  {
  253.         case '\r':
  254.             if (!ColumnLeft &&
  255.             (TS.vert == BOTTOM_TEXT))
  256.             y = getmaxy();
  257.             break;
  258.         case '\n':
  259.             x += 1+textheight(buf);
  260.             break;
  261.         default:
  262.             if (TS.horiz == BOTTOM_TEXT)
  263.             y -= textwidth(buf);
  264.             break;
  265.         }
  266.         moveto(x,y);
  267.         j = (str[i])? 0 : -1;// terminate when ready
  268.         break;
  269.     default:
  270.         if (j < GC_BUF_SIZE - 1)
  271.         ch = buf[j++] = str[i];
  272.         break;
  273.     }
  274.     }
  275.     return ch;
  276. }
  277.  
  278. int GraphicsConsole::putch(int c)
  279. {
  280.     char chs[2];
  281.  
  282.     chs[0] = c; chs[1] = '\0';
  283.     return cputs(chs);
  284. }
  285.  
  286. void GraphicsConsole::rubout(int ch)
  287. {
  288.     int x1, y1, x2, y2, lastchX, lastchY;
  289.     struct textsettingstype TS;
  290.     struct fillsettingstype FS;
  291.     char chs[2];
  292.  
  293.     gettextsettings(&TS);
  294.     // Only works for left justified text!
  295.     if (TS.direction == HORIZ_DIR)  {
  296.     if (TS.horiz != LEFT_TEXT)
  297.         return;
  298.     }
  299.     else if (TS.horiz != BOTTOM_TEXT)
  300.     return;
  301.     setwritemode(OutputWriteMode);
  302.     ProportionalBackSpace(lastchX,lastchY,
  303.     getx(),gety(),ch,ch,TS);
  304.     moveto(lastchX,lastchY);
  305.     chs[0] = ch;
  306.     chs[1] = '\0';
  307.     // Only erase XOR_PUT, stroked fonts!
  308.     if ((OutputWriteMode == COPY_PUT) ||
  309.     (TS.font == DEFAULT_FONT))  {
  310.     getfillsettings(&FS);
  311.     if (!TextBkColor)
  312.         setfillstyle(TextBkPattern,getbkcolor());
  313.     else
  314.         setfillstyle(TextBkPattern,TextBkColor);
  315.     TextBox(getx(),gety(),chs,TS,x1,y1,x2,y2);
  316.     bar(x1,y1,x2,y2);
  317.     setfillstyle(FS.pattern,FS.color);
  318.     }
  319.     else  {
  320.     outtextxy(getx(),gety(),chs);
  321.     moveto(lastchX,lastchY);
  322.     }
  323. }
  324.  
  325. int GraphicsConsole::cscanf(const char *format,...)
  326. {
  327.     va_list argv;
  328.     int cnt;
  329.     char buf[GC_BUF_SIZE];
  330.  
  331.     buf[0] = GC_BUF_SIZE - 2;
  332.     cgets(buf);
  333.     va_start(argv,format);
  334.     cnt = vsscanf(&buf[2],format,argv);
  335.     va_end(argv);
  336.     return cnt;
  337. }
  338.  
  339. char * GraphicsConsole::cgets(char *str)
  340. {
  341.     int i, imax, x, y, x1, y1, x2, y2;
  342.     int lastchX, lastchY, nextchX, nextchY;
  343.     struct textsettingstype TS;
  344.     struct fillsettingstype FS;
  345.  
  346.     if (!str)
  347.     return str;
  348.     if ((imax = str[0]) < 2)
  349.     return (char *) 0;
  350.     x = getx(); y = gety();
  351.     gettextsettings(&TS);
  352.     setwritemode(InputWriteMode);
  353.     getfillsettings(&FS);
  354.     if (!TextBkColor)
  355.     setfillstyle(TextBkPattern,getbkcolor());
  356.     else
  357.     setfillstyle(TextBkPattern,TextBkColor);
  358.     InputDone = 0;
  359.     str[i = 2] = '\0';
  360.     while (!InputDone)  {
  361.     // Cursor only for stroked fonts!
  362.     if (CursorChar[0] && (TS.font != DEFAULT_FONT))
  363.     while (!kbhit() && !InputDone)  {
  364.         setwritemode(XOR_PUT);
  365.         if (i > 2)
  366.         ProportionalSpace(getx(),gety(),
  367.             nextchX,nextchY,str[i-1],
  368.             CursorChar[0],TS);
  369.         else  {
  370.             nextchX = getx();
  371.             nextchY = gety();
  372.         }
  373.         outtextxy(nextchX,nextchY,CursorChar);
  374.         if (!kbhit())
  375.             delay(CursorOnMsec);
  376.         outtextxy(nextchX,nextchY,CursorChar);
  377.         if (!kbhit())
  378.             delay(CursorOffMsec);
  379.         setwritemode(InputWriteMode);
  380.     }
  381.     // InputDone is also used to interrupt cgets()
  382.     // e.g. by mouse interrupt handler etc.
  383.     while (!kbhit() && !InputDone);
  384.     if (InputDone)
  385.         str[i] = '\13';
  386.     else
  387.         str[i] = getch();
  388.     switch (str[i])  {
  389.     case 13:  // Carriage Return
  390.         if (TS.direction == HORIZ_DIR)
  391.         if (!ColumnLeft && (TS.horiz == LEFT_TEXT))
  392.             moveto(0,1+y+textheight("a"));
  393.         else
  394.             moveto(x,1+y+textheight("a"));
  395.         else
  396.         if (!ColumnLeft && (TS.vert == BOTTOM_TEXT))
  397.             moveto(1+x+textheight("a"),getmaxy());
  398.         else
  399.             moveto(1+x+textheight("a"),y);
  400.         str[i] = '\0';
  401.         str[1] = i - 2;
  402.         InputDone = 1;
  403.         break;
  404.     case 8:  // Back Space
  405.         if (i > 2)  {
  406.         str[i--] = '\0';
  407.         // Only erase XOR_PUT, stroked fonts!
  408.         if ((InputWriteMode == COPY_PUT) ||
  409.             (TS.font == DEFAULT_FONT))  {
  410.             TextBox(getx(),gety(),&str[i],TS,x1,y1,x2,y2);
  411.             bar(x1,y1,x2,y2);
  412.         }
  413.         else
  414.             outtextxy(getx(),gety(),&str[i]);
  415.         if (i > 2)  {
  416.             ProportionalBackSpace(lastchX,lastchY,
  417.             getx(),gety(),str[i-1],str[i],TS);
  418.             moveto(lastchX,lastchY);
  419.         }
  420.         str[i] = '\0';
  421.         }
  422.         break;
  423.     default:
  424.         if (i - 2 >= imax)  {
  425.         str[i] = '\0';
  426.         break;
  427.         }
  428.         if (i > 2)  {
  429.         ProportionalSpace(getx(),gety(),
  430.             nextchX,nextchY,str[i-1],str[i],TS);
  431.         moveto(nextchX,nextchY);
  432.         }
  433.         else  {
  434.         nextchX = getx();
  435.         nextchY = gety();
  436.         }
  437.         str[i+1] = '\0';
  438.         if (ClearTextBk)  {
  439.         TextBox(nextchX,nextchY,&str[i],TS,x1,y1,x2,y2);
  440.         bar(x1,y1,x2,y2);
  441.         }
  442.         outtextxy(nextchX,nextchY,&str[i]);
  443.         i++;
  444.         break;
  445.     }
  446.     }
  447.     if (InputRewrite && str[1])  {
  448.     setwritemode(COPY_PUT);
  449.     outtextxy(x,y,&str[2]);
  450.     }
  451.     setfillstyle(FS.pattern,FS.color);
  452.     return &str[2];
  453. }
  454.  
  455.  
  456. // comment out next line to use gconio in your applications
  457. #define TEST_GCONIO_CPP
  458. #ifdef  TEST_GCONIO_CPP
  459.  
  460. #include <stdio.h>
  461. #include <stdlib.h>
  462.  
  463. #define MAXS 40
  464.  
  465. main()
  466. {
  467.     int gdriver, gmode, gerror;
  468.     int dx, dy, c;
  469.     char s[MAXS];
  470.     GraphicsConsole GC;
  471.  
  472.     gdriver = DETECT;
  473.     initgraph(&gdriver, &gmode, "..\\bgi");
  474.     gerror = graphresult();
  475.     if (gerror != grOk)  /* an error occurred */
  476.     {
  477.        printf("Graphics error: %s\n", grapherrormsg(gerror));
  478.        printf("Press any key to halt:");
  479.        getchar();
  480.        exit(1);
  481.     }
  482.  
  483.     dx = getmaxx() / (getmaxcolor()+1);
  484.     clearviewport();
  485.     for (c = 0; c <= getmaxcolor(); c++)  {
  486.     setfillstyle(XHATCH_FILL,c);
  487.     bar3d(c*dx,0,(c+1)*dx,getmaxy(),0,0);
  488.     }
  489.     settextjustify(LEFT_TEXT,TOP_TEXT);
  490.     settextstyle(TRIPLEX_FONT,HORIZ_DIR,1);
  491.     GC.cputs("Test getche(): ");
  492.     GC.getche();
  493.     GC.cputs("\r\nTest cscanf(\"Hello %s \",s): ");
  494.     GC.cscanf("Hello %s ",s);
  495.     GC.cprintf("\r\ns: %s",s);
  496.     GC.cputs("\r\n\r\nAnd rubout: ");
  497.     GC.rubout(GC.getche());
  498.  
  499.     GC.ColumnLeft = 1;
  500.     moveto(30,gety());
  501.     GC.cprintf("\r\nHello graphics %s!\r\n\r\n","world");
  502.     GC.cputs("Include gconio.hpp in your application.\r\n");
  503.     GC.cputs("Instantiate the GraphicsConsole class\r\n");
  504.     GC.cputs("to have complete text i/o capabilities\r\n");
  505.     GC.cputs("in all graphics modes.\r\n\r\n");
  506.     GC.cputs("Let's try cgets().  Enter: ");
  507.     s[0] = MAXS-2;
  508.     GC.cgets(s);
  509.     GC.ColumnLeft = 0;
  510.  
  511.  
  512.     setbkcolor(BLUE);
  513.     setcolor(WHITE);
  514.     clearviewport();
  515.     settextstyle(SANS_SERIF_FONT,VERT_DIR,4);
  516.     settextjustify(LEFT_TEXT,BOTTOM_TEXT);
  517.     moveto(0,getmaxy());
  518.     GC.cputs("It even works with\r\n");
  519.     GC.cputs("vertical text.\r\n\r\n");
  520.     GC.cputs("\r\n");
  521.     GC.cputs("And cgets(): ");
  522.     s[0] = MAXS-2;
  523.     GC.cgets(s);
  524.  
  525.     clearviewport();
  526.     settextstyle(GOTHIC_FONT,HORIZ_DIR,4);
  527.     settextjustify(CENTER_TEXT,TOP_TEXT);
  528.     moveto(getmaxx()/2,10);
  529.     GC.cputs("Besure to call GraphicsConsole member\r\n");
  530.     GC.cputs("functions only after calling initgraph()\r\n");
  531.     GC.cputs("and before calling closegraph().");
  532.  
  533.     settextstyle(SMALL_FONT,HORIZ_DIR,8);
  534.     settextjustify(CENTER_TEXT,TOP_TEXT);
  535.     moveto(getmaxx() / 2,getmaxy() / 2);
  536.     GC.cputs("Goodbye time - \r\n");
  537.     GC.cputs("consuming graphic\r\n");
  538.     GC.cputs("text programming!\r\n");
  539.     GC.cputs("\n");
  540.     GC.cputs("Press any key to continue ...");
  541.     GC.getch();
  542.     closegraph();
  543.  
  544.     puts("If you find gconio useful and are using it in your");
  545.     puts("applications, how about telling a friend about it.");
  546.     puts("Gconio is freeware - I only ask that you leave my");
  547.     puts("copyright notice untouched!  I will try to answer");
  548.     puts("as many of your questions and/or comments (time ");
  549.     puts("and money permitting).  Thanks!  John CIS: 73757,2233");
  550.     puts("");
  551.     puts("PSW / Power SoftWare");
  552.     puts("P.O. Box 10072");
  553.     puts("McLean, Virginia 22102 8072");
  554.     puts("(703) 759-3838");
  555.     puts("");
  556.     puts("That's all folks!");
  557.     puts("");
  558.     puts("Press enter to quit.");
  559.     getchar();
  560. }
  561.  
  562. #endif