/* TECO for DOS Copyright (C) 1986-1991 Matt Fichtenbaum */ /* Based on Ultrix TECO (C) 1986-1990 GenRad Inc., Concord, MA 01742 */ /* These programs may be copied if this copyright notice is included and */ /* only on a "not for sale or profit" basis */ /* te_displ.c: vga-only screen routines to substitute for Microsoft library */ /* 03/10/93 20.29 */ /* Routines: * _clearscreen - clear whole screen, or window * _gettextposition - return current cursor loc * _getvideoconfig - returns screen size and mode * _outtext - write text at current loc * _setbkcolor - set background color * _settextcolor - set text color * _settextposition - position cursor * _settextwindow - defines active screen area (y only) * _wrapon - set wraparound (dummy routine) */ #include "te_graph.h" #include "te_defs.h" #include /* globals */ #define VIDEO_COLOR_BUFFER 0xb8000000L #define VIDEO_MONO_BUFFER 0xb0000000L #define DOS_EQPT_FLAG (unsigned char _far *) 0x00400010 #define VIDEOMODE (unsigned char _far *) 0x00400049 #define VIDEOCOLS (unsigned short _far *) 0x0040004a #define VIDEOROWS (unsigned char _far *) 0x00400084 #define VIDEOPAGE (unsigned char _far *) 0x00400062 #define VIDEOSCRN (unsigned short _far *) 0x0040004c #define vga_c (unsigned char _far *) video_buffer #define vga_w (unsigned short _far *) video_buffer unsigned long video_buffer = VIDEO_COLOR_BUFFER; static unsigned char size_y, size_x; /* screen size */ static unsigned char x = 1, y = 1; /* current cursor position */ static unsigned char w_top = 1, w_bot, w_left = 1, w_right; /* current window */ static unsigned char should_scroll = 0; /* nonzero if last line ran off end */ static void w_scroll(void); static void set_cursor(void); unsigned char getvideoconfig(unsigned short *mode, short *rows, short *cols); struct cchar { unsigned char c; /* displayed character */ unsigned char a; /* attributes */ }; union char_att { unsigned short w; struct cchar c; } blank = { 0x0720 }; /* get video mode and dimensions */ /* returns bit 0 = 0 if color mode, 1 if mono */ /* bit 1 = 0 if graphics mode, 1 if text */ unsigned char getvideoconfig (unsigned short *mode, short *rows, short *cols) { unsigned char return_value = 0; unsigned short nchars; union REGS r; r.x.ax = 0x0500; /* set page 0 */ int86(0x10, &r, &r); if ((*DOS_EQPT_FLAG & 0x30) == 0x30) { video_buffer = VIDEO_MONO_BUFFER; return_value = 1; } else video_buffer = VIDEO_COLOR_BUFFER; *mode = *VIDEOMODE; /* mode */ w_right = size_x = *cols = *VIDEOCOLS; /* columns */ w_bot = size_y = *rows = *VIDEOROWS + 1; if ((nchars = 2 * size_x * size_y) > 2 * *VIDEOSCRN || nchars <= *VIDEOSCRN/4) return_value |= 2; return(return_value); } /* set window */ void _settextwindow(short r1, short c1, short r2, short c2) { w_top = r1; w_bot = r2; w_left = c1; w_right = c2; if (w_top < 1) w_top = 1; if (w_top > size_y) w_top = size_y; if (w_bot < 1) w_bot = 1; if (w_bot > size_y) w_bot = size_y; if (w_bot < w_top) w_bot = w_top; if (w_left < 1) w_left = 1; if (w_left > size_x) w_left = size_y; if (w_right < 1) w_right = 1; if (w_right > size_x) w_right = size_x; if (w_right < w_left) w_right = w_left; x = y = 1; set_cursor(); should_scroll = 0; } /* set colors */ long _setbkcolor(long color) { short old_bkcolor = blank.c.a >> 4; blank.c.a &= 0x0f; blank.c.a |= (color & 0x0f) << 4; return ((long) old_bkcolor); } short _settextcolor(short color) { short old_color = blank.c.a & 0x0f; blank.c.a &= 0xf0; blank.c.a |= color & 0x0f; return(old_color); } /* set, get text position */ struct rccoord _settextposition(short row, short column) { struct rccoord rval; rval.row = y; rval.col = x; if ((y = row) > w_bot) y = w_bot; if ((x = column) > w_right) x = w_right; set_cursor(); should_scroll = 0; return(rval); } struct rccoord _gettextposition(void) { struct rccoord rval; rval.row = y; rval.col = x; return(rval); } /* set wrap (a dummy function - it's always on */ short _wrapon(short flag) { return(_GWRAPOFF); } /* clear screen or window */ void _clearscreen(short area) { register unsigned short _far *p = vga_w; register unsigned long n; unsigned short ir, ic; if (area != _GCLEARSCREEN) p += (w_top - 1) * size_x; if (area == _GCLEARSCREEN || (w_left == 1 && w_right == size_x)) for (n = size_x * ((area != _GCLEARSCREEN) ? (w_bot - w_top + 1) : size_y); n > 0; n--) *p++ = blank.w; else /* else clear partial lines */ { for (ir = w_top; ir <= w_bot; ir++) { p = vga_w + (ir - 1) * size_x + w_left - 1; for (ic = w_left; ic <= w_right; ic++) *p++ = blank.w; } } x = y = 1; set_cursor(); } /* output a text string */ /* characters treated literally except \n, \r */ void _outtext(unsigned const char *buffer) { register unsigned char _far *pc; register unsigned char _far *pv = vga_c + 2 * ((w_top + y - 2) * size_x + w_left + x - 2); register unsigned short rx = x; unsigned short x_max = w_right - w_left + 1; pc = (unsigned char _far *) buffer; while (*pc != '\0') { if (*pc == 015) /* cr - back to left margin */ { should_scroll = 0; /* back to margin - no scroll */ rx = 1; pv = vga_c + 2 * ((w_top + y - 2) * size_x + w_left + rx - 2); ++pc; /* skip this char */ } else if (*pc == 012) /* lf - next line, scroll if nec */ { should_scroll = 0; /* move to next line - supersedes scroll */ if (y < w_bot - w_top + 1) { pv += 2 * size_x; /* no scroll */ ++y; } else w_scroll(); /* scroll - use bios */ ++pc; } else /* printing char */ { if (should_scroll != 0) /* is there a leftover scroll? */ { if (y >= w_bot - w_top + 1) w_scroll(); else ++y; pv = vga_c + 2 * ((w_top + y - 2) * size_x + w_left + rx - 2); should_scroll = 0; } *pv++ = *pc++; *pv++ = blank.c.a; if (++rx > x_max) { should_scroll = rx = 1; } } } x = rx; set_cursor(); } /* scroll window up one line */ static void w_scroll() { union REGS xr; if (!WN_scroll) display_mouse(MOUSE_SUSPEND); /* if window is off, hide mouse */ xr.x.ax = 0x0601; /* func 6, 1 line */ xr.h.bh = blank.c.a; /* attribute */ xr.h.ch = w_top - 1; /* coordinates */ xr.h.cl = w_left - 1; xr.h.dh = w_bot - 1; xr.h.dl = w_right - 1; int86(0x10, &xr, &xr); if (!WN_scroll) display_mouse(MOUSE_RESUME); } /* set hardware cursor to current x, y in current window */ static void set_cursor() { union REGS xr; xr.h.ah = 0x02; xr.h.bh = 0; xr.h.dh = w_top + y - 2; xr.h.dl = w_left + x - 2; int86(0x10, &xr, &xr); }