home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- * File: VIDPRIM.C
- * Date: Feb. 1991
- * Function: Primitive video operations
- * Authors: Craig Miller, George Spofford
- * Compilers: MSC 6.0, Turbo C++ 1.0, MetaWare HighC-386 1.7
- * Switches:
- * MSC 6.0: Assumes large memory model
- * cl -AL -Ox -c vidprim.c
- * High C:
- * hc386 -c -DDOS_386 vidprim.c
- *
- * Object code may be freely used. Source code may be used freely
- * if authorship/publication is acknowledged
- ****************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <stdarg.h>
- #include <dos.h> /* for int86(), FP_OFF and FP_SEG macros */
- #define VIDPRIM_SRC
- #include "vidprim.h"
-
- #define N_COLS 80 /* fixed # of columns in std, CGA/EGA/VGA */
- #define _TEXTMONO 7 /* code for monochrome text mode */
-
- #if ! defined (DOS_386) /* assuming large-model 8086 compile */
-
- #define _FAR far
- #define FFMEMCPY memcpy
- #define FF_R_MEMCPY memmove
-
- #else /* assuming MetaWare High C-386 v. 1.7 */
-
- #define _FAR _far
- #define SS_SEG 0x1C /* Phar Lap's screen segment selector */
-
- #define max( a, b) ((a) > (b) ? (a) : (b))
-
- /* use MetaWare's _movedata function for forward copy */
- #define FFMEMCPY( t, f, n) \
- _movedata (FP_SEG(f), FP_OFF(f), FP_SEG(t), FP_OFF(t), n)
-
- /* quick define of reverse copy function */
- void FF_R_MEMCPY (void _FAR *t, void _FAR *f, int n)
- {
- register char _FAR *tp;
- register char _FAR *fp;
- register int loop = n;
-
- for (tp = ((char _FAR *) t) + loop,
- fp = ((char _FAR *) f) + loop;
- --loop >= 0;
- *--tp = *--fp)
- ;
- }
-
- #endif
-
- /* ptr to display memory */
- static short _FAR *dispmem = (short _FAR *) NULL;
- /* current display attribute */
- static color_t curattrib = 0x07;
- /* current display window */
- static bbox_t curbox = {{0,0},{25,80}};
-
- /* Display state: */
- static struct {
- int mode; /* mode */
- int cols; /* # of text columns on screen */
- int rows; /* # of text rows on screen */
- } CurDispState;
-
-
- /* VideoBios1: Makes EGA or VGA video bios call. Used for BIOS
- ** calls that use registers AL - BH as input, and return AL==0x12
- ** if successful (See BIOS #defines in VIDPRIM.H)
- */
- int VideoBios1 (unsigned char al, unsigned char ah,
- unsigned char bl, unsigned char bh)
- {
- union REGS inregs, outregs;
-
- inregs.h.al = al;
- inregs.h.ah = ah;
- inregs.h.bl = bl;
- inregs.h.bh = bh;
- int86 ( 0x10, &inregs, &outregs);
- return ( outregs.h.al == 0x12 );
- }
-
-
- /* VideoBios2: Makes EGA or VGA video bios call. Used for BIOS
- ** calls that use registers AL - BL as input and BH as output.
- ** Returns register BH. (See BIOS #defines in VIDPRIM.H)
- */
- unsigned char VideoBios2 (unsigned char al, unsigned char ah,
- unsigned char bl)
- {
- union REGS inregs, outregs;
-
- inregs.h.al = al;
- inregs.h.ah = ah;
- inregs.h.bl = bl;
- int86 ( 0x10, &inregs, &outregs);
- return ( outregs.h.bh );
- }
-
-
- /* InitDisplay: Sets the text display to the given mode (3 or 7)
- ** and the number of text lines given.
- */
- void _PASCAL InitDisplay (int mode, int rows)
- {
- EGA_setvideomode (mode); /* set the mode (either 3 or 7) */
- CurDispState.mode = mode;
- CurDispState.cols = N_COLS;
-
- switch (rows) {
- case 50:
- VGA_400lines();
- CurDispState.rows = 50;
- EGA_SetFont (FONT8X8NORESET);
- break;
- case 43:
- CurDispState.rows = 43;
- EGA_SetFont (FONT8X8NORESET);
- break;
- case 25:
- default:
- VGA_400lines();
- EGA_SetFont (FONT8X16NORESET);
- CurDispState.rows = 25;
- }
-
- #if ! defined (DOS_386)
- dispmem = (short _FAR *)
- ((CurDispState.mode == _TEXTMONO) ? 0xB0000000 : 0xB8000000);
- #else
- { /* 48-bit far ptr creation */
- struct _farptrovly {int off; short seg;};
-
- ((struct _farptrovly *) &dispmem)->seg =
- SS_SEG; /* Phar Lap screen seg */
- ((struct _farptrovly *) &dispmem)->off = 0x00000000;
- }
- #endif
-
- curbox.o[DOWN] = 0;
- curbox.o[ACROSS] = 0;
- curbox.n[DOWN] = CurDispState.rows;
- curbox.n[ACROSS] = CurDispState.cols;
-
- curattrib = 0x07;
- }
-
-
- /* SetCurAttrib: Sets the current display attribute.
- ** Returns the previous current-attribute value.
- */
- color_t SetCurAttrib (color_t attr)
- {
- color_t ret;
-
- ret = curattrib;
- curattrib = attr;
- return (ret);
- }
-
-
- /* SetCurBox
- ** Sets the current screen display window
- */
- void SetCurBox (bbox_t *bbp)
- {
- memcpy (&curbox, bbp, sizeof (bbox_t));
- }
-
-
- /* SetTextCursor: Sets current cursor position to
- ** R,C (coordinate system starts at 0, 0)
- */
- void _PASCAL SetTextCursor (int r, int c)
- {
- union REGS regs;
-
- regs.h.ah = 0x02; /* func. is set cursor position */
- regs.h.bh = 0;
- regs.h.dh = (char) r;
- regs.h.dl = (char) c;
- int86 (0x10, ®s, ®s); /* set cursor at row, col */
- }
-
-
- /* ScrollBox: Scrolls the given region down by ND rows and
- ** right by NA columns
- */
- void _PASCAL ScrollBox (bbox_t *bbp, int nd, int na)
- {
- short _FAR *tptr; /* primary display memory ptr */
- short _FAR *fptr; /* secondary display ptr */
- register int loop; /* primary loop index */
- register int loop2; /* secondary loop index */
- short _FAR *boxptr; /* ptr to UL corner of scroll-box */
- short attr; /* background filler */
- int nbytes; /* # of bytes to transfer per move */
-
- /* calculate region reference ptr */
- boxptr = dispmem + bbp->o[DOWN] * CurDispState.cols
- + bbp->o[ACROSS];
- /* make newly-blank-space representation */
- attr = ((short) (curattrib << 8)) + ' ';
-
- /*------------------- VERTICAL ------------------------*/
- if (nd != 0) { /* if scrolling vertically */
- nbytes = bbp->n[ACROSS] * /* scroll the entire */
- sizeof(short); /* width of the box. */
- if (nd < 0) {
-
- /*----------------------- SCROLL UP -------------------*/
- nd = -nd;
- if (nd > bbp->n[DOWN]) /* clip # to scroll to box size */
- nd = bbp->n[DOWN];
-
- /* copy rows, advancing downwards */
- for (tptr = boxptr, fptr =
- boxptr + nd * CurDispState.cols,
- loop = bbp->n[DOWN] - nd;
- --loop >= 0;
- tptr += CurDispState.cols, fptr += CurDispState.cols)
- FFMEMCPY (tptr, fptr, nbytes);
-
- /* blank each remaining row with current attribute
- * tptr is set to first row after scrolled region. */
-
- for (loop2 = nd, fptr = tptr; --loop2 >= 0;
- fptr += CurDispState.cols)
- for (tptr = fptr, loop = bbp->n[ACROSS];
- --loop >= 0; *tptr++ = attr)
- ;
- }
- else {
- /*------------------- SCROLL DOWN ---------------------*/
- if (nd > bbp->n[DOWN]) /* clip to region */
- nd = bbp->n[DOWN];
-
- /* copy rows, advancing upwards */
- for (tptr = boxptr + (bbp->n[DOWN]-1) * CurDispState.cols,
- fptr = boxptr + (bbp->n[DOWN]-1-nd) * CurDispState.cols,
- loop = bbp->n[DOWN] - nd;
- --loop >= 0;
- tptr -= CurDispState.cols, fptr -= CurDispState.cols)
- FFMEMCPY (tptr, fptr, nbytes);
-
- /* blank each remaining rows with current attribute
- * tptr is set to first row above scrolled region. */
- for (loop2 = nd, fptr = tptr; --loop2 >= 0;
- fptr -= CurDispState.cols)
- for (tptr = fptr, loop = bbp->n[ACROSS];
- --loop >= 0; *tptr++ = attr)
- ;
- }
- } /* vertical scroll */
-
- /*--------------- HORIZONTAL ------------------------*/
- if (na != 0) { /* if any horizontal scroll */
- if (na > 0) {
-
- /*----------------- SCROLL RIGHT ----------------------*/
- /* scroll only NA chars */
- nbytes = (bbp->n[ACROSS] - na) * sizeof (short);
- if (na > bbp->n[ACROSS]) /* clip to size of box */
- na = bbp->n[ACROSS];
-
- /* in each row, slide columns to
- screen right (-> high memory) */
- for (fptr = boxptr, tptr = boxptr + na,
- loop = bbp->n[DOWN];
- --loop >= 0;
- fptr += CurDispState.cols, tptr += CurDispState.cols)
- /* copy from high- to low-mem */
- FF_R_MEMCPY (tptr, fptr, nbytes);
-
- /* in each row, blank unmoved columns */
- for (loop2 = bbp->n[DOWN], fptr = boxptr; --loop2 >= 0;
- fptr += CurDispState.cols)
- for (tptr = fptr, loop = na; --loop >= 0; *tptr++ = attr)
- ;
- }
- else {
-
- /*----------------- SCROLL LEFT -----------------------*/
- na = -na; /* take positive quantity */
- nbytes = (bbp->n[ACROSS] - na) * sizeof (short);
- if (na > bbp->n[ACROSS]) /* clip to box */
- na = bbp->n[ACROSS];
-
- /* in each row, move columns to
- screen left (-> low memory) */
- for (tptr = boxptr, fptr = boxptr + na,
- loop = bbp->n[DOWN];
- --loop >= 0;
- tptr += CurDispState.cols, fptr += CurDispState.cols)
- FFMEMCPY (tptr, fptr, nbytes);
-
- /* blank out unmoved columns */
- for (loop2 = bbp->n[DOWN], fptr =
- boxptr + bbp->n[ACROSS] - na;
- --loop2 >= 0;
- fptr += CurDispState.cols)
- for (loop = na, tptr = fptr; --loop >= 0;
- *tptr++ = attr)
- ;
- }
- } /* horizontal scroll */
- }
-
-
- /* ClearBox: Clears out region represented in bounding box
- ** to current attribute.
- */
- void ClearBox (bbox_t *bbp)
- {
- ScrollBox (bbp, bbp->n[DOWN], 0);
- }
-
-
-
- /* ClearScreen
- ** Clears screen to currently set attribute.
- */
- void ClearScreen (void)
- {
- bbox_t bbox;
-
- BBSET( bbox, 0, 0, CurDispState.rows, CurDispState.cols);
- ClearBox (&bbox);
- }
-
-
- /* CursorOff
- ** Turns text cursor off.
- */
- void CursorOff (void)
- {
- SetTextCursor (CurDispState.rows + 1, 0);
- }
-
-
- /* x_outch: Places a character on the screen, at R,C
- ** using the current text-rendering attributes.
- ** Returns # of chars put of screen (1 or 0)
- */
- int _PASCAL x_outch (int r, int c, char ch)
- {
- register short _FAR *locdispmem;
- /* clip to current box */
- if ( ((unsigned) r) >= ((unsigned) curbox.n[DOWN])
- || ((unsigned) c) >= ((unsigned) curbox.n[ACROSS]) )
- return (0);
-
- locdispmem = dispmem + ((curbox.o[DOWN] + r) *
- CurDispState.cols + curbox.o[ACROSS] + c);
- *locdispmem = (short) (curattrib << 8) + (unsigned char) ch;
- return (1);
- }
-
-
-
- /* x_outtext: Places a character string on the screen
- ** starting at R,C, using the current text-rendering attributes
- */
- int _PASCAL x_outtext (int r, int c, char *str)
- {
- register short _FAR *locdispmem;
- register char *cp;
- int n, total;
- short attrmask;
-
- /* clip to box */
- /* if out of curbox */
- if ( ((unsigned) r) >= ((unsigned) curbox.n[DOWN])
- || ((unsigned) c) >= ((unsigned) curbox.n[ACROSS]) )
- return (0);
-
- locdispmem = dispmem + (curbox.o[DOWN] + r) *
- CurDispState.cols + curbox.o[ACROSS] + c;
- attrmask = curattrib << 8;
- for (cp = str, n = max (0, curbox.n[ACROSS] - c), total = 0;
- *cp && --n >= 0;
- ++total)
- *locdispmem++ = attrmask | * (unsigned char *) cp++;
-
- return (total);
- }
-
- /* xput_string
- ** Acts as a screen-printf() with row, column addressing
- */
- int _CDECL xput_string (int r, int c, char *fmt,...)
- {
- static char buf[256];
- va_list argptr;
- /* if out of curbox, don't write */
- if ( ((unsigned) r) >= ((unsigned) curbox.n[DOWN])
- || ((unsigned) c) >= ((unsigned) curbox.n[ACROSS]) )
- return (0);
-
- va_start (argptr, fmt); /* format arguments */
- vsprintf (buf, fmt, argptr);
- va_end (argptr);
-
- return (x_outtext (r, c, buf));
- }
-
- /* END OF VIDPRIM.C */
-