1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
|
/* pc.c */
/* Author:
* Guntram Blohm
* Buchenstrasse 19
* 7904 Erbach, West Germany
* Tel. ++49-7305-6997
* sorry - no regular network connection
*/
/* This file implements the ibm pc bios interface. See IBM documentation
* for details.
* If TERM is set upon invocation of elvis, this code is ignored completely,
* and the standard termcap functions are used, thus, even not-so-close
* compatibles can run elvis. For close compatibles however, bios output
* is much faster (and permits reverse scrolling, adding and deleting lines,
* and much more ansi.sys isn't capable of). GB.
*/
#include "config.h"
#include "vi.h"
#if MSDOS
#include <dos.h>
static void video();
/* vmode contains the screen attribute index and is set by attrset.*/
int vmode;
/* The following array contains attribute definitions for
* color/monochrome attributes. Screen selects one of the sets.
* Maybe i'll put them into elvis options one day.
*/
static int screen;
static char attr[2][5] =
{
/* :se: :so: :VB: :ul: :as: */
{ 0x1f, 0x1d, 0x1e, 0x1a, 0x1c, }, /* color */
{ 0x07, 0x70, 0x0f, 0x01, 0x0f, }, /* monochrome */
};
/*
* bios interface functions for elvis - pc version
*/
/* cursor up: determine current position, decrement row, set position */
void v_up()
{
int dx;
video(0x300,(int *)0,&dx);
dx-=0x100;
video(0x200,(int *)0,&dx);
}
#ifndef NO_CURSORSHAPE
/* cursor big: set begin scan to end scan - 4 */
void v_cb()
{
int cx;
video(0x300, &cx, (int *)0);
cx=((cx&0xff)|(((cx&0xff)-4)<<8));
video(0x100, &cx, (int *)0);
}
/* cursor small: set begin scan to end scan - 1 */
void v_cs()
{
int cx;
video(0x300, &cx, (int *)0);
cx=((cx&0xff)|(((cx&0xff)-1)<<8));
video(0x100, &cx, (int *)0);
}
#endif
/* clear to end: get cursor position and emit the aproppriate number
* of spaces, without moving cursor.
*/
void v_ce()
{
int cx, dx;
video(0x300,(int *)0,&dx);
cx=COLS-(dx&0xff);
video(0x920,&cx,(int *)0);
}
/* clear screen: clear all and set cursor home */
void v_cl()
{
int cx=0, dx=((LINES-1)<<8)+COLS-1;
video(0x0600,&cx,&dx);
dx=0;
video(0x0200,&cx,&dx);
}
/* clear to bottom: get position, clear to eol, clear next line to end */
void v_cd()
{
int cx, dx, dxtmp;
video(0x0300,(int *)0,&dx);
dxtmp=(dx&0xff00)|(COLS-1);
cx=dx;
video(0x0600,&cx,&dxtmp);
cx=(dx&0xff00)+0x100;
dx=((LINES-1)<<8)+COLS-1;
video(0x600,&cx,&dx);
}
/* add line: scroll rest of screen down */
void v_al()
{
int cx,dx;
video(0x0300,(int *)0,&dx);
cx=(dx&0xff00);
dx=((LINES-1)<<8)+COLS-1;
video(0x701,&cx,&dx);
}
/* delete line: scroll rest up */
void v_dl()
{
int cx,dx;
video(0x0300,(int *)0,&dx);
cx=(dx&0xff00)/*+0x100*/;
dx=((LINES-1)<<8)+COLS-1;
video(0x601,&cx,&dx);
}
/* scroll reverse: scroll whole screen */
void v_sr()
{
int cx=0, dx=((LINES-1)<<8)+COLS-1;
video(0x0701,&cx,&dx);
}
/* set cursor */
void v_move(x,y)
int x, y;
{
int dx=(y<<8)+x;
video(0x200,(int *)0,&dx);
}
/* put character: set attribute first, then execute char.
* Also remember if current line has changed.
*/
int v_put(ch)
int ch;
{
int cx=1;
ch&=0xff;
if (ch>=' ')
video(0x900|ch,&cx,(int *)0);
video(0xe00|ch,(int *)0, (int *)0);
if (ch=='\n')
{ exwrote = TRUE;
video(0xe0d, (int *)0, (int *)0);
}
return ch;
}
/* determine number of screen columns. Also set attrset according
* to monochrome/color screen.
*/
int v_cols()
{
union REGS regs;
regs.h.ah=0x0f;
int86(0x10, ®s, ®s);
if (regs.h.al==7) /* monochrome mode ? */
screen=1;
else
screen=0;
return regs.h.ah;
}
/* Getting the number of rows is hard. Most screens support 25 only,
* EGA/VGA also support 43/50 lines, and some OEM's even more.
* Unfortunately, there is no standard bios variable for the number
* of lines, and the bios screen memory size is always rounded up
* to 0x1000. So, we'll really have to cheat.
* When using the screen memory size, keep in mind that each character
* byte has an associated attribute byte.
*
* uses: word at 40:4c contains memory size
* byte at 40:84 # of rows-1 (sometimes)
* byte at 40:4a # of columns
*/
int v_rows()
{
int line, oldline;
/* screen size less then 4K? then we have 25 lines only */
if (*(int far *)(0x0040004cl)<=4096)
return 25;
/* VEGA vga uses the bios byte at 0x40:0x84 for # of rows.
* Use that byte, if it makes sense together with memory size.
*/
if ((((*(unsigned char far *)(0x0040004aL)*2*
(*(unsigned char far *)(0x00400084L)+1))+0xfff)&(~0xfff))==
*(unsigned int far *)(0x0040004cL))
return *(unsigned char far *)(0x00400084L)+1;
/* uh oh. Emit '\n's until screen starts scrolling. */
v_move(oldline=0, 0);
for (;;)
{
video(0xe0a,(int *)0,(int *)0);
video(0x300,(int *)0,&line);
line>>=8;
if (oldline==line)
return line+1;
oldline=line;
}
}
/* the REAL bios interface -- used internally only. */
static void video(ax, cx, dx)
int ax, *cx, *dx;
{
union REGS regs;
regs.x.ax=ax;
if ((ax&0xff00)==0x600 || (ax&0xff00)==0x700)
regs.h.bh=attr[screen][vmode];
else
{
regs.h.bh=0;
regs.h.bl=attr[screen][vmode];
}
if (cx) regs.x.cx=*cx;
if (dx) regs.x.dx=*dx;
int86(0x10, ®s, ®s);
if (dx) *dx=regs.x.dx;
if (cx) *cx=regs.x.cx;
}
/* The following function determines which character is used for
* commandline-options by command.com. This system call is undocumented
* and valid for versions < 4.00 only.
*/
int switchar()
{
union REGS regs;
regs.x.ax=0x3700;
int86(0x21, ®s, ®s);
return regs.h.dl;
}
#endif
|