1 #include <u.h> 2 #include <libc.h> 3 #include "compat.h" 4 #include "kbd.h" 5 #include "error.h" 6 7 #define Image IMAGE 8 #include <draw.h> 9 #include <memdraw.h> 10 #include <cursor.h> 11 #include "screen.h" 12 13 enum 14 { 15 CURSORDIM = 16 16 }; 17 18 Memimage *gscreen; 19 Point ZP; 20 int cursorver; 21 Point cursorpos; 22 23 static Memimage *back; 24 static Memimage *conscol; 25 static Memimage *curscol; 26 static Point curpos; 27 static Memsubfont *memdefont; 28 static Rectangle flushr; 29 static Rectangle window; 30 static int h; 31 static int w; 32 33 static Rectangle cursorr; 34 static Point offscreen; 35 static uchar cursset[CURSORDIM*CURSORDIM/8]; 36 static uchar cursclr[CURSORDIM*CURSORDIM/8]; 37 static int cursdrawvers = -1; 38 static Memimage *cursorset; 39 static Memimage *cursorclear; 40 static Cursor screencursor; 41 42 Cursor arrow = { 43 { -1, -1 }, 44 { 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C, 45 0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04, 46 0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04, 47 0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40, 48 }, 49 { 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0, 50 0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8, 51 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8, 52 0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00, 53 }, 54 }; 55 56 void 57 screeninit(int x, int y, char *chanstr) 58 { 59 Point p, q; 60 char *greet; 61 char buf[128]; 62 Memimage *grey; 63 Rectangle r; 64 int chan; 65 66 cursorver = 0; 67 68 memimageinit(); 69 chan = strtochan(chanstr); 70 if(chan == 0) 71 error("bad screen channel string"); 72 73 r = Rect(0, 0, x, y); 74 gscreen = allocmemimage(r, chan); 75 if(gscreen == nil){ 76 snprint(buf, sizeof buf, "can't allocate screen image: %r"); 77 error(buf); 78 } 79 80 offscreen = Pt(x + 100, y + 100); 81 cursorr = Rect(0, 0, CURSORDIM, CURSORDIM); 82 cursorset = allocmemimage(cursorr, GREY8); 83 cursorclear = allocmemimage(cursorr, GREY1); 84 if(cursorset == nil || cursorclear == nil){ 85 freememimage(gscreen); 86 freememimage(cursorset); 87 freememimage(cursorclear); 88 gscreen = nil; 89 cursorset = nil; 90 cursorclear = nil; 91 snprint(buf, sizeof buf, "can't allocate cursor images: %r"); 92 error(buf); 93 } 94 95 drawlock(); 96 97 /* 98 * set up goo for screenputs 99 */ 100 memdefont = getmemdefont(); 101 102 back = memwhite; 103 conscol = memblack; 104 105 /* a lot of work to get a grey color */ 106 curscol = allocmemimage(Rect(0,0,1,1), RGBA32); 107 curscol->flags |= Frepl; 108 curscol->clipr = gscreen->r; 109 memfillcolor(curscol, 0xff0000ff); 110 111 memfillcolor(gscreen, 0x444488FF); 112 113 w = memdefont->info[' '].width; 114 h = memdefont->height; 115 116 window.min = addpt(gscreen->r.min, Pt(20,20)); 117 window.max.x = window.min.x + Dx(gscreen->r)*3/4-40; 118 window.max.y = window.min.y + Dy(gscreen->r)*3/4-100; 119 120 memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S); 121 window = insetrect(window, 4); 122 memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S); 123 124 /* a lot of work to get a grey color */ 125 grey = allocmemimage(Rect(0,0,1,1), CMAP8); 126 grey->flags |= Frepl; 127 grey->clipr = gscreen->r; 128 memfillcolor(grey, 0xAAAAAAFF); 129 memimagedraw(gscreen, Rect(window.min.x, window.min.y, 130 window.max.x, window.min.y+h+5+6), grey, ZP, nil, ZP, S); 131 freememimage(grey); 132 window = insetrect(window, 5); 133 134 greet = " Plan 9 Console "; 135 p = addpt(window.min, Pt(10, 0)); 136 q = memsubfontwidth(memdefont, greet); 137 memimagestring(gscreen, p, conscol, ZP, memdefont, greet); 138 window.min.y += h+6; 139 curpos = window.min; 140 window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h; 141 flushmemscreen(gscreen->r); 142 143 drawunlock(); 144 145 setcursor(&arrow); 146 } 147 148 uchar* 149 attachscreen(Rectangle* r, ulong* chan, int* d, int* width, int *softscreen) 150 { 151 *r = gscreen->r; 152 *d = gscreen->depth; 153 *chan = gscreen->chan; 154 *width = gscreen->width; 155 *softscreen = 1; 156 157 return gscreen->data->bdata; 158 } 159 160 void 161 getcolor(ulong , ulong* pr, ulong* pg, ulong* pb) 162 { 163 *pr = 0; 164 *pg = 0; 165 *pb = 0; 166 } 167 168 int 169 setcolor(ulong , ulong , ulong , ulong ) 170 { 171 return 0; 172 } 173 174 /* 175 * called with cursor unlocked, drawlock locked 176 */ 177 void 178 cursordraw(Memimage *dst, Rectangle r) 179 { 180 static uchar set[CURSORDIM*CURSORDIM], clr[CURSORDIM*CURSORDIM/8]; 181 static int ver = -1; 182 int i, j, n; 183 184 lock(&cursor); 185 if(ver != cursorver){ 186 n = 0; 187 for(i = 0; i < CURSORDIM*CURSORDIM/8; i += CURSORDIM/8){ 188 for(j = 0; j < CURSORDIM; j++){ 189 if(cursset[i + (j >> 3)] & (1 << (7 - (j & 7)))) 190 set[n] = 0xaa; 191 else 192 set[n] = 0; 193 n++; 194 } 195 } 196 memmove(clr, cursclr, CURSORDIM*CURSORDIM/8); 197 ver = cursorver; 198 unlock(&cursor); 199 loadmemimage(cursorset, cursorr, set, CURSORDIM*CURSORDIM); 200 loadmemimage(cursorclear, cursorr, clr, CURSORDIM*CURSORDIM/8); 201 }else 202 unlock(&cursor); 203 memimagedraw(dst, r, memwhite, ZP, cursorclear, ZP, SoverD); 204 memimagedraw(dst, r, curscol, ZP, cursorset, ZP, SoverD); 205 } 206 207 /* 208 * called with cursor locked, drawlock possibly unlocked 209 */ 210 Rectangle 211 cursorrect(void) 212 { 213 Rectangle r; 214 215 r.min.x = cursorpos.x + cursor.offset.x; 216 r.min.y = cursorpos.y + cursor.offset.y; 217 r.max.x = r.min.x + CURSORDIM; 218 r.max.y = r.min.y + CURSORDIM; 219 return r; 220 } 221 222 /* 223 * called with cursor locked, drawlock possibly unlocked 224 */ 225 void 226 setcursor(Cursor* curs) 227 { 228 cursorver++; 229 memmove(cursset, curs->set, CURSORDIM*CURSORDIM/8); 230 memmove(cursclr, curs->clr, CURSORDIM*CURSORDIM/8); 231 } 232 233 int 234 cursoron(int dolock) 235 { 236 if(dolock) 237 lock(&cursor); 238 cursorpos = mousexy(); 239 if(dolock) 240 unlock(&cursor); 241 242 return 0; 243 } 244 245 void 246 cursoroff(int dolock) 247 { 248 if(dolock) 249 lock(&cursor); 250 cursorpos = offscreen; 251 if(dolock) 252 unlock(&cursor); 253 } 254 255 void 256 blankscreen(int blank) 257 { 258 USED(blank); 259 } 260 261 static void 262 screenflush(void) 263 { 264 flushmemscreen(flushr); 265 flushr = Rect(10000, 10000, -10000, -10000); 266 } 267 268 static void 269 addflush(Rectangle r) 270 { 271 if(flushr.min.x >= flushr.max.x) 272 flushr = r; 273 else 274 combinerect(&flushr, r); 275 } 276 277 static void 278 scroll(void) 279 { 280 int o; 281 Point p; 282 Rectangle r; 283 284 o = 8*h; 285 r = Rpt(window.min, Pt(window.max.x, window.max.y-o)); 286 p = Pt(window.min.x, window.min.y+o); 287 memimagedraw(gscreen, r, gscreen, p, nil, p, S); 288 r = Rpt(Pt(window.min.x, window.max.y-o), window.max); 289 memimagedraw(gscreen, r, back, ZP, nil, ZP, S); 290 flushmemscreen(gscreen->r); 291 292 curpos.y -= o; 293 } 294 295 static void 296 screenputc(char *buf) 297 { 298 Point p; 299 int w, pos; 300 Rectangle r; 301 static int *xp; 302 static int xbuf[256]; 303 304 if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)]) 305 xp = xbuf; 306 307 switch(buf[0]){ 308 case '\n': 309 if(curpos.y+h >= window.max.y) 310 scroll(); 311 curpos.y += h; 312 screenputc("\r"); 313 break; 314 case '\r': 315 xp = xbuf; 316 curpos.x = window.min.x; 317 break; 318 case '\t': 319 p = memsubfontwidth(memdefont, " "); 320 w = p.x; 321 *xp++ = curpos.x; 322 pos = (curpos.x-window.min.x)/w; 323 pos = 8-(pos%8); 324 r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h); 325 memimagedraw(gscreen, r, back, back->r.min, memopaque, ZP, S); 326 addflush(r); 327 curpos.x += pos*w; 328 break; 329 case '\b': 330 if(xp <= xbuf) 331 break; 332 xp--; 333 r = Rect(*xp, curpos.y, curpos.x, curpos.y + h); 334 memimagedraw(gscreen, r, back, back->r.min, memopaque, ZP, S); 335 addflush(r); 336 curpos.x = *xp; 337 break; 338 default: 339 p = memsubfontwidth(memdefont, buf); 340 w = p.x; 341 342 if(curpos.x >= window.max.x-w) 343 screenputc("\n"); 344 345 *xp++ = curpos.x; 346 r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h); 347 memimagedraw(gscreen, r, back, back->r.min, memopaque, ZP, S); 348 memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf); 349 addflush(r); 350 curpos.x += w; 351 } 352 } 353 354 void 355 screenputs(char *s, int n) 356 { 357 int i; 358 Rune r; 359 char buf[4]; 360 361 drawlock(); 362 while(n > 0){ 363 i = chartorune(&r, s); 364 if(i == 0){ 365 s++; 366 --n; 367 continue; 368 } 369 memmove(buf, s, i); 370 buf[i] = 0; 371 n -= i; 372 s += i; 373 screenputc(buf); 374 } 375 screenflush(); 376 drawunlock(); 377 } 378