xref: /plan9/sys/src/cmd/unix/drawterm/kern/term.c (revision 8ccd4a6360d974db7bd7bbd4f37e7018419ea908)
1 #include	"u.h"
2 #include	"lib.h"
3 #include	"dat.h"
4 #include	"fns.h"
5 #include	"error.h"
6 
7 #include	<draw.h>
8 #include	<memdraw.h>
9 #include	"screen.h"
10 
11 #define	MINX	8
12 #define	Backgnd		0xFF	/* white */
13 
14 		Memsubfont	*memdefont;
15 
16 struct{
17 	Point	pos;
18 	int	bwid;
19 }out;
20 
21 Lock	screenlock;
22 
23 Memimage *conscol;
24 Memimage *back;
25 extern Memimage *gscreen;
26 
27 static Rectangle flushr;
28 static Rectangle window;
29 static Point curpos;
30 static int h;
31 static void	termscreenputs(char*, int);
32 
33 
34 static void
screenflush(void)35 screenflush(void)
36 {
37 	drawflushr(flushr);
38 	flushr = Rect(10000, 10000, -10000, -10000);
39 }
40 
41 static void
addflush(Rectangle r)42 addflush(Rectangle r)
43 {
44 	if(flushr.min.x >= flushr.max.x)
45 		flushr = r;
46 	else
47 		combinerect(&flushr, r);
48 }
49 
50 static void
screenwin(void)51 screenwin(void)
52 {
53 	Point p;
54 	char *greet;
55 	Memimage *grey;
56 
57 	drawqlock();
58 	back = memwhite;
59 	conscol = memblack;
60 	memfillcolor(gscreen, 0x444488FF);
61 
62 	h = memdefont->height;
63 
64 	window.min = addpt(gscreen->r.min, Pt(20,20));
65 	window.max.x = window.min.x + Dx(gscreen->r)*3/4-40;
66 	window.max.y = window.min.y + Dy(gscreen->r)*3/4-100;
67 
68 	memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S);
69 	window = insetrect(window, 4);
70 	memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
71 
72 	/* a lot of work to get a grey color */
73 	grey = allocmemimage(Rect(0,0,1,1), CMAP8);
74 	grey->flags |= Frepl;
75 	grey->clipr = gscreen->r;
76 	memfillcolor(grey, 0xAAAAAAFF);
77 	memimagedraw(gscreen, Rect(window.min.x, window.min.y,
78 			window.max.x, window.min.y+h+5+6), grey, ZP, nil, ZP, S);
79 	freememimage(grey);
80 	window = insetrect(window, 5);
81 
82 	greet = " Plan 9 Console ";
83 	p = addpt(window.min, Pt(10, 0));
84 	memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
85 	window.min.y += h+6;
86 	curpos = window.min;
87 	window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
88 	flushmemscreen(gscreen->r);
89 	drawqunlock();
90 }
91 
92 void
terminit(void)93 terminit(void)
94 {
95 	memdefont = getmemdefont();
96 	out.pos.x = MINX;
97 	out.pos.y = 0;
98 	out.bwid = memdefont->info[' '].width;
99 	screenwin();
100 	screenputs = termscreenputs;
101 }
102 
103 static void
scroll(void)104 scroll(void)
105 {
106 	int o;
107 	Point p;
108 	Rectangle r;
109 
110 	o = 8*h;
111 	r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
112 	p = Pt(window.min.x, window.min.y+o);
113 	memimagedraw(gscreen, r, gscreen, p, nil, p, S);
114 	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
115 	memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
116 	flushmemscreen(gscreen->r);
117 	curpos.y -= o;
118 }
119 
120 static void
screenputc(char * buf)121 screenputc(char *buf)
122 {
123 	Point p;
124 	int w, pos;
125 	Rectangle r;
126 	static int *xp;
127 	static int xbuf[256];
128 
129 	if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
130 		xp = xbuf;
131 
132 	switch(buf[0]) {
133 	case '\n':
134 		if(curpos.y+h >= window.max.y)
135 			scroll();
136 		curpos.y += h;
137 		screenputc("\r");
138 		break;
139 	case '\r':
140 		xp = xbuf;
141 		curpos.x = window.min.x;
142 		break;
143 	case '\t':
144 		p = memsubfontwidth(memdefont, " ");
145 		w = p.x;
146 		*xp++ = curpos.x;
147 		pos = (curpos.x-window.min.x)/w;
148 		pos = 8-(pos%8);
149 		r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
150 		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
151 		addflush(r);
152 		curpos.x += pos*w;
153 		break;
154 	case '\b':
155 		if(xp <= xbuf)
156 			break;
157 		xp--;
158 		r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
159 		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
160 		addflush(r);
161 		curpos.x = *xp;
162 		break;
163 	default:
164 		p = memsubfontwidth(memdefont, buf);
165 		w = p.x;
166 
167 		if(curpos.x >= window.max.x-w)
168 			screenputc("\n");
169 
170 		*xp++ = curpos.x;
171 		r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h);
172 		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
173 		memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
174 		addflush(r);
175 		curpos.x += w;
176 	}
177 }
178 
179 static void
termscreenputs(char * s,int n)180 termscreenputs(char *s, int n)
181 {
182 	int i, locked;
183 	Rune r;
184 	char buf[4];
185 
186 	lock(&screenlock);
187 	locked = drawcanqlock();
188 	while(n > 0){
189 		i = chartorune(&r, s);
190 		if(i == 0){
191 			s++;
192 			--n;
193 			continue;
194 		}
195 		memmove(buf, s, i);
196 		buf[i] = 0;
197 		n -= i;
198 		s += i;
199 		screenputc(buf);
200 	}
201 	if(locked)
202 		drawqunlock();
203 	screenflush();
204 	unlock(&screenlock);
205 }
206