/cui/buffer.d

http://github.com/wilkie/djehuty · D · 423 lines · 299 code · 103 blank · 21 comment · 35 complexity · 34095ff2ab288cd6b5be6dba48b93ff6 MD5 · raw file

  1. module cui.buffer;
  2. import djehuty;
  3. import data.list;
  4. import synch.semaphore;
  5. import io.console;
  6. import cui.widget;
  7. // Section: Console
  8. // Description: This console control is a line buffer that is similar to having a terminal inside a terminal. It is basically a terminal window. Extending this class will allow for other types of terminals and emulations. For instance, the VT100 control is a buffer control with VT100 ANSI emulation.
  9. class CuiBuffer : CuiWidget
  10. {
  11. this( uint x, uint y, uint width, uint height)
  12. {
  13. _drawLock = new Semaphore(1);
  14. _x = x;
  15. _y = y;
  16. _r = _x + width;
  17. _b = _y + height;
  18. _w = width;
  19. _h = height;
  20. _buffer = new List!(BufferLine)();
  21. for (uint i; i<_h; i++) {
  22. BufferLine bf = new BufferLine;
  23. bf.line = new emptyChar[width];
  24. bf.bgclr = new Color[width];
  25. bf.fgclr = new Color[width];
  26. _buffer.add(bf);
  27. }
  28. position(0,0);
  29. }
  30. override void onKeyChar(dchar chr)
  31. {
  32. static char lastchr;
  33. if (chr == 10)
  34. {
  35. if (lastchr != 13)
  36. {
  37. chr = 13;
  38. }
  39. }
  40. if (chr == 8)
  41. {
  42. if (_curx != _x)
  43. {
  44. position((_curx-_x)-1, (_cury-_y));
  45. writeChar(' ');
  46. position((_curx-_x)-1, (_cury-_y));
  47. }
  48. else
  49. {
  50. position(_w-1, (_cury-_y)-1);
  51. writeChar(' ');
  52. position(_w-1, (_cury-_y)-1);
  53. }
  54. }
  55. else if (chr == 13)
  56. {
  57. if (_cury + 1 == _b)
  58. {
  59. _linefeed();
  60. position(0, (_cury-_y));
  61. }
  62. else
  63. {
  64. position(0, (_cury-_y)+1);
  65. }
  66. }
  67. else
  68. {
  69. writeChar(chr);
  70. }
  71. lastchr = chr;
  72. }
  73. override void onAdd()
  74. {
  75. }
  76. override void onInit()
  77. {
  78. redraw();
  79. }
  80. override void onMouseWheelY(int amt)
  81. {
  82. // + amt : subtract from _firstVisible
  83. // - amt : add to _firstVisible
  84. amt *= 5;
  85. uint _oldFV = _firstVisible;
  86. if (amt > 0 && amt > _firstVisible)
  87. {
  88. _firstVisible = 0;
  89. }
  90. else
  91. {
  92. _firstVisible -= amt;
  93. }
  94. if (_firstVisible > _buffer.length() - _h)
  95. {
  96. _firstVisible = _buffer.length() - _h;
  97. }
  98. if (_oldFV != _firstVisible)
  99. {
  100. redraw();
  101. }
  102. }
  103. override void onDraw() {
  104. _drawLock.down();
  105. Console.position(0,30);
  106. Console.put("a ", _curx, " ", _cury);
  107. // Blank out the space of the buffer
  108. uint curx = 0;
  109. uint cury = _firstVisible;
  110. Color fgclr;
  111. Color bgclr;
  112. fgclr = _buffer[cury].fgclr[0];
  113. bgclr = _buffer[cury].bgclr[0];
  114. Console.forecolor = fgclr;
  115. Console.backcolor = bgclr;
  116. BufferLine bf;
  117. for (uint y = _y; y < _b; y++, cury++) {
  118. Console.position(0,30);
  119. Console.put("y ", _curx, " ", _cury);
  120. Console.position(_x, y);
  121. bf = _buffer[cury];
  122. curx = 0;
  123. for (curx = 0; curx < _w; curx++) {
  124. if (bf.fgclr[curx] != fgclr || bf.bgclr[curx] != bgclr) {
  125. Console.forecolor = bf.fgclr[curx];
  126. Console.backcolor = bf.bgclr[curx];
  127. fgclr = bf.fgclr[curx];
  128. bgclr = bf.bgclr[curx];
  129. }
  130. Console.put(bf.line[curx]);
  131. }
  132. }
  133. _drawLock.up();
  134. }
  135. void redraw() {
  136. onDraw();
  137. }
  138. // Methods
  139. void forecolor(Color fgclr) {
  140. _drawLock.down();
  141. _curfg = fgclr;
  142. _drawLock.up();
  143. }
  144. void backcolor(Color bgclr) {
  145. _drawLock.down();
  146. _curbg = bgclr;
  147. _drawLock.up();
  148. }
  149. void setColors(Color fgclr, Color bgclr) {
  150. _drawLock.down();
  151. _curfg = fgclr;
  152. _curbg = bgclr;
  153. _drawLock.up();
  154. }
  155. void writeChar(dchar chr) {
  156. static int a = 0;
  157. Console.position((a * 10),29);
  158. Console.put(_curx, " ", _cury);
  159. if (_cury >= _b)
  160. {
  161. _linefeed();
  162. Console.position((a * 10),29);
  163. Console.put("lf: ", _curx, " ", _cury);
  164. }
  165. a++;
  166. a %= 3;
  167. _drawLock.down();
  168. Console.position(_curx, _cury);
  169. Console.forecolor = _curfg;
  170. Console.backcolor = _curbg;
  171. Console.put(chr);
  172. uint idx_y = (_cury-_y)+_firstVisible;
  173. uint idx_x = (_curx-_x);
  174. _buffer[idx_y].line[idx_x] = cast(emptyChar)chr;
  175. _buffer[idx_y].bgclr[idx_x] = _curbg;
  176. _buffer[idx_y].fgclr[idx_x] = _curfg;
  177. _curx++;
  178. _drawLock.up();
  179. if (_curx == _r)
  180. {
  181. Console.position((a * 10),29);
  182. Console.put("lf: ", _curx, " ", _cury);
  183. _linefeed();
  184. Console.position((a * 10),29);
  185. Console.put("af: ", _curx, " ", _cury);
  186. }
  187. }
  188. void writeChar(uint x, uint y, dchar chr)
  189. {
  190. _drawLock.down();
  191. _buffer[y].line[x] = cast(emptyChar)chr;
  192. _buffer[y].bgclr[x] = _curbg;
  193. _buffer[y].fgclr[x] = _curfg;
  194. Console.position(x+_x, y+_y);
  195. Console.forecolor = _curfg;
  196. Console.backcolor = _curbg;
  197. Console.put(chr);
  198. _drawLock.up();
  199. }
  200. void position(uint x, uint y)
  201. {
  202. _drawLock.down();
  203. _curx = x + _x;
  204. _cury = y + _y;
  205. if (_curx >= _r)
  206. {
  207. _curx = _r-1;
  208. }
  209. if (_cury >= _b)
  210. {
  211. _cury = _b-1;
  212. }
  213. Console.position(_curx, _cury);
  214. _drawLock.up();
  215. }
  216. void setRelative(int x, int y)
  217. {
  218. uint new_x = (_curx-_x) + x;
  219. uint new_y = (_cury-_y) + y;
  220. position(new_x, new_y);
  221. }
  222. void getPosition(out uint x, out uint y)
  223. {
  224. x = _curx - _x;
  225. y = _cury - _y;
  226. }
  227. protected:
  228. void _linefeed() {
  229. Console.position((4 * 10),29);
  230. Console.put("af: ", _curx, " ", _cury);
  231. _drawLock.down();
  232. bool needRedraw = false;
  233. // met right edge; goto next line
  234. // linefeed
  235. _cury++;
  236. while (_cury >= _b) {
  237. Console.position((4 * 10),29);
  238. Console.put("bf: ", _curx, " ", _cury);
  239. // we have reached the bottom
  240. // we have to move the first line
  241. // to the buffer
  242. BufferLine bl;
  243. for(uint i=0; i<_linesToScroll;i++) {
  244. bl = null;
  245. while (bl is null) {
  246. bl = new BufferLine();
  247. }
  248. Console.position((4 * 10),29);
  249. Console.put("ef: ", _curx, " ", _cury);
  250. bl.fgclr = new Color[_w];
  251. Console.position((4 * 10),29);
  252. Console.put("ff: ", _curx, " ", _cury);
  253. bl.bgclr = new Color[_w];
  254. Console.position((4 * 10),29);
  255. Console.put("df: ", _curx, " ", _cury);
  256. bl.line = new emptyChar[_w];
  257. Console.position((4 * 10),29);
  258. Console.put("gf: ", _curx, " ", _cury);
  259. _buffer.add(bl);
  260. Console.position((4 * 10),29);
  261. Console.put("hf: ", _curx, " ", _cury);
  262. }
  263. Console.position((4 * 10),29);
  264. Console.put("cf: ", _curx, " ", _cury);
  265. _firstVisible += _linesToScroll;
  266. // redraw the entire view
  267. needRedraw = true;
  268. // position ourselves at the new
  269. // line, which is just the previous
  270. // line again
  271. _cury -= _linesToScroll;
  272. }
  273. // carriage return
  274. _curx=_x;
  275. _drawLock.up();
  276. if (needRedraw) { redraw(); }
  277. }
  278. void _screenfeed()
  279. {
  280. _drawLock.down();
  281. // we have reached the bottom
  282. // we have to move the first line
  283. // to the buffer
  284. for(uint i=0; i<_h;i++)
  285. {
  286. BufferLine bl = new BufferLine();
  287. bl.line = new emptyChar[_w];
  288. bl.fgclr = new Color[_w];
  289. bl.bgclr = new Color[_w];
  290. _buffer.add(bl);
  291. }
  292. _firstVisible += _h;
  293. // go home
  294. _cury = _y;
  295. _curx = _x;
  296. _drawLock.up();
  297. redraw();
  298. }
  299. uint _x = 0;
  300. uint _y = 0;
  301. uint _r = 0;
  302. uint _b = 0;
  303. uint _w = 0;
  304. uint _h = 0;
  305. typedef dchar emptyChar = ' ';
  306. // keep a line buffer of previous lines, for scrollback, etc
  307. class BufferLine {
  308. emptyChar[] line = null;
  309. Color[] fgclr = null;
  310. Color[] bgclr = null;
  311. }
  312. List!(BufferLine) _buffer;
  313. uint _firstVisible; // first line visible
  314. Color _curfg = Color.White;
  315. Color _curbg = Color.Gray;
  316. uint _curx;
  317. uint _cury;
  318. uint _linesToScroll = 7;
  319. Semaphore _drawLock;
  320. }