-
Notifications
You must be signed in to change notification settings - Fork 1
/
pc.c
270 lines (223 loc) · 5.38 KB
/
pc.c
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