home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- * gr.c
- *
- * Support routines for graphics mode.
- **********************************************************************
- This file is part of
-
- STK -- The sprite toolkit -- version 1.0
-
- Copyright (C) Jari Karjala 1990
-
- The sprite toolkit (STK) is a FreeWare toolkit for creating high
- resolution sprite graphics with PCompatible hardware. This toolkit
- is provided as is without any warranty or such thing. See the file
- COPYING for further information.
-
- **********************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdarg.h>
- #include <string.h>
- #include <signal.h>
- #include <conio.h>
- #include <graphics.h>
- #include <dos.h>
-
- #include "gr.h"
- #include "gr_int9.h"
-
- /**********************************************************************
- * The maximum coordinate values
- **********************************************************************/
- int gr_max_x;
- int gr_max_y;
-
- int gr_text_mode = GR_MODE_CLEAR;
-
-
-
- /**********************************************************************
- * Detect the graphics card and mode of the system.
- * The type parameter can be used to specify special requests (see above).
- * graphdriver and graphmode parameters are returned. They contain -1
- * if some error occured (cannot find requested mode, etc)
- **********************************************************************/
- void gr_detect(int type, int *graphdriver, int *graphmode)
- {
- detectgraph(graphdriver, graphmode);
-
- switch (type) {
- case GR_TYPE_ANY:
- break;
- case GR_TYPE_SPR:
- if (*graphdriver==EGA || *graphdriver==VGA) {
- *graphdriver = EGAMONO;
- *graphmode = EGAMONOHI;
- }
- else if (*graphdriver!=HERCMONO) {
- *graphdriver = *graphmode = -1;
- }
- break;
- default:
- break;
- }
- }
-
-
- /***************************************************************************
- * Called at the end of the program
- ***************************************************************************/
- void gr_end(void)
- {
- closegraph();
- }
-
- /***************************************************************************
- * Initializes the graphics system. Search BGI drivers from the path defined
- * in the enviroment variable BGIDIR or current directory. Set videomode
- * into the BIOS are to fool mouse drivers with Hercules graphics.
- * Set gr_end at exit and ctrl-C.
- * Terminate with error message if initialization fails.
- *
- * graphdriver pointer to the driver ID (or DETECT)
- * graphmode pointer to the mode ID
- ***************************************************************************/
- void gr_start(int *graphdriver, int *graphmode)
- {
- int ErrorCode;
- char *bgidir;
- unsigned char far *Mode = (unsigned char far *)MK_FP(0x40, 0x49);
-
- if ((bgidir=getenv("BGIDIR"))==NULL) /* Find BGIs in other dirs also */
- bgidir="";
-
- initgraph( graphdriver, graphmode, bgidir);
- ErrorCode = graphresult(); /* Read result of initialization*/
- if( ErrorCode != grOk ){ /* Error occured during init */
- printf(" Graphics System Error: %s\n", grapherrormsg( ErrorCode ) );
- exit( 1 );
- }
-
- if (*graphdriver == HERCMONO) /* Just to fool mouse drivers */
- *Mode = 6;
-
- signal(SIGINT, gr_end); /* Back to text when user break */
- atexit(gr_end); /* Back to text when end-of-pgm */
-
- gr_max_x = getmaxx();
- gr_max_y = getmaxy();
-
- }
-
-
- /***************************************************************************
- * Output one character at the current cursor location, advance cursor.
- * Understands \n and \r correctly (no scrolling, though)
- ***************************************************************************/
- void gr_putch(char ch)
- {
- static char buf[2] = "?";
-
- buf[0]=ch;
-
- switch (ch) {
- case '\n':
- moveto(0, gety()+textheight(buf));
- break;
- case '\r':
- moveto(0, gety());
- break;
- default:
- if (gr_text_mode == GR_MODE_CLEAR) {
- struct fillsettingstype fs;
- /** clear the background **/
- getfillsettings(&fs);
- setfillstyle(EMPTY_FILL,0);
- bar(getx(),gety(),
- getx()+textwidth(buf),gety()+textheight(buf));
- setfillstyle(fs.pattern, fs.color);
- }
- outtext(buf);
- if (getx() > getmaxx())
- moveto(0, gety()+textheight(buf));
- }
- }
-
- /***************************************************************************
- * Output the given string.
- ***************************************************************************/
- void gr_puts(char *s)
- {
- while(*s)
- gr_putch(*s++);
-
- gr_putch('\n');
- }
-
-
- /***************************************************************************
- * As printf, but in the graphics mode.
- ***************************************************************************/
- void gr_printf(char *s,...)
- {
- char buf[100];
- va_list argptr;
-
- va_start(argptr,100);
- vsprintf(buf,s,argptr);
- va_end(argptr);
- gr_puts(buf);
- }
-
- /**********************************************************************
- * Print text at the given position. (x and y in pixels)
- **********************************************************************/
- void gr_xy_printf(int x, int y, char *s,...)
- {
- char buf[100];
- va_list argptr;
-
- va_start(argptr,100);
- vsprintf(buf,s,argptr);
- va_end(argptr);
-
- moveto(x,y);
- gr_puts(buf);
- }
-
- /**********************************************************************
- * Print text into both graphics pages at the given position.
- * (x and y in pixels) Page 0 is left active.
- **********************************************************************/
- void gr_dual_xy_printf(int x, int y, char *s,...)
- {
- char buf[100];
- va_list argptr;
-
- va_start(argptr,100);
- vsprintf(buf,s,argptr);
- va_end(argptr);
-
- setactivepage(1);
- moveto(x,y);
- gr_puts(buf);
-
- setactivepage(0);
- moveto(x,y);
- gr_puts(buf);
- }
-
- /**********************************************************************
- * Read a string from screen in graphics mode (at most max_len<80 chrs)
- * Backspace deletes characters, Esc returns a null pointer.
- **********************************************************************/
- char *gr_gets(char *cpdest, int max_len)
- {
- char buf[80], buf2[2]=" ", *cp=buf, ch;
- int quit = 0;
- struct fillsettingstype fs;
- /** clear the old char **/
- getfillsettings(&fs);
- setfillstyle(EMPTY_FILL,0);
-
- while (!quit) {
- gr_putch('_');
- ch=getch();
- /** remove underline **/
- buf2[0] = '_';
- bar(getx()-textwidth(buf2), gety(),
- getx(), gety()+textheight(buf2));
- moveto(getx()-textwidth(buf2),gety());
-
- switch (ch) {
- case 8: /** backspace **/
- if (cp>buf) {
- cp--;
- buf2[0] = *cp;
- bar(getx()-textwidth(buf2), gety(),
- getx(), gety()+textheight(buf2));
- moveto(getx()-textwidth(buf2),gety());
- }
- break;
-
- case 13: /** enter **/
- quit = 1;
- break;
-
- case 27: /** esc **/
- cp = NULL;
- quit = 1;
- break;
-
- default:
- if (cp < buf+max_len-1) {
- gr_putch(ch);
- *cp++ = ch;
- }
- }
- }
-
- setfillstyle(fs.pattern, fs.color);
- if (cp==NULL)
- return NULL;
- *cp++ = '\0';
- strcpy(cpdest, buf);
- return cpdest;
- }
-
- /**********************************************************************
- * Return a keypress if one pending, otherwise 0.
- * Extended codes contain 0 in the low byte.
- *
- * Automatic key repeat disabled by setting kbd buffer head and tail
- * equal. If someone knows a better solution, I would like to hear
- * about it.
- **********************************************************************/
- int gr_inkey(void)
- {
- unsigned int far *fptail, far *fphead;
- int c;
-
- c = 0;
- fptail = MK_FP(0x40,0x1A);
- fphead = MK_FP(0x40,0x1C);
-
- disable();
- if (*fptail!=*fphead) { /** there were a keypress **/
- c = getch();
- if (!c) /** extended code (F-keys, cursor keys etc) **/
- c = getch() << 8;
- *fptail = *fphead;
- }
- enable();
-
- return c;
- }
-
-
- /**********************************************************************
- * Array of booleans for each key of the keyboard (indexed by the scan
- * code value). Non-zero if key pressed, zero otherwise.
- * The array is updated during the kbd_grab, see the function
- * gr_start_kbd_grab below.
- **********************************************************************/
- char gr_keys[128];
-
- /**********************************************************************
- * Restore the original keyboard handler
- **********************************************************************/
- void gr_end_kbd_grab(void)
- {
- setvect(9, gr_old_int9);
- }
-
- /**********************************************************************
- * Set a new handler for the keyboard. This handler sets and resets
- * the gr_keys array values for each scancode received, flushes the
- * keyboard buffer and then calls the original handler.
- **********************************************************************/
- void gr_start_kbd_grab(void)
- {
- static int first_time = 1;
-
- gr_old_int9 = getvect(9);
- memset(gr_keys, 0, sizeof(gr_keys));
- setvect(9, gr_int9);
- if (first_time) {
- atexit(gr_end_kbd_grab);
- first_time = 0;
- }
- }
-
-