PageRenderTime 56ms CodeModel.GetById 27ms app.highlight 25ms RepoModel.GetById 1ms app.codeStats 0ms

/cui/buffer.d

http://github.com/wilkie/djehuty
D | 423 lines | 299 code | 103 blank | 21 comment | 35 complexity | 34095ff2ab288cd6b5be6dba48b93ff6 MD5 | raw file
  1module cui.buffer;
  2
  3import djehuty;
  4
  5import data.list;
  6
  7import synch.semaphore;
  8
  9import io.console;
 10
 11import cui.widget;
 12
 13// Section: Console
 14
 15// 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.
 16class CuiBuffer : CuiWidget
 17{
 18	this( uint x, uint y, uint width, uint height)
 19	{
 20		_drawLock = new Semaphore(1);
 21
 22		_x = x;
 23		_y = y;
 24		_r = _x + width;
 25		_b = _y + height;
 26		_w = width;
 27		_h = height;
 28
 29		_buffer = new List!(BufferLine)();
 30
 31		for (uint i; i<_h; i++) {
 32			BufferLine bf = new BufferLine;
 33			bf.line = new emptyChar[width];
 34			bf.bgclr = new Color[width];
 35			bf.fgclr = new Color[width];
 36			_buffer.add(bf);
 37		}
 38
 39		position(0,0);
 40	}
 41
 42	override void onKeyChar(dchar chr)
 43	{
 44		static char lastchr;
 45
 46		if (chr == 10)
 47		{
 48			if (lastchr != 13)
 49			{
 50				chr = 13;
 51			}
 52		}
 53
 54		if (chr == 8)
 55		{
 56			if (_curx != _x)
 57			{
 58				position((_curx-_x)-1, (_cury-_y));
 59				writeChar(' ');
 60				position((_curx-_x)-1, (_cury-_y));
 61			}
 62			else
 63			{
 64				position(_w-1, (_cury-_y)-1);
 65				writeChar(' ');
 66				position(_w-1, (_cury-_y)-1);
 67			}
 68		}
 69		else if (chr == 13)
 70		{
 71			if (_cury + 1 == _b)
 72			{
 73				_linefeed();
 74				position(0, (_cury-_y));
 75			}
 76			else
 77			{
 78				position(0, (_cury-_y)+1);
 79			}
 80		}
 81		else
 82		{
 83			writeChar(chr);
 84		}
 85
 86		lastchr = chr;
 87	}
 88
 89	override void onAdd()
 90	{
 91	}
 92
 93	override void onInit()
 94	{
 95		redraw();
 96	}
 97
 98	override void onMouseWheelY(int amt)
 99	{
100		// + amt : subtract from _firstVisible
101		// - amt : add to _firstVisible
102
103		amt *= 5;
104
105		uint _oldFV = _firstVisible;
106
107		if (amt > 0 && amt > _firstVisible)
108		{
109			_firstVisible = 0;
110		}
111		else
112		{
113			_firstVisible -= amt;
114		}
115
116		if (_firstVisible > _buffer.length() - _h)
117		{
118			_firstVisible = _buffer.length() - _h;
119		}
120
121		if (_oldFV != _firstVisible)
122		{
123			redraw();
124		}
125	}
126	
127	override void onDraw() {
128		_drawLock.down();
129
130		Console.position(0,30);
131		Console.put("a ", _curx, " ", _cury);
132
133		// Blank out the space of the buffer
134		uint curx = 0;
135		uint cury = _firstVisible;
136
137		Color fgclr;
138		Color bgclr;
139
140		fgclr = _buffer[cury].fgclr[0];
141		bgclr = _buffer[cury].bgclr[0];
142
143		Console.forecolor = fgclr;
144		Console.backcolor = bgclr;
145
146		BufferLine bf;
147
148		for (uint y = _y; y < _b; y++, cury++) {
149			Console.position(0,30);
150			Console.put("y ", _curx, " ", _cury);
151			Console.position(_x, y);
152
153			bf = _buffer[cury];
154
155			curx = 0;
156			for (curx = 0; curx < _w; curx++) {
157				if (bf.fgclr[curx] != fgclr || bf.bgclr[curx] != bgclr) {
158					Console.forecolor = bf.fgclr[curx];
159					Console.backcolor = bf.bgclr[curx];
160					fgclr = bf.fgclr[curx];
161					bgclr = bf.bgclr[curx];
162				}
163				Console.put(bf.line[curx]);
164			}
165		}
166
167		_drawLock.up();
168	}
169
170	void redraw() {
171		onDraw();
172	}
173
174	// Methods
175
176	void forecolor(Color fgclr) {
177		_drawLock.down();
178
179		_curfg = fgclr;
180
181		_drawLock.up();
182	}
183
184	void backcolor(Color bgclr) {
185		_drawLock.down();
186
187		_curbg = bgclr;
188
189		_drawLock.up();
190	}
191
192	void setColors(Color fgclr, Color bgclr) {
193		_drawLock.down();
194
195		_curfg = fgclr;
196		_curbg = bgclr;
197
198		_drawLock.up();
199	}
200
201	void writeChar(dchar chr) {
202		static int a = 0;
203		Console.position((a * 10),29);
204		Console.put(_curx, " ", _cury);
205
206		if (_cury >= _b)
207		{
208			_linefeed();
209
210			Console.position((a * 10),29);
211			Console.put("lf: ", _curx, " ", _cury);
212		}
213		a++;
214		a %= 3;
215
216		_drawLock.down();
217
218		Console.position(_curx, _cury);
219		Console.forecolor = _curfg;
220		Console.backcolor = _curbg;
221
222		Console.put(chr);
223
224		uint idx_y = (_cury-_y)+_firstVisible;
225		uint idx_x = (_curx-_x);
226
227
228		_buffer[idx_y].line[idx_x] = cast(emptyChar)chr;
229		_buffer[idx_y].bgclr[idx_x] = _curbg;
230		_buffer[idx_y].fgclr[idx_x] = _curfg;
231
232		_curx++;
233
234		_drawLock.up();
235
236		if (_curx == _r)
237		{
238
239		Console.position((a * 10),29);
240			Console.put("lf: ", _curx, " ", _cury);
241			_linefeed();
242
243		Console.position((a * 10),29);
244			Console.put("af: ", _curx, " ", _cury);
245		}
246	}
247
248	void writeChar(uint x, uint y, dchar chr)
249	{
250		_drawLock.down();
251
252		_buffer[y].line[x] = cast(emptyChar)chr;
253		_buffer[y].bgclr[x] = _curbg;
254		_buffer[y].fgclr[x] = _curfg;
255
256		Console.position(x+_x, y+_y);
257		Console.forecolor = _curfg;
258		Console.backcolor = _curbg;
259
260		Console.put(chr);
261
262		_drawLock.up();
263	}
264
265	void position(uint x, uint y)
266	{
267		_drawLock.down();
268
269		_curx = x + _x;
270		_cury = y + _y;
271
272		if (_curx >= _r)
273		{
274			_curx = _r-1;
275		}
276
277		if (_cury >= _b)
278		{
279			_cury = _b-1;
280		}
281
282		Console.position(_curx, _cury);
283
284		_drawLock.up();
285	}
286
287	void setRelative(int x, int y)
288	{
289		uint new_x = (_curx-_x) + x;
290		uint new_y = (_cury-_y) + y;
291
292		position(new_x, new_y);
293	}
294
295	void getPosition(out uint x, out uint y)
296	{
297		x = _curx - _x;
298		y = _cury - _y;
299	}
300
301protected:
302
303	void _linefeed() {
304		Console.position((4 * 10),29);
305		Console.put("af: ", _curx, " ", _cury);
306		_drawLock.down();
307
308		bool needRedraw = false;
309
310		// met right edge; goto next line
311
312		// linefeed
313		_cury++;
314
315		while (_cury >= _b) {
316			Console.position((4 * 10),29);
317			Console.put("bf: ", _curx, " ", _cury);
318			// we have reached the bottom
319			// we have to move the first line
320			// to the buffer
321
322			BufferLine bl;
323
324			for(uint i=0; i<_linesToScroll;i++) {
325				bl = null;
326				while (bl is null) {
327					bl = new BufferLine();
328				}
329				Console.position((4 * 10),29);
330				Console.put("ef: ", _curx, " ", _cury);
331				bl.fgclr = new Color[_w];
332				Console.position((4 * 10),29);
333				Console.put("ff: ", _curx, " ", _cury);
334				bl.bgclr = new Color[_w];
335				Console.position((4 * 10),29);
336				Console.put("df: ", _curx, " ", _cury);
337				bl.line = new emptyChar[_w];
338				Console.position((4 * 10),29);
339				Console.put("gf: ", _curx, " ", _cury);
340				_buffer.add(bl);
341				Console.position((4 * 10),29);
342				Console.put("hf: ", _curx, " ", _cury);
343			}
344			Console.position((4 * 10),29);
345			Console.put("cf: ", _curx, " ", _cury);
346
347			_firstVisible += _linesToScroll;
348
349			// redraw the entire view
350			needRedraw = true;
351
352			// position ourselves at the new
353			// line, which is just the previous
354			// line again
355			_cury -= _linesToScroll;
356		}
357
358		// carriage return
359		_curx=_x;
360
361		_drawLock.up();
362
363		if (needRedraw) { redraw(); }
364	}
365
366	void _screenfeed()
367	{
368		_drawLock.down();
369
370		// we have reached the bottom
371		// we have to move the first line
372		// to the buffer
373
374		for(uint i=0; i<_h;i++)
375		{
376			BufferLine bl = new BufferLine();
377			bl.line = new emptyChar[_w];
378			bl.fgclr = new Color[_w];
379			bl.bgclr = new Color[_w];
380			_buffer.add(bl);
381		}
382
383		_firstVisible += _h;
384
385		// go home
386		_cury = _y;
387		_curx = _x;
388
389		_drawLock.up();
390
391		redraw();
392	}
393
394	uint _x = 0;
395	uint _y = 0;
396
397	uint _r = 0;
398	uint _b = 0;
399
400	uint _w = 0;
401	uint _h = 0;
402
403	typedef dchar emptyChar = ' ';
404
405	// keep a line buffer of previous lines, for scrollback, etc
406	class BufferLine {
407		emptyChar[] line = null;
408		Color[] fgclr = null;
409		Color[] bgclr = null;
410	}
411	List!(BufferLine) _buffer;
412	uint _firstVisible;	// first line visible
413
414	Color _curfg = Color.White;
415	Color _curbg = Color.Gray;
416
417	uint _curx;
418	uint _cury;
419
420	uint _linesToScroll = 7;
421
422	Semaphore _drawLock;
423}