screen.c 7.3 KB

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