home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / progrmng / stk110.lzh / STKSRC.COM / GR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-25  |  13.0 KB  |  430 lines

  1. /**********************************************************************
  2. * gr.c
  3. *
  4. * Support routines for graphics mode.
  5. **********************************************************************
  6.                     This file is part of
  7.  
  8.          STK -- The sprite toolkit -- version 1.1
  9.  
  10.               Copyright (C) Jari Karjala 1991
  11.  
  12. The sprite toolkit (STK) is a FreeWare toolkit for creating high
  13. resolution sprite graphics with PCompatible hardware. This toolkit 
  14. is provided as is without any warranty or such thing. See the file
  15. COPYING for further information.
  16.  
  17. **********************************************************************/
  18.  
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <stdarg.h>
  22. #include <string.h>
  23. #include <signal.h>
  24. #include <conio.h>
  25. #include <graphics.h>
  26. #include <dos.h>
  27.  
  28. #include "gr.h"         /* no WORDs or BYTEs allowed in gr.h */
  29. #include "grtypes.h"
  30. #include "gr_int9.h"
  31. #include "gr_low.h"
  32.  
  33. /**********************************************************************
  34. * The maximum coordinate values 
  35. **********************************************************************/
  36. int gr_max_x;
  37. int gr_max_y;
  38.  
  39. int gr_text_mode = GR_MODE_CLEAR;
  40.  
  41. int gr_visualpage=0;
  42. int gr_activepage=0;
  43.  
  44. /*********************************************************************
  45. * Pointer into an byte array containing the character font for 
  46. * 8x8 pixel fixed point font. Initialized to ROM font (FFA6:000E).
  47. ********************************************************************/
  48. unsigned char far *gr_font_addr = MK_FP(0xFFA6,0x000E);
  49.  
  50. static int fast_putch = 0;
  51.  
  52. /**********************************************************************
  53. * Detect the graphics card and mode of the system.
  54. * The type parameter can be used to specify special requests (see above).
  55. * graphdriver and graphmode parameters are returned. They contain -1
  56. * if some error occured (cannot find requested mode, etc)
  57. **********************************************************************/
  58. void gr_detect(int type, int *graphdriver, int *graphmode)
  59. {
  60.     detectgraph(graphdriver, graphmode);
  61.     
  62.     switch (type) {
  63.         case GR_TYPE_ANY:
  64.             break;
  65.         case GR_TYPE_SPR:
  66.             if (*graphdriver==EGA || *graphdriver==VGA) {
  67.                 *graphdriver = EGA;
  68.                 *graphmode = EGAHI;
  69.             }
  70.             else
  71.             if (*graphdriver==EGAMONO) {
  72.                 *graphdriver = EGAMONO;
  73.                 *graphmode = EGAMONOHI;
  74.             }
  75.             else if (*graphdriver!=HERCMONO) {
  76.                 *graphdriver = *graphmode = -1;
  77.                 break;
  78.             }
  79.             break;
  80.         default:
  81.             break;
  82.     }
  83. }
  84.  
  85.  
  86. /***************************************************************************
  87. * Called at the end of the program
  88. ***************************************************************************/
  89. void gr_end(void)
  90. {
  91.     closegraph();
  92. }
  93.  
  94. /***************************************************************************
  95. * Initializes the graphics system. Search BGI drivers from the path defined
  96. * in the enviroment variable BGIDIR or current directory. Set videomode
  97. * into the BIOS are to fool mouse drivers with Hercules graphics.
  98. * Set gr_end at exit and ctrl-C.
  99. * Terminate with error message if initialization fails.
  100. *
  101. * graphdriver   pointer to the driver ID (or DETECT)
  102. * graphmode     pointer to the mode ID
  103. ***************************************************************************/
  104. void gr_start(int *graphdriver, int *graphmode)
  105. {
  106.   int ErrorCode;
  107.   char *bgidir;
  108.   unsigned char far *Mode = (unsigned char far *)MK_FP(0x40, 0x49);
  109.  
  110.   if ((bgidir=getenv("BGIDIR"))==NULL)  /* Find BGIs in other dirs also */
  111.       bgidir="";
  112.  
  113.   initgraph( graphdriver, graphmode, bgidir);
  114.   ErrorCode = graphresult();            /* Read result of initialization*/
  115.   if( ErrorCode != grOk ){              /* Error occured during init    */
  116.     printf(" Graphics System Error: %s\n", grapherrormsg( ErrorCode ) );
  117.     exit( 1 );
  118.   }
  119.   
  120.   if (*graphdriver == HERCMONO)         /* Just to fool mouse drivers */
  121.      *Mode = 6;
  122.  
  123.   signal(SIGINT, gr_end);          /* Back to text when user break */
  124.   atexit(gr_end);                  /* Back to text when end-of-pgm */
  125.   
  126.     if ((*graphdriver==EGA && *graphmode==EGAHI) || *graphdriver==EGAMONO) {
  127.         fast_putch = 1;
  128.         gr_low_addr = gr_low_ega_mono_addr;
  129.         gr_low_putch = gr_low_ega_mono_putch;
  130.     }
  131.     else if (*graphdriver==HERCMONO) {
  132.         fast_putch = 1;
  133.         gr_low_addr = gr_low_herc_addr;
  134.         gr_low_putch = gr_low_herc_putch;
  135.     }
  136.  
  137.   gr_max_x = getmaxx();
  138.   gr_max_y = getmaxy();
  139.  
  140. }
  141.  
  142. /*********************************************************************
  143. * Set the active graphics page for writing and reading (0/1).
  144. * Also set the 'gr_activepage' variable
  145. *********************************************************************/
  146. void gr_setactivepage(int page)
  147. {
  148.     gr_activepage = page;
  149.     setactivepage(page);
  150. }
  151.  
  152. /*********************************************************************
  153. * Set the visual graphics page
  154. * Also set the 'gr_visualpage' variable
  155. *********************************************************************/
  156. void gr_setvisualpage(int page)
  157. {
  158.     gr_visualpage = page;
  159.     setvisualpage(page);
  160. }
  161.  
  162. /***************************************************************************
  163. * Output one character at the current cursor location, advance cursor.
  164. * Understands \n and \r correctly (no scrolling, though)
  165. ***************************************************************************/
  166. void gr_putch(char ch)
  167. {
  168.     static char buf[2] = "?";
  169.     int x=getx(), y=gety();
  170.     
  171.     buf[0]=ch;
  172.  
  173.     switch (ch) {
  174.         case '\n':
  175.             moveto(0, y+textheight(buf));
  176.             break;
  177.         case '\r':
  178.             moveto(0, y);
  179.             break;
  180.         default:
  181.             if (gr_text_mode == GR_MODE_CLEAR_FAST && fast_putch) {
  182.                     unsigned char far *addr = gr_low_addr(x,y,gr_activepage);
  183.                     gr_low_putch(addr, ch);
  184.                     moveto(x+8, y);
  185.             }
  186.             else if (gr_text_mode == GR_MODE_OR)
  187.                 outtext(buf);
  188.             else {
  189.                     struct fillsettingstype fs;
  190.                     /** clear the background **/
  191.                     getfillsettings(&fs);
  192.                     setfillstyle(EMPTY_FILL,0);
  193.                     bar(getx(),gety(),
  194.                         getx()+textwidth(buf),gety()+textheight(buf));
  195.                     setfillstyle(fs.pattern, fs.color);
  196.                     outtext(buf);
  197.             }
  198.                         
  199.             if (getx() > gr_max_x)
  200.                 moveto(0, y+textheight(buf));
  201.     }
  202. }
  203.  
  204. /***************************************************************************
  205. * Output the given string.
  206. ***************************************************************************/
  207. void gr_puts(char *s)
  208. {
  209.     while(*s)
  210.         gr_putch(*s++); 
  211.     
  212.     gr_putch('\n');
  213. }
  214.  
  215.  
  216. /***************************************************************************
  217. * As printf, but in the graphics mode.
  218. ***************************************************************************/
  219. void gr_printf(char *s,...)
  220. {
  221.     char buf[100];
  222.     va_list argptr;
  223.  
  224.     va_start(argptr,s);
  225.     vsprintf(buf,s,argptr);
  226.     va_end(argptr);
  227.     gr_puts(buf);
  228. }
  229.  
  230. /**********************************************************************
  231. * Print text at the given position. (x and y in pixels) 
  232. **********************************************************************/
  233. void gr_xy_printf(int x, int y, char *s,...)
  234. {
  235.     char buf[100];
  236.     va_list argptr;
  237.  
  238.     va_start(argptr,s);
  239.     vsprintf(buf,s,argptr);
  240.     va_end(argptr);
  241.  
  242.     moveto(x,y);
  243.     gr_puts(buf);
  244. }
  245.  
  246. /**********************************************************************
  247. * Print text horizontally centered.
  248. * (x centered, at given y in pixels).
  249. **********************************************************************/
  250. void gr_center_printf(int y, char *s,...)
  251. {
  252.     char buf[100];
  253.     va_list argptr;
  254.     int x;
  255.     
  256.     va_start(argptr,s);
  257.     vsprintf(buf,s,argptr);
  258.     va_end(argptr);
  259.     
  260.     x = (gr_max_x-textwidth(buf))/2;
  261.     
  262.     moveto(x,y);
  263.     gr_puts(buf);
  264. }
  265.  
  266. /**********************************************************************
  267. * Print text into both graphics pages at the given position.
  268. * (x and y in pixels) Curretn gr_activepage is left active.
  269. **********************************************************************/
  270. void gr_dual_xy_printf(int x, int y, char *s,...)
  271. {
  272.     char buf[100];
  273.     va_list argptr;
  274.  
  275.     va_start(argptr,s);
  276.     vsprintf(buf,s,argptr);
  277.     va_end(argptr);
  278.  
  279.     gr_setactivepage(gr_activepage^1);
  280.     moveto(x,y);
  281.     gr_puts(buf);
  282.     
  283.     gr_setactivepage(gr_activepage^1);
  284.     moveto(x,y);
  285.     gr_puts(buf);
  286. }
  287.  
  288. /**********************************************************************
  289. * Print text into both graphics pages at the given position.
  290. * (x centered, at given y in pixels).
  291. **********************************************************************/
  292. void gr_dual_center_printf(int y, char *s,...)
  293. {
  294.     char buf[100];
  295.     va_list argptr;
  296.     int x;
  297.     
  298.     va_start(argptr,s);
  299.     vsprintf(buf,s,argptr);
  300.     va_end(argptr);
  301.     
  302.     x = (gr_max_x-textwidth(buf))/2;
  303.     
  304.     gr_setactivepage(gr_activepage^1);
  305.     moveto(x,y);
  306.     gr_puts(buf);
  307.     
  308.     gr_setactivepage(gr_activepage^1);
  309.     moveto(x,y);
  310.     gr_puts(buf);
  311. }
  312.  
  313. /**********************************************************************
  314. * Read a string from screen in graphics mode (at most max_len<80 chrs)
  315. * Backspace deletes characters, Esc returns a null pointer.
  316. **********************************************************************/
  317. char *gr_gets(char *cpdest, int max_len)
  318. {
  319.     char buf[80], buf2[2]=" ", *cp=buf, ch;
  320.     int quit = 0;
  321.     struct fillsettingstype fs;
  322.     /** clear the old char **/
  323.     getfillsettings(&fs);
  324.     
  325.     while (!quit) {
  326.         gr_putch('_');
  327.         ch=getch();
  328.         /** remove underline **/
  329.         buf2[0] = '_';
  330.         bar(getx()-textwidth(buf2), gety(),
  331.             getx(), gety()+textheight(buf2));
  332.         moveto(getx()-textwidth(buf2),gety());
  333.         
  334.         switch (ch) {
  335.             case 8:     /** backspace **/
  336.                 if (cp>buf) {
  337.                     cp--;
  338.                     buf2[0] = *cp;
  339.                     bar(getx()-textwidth(buf2), gety(),
  340.                         getx(), gety()+textheight(buf2));
  341.                     moveto(getx()-textwidth(buf2),gety());
  342.                 }
  343.                 break;
  344.                 
  345.             case 13:    /** enter **/
  346.                 quit = 1;
  347.                 break;
  348.                 
  349.             case 27:    /** esc **/
  350.                 cp = NULL;
  351.                 quit = 1;
  352.                 break;
  353.                 
  354.             default:
  355.                 if (cp < buf+max_len-1) {
  356.                     gr_putch(ch);
  357.                     *cp++ = ch;
  358.                 }
  359.         }
  360.     }
  361.     
  362.     setfillstyle(fs.pattern, fs.color);
  363.     if (cp==NULL)
  364.         return NULL;
  365.     *cp++ = '\0';
  366.     strcpy(cpdest, buf);
  367.     return cpdest;
  368. }
  369.  
  370. /**********************************************************************
  371. * Return a keypress if one pending, otherwise 0.
  372. * Extended codes contain 0 in the low byte.
  373. **********************************************************************/
  374. int gr_inkey(void)
  375. {
  376.     unsigned int far *fptail, far *fphead;
  377.     int c;
  378.     
  379.     c = 0;
  380.     fptail = MK_FP(0x40,0x1A);
  381.     fphead = MK_FP(0x40,0x1C);
  382.     
  383.     disable();
  384.     if (*fptail!=*fphead) {   /** there were a keypress **/
  385.         c = getch();
  386.         if (!c)     /** extended code (F-keys, cursor keys etc) **/
  387.             c = getch() << 8;
  388.         *fptail = *fphead;
  389.     }
  390.     enable();
  391.     
  392.     return c;
  393. }
  394.  
  395.  
  396. /**********************************************************************
  397. * Array of booleans for each key of the keyboard (indexed by the scan
  398. * code value). Non-zero if key pressed, zero otherwise.
  399. * The array is updated during the kbd_grab, see the function 
  400. * gr_start_kbd_grab below.
  401. **********************************************************************/
  402. char gr_keys[128];
  403.  
  404. /**********************************************************************
  405. * Restore the original keyboard handler
  406. **********************************************************************/
  407. void gr_end_kbd_grab(void)
  408. {
  409.     setvect(9, gr_old_int9);    
  410. }
  411.  
  412. /**********************************************************************
  413. * Set a new handler for the keyboard. This handler sets and resets
  414. * the gr_keys array values for each scancode received, flushes the
  415. * keyboard buffer and then calls the original handler.
  416. **********************************************************************/
  417. void gr_start_kbd_grab(void)
  418. {
  419.     static int first_time = 1;
  420.     
  421.     gr_old_int9 = getvect(9);
  422.     memset(gr_keys, 0, sizeof(gr_keys));
  423.     setvect(9, gr_int9);
  424.     if (first_time) {
  425.         atexit(gr_end_kbd_grab);
  426.         first_time = 0;
  427.     }
  428. }
  429.  
  430.