screen.c 7.4 KB

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