Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 6 additions & 11 deletions demos/hello/source/hello.d
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,11 @@ import std.string;

import dcell;

void emitStr(Screen s, int x, int y, Style style, string str)
void centerStr(Screen s, int y, Style style, string str)
{
// NB: this naively assumes only ASCII
while (str != "")
{
s[x, y] = Cell(str[0], style);
str = str[1 .. $];
x += 1;
}
s.style = style;
s.position = Coord((s.size.x - cast(int)(str.length)) / 2, y);
s.write(str);
}

void displayHelloWorld(Screen s)
Expand All @@ -32,11 +28,10 @@ void displayHelloWorld(Screen s)
Style def;
def.bg = Color.silver;
def.fg = Color.black;
s.setStyle(def);
s.clear();
Style style = {fg: Color.red, bg: Color.papayaWhip};
emitStr(s, size.x / 2 - 9, size.y / 2 - 1, style, " Hello, World! ");
emitStr(s, size.x / 2 - 11, size.y / 2 + 1, def, " Press ESC to exit. ");
centerStr(s, size.y / 2 - 1, style, " Hello There! ");
centerStr(s, size.y / 2 + 1, def, " Press ESC to exit. ");

// this demonstrates a different method.
// it places a red X in the center of the screen.
Expand Down
157 changes: 131 additions & 26 deletions source/dcell/cell.d
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module dcell.cell;
import std.algorithm;
import std.exception;
import std.traits;
import std.uni;
import std.utf;

import eastasianwidth;
Expand Down Expand Up @@ -47,7 +48,7 @@ struct Cell
style = st;
}

@property const(string) text() pure @safe const
@property const(string) text() nothrow pure @safe const
{
return ss;
}
Expand All @@ -72,7 +73,7 @@ struct Cell
* be sensitive to which Unicode edition is being supported). Therefore the results
* may not be perfectly correct for a given platform or font or context.
*/
@property ubyte width() const pure @safe
@property ubyte width() const nothrow pure @safe
{
return dw;
}
Expand Down Expand Up @@ -158,23 +159,23 @@ class CellBuffer
private Cell[] cells; // current content - linear for performance
private Cell[] prev; // previous content - linear for performance

private size_t index(Coord pos) nothrow pure const
private size_t index(Coord pos) nothrow pure const @safe @nogc
{
return index(pos.x, pos.y);
}

private size_t index(size_t x, size_t y) nothrow pure const
private size_t index(size_t x, size_t y) nothrow pure const @safe @nogc
{
assert(size_.x > 0);
return (y * size_.x + x);
}

package bool isLegal(Coord pos) nothrow pure const
package bool isLegal(Coord pos) nothrow pure const @safe @nogc
{
return ((pos.x >= 0) && (pos.y >= 0) && (pos.x < size_.x) && (pos.y < size_.y));
}

this(const size_t cols, const size_t rows)
this(const size_t cols, const size_t rows) @safe
{
assert((cols >= 0) && (rows >= 0) && (cols < int.max) && (rows < int.max));
cells = new Cell[cols * rows];
Expand All @@ -188,7 +189,7 @@ class CellBuffer
}
}

this(Coord size)
this(Coord size) @safe
{
this(size.x, size.y);
}
Expand All @@ -202,7 +203,7 @@ class CellBuffer
* Params:
* pos = coordinates of cell to check
*/
bool dirty(Coord pos) pure const
bool dirty(Coord pos) nothrow pure const @safe
{
if (isLegal(pos))
{
Expand All @@ -223,7 +224,7 @@ class CellBuffer
* pos = coordinate of sell to update
* b = mark all dirty if true, or clean if false
*/
void setDirty(Coord pos, bool b) pure
void setDirty(Coord pos, bool b) pure @safe
{
if (isLegal(pos))
{
Expand All @@ -245,7 +246,7 @@ class CellBuffer
* Params:
* b = mark all dirty if true, or clean if false
*/
void setAllDirty(bool b) pure
void setAllDirty(bool b) pure @safe
{
// structured this way for efficiency
if (b)
Expand All @@ -264,17 +265,17 @@ class CellBuffer
}
}

ref Cell opIndex(Coord pos)
ref Cell opIndex(Coord pos) nothrow @safe
{
return this[pos.x, pos.y];
}

ref Cell opIndex(size_t x, size_t y)
ref Cell opIndex(size_t x, size_t y) nothrow @safe
{
return cells[index(x, y)];
}

Cell get(Coord pos) nothrow pure
Cell get(Coord pos) nothrow pure @safe
{
if (isLegal(pos))
{
Expand All @@ -290,7 +291,7 @@ class CellBuffer
* c = content to store for the cell.
* pos = coordinate of the cell
*/
void opIndexAssign(Cell c, size_t x, size_t y) pure
void opIndexAssign(Cell c, size_t x, size_t y) pure @safe
{
if ((x < size_.x) && (y < size_.y))
{
Expand All @@ -302,7 +303,7 @@ class CellBuffer
}
}

void opIndexAssign(Cell c, Coord pos) pure
void opIndexAssign(Cell c, Coord pos) pure @safe
{
this[pos.x, pos.y] = c;
}
Expand All @@ -315,7 +316,7 @@ class CellBuffer
* character (including combining marks) is written.
* pos = coordinate to update.
*/
void opIndexAssign(string s, Coord pos) pure
void opIndexAssign(string s, Coord pos) pure @safe
{
if (s == "" || s[0] < ' ')
{
Expand All @@ -328,15 +329,15 @@ class CellBuffer
}
}

void opIndexAssign(Style style, Coord pos) pure
void opIndexAssign(Style style, Coord pos) nothrow pure @safe
{
if (isLegal(pos))
{
cells[index(pos)].style = style;
}
}

void opIndexAssign(string s, size_t x, size_t y) pure
void opIndexAssign(string s, size_t x, size_t y) pure @safe
{
if (s == "" || s[0] < ' ')
{
Expand All @@ -346,12 +347,12 @@ class CellBuffer
cells[index(x, y)].text = s;
}

void opIndexAssign(Style v, size_t x, size_t y) pure
void opIndexAssign(Style v, size_t x, size_t y) nothrow pure @safe
{
cells[index(x, y)].style = v;
}

int opDollar(size_t dim)()
int opDollar(size_t dim)() nothrow pure @safe
{
if (dim == 0)
{
Expand All @@ -363,7 +364,7 @@ class CellBuffer
}
}

void fill(Cell c) pure
void fill(Cell c) pure @safe
{
if (c.text == "" || c.text[0] < ' ')
{
Expand All @@ -378,7 +379,7 @@ class CellBuffer
/**
* Fill the entire contents, but leave any text styles undisturbed.
*/
void fill(string s) pure
void fill(string s) pure @safe
{
foreach (i; 0 .. cells.length)
{
Expand All @@ -389,7 +390,7 @@ class CellBuffer
/**
* Fill the entire contents, including the given style.
*/
void fill(string s, Style style) pure
void fill(string s, Style style) pure @safe
{
Cell c = Cell(s, style);
fill(c);
Expand All @@ -402,7 +403,7 @@ class CellBuffer
* content. The entire set of contents are marked dirty, because
* presumably everything needs to be redrawn when this happens.
*/
void resize(Coord size)
void resize(Coord size) @safe
{
if (size_ == size)
{
Expand Down Expand Up @@ -430,16 +431,82 @@ class CellBuffer
prev = new Cell[size.x * size.y];
}

void resize(int cols, int rows)
void resize(int cols, int rows) @safe
{
resize(Coord(cols, rows));
}

Coord size() const pure nothrow
Coord size() const pure nothrow @safe
{
return size_;
}

// This is the default style we use when writing content using
// put and similar APIs.
Style style;

// This is the current position that will be writing when when using
// put or write.
Coord position;

void put(Grapheme g) @safe
{
if (isLegal(position))
{
auto ix = index(position);
string str = toUTF8(g[]);
cells[ix].text = str;
cells[ix].style = style;
auto w = cells[ix].width;
final switch (w)
{
case 0:
break;
case 1:
position.x++;
if (position.x >= size_.x)
{
// auto wrap
position.y++;
position.x = 0;
}
break;
case 2:
position.x++;
if (isLegal(position))
{
cells[index(position)].text = "";
}
position.x++;
if (position.x >= size_.x)
{
position.y++;
position.x = 0;
}
}
}
}

// Put uses a range put, and can thus support a formatted writer, but
// note that this WILL NOT WORK with grapheme clusters, because the formatted
// writer does not know about unicode segmentation. Use write() and create
// a string elsewhere if you need to work with grapheme clusters. Single code
// point use cases (i.e. most simple text, or precomposed scripts) will work fine.
void put(Char)(Char c) @safe if (isSomeChar!Char)
{
put(Grapheme(c));
}

// Write a string at the current `position`, using the current `style`.
// This will wrap if it reaches the end of the terminal.
void write(Str)(Str s) @safe if (isSomeString!Str)
{
foreach (g; s.byGrapheme)
{
put(g);
}
}

unittest
{
auto cb = new CellBuffer(80, 24);
Expand Down Expand Up @@ -553,3 +620,41 @@ class CellBuffer
assert(cb[131, 49].text == "D");
}
}

unittest
{
auto cb = new CellBuffer(80, 24);
cb.put('1');
cb.position = Coord(5, 10);
cb.style.attr = Attr.bold;
cb.put('2');

assert(cb[0, 0].text == "1");
assert(cb[5, 10].text == "2");
assert(cb[5, 10].style.attr == Attr.bold);

cb.position = Coord(76, 1);
cb.write("this wraps");
assert(cb[76, 1].text == "t");
assert(cb[77, 1].text == "h");
assert(cb[78, 1].text == "i");
assert(cb[79, 1].text == "s");
assert(cb[0, 2].text == " ");
assert(cb[1, 2].text == "w");
assert(cb[2, 2].text == "r");
assert(cb[3, 2].text == "a");
assert(cb[4, 2].text == "p");
assert(cb[5, 2].text == "s");

cb.position = Coord(0, 3);
cb.write("¥ yen sign");
assert(cb[0, 3].text == "¥");
assert(cb[0, 3].width == 2);
assert(cb[1, 3].text == "");
assert(cb[1, 3].width == 0);
assert(cb[2, 3].text == " ");
assert(cb[2, 3].width == 1);
assert(cb[3, 3].text == "y");
assert(cb[4, 3].text == "e");
assert(cb[5, 3].text == "n");
}
Loading