screen.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include "compat.h"
  12. #include "kbd.h"
  13. #include "error.h"
  14. #define Image IMAGE
  15. #include <draw.h>
  16. #include <memdraw.h>
  17. #include <cursor.h>
  18. #include "screen.h"
  19. enum
  20. {
  21. CURSORDIM = 16
  22. };
  23. Memimage *gscreen;
  24. Point ZP;
  25. int cursorver;
  26. Point cursorpos;
  27. static Memimage *back;
  28. static Memimage *conscol;
  29. static Memimage *curscol;
  30. static Point curpos;
  31. static Memsubfont *memdefont;
  32. static Rectangle flushr;
  33. static Rectangle window;
  34. static int h;
  35. static int w;
  36. static Rectangle cursorr;
  37. static Point offscreen;
  38. static uint8_t cursset[CURSORDIM*CURSORDIM/8];
  39. static uint8_t cursclr[CURSORDIM*CURSORDIM/8];
  40. static Memimage *cursorset;
  41. static Memimage *cursorclear;
  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. void
  56. screeninit(int x, int y, char *chanstr)
  57. {
  58. Point p, q;
  59. char *greet;
  60. char buf[128];
  61. Memimage *grey;
  62. Rectangle r;
  63. int chan;
  64. cursorver = 0;
  65. memimageinit();
  66. chan = strtochan(chanstr);
  67. if(chan == 0)
  68. error("bad screen channel string");
  69. r = Rect(0, 0, x, y);
  70. gscreen = allocmemimage(r, chan);
  71. if(gscreen == nil){
  72. snprint(buf, sizeof buf, "can't allocate screen image: %r");
  73. error(buf);
  74. }
  75. offscreen = Pt(x + 100, y + 100);
  76. cursorr = Rect(0, 0, CURSORDIM, CURSORDIM);
  77. cursorset = allocmemimage(cursorr, GREY8);
  78. cursorclear = allocmemimage(cursorr, GREY1);
  79. if(cursorset == nil || cursorclear == nil){
  80. freememimage(gscreen);
  81. freememimage(cursorset);
  82. freememimage(cursorclear);
  83. gscreen = nil;
  84. cursorset = nil;
  85. cursorclear = nil;
  86. snprint(buf, sizeof buf, "can't allocate cursor images: %r");
  87. error(buf);
  88. }
  89. drawlock();
  90. /*
  91. * set up goo for screenputs
  92. */
  93. memdefont = getmemdefont();
  94. back = memwhite;
  95. conscol = memblack;
  96. /* a lot of work to get a grey color */
  97. curscol = allocmemimage(Rect(0,0,1,1), RGBA32);
  98. curscol->flags |= Frepl;
  99. curscol->clipr = gscreen->r;
  100. memfillcolor(curscol, 0xff0000ff);
  101. memfillcolor(gscreen, 0x444488FF);
  102. w = memdefont->info[' '].width;
  103. h = memdefont->height;
  104. window.min = addpt(gscreen->r.min, Pt(20,20));
  105. window.max.x = window.min.x + Dx(gscreen->r)*3/4-40;
  106. window.max.y = window.min.y + Dy(gscreen->r)*3/4-100;
  107. memimagedraw(gscreen, window, memblack, ZP, memopaque, ZP, S);
  108. window = insetrect(window, 4);
  109. memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
  110. /* a lot of work to get a grey color */
  111. grey = allocmemimage(Rect(0,0,1,1), CMAP8);
  112. grey->flags |= Frepl;
  113. grey->clipr = gscreen->r;
  114. memfillcolor(grey, 0xAAAAAAFF);
  115. memimagedraw(gscreen, Rect(window.min.x, window.min.y,
  116. window.max.x, window.min.y+h+5+6), grey, ZP, nil, ZP, S);
  117. freememimage(grey);
  118. window = insetrect(window, 5);
  119. greet = " Plan 9 Console ";
  120. p = addpt(window.min, Pt(10, 0));
  121. q = memsubfontwidth(memdefont, greet);
  122. memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
  123. window.min.y += h+6;
  124. curpos = window.min;
  125. window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h;
  126. flushmemscreen(gscreen->r);
  127. drawunlock();
  128. setcursor(&arrow);
  129. USED(q);
  130. }
  131. uint8_t*
  132. attachscreen(Rectangle* r, uint32_t* chan, int* d, int* width,
  133. int *softscreen)
  134. {
  135. *r = gscreen->r;
  136. *d = gscreen->depth;
  137. *chan = gscreen->chan;
  138. *width = gscreen->width;
  139. *softscreen = 1;
  140. return gscreen->data->bdata;
  141. }
  142. void
  143. getcolor(uint32_t i, uint32_t* pr, uint32_t* pg, uint32_t* pb)
  144. {
  145. *pr = 0;
  146. *pg = 0;
  147. *pb = 0;
  148. }
  149. int
  150. setcolor(uint32_t i, uint32_t n, uint32_t t, uint32_t u)
  151. {
  152. return 0;
  153. }
  154. /*
  155. * called with cursor unlocked, drawlock locked
  156. */
  157. void
  158. cursordraw(Memimage *dst, Rectangle r)
  159. {
  160. static uint8_t set[CURSORDIM*CURSORDIM], clr[CURSORDIM*CURSORDIM/8];
  161. static int ver = -1;
  162. int i, j, n;
  163. lock(&cursor.lock);
  164. if(ver != cursorver){
  165. n = 0;
  166. for(i = 0; i < CURSORDIM*CURSORDIM/8; i += CURSORDIM/8){
  167. for(j = 0; j < CURSORDIM; j++){
  168. if(cursset[i + (j >> 3)] & (1 << (7 - (j & 7))))
  169. set[n] = 0xaa;
  170. else
  171. set[n] = 0;
  172. n++;
  173. }
  174. }
  175. memmove(clr, cursclr, CURSORDIM*CURSORDIM/8);
  176. ver = cursorver;
  177. unlock(&cursor.lock);
  178. loadmemimage(cursorset, cursorr, set, CURSORDIM*CURSORDIM);
  179. loadmemimage(cursorclear, cursorr, clr, CURSORDIM*CURSORDIM/8);
  180. }else
  181. unlock(&cursor.lock);
  182. memimagedraw(dst, r, memwhite, ZP, cursorclear, ZP, SoverD);
  183. memimagedraw(dst, r, curscol, ZP, cursorset, ZP, SoverD);
  184. }
  185. /*
  186. * called with cursor locked, drawlock possibly unlocked
  187. */
  188. Rectangle
  189. cursorrect(void)
  190. {
  191. Rectangle r;
  192. r.min.x = cursorpos.x + cursor.cursor.offset.x;
  193. r.min.y = cursorpos.y + cursor.cursor.offset.y;
  194. r.max.x = r.min.x + CURSORDIM;
  195. r.max.y = r.min.y + CURSORDIM;
  196. return r;
  197. }
  198. /*
  199. * called with cursor locked, drawlock possibly unlocked
  200. */
  201. void
  202. setcursor(Cursor* curs)
  203. {
  204. cursorver++;
  205. memmove(cursset, curs->set, CURSORDIM*CURSORDIM/8);
  206. memmove(cursclr, curs->clr, CURSORDIM*CURSORDIM/8);
  207. }
  208. int
  209. cursoron(int dolock)
  210. {
  211. if(dolock)
  212. lock(&cursor.lock);
  213. cursorpos = mousexy();
  214. if(dolock)
  215. unlock(&cursor.lock);
  216. return 0;
  217. }
  218. void
  219. cursoroff(int dolock)
  220. {
  221. if(dolock)
  222. lock(&cursor.lock);
  223. cursorpos = offscreen;
  224. if(dolock)
  225. unlock(&cursor.lock);
  226. }
  227. void
  228. blankscreen(int blank)
  229. {
  230. USED(blank);
  231. }
  232. static void
  233. screenflush(void)
  234. {
  235. flushmemscreen(flushr);
  236. flushr = Rect(10000, 10000, -10000, -10000);
  237. }
  238. static void
  239. addflush(Rectangle r)
  240. {
  241. if(flushr.min.x >= flushr.max.x)
  242. flushr = r;
  243. else
  244. combinerect(&flushr, r);
  245. }
  246. static void
  247. scroll(void)
  248. {
  249. int o;
  250. Point p;
  251. Rectangle r;
  252. o = 8*h;
  253. r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
  254. p = Pt(window.min.x, window.min.y+o);
  255. memimagedraw(gscreen, r, gscreen, p, nil, p, S);
  256. r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
  257. memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
  258. flushmemscreen(gscreen->r);
  259. curpos.y -= o;
  260. }
  261. static void
  262. screenputc(char *buf)
  263. {
  264. Point p;
  265. int w, pos;
  266. Rectangle r;
  267. static int *xp;
  268. static int xbuf[256];
  269. /* This just hasn't any sense, checking if it's smaller
  270. * or more or equal to the size of an array guessing it's full.
  271. * I think there was an age in what the size of an array was the number
  272. * of its elements...
  273. * Compiler: error: array index 1024 is past the end of the array
  274. * if(xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
  275. */
  276. if(xp < xbuf || xp >= xbuf)
  277. xp = xbuf;
  278. switch(buf[0]){
  279. case '\n':
  280. if(curpos.y+h >= window.max.y)
  281. scroll();
  282. curpos.y += h;
  283. screenputc("\r");
  284. break;
  285. case '\r':
  286. xp = xbuf;
  287. curpos.x = window.min.x;
  288. break;
  289. case '\t':
  290. p = memsubfontwidth(memdefont, " ");
  291. w = p.x;
  292. *xp++ = curpos.x;
  293. pos = (curpos.x-window.min.x)/w;
  294. pos = 8-(pos%8);
  295. r = Rect(curpos.x, curpos.y, curpos.x+pos*w, curpos.y + h);
  296. memimagedraw(gscreen, r, back, back->r.min, memopaque, ZP, S);
  297. addflush(r);
  298. curpos.x += pos*w;
  299. break;
  300. case '\b':
  301. if(xp <= xbuf)
  302. break;
  303. xp--;
  304. r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
  305. memimagedraw(gscreen, r, back, back->r.min, memopaque, ZP, S);
  306. addflush(r);
  307. curpos.x = *xp;
  308. break;
  309. default:
  310. p = memsubfontwidth(memdefont, buf);
  311. w = p.x;
  312. if(curpos.x >= window.max.x-w)
  313. screenputc("\n");
  314. *xp++ = curpos.x;
  315. r = Rect(curpos.x, curpos.y, curpos.x+w, curpos.y + h);
  316. memimagedraw(gscreen, r, back, back->r.min, memopaque, ZP, S);
  317. memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
  318. addflush(r);
  319. curpos.x += w;
  320. }
  321. }
  322. void
  323. screenputs(char *s, int n)
  324. {
  325. int i;
  326. Rune r;
  327. char buf[4];
  328. drawlock();
  329. while(n > 0){
  330. i = chartorune(&r, s);
  331. if(i == 0){
  332. s++;
  333. --n;
  334. continue;
  335. }
  336. memmove(buf, s, i);
  337. buf[i] = 0;
  338. n -= i;
  339. s += i;
  340. screenputc(buf);
  341. }
  342. screenflush();
  343. drawunlock();
  344. }