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