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