Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "u.h"
2
#include "../port/lib.h"
3
#include "mem.h"
4
#include "dat.h"
5
#include "fns.h"
6
#include "io.h"
7
#include "../port/error.h"
8
 
9
#define	Image	IMAGE
10
#include <draw.h>
11
#include <memdraw.h>
12
#include <cursor.h>
13
#include "screen.h"
14
 
15
static Memimage* back;
16
static Memimage *conscol;
17
 
18
static Point curpos;
19
static Rectangle window;
20
static int *xp;
21
static int xbuf[256];
22
Lock vgascreenlock;
23
int drawdebug;
24
 
25
void
26
vgaimageinit(ulong chan)
27
{
28
	if(back == nil){
29
		back = allocmemimage(Rect(0,0,1,1), chan);	/* RSC BUG */
30
		if(back == nil)
31
			panic("back alloc");		/* RSC BUG */
32
		back->flags |= Frepl;
33
		back->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
34
		memfillcolor(back, DBlack);
35
	}
36
 
37
	if(conscol == nil){
38
		conscol = allocmemimage(Rect(0,0,1,1), chan);	/* RSC BUG */
39
		if(conscol == nil)
40
			panic("conscol alloc");	/* RSC BUG */
41
		conscol->flags |= Frepl;
42
		conscol->clipr = Rect(-0x3FFFFFF, -0x3FFFFFF, 0x3FFFFFF, 0x3FFFFFF);
43
		memfillcolor(conscol, DWhite);
44
	}
45
}
46
 
47
static void
48
vgascroll(VGAscr* scr)
49
{
50
	int h, o;
51
	Point p;
52
	Rectangle r;
53
 
54
	h = scr->memdefont->height;
55
	o = 8*h;
56
	r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
57
	p = Pt(window.min.x, window.min.y+o);
58
	memimagedraw(scr->gscreen, r, scr->gscreen, p, nil, p, S);
59
	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
60
	memimagedraw(scr->gscreen, r, back, ZP, nil, ZP, S);
61
 
62
	curpos.y -= o;
63
}
64
 
65
static void
66
vgascreenputc(VGAscr* scr, char* buf, Rectangle *flushr)
67
{
68
	Point p;
69
	int h, w, pos;
70
	Rectangle r;
71
 
72
//	drawdebug = 1;
73
	if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
74
		xp = xbuf;
75
 
76
	h = scr->memdefont->height;
77
	switch(buf[0]){
78
 
79
	case '\n':
80
		if(curpos.y+h >= window.max.y){
81
			vgascroll(scr);
82
			*flushr = window;
83
		}
84
		curpos.y += h;
85
		vgascreenputc(scr, "\r", flushr);
86
		break;
87
 
88
	case '\r':
89
		xp = xbuf;
90
		curpos.x = window.min.x;
91
		break;
92
 
93
	case '\t':
94
		p = memsubfontwidth(scr->memdefont, " ");
95
		w = p.x;
96
		if(curpos.x >= window.max.x-4*w)
97
			vgascreenputc(scr, "\n", flushr);
98
 
99
		pos = (curpos.x-window.min.x)/w;
100
		pos = 4-(pos%4);
101
		*xp++ = curpos.x;
102
		r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
103
		memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
104
		curpos.x += pos*w;
105
		break;
106
 
107
	case '\b':
108
		if(xp <= xbuf)
109
			break;
110
		xp--;
111
		r = Rect(*xp, curpos.y, curpos.x, curpos.y+h);
112
		memimagedraw(scr->gscreen, r, back, back->r.min, nil, ZP, S);
113
		combinerect(flushr, r);
114
		curpos.x = *xp;
115
		break;
116
 
117
	case '\0':
118
		break;
119
 
120
	default:
121
		p = memsubfontwidth(scr->memdefont, buf);
122
		w = p.x;
123
 
124
		if(curpos.x >= window.max.x-w)
125
			vgascreenputc(scr, "\n", flushr);
126
 
127
		*xp++ = curpos.x;
128
		r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y+h);
129
		memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
130
		memimagestring(scr->gscreen, curpos, conscol, ZP, scr->memdefont, buf);
131
		combinerect(flushr, r);
132
		curpos.x += w;
133
	}
134
//	drawdebug = 0;
135
}
136
 
137
static void
138
vgascreenputs(char* s, int n)
139
{
140
	int i, gotdraw;
141
	Rune r;
142
	char buf[4];
143
	VGAscr *scr;
144
	Rectangle flushr;
145
 
146
	scr = &vgascreen[0];
147
 
148
	if(!islo()){
149
		/*
150
		 * Don't deadlock trying to
151
		 * print in an interrupt.
152
		 */
153
		if(!canlock(&vgascreenlock))
154
			return;
155
	}
156
	else
157
		lock(&vgascreenlock);
158
 
159
	/*
160
	 * Be nice to hold this, but not going to deadlock
161
	 * waiting for it.  Just try and see.
162
	 */
163
	gotdraw = canqlock(&drawlock);
164
 
165
	flushr = Rect(10000, 10000, -10000, -10000);
166
 
167
	while(n > 0){
168
		i = chartorune(&r, s);
169
		if(i == 0){
170
			s++;
171
			--n;
172
			continue;
173
		}
174
		memmove(buf, s, i);
175
		buf[i] = 0;
176
		n -= i;
177
		s += i;
178
		vgascreenputc(scr, buf, &flushr);
179
	}
180
	flushmemscreen(flushr);
181
 
182
	if(gotdraw)
183
		qunlock(&drawlock);
184
	unlock(&vgascreenlock);
185
}
186
 
187
void
188
vgascreenwin(VGAscr* scr)
189
{
190
	int h, w;
191
 
192
	h = scr->memdefont->height;
193
	w = scr->memdefont->info[' '].width;
194
 
195
	window = insetrect(scr->gscreen->r, 48);
196
	window.max.x = window.min.x+((window.max.x-window.min.x)/w)*w;
197
	window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
198
	curpos = window.min;
199
 
200
	screenputs = vgascreenputs;
201
}
202
 
203
/*
204
 * Supposedly this is the way to turn DPMS
205
 * monitors off using just the VGA registers.
206
 * Unfortunately, it seems to mess up the video mode
207
 * on the cards I've tried.
208
 */
209
void
210
vgablank(VGAscr*, int blank)
211
{
212
	uchar seq1, crtc17;
213
 
214
	if(blank) {
215
		seq1 = 0x00;
216
		crtc17 = 0x80;
217
	} else {
218
		seq1 = 0x20;
219
		crtc17 = 0x00;
220
	}
221
 
222
	outs(Seqx, 0x0100);			/* synchronous reset */
223
	seq1 |= vgaxi(Seqx, 1) & ~0x20;
224
	vgaxo(Seqx, 1, seq1);
225
	crtc17 |= vgaxi(Crtx, 0x17) & ~0x80;
226
	delay(10);
227
	vgaxo(Crtx, 0x17, crtc17);
228
	outs(Crtx, 0x0300);				/* end synchronous reset */
229
}
230
 
231
void
232
addvgaseg(char *name, ulong pa, ulong size)
233
{
234
	Physseg seg;
235
 
236
	memset(&seg, 0, sizeof seg);
237
	seg.attr = SG_PHYSICAL;
238
	seg.name = name;
239
	seg.pa = pa;
240
	seg.size = size;
241
	addphysseg(&seg);
242
}
243
 
244
void
245
cornerstring(char *s)
246
{
247
	int h, w;
248
	VGAscr *scr;
249
	Rectangle r;
250
	Point p;
251
 
252
	scr = &vgascreen[0];
253
	if(scr->vaddr == nil || screenputs != vgascreenputs)
254
		return;
255
	p = memsubfontwidth(scr->memdefont, s);
256
	w = p.x;
257
	h = scr->memdefont->height;
258
 
259
	r = Rect(0, 0, w, h);
260
	memimagedraw(scr->gscreen, r, back, back->r.min, nil, back->r.min, S);
261
	memimagestring(scr->gscreen, r.min, conscol, ZP, scr->memdefont, s);
262
//	flushmemscreen(r);
263
}